| 
 | 1 | +#!/usr/bin/env bash  | 
 | 2 | +# Copyright (c) 2025, Nordic Semiconductor ASA  | 
 | 3 | +# SPDX-License-Identifier: Apache-2.0  | 
 | 4 | +#  | 
 | 5 | +# This script installs Wi-Fi certificates to a device using the `device_credentials_installer` tool.  | 
 | 6 | +#  | 
 | 7 | +# shellcheck disable=SC2086,SC2154  | 
 | 8 | +# Usage:  | 
 | 9 | +#   ./install_certs.sh <path_to_certs> [port] [mode]  | 
 | 10 | +#  | 
 | 11 | +# Arguments:  | 
 | 12 | +#   <path_to_certs>  Path to the directory containing the certificate files.  | 
 | 13 | +#   [port]           (Optional) Serial port to use for communication with the device. Default is  | 
 | 14 | +#                    /dev/ttyACM1.  | 
 | 15 | +#   [mode]           (Optional) Mode of operation: AP or STA. Default is STA.  | 
 | 16 | +#  | 
 | 17 | +# Dependencies:  | 
 | 18 | +#   - `device_credentials_installer` tool must be installed. You can install it using:  | 
 | 19 | +#     pip3 install nrfcloud-utils  | 
 | 20 | +#  | 
 | 21 | +# Certificate Files:  | 
 | 22 | +#   The script expects the following certificate files in the specified directory:  | 
 | 23 | +#   - ca.pem: CA certificate for Wi-Fi Enterprise mode (Phase 1)  | 
 | 24 | +#   - client-key.pem: Client private key for Wi-Fi Enterprise mode (Phase 1)  | 
 | 25 | +#   - server-key.pem: Server private key for Wi-Fi Enterprise mode, for used in AP mode.  | 
 | 26 | +#   - client.pem: Client certificate for Wi-Fi Enterprise mode (Phase 1)  | 
 | 27 | +#   - server.pem: Server certificate for Wi-Fi Enterprise mode, for used in AP mode.  | 
 | 28 | +#   - ca2.pem: CA certificate for Wi-Fi Enterprise mode (Phase 2)  | 
 | 29 | +#   - client-key2.pem: Client private key for Wi-Fi Enterprise mode (Phase 2)  | 
 | 30 | +#   - client2.pem: Client certificate for Wi-Fi Enterprise mode (Phase 2)  | 
 | 31 | +#  | 
 | 32 | +# Each certificate file is associated with a specific security tag (sec_tag) which is used during  | 
 | 33 | +# installation.  | 
 | 34 | +#  | 
 | 35 | +# The script performs the following steps:  | 
 | 36 | +#   1. Checks if the required arguments are provided.  | 
 | 37 | +#   2. Validates the existence of the certificate directory.  | 
 | 38 | +#   3. Checks if the `device_credentials_installer` tool is available.  | 
 | 39 | +#   4. Iterates over the expected certificate files and installs them to the device if they exist.  | 
 | 40 | +#   5. Logs the success or failure of each certificate installation.  | 
 | 41 | +#  | 
 | 42 | +# Note:  | 
 | 43 | +#   - If a certificate file is missing, the script will skip its installation and log a warning.  | 
 | 44 | +#   - The script will terminate on the first encountered error (set -e).  | 
 | 45 | +set -e  | 
 | 46 | + | 
 | 47 | +if [ -z "$1" ]; then  | 
 | 48 | +  echo -e "\033[31mError: Usage: $0 <path_to_certs> [port] [mode]\033[0m"  | 
 | 49 | +  exit 1  | 
 | 50 | +fi  | 
 | 51 | + | 
 | 52 | +CERT_PATH=$1  | 
 | 53 | +PORT=${2:-/dev/ttyACM1}  # Default port is /dev/ttyACM1 if not provided  | 
 | 54 | +MODE=${3:-STA}  # Default mode is STA if not provided  | 
 | 55 | + | 
 | 56 | +if [ ! -d "$CERT_PATH" ]; then  | 
 | 57 | +  echo -e "\033[31mError: Directory $CERT_PATH does not exist.\033[0m"  | 
 | 58 | +  exit 1  | 
 | 59 | +fi  | 
 | 60 | + | 
 | 61 | +echo -e "\033[33mWarning: Please make sure that the UART is not being used by another" \  | 
 | 62 | +  " application.\033[0m"  | 
 | 63 | + | 
 | 64 | +read -r -p "Press Enter to continue or Ctrl+C to exit..."  | 
 | 65 | + | 
 | 66 | +if ! command -v device_credentials_installer &> /dev/null; then  | 
 | 67 | +  echo -e "\033[31mError: device_credentials_installer could not be found.\033[0m"  | 
 | 68 | +  echo "Please install it using: pip3 install nrfcloud-utils"  | 
 | 69 | +  exit 1  | 
 | 70 | +fi  | 
 | 71 | + | 
 | 72 | +INSTALLED_VERSION=$(pip3 show nrfcloud-utils | grep Version | awk '{print $2}')  | 
 | 73 | +REQUIRED_VERSION="1.0.4"  | 
 | 74 | + | 
 | 75 | +if [ "$(printf '%s\n' "$REQUIRED_VERSION" "$INSTALLED_VERSION" | sort -V | head -n1)" != \  | 
 | 76 | +"$REQUIRED_VERSION" ]; then  | 
 | 77 | +  echo -e "\033[31mError: device_credentials_installer >= $REQUIRED_VERSION required. Installed: \  | 
 | 78 | +$INSTALLED_VERSION.\033[0m"  | 
 | 79 | +  echo "Update: pip3 install --upgrade nrfcloud-utils"  | 
 | 80 | +  exit 1  | 
 | 81 | +fi  | 
 | 82 | + | 
 | 83 | +# From zephyr/subsys/net/lib/tls_credentials/tls_credentials_shell.c  | 
 | 84 | +TLS_CREDENTIAL_CA_CERTIFICATE=0 # CA  | 
 | 85 | +TLS_CREDENTIAL_PUBLIC_CERTIFICATE=1 # SERV  | 
 | 86 | +TLS_CREDENTIAL_PRIVATE_KEY=2 # PK  | 
 | 87 | + | 
 | 88 | + | 
 | 89 | +WIFI_CERT_SEC_TAG_BASE=0x1020001  | 
 | 90 | +declare -A WIFI_CERT_SEC_TAG_MAP=(  | 
 | 91 | +  ["ca.pem"]="{\"$TLS_CREDENTIAL_CA_CERTIFICATE\" $((WIFI_CERT_SEC_TAG_BASE))}"  | 
 | 92 | +  ["client-key.pem"]="{\"$TLS_CREDENTIAL_PRIVATE_KEY\" $((WIFI_CERT_SEC_TAG_BASE + 1))}"  | 
 | 93 | +  ["server-key.pem"]="{\"$TLS_CREDENTIAL_PRIVATE_KEY\" $((WIFI_CERT_SEC_TAG_BASE + 2))}"  | 
 | 94 | +  ["client.pem"]="{\"$TLS_CREDENTIAL_PUBLIC_CERTIFICATE\" $((WIFI_CERT_SEC_TAG_BASE + 3))}"  | 
 | 95 | +  ["server.pem"]="{\"$TLS_CREDENTIAL_PUBLIC_CERTIFICATE\" $((WIFI_CERT_SEC_TAG_BASE + 4))}"  | 
 | 96 | +  ["ca2.pem"]="{\"$TLS_CREDENTIAL_CA_CERTIFICATE\" $((WIFI_CERT_SEC_TAG_BASE + 5))}"  | 
 | 97 | +  ["client-key2.pem"]="{\"$TLS_CREDENTIAL_PRIVATE_KEY\" $((WIFI_CERT_SEC_TAG_BASE + 6))}"  | 
 | 98 | +  ["client2.pem"]="{\"$TLS_CREDENTIAL_PUBLIC_CERTIFICATE\" $((WIFI_CERT_SEC_TAG_BASE + 7))}"  | 
 | 99 | +)  | 
 | 100 | + | 
 | 101 | +# Select certificates based on mode  | 
 | 102 | +if [ "$MODE" == "AP" ]; then  | 
 | 103 | +  CERT_FILES=("ca.pem" "server-key.pem" "server.pem")  | 
 | 104 | +else  | 
 | 105 | +  CERT_FILES=("ca.pem" "client-key.pem" "client.pem" "ca2.pem" "client-key2.pem" "client2.pem")  | 
 | 106 | +fi  | 
 | 107 | + | 
 | 108 | +total_certs=${#CERT_FILES[@]}  | 
 | 109 | +processed_certs=0  | 
 | 110 | + | 
 | 111 | +for cert in "${CERT_FILES[@]}"; do  | 
 | 112 | +  processed_certs=$((processed_certs + 1))  | 
 | 113 | +  echo "Processing certificate $processed_certs of $total_certs: $cert"  | 
 | 114 | + | 
 | 115 | +  if [ ! -f "$CERT_PATH/$cert" ]; then  | 
 | 116 | +  echo -e "\033[31mWarning: Certificate file $CERT_PATH/$cert does not exist. Skipping...\033[0m"  | 
 | 117 | +  continue  | 
 | 118 | +  fi  | 
 | 119 | + | 
 | 120 | +  cert_info=${WIFI_CERT_SEC_TAG_MAP[$cert]}  | 
 | 121 | +  cert_type=$(echo "$cert_info" | awk -F'[{} ]' '{print $2}' | tr -d '"')  | 
 | 122 | +  cert_type_int=$((10#$cert_type))  | 
 | 123 | +  sec_tag=$(echo "$cert_info" | awk -F'[{} ]' '{print $3}' | tr -d '"')  | 
 | 124 | +  sec_tag_int=$((10#$sec_tag))  | 
 | 125 | +  if device_credentials_installer --local-cert-file "$CERT_PATH/$cert" \  | 
 | 126 | +  --cmd-type tls_cred_shell --delete \  | 
 | 127 | +  --port $PORT -S $sec_tag_int --cert-type $cert_type_int; then  | 
 | 128 | +  echo "Successfully installed $cert."  | 
 | 129 | +  else  | 
 | 130 | +  echo -e "\033[31mFailed to install $cert.\033[0m"  | 
 | 131 | +  fi  | 
 | 132 | +done  | 
 | 133 | + | 
 | 134 | + | 
 | 135 | +echo "Certificate installation process completed."  | 
0 commit comments