From 5e1b0b97b59ba6a04950a15c6dbc8cbfd7612c3c Mon Sep 17 00:00:00 2001 From: Aditya Patwardhan Date: Wed, 24 Aug 2022 23:19:51 +0530 Subject: [PATCH] mqtt/ssl_ds example: Remove configure_ds.py script, use esp-secure-cert-tool instread --- examples/protocols/mqtt/ssl_ds/README.md | 14 +- .../protocols/mqtt/ssl_ds/configure_ds.py | 393 ------------------ .../mqtt/ssl_ds/main/idf_component.yml | 3 + 3 files changed, 12 insertions(+), 398 deletions(-) delete mode 100644 examples/protocols/mqtt/ssl_ds/configure_ds.py create mode 100644 examples/protocols/mqtt/ssl_ds/main/idf_component.yml diff --git a/examples/protocols/mqtt/ssl_ds/README.md b/examples/protocols/mqtt/ssl_ds/README.md index 065bcfca2b..cbb7f0c4fd 100644 --- a/examples/protocols/mqtt/ssl_ds/README.md +++ b/examples/protocols/mqtt/ssl_ds/README.md @@ -40,22 +40,26 @@ openssl genrsa -out client.key openssl req -out client.csr -key client.key -new ``` -Paste the generated CSR in the [Mosquitto test certificate signer](https://test.mosquitto.org/ssl/index.php), click Submit and copy the downloaded `client.crt` in the `main` directory. - -Please note, that the supplied file `client.crt` in the `main` directory is only a placeholder for your client certificate (i.e. the example "as is" would compile but would not connect to the broker) +Paste the generated CSR in the [Mosquitto test certificate signer](https://test.mosquitto.org/ssl/index.php), click Submit and downloaded the `client.crt`. This `client.crt` file shall be used as the device certificate. #### 3) Configure the DS peripheral -* The DS peripheral can be configured with the python script [configure_ds.py](README.md#configure_ds-py) by executing the following command +* i) Install the [esp_secure_cert configuration utility](https://github.com/espressif/esp_secure_cert_mgr/tree/main/tools#esp_secure_cert-configuration-tool) with following command: +``` +pip install esp-secure-cert-tool +``` +* The DS peripheral can be configured by executing the following command: ``` - python configure_ds.py --port /* USB COM port */ --private-key /* RSA priv key */ +configure_esp_secure_cert.py -p /* Serial port */ --device-cert /* Device cert */ --private-key /* RSA priv key */ --target_chip /* target chip */ --configure_ds ``` In the command USB COM port is nothing but the serial port to which the ESP chip is connected. see [check serial port](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/establish-serial-connection.html#check-port-on-windows) for more details. RSA private key is nothing but the client private key ( RSA ) generated in Step 2. +> Note: More details about the `esp-secure-cert-tool` utility can be found [here](https://github.com/espressif/esp_secure_cert_mgr/tree/main/tools). + #### 4) Connection cofiguration * Open the project configuration menu (`idf.py menuconfig`) * Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details. diff --git a/examples/protocols/mqtt/ssl_ds/configure_ds.py b/examples/protocols/mqtt/ssl_ds/configure_ds.py deleted file mode 100644 index d847db23a6..0000000000 --- a/examples/protocols/mqtt/ssl_ds/configure_ds.py +++ /dev/null @@ -1,393 +0,0 @@ -#!/usr/bin/env python -# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Apache-2.0 -import argparse -import hashlib -import hmac -import json -import os -import struct -import subprocess -import sys - -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import serialization -from cryptography.hazmat.primitives.asymmetric import rsa -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from cryptography.utils import int_to_bytes - -try: - import nvs_partition_gen as nvs_gen -except ImportError: - idf_path = os.getenv('IDF_PATH') - if not idf_path or not os.path.exists(idf_path): - raise Exception('IDF_PATH not found') - sys.path.insert(0, os.path.join(idf_path, 'components', 'nvs_flash', 'nvs_partition_generator')) - import nvs_partition_gen as nvs_gen - -# Check python version is proper or not to avoid script failure -assert sys.version_info >= (3, 6, 0), 'Python version too low.' - -esp_ds_data_dir = 'esp_ds_data' -# hmac_key_file is generated when HMAC_KEY is calculated, it is used when burning HMAC_KEY to efuse -hmac_key_file = esp_ds_data_dir + '/hmac_key.bin' -# csv and bin filenames are default filenames for nvs partition files created with this script -csv_filename = esp_ds_data_dir + '/pre_prov.csv' -bin_filename = esp_ds_data_dir + '/pre_prov.bin' -expected_json_path = os.path.join('build', 'config', 'sdkconfig.json') -# Targets supported by the script -supported_targets = {'esp32s2', 'esp32c3', 'esp32s3'} -supported_key_size = {'esp32s2':[1024, 2048, 3072, 4096], 'esp32c3':[1024, 2048, 3072], 'esp32s3':[1024, 2048, 3072, 4096]} - - -# @return -# on success idf_target - value of the IDF_TARGET read from build/config/sdkconfig.json -# on failure None -def get_idf_target(): - if os.path.exists(expected_json_path): - sdkconfig = json.load(open(expected_json_path)) - idf_target_read = sdkconfig['IDF_TARGET'] - return idf_target_read - else: - print('ERROR: IDF_TARGET has not been set for the supported targets,' - "\nplase execute command \"idf.py set-target {TARGET}\" in the example directory") - return None - - -def load_privatekey(key_file_path, password=None): - key_file = open(key_file_path, 'rb') - key = key_file.read() - key_file.close() - return serialization.load_pem_private_key(key, password=password, backend=default_backend()) - - -def number_as_bytes(number, pad_bits=None): - """ - Given a number, format as a little endian array of bytes - """ - result = int_to_bytes(number)[::-1] - while pad_bits is not None and len(result) < (pad_bits // 8): - result += b'\x00' - return result - - -# @return -# c : ciphertext_c -# iv : initialization vector -# key_size : key size of the RSA private key in bytes. -# @input -# privkey : path to the RSA private key -# priv_key_pass : path to the RSA privaete key password -# hmac_key : HMAC key value ( to calculate DS params) -# idf_target : The target chip for the script (e.g. esp32s2, esp32c3, esp32s3) -# @info -# The function calculates the encrypted private key parameters. -# Consult the DS documentation (available for the ESP32-S2) in the esp-idf programming guide for more details about the variables and calculations. -def calculate_ds_parameters(privkey, priv_key_pass, hmac_key, idf_target): - private_key = load_privatekey(privkey, priv_key_pass) - if not isinstance(private_key, rsa.RSAPrivateKey): - print('ERROR: Only RSA private keys are supported') - sys.exit(-1) - if hmac_key is None: - print('ERROR: hmac_key cannot be None') - sys.exit(-2) - - priv_numbers = private_key.private_numbers() - pub_numbers = private_key.public_key().public_numbers() - Y = priv_numbers.d - M = pub_numbers.n - key_size = private_key.key_size - if key_size not in supported_key_size[idf_target]: - print('ERROR: Private key size {0} not supported for the target {1},\nthe supported key sizes are {2}' - .format(key_size, idf_target, str(supported_key_size[idf_target]))) - sys.exit(-1) - - iv = os.urandom(16) - - rr = 1 << (key_size * 2) - rinv = rr % pub_numbers.n - mprime = - rsa._modinv(M, 1 << 32) - mprime &= 0xFFFFFFFF - length = key_size // 32 - 1 - - # get max supported key size for the respective target - max_len = max(supported_key_size[idf_target]) - aes_key = hmac.HMAC(hmac_key, b'\xFF' * 32, hashlib.sha256).digest() - - md_in = number_as_bytes(Y, max_len) + \ - number_as_bytes(M, max_len) + \ - number_as_bytes(rinv, max_len) + \ - struct.pack('