diff --git a/components/protocomm/CMakeLists.txt b/components/protocomm/CMakeLists.txt index e74a13cf30..ab026e55c8 100644 --- a/components/protocomm/CMakeLists.txt +++ b/components/protocomm/CMakeLists.txt @@ -6,8 +6,9 @@ endif() set(include_dirs include/common include/security - include/transports) -set(priv_include_dirs proto-c src/common src/crypto/srp6a/include) + include/transports + include/crypto/srp6a) +set(priv_include_dirs proto-c src/common) set(srcs "src/common/protocomm.c" "proto-c/constants.pb-c.c" diff --git a/components/protocomm/include/crypto/srp6a/esp_srp.h b/components/protocomm/include/crypto/srp6a/esp_srp.h new file mode 100644 index 0000000000..23db7db35c --- /dev/null +++ b/components/protocomm/include/crypto/srp6a/esp_srp.h @@ -0,0 +1,228 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief SRP-6a protocol implementation + * + * More information on protocol can be found: https://datatracker.ietf.org/doc/html/rfc5054 + * + * This implementation is used by security2 of wifi_provisioning and local control features. + * Details on how these protocols use this feature can be found here: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/provisioning/provisioning.html#security-2-scheme + * + * Below is the example usage of the srp6a protocol in protocomm component, + * which can help understand the APIs better. + * + * Variables used: + * + * N, g: group parameters (prime and generator) + * s: salt + * B, b: server's public and private values + * A, a: client's public and private values + * I: user name (aka "identity") + * P: password + * v: verifier + * k: SRP-6 multiplier + * + * salt (s) is random of given length, 16 in our case, which along with username and password + * is used to generate verifier. + * + * x = SHA1(s | SHA1(I | ":" | P)) + * v = g^x % N + * + * Steps involved (From protocomm component usage): + * Step1. Client Hello (PhoneApp): + * a. Generate Key pair: + * a (cli_privkey) = 256 bit random value, + * A (cli_pubkey) = g^a. + * g - generator, N - large safe prime, All arithmetic operations are performed in ring of integers modulo N, + * thus all occurrences like y^z should be read as y^z modulo N. + * b. SessionCmd0 (cli_pubkey, username I) + * + * Step2. Device(ESP): + * a. Obtain Salt and verifier stored on ESP + * Salt s = 256 bit random value, + * Verifier v = g^× where x = H(s | I | P) + * b. Generate Key Pair + * b (dev_privkey) = 256 bit random value + * B(dev_pubkey) = k*v + g^b where k = H(N, g) + * c. Shared Key K = H(S) where, + * S = (A * v^u) ^ b + * u = H(A, B) + * d. SessionResp0(dev_pubkey B, dev_random) + * + * Step3. Client (PhoneApp) + * a. shared_key(K) = H(S) where, + * S = (B - k*v) ^ (a + ux), + * u = H(A, B), + * k = H(N, g), + * V = g^x, + * x = H(s | I | P). + * b. Verification token + * client proof M = H[H(N) XOR H(g) | H(I) | S | A | B | K] + * c. SessionCmd1(Client proof M1) + * + * Step4. Device (ESP): + * a. Verify client: + * device generates M1 = H[H(N) XOR H(g) | H(I) | S | A | B | K] + * device verifies this M1 with the M1 obtained from Client + * b. Verification token: Device generate device proof M2 = H(A, M, K) + * c. Initialization Vector(IV): + * dev_rand = gen_16byte_random) This random number is to be used for AES-GCM operation + * for encryption and decryption of the data using the shared secret + * d. SessionResp1 (DeviceProofM2, dev_rand) + * + * Step5. Client (PhoneApp) + * a. Verify Device + * Client calculates device proof M2 as M2 = H(A, M, K) + * verifies this M2 with M2 obtained from device + */ + +/** + * @brief Large prime+generator to be used for the algorithm + */ +typedef enum { + /* SRP specific: + * N = 3072 bit large safe prime, + * g = generator */ + ESP_NG_3072 = 0, +} esp_ng_type_t; + +typedef struct esp_srp_handle esp_srp_handle_t; + +/** + * @brief Initialize srp context for given NG type + * + * @param ng NG type given by `esp_ng_type_t` + * @return esp_srp_handle_t* srp handle + * + * @note the handle gets freed with `esp_srp_free` + */ +esp_srp_handle_t *esp_srp_init(esp_ng_type_t ng); + +/** + * @brief free esp_srp_context + * + * @param hd handle to be free + */ +void esp_srp_free(esp_srp_handle_t *hd); + +/** + * @brief Returns B (pub key) and salt. [Step2.b] + * + * @param hd esp_srp handle + * @param username Username not expected NULL terminated + * @param username_len Username length + * @param pass Password not expected to be NULL terminated + * @param pass_len Pasword length + * @param salt_len Salt length + * @param bytes_B Public Key returned + * @param len_B Length of the public key + * @param bytes_salt Salt bytes generated + * @return esp_err_t ESP_OK on success, appropriate error otherwise + * + * @note *bytes_B MUST NOT BE FREED BY THE CALLER + * @note *bytes_salt MUST NOT BE FREE BY THE CALLER + */ +esp_err_t esp_srp_srv_pubkey(esp_srp_handle_t *hd, const char *username, int username_len, + const char *pass, int pass_len, int salt_len, + char **bytes_B, int *len_B, char **bytes_salt); + +/** + * @brief Generate salt-verifier pair, given username, password and salt length + * + * @param[in] username username + * @param[in] username_len length of the username + * @param[in] pass password + * @param[in] pass_len length of the password + * @param[out] bytes_salt generated salt on successful generation, or NULL + * @param[in] salt_len salt length + * @param[out] verifier generated verifier on successful generation, or NULL + * @param[out] verifier_len length of the generated verifier + * @return esp_err_t ESP_OK on success, appropriate error otherwise + * + * @note if API has returned ESP_OK, salt and verifier generated need to be freed by caller + * @note Usually, username and password are not saved on the device. Rather salt and verifier are + * generated outside the device and are embedded. + * this covenience API can be used to generate salt and verifier on the fly for development use case. + * OR for devices which intentionally want to generate different password each time and can send it + * to the client securely. e.g., a device has a display and it shows the pin + */ +esp_err_t esp_srp_gen_salt_verifier(const char *username, int username_len, + const char *pass, int pass_len, + char **bytes_salt, int salt_len, + char **verifier, int *verifier_len); + +/** + * @brief Set the Salt and Verifier pre-generated for a given password. + * This should be used only if the actual password is not available. + * The public key can then be generated using esp_srp_srv_pubkey_from_salt_verifier() + * and not esp_srp_srv_pubkey() + * + * @param hd esp_srp_handle + * @param salt pre-generated salt bytes + * @param salt_len length of the salt bytes + * @param verifier pre-generated verifier + * @param verifier_len length of the verifier bytes + * @return esp_err_t ESP_OK on success, appropriate error otherwise + */ +esp_err_t esp_srp_set_salt_verifier(esp_srp_handle_t *hd, const char *salt, int salt_len, + const char *verifier, int verifier_len); + +/** + * @brief Returns B (pub key)[Step2.b] when the salt and verifier are set using esp_srp_set_salt_verifier() + * + * @param hd esp_srp handle + * @param bytes_B Key returned to the called + * @param len_B Length of the key returned + * @return esp_err_t ESP_OK on success, appropriate error otherwise + * + * @note *bytes_B MUST NOT BE FREED BY THE CALLER + */ +esp_err_t esp_srp_srv_pubkey_from_salt_verifier(esp_srp_handle_t *hd, char **bytes_B, int *len_B); + +/** + * @brief Get session key in `*bytes_key` given by len in `*len_key`. [Step2.c]. + * + * This calculated session key is used for further communication given the proofs are + * exchanged/authenticated with `esp_srp_exchange_proofs` + * + * @param hd esp_srp handle + * @param bytes_A Private Key + * @param len_A Private Key length + * @param bytes_key Key returned to the caller + * @param len_key length of the key in *bytes_key + * @return esp_err_t ESP_OK on success, appropriate error otherwise + * + * @note *bytes_key MUST NOT BE FREED BY THE CALLER + */ +esp_err_t esp_srp_get_session_key(esp_srp_handle_t *hd, char *bytes_A, int len_A, char **bytes_key, uint16_t *len_key); + +/** + * @brief Complete the authentication. If this step fails, the session_key exchanged should not be used + * + * This is the final authentication step in SRP algorithm [Step4.1, Step4.b, Step4.c] + * + * @param hd esp_srp handle + * @param username Username not expected NULL terminated + * @param username_len Username length + * @param bytes_user_proof param in + * @param bytes_host_proof parameter out (should be SHA512_DIGEST_LENGTH) bytes in size + * @return esp_err_t ESP_OK if user's proof is ok and subsequently bytes_host_proof is populated with our own proof. + */ +esp_err_t esp_srp_exchange_proofs(esp_srp_handle_t *hd, char *username, uint16_t username_len, + char *bytes_user_proof, char *bytes_host_proof); + +#ifdef __cplusplus +} +#endif diff --git a/components/protocomm/src/crypto/srp6a/esp_srp.c b/components/protocomm/src/crypto/srp6a/esp_srp.c index 36fbc08342..bf3dd25cc5 100644 --- a/components/protocomm/src/crypto/srp6a/esp_srp.c +++ b/components/protocomm/src/crypto/srp6a/esp_srp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,44 @@ static const char *TAG = "srp6a"; +typedef struct esp_srp_handle { + esp_ng_type_t type; + esp_mpi_ctx_t *ctx; + + /* N + * the bytes_n simply points to the static array + */ + esp_mpi_t *n; + const char *bytes_n; + int len_n; + + /* g + * the bytes_g simply points to the static array + */ + esp_mpi_t *g; + const char *bytes_g; + int len_g; + + /* Salt */ + esp_mpi_t *s; + char *bytes_s; + int len_s; + /* Verifier */ + esp_mpi_t *v; + /* B */ + esp_mpi_t *B; + char *bytes_B; + int len_B; + /* b */ + esp_mpi_t *b; + /* A */ + esp_mpi_t *A; + char *bytes_A; + int len_A; + /* K - session key*/ + char *session_key; +} esp_srp_handle; + static void hexdump_mpi(const char *name, esp_mpi_t *bn) { int len = 0; @@ -59,15 +97,13 @@ static const char N_3072[] = { static const char g_3072[] = { 5 }; -esp_err_t esp_srp_init(esp_srp_handle_t *hd, esp_ng_type_t ng) +esp_srp_handle_t *esp_srp_init(esp_ng_type_t ng) { - if (hd->allocated) { - esp_srp_free(hd); + esp_srp_handle_t *hd = calloc(1, sizeof(esp_srp_handle)); + if (!hd) { + return NULL; } - memset(hd, 0, sizeof(*hd)); - hd->allocated = 1; - hd->ctx = esp_mpi_ctx_new(); if (! hd->ctx) { goto error; @@ -90,18 +126,17 @@ esp_err_t esp_srp_init(esp_srp_handle_t *hd, esp_ng_type_t ng) goto error; } hd->type = ng; - return ESP_OK; + return hd; error: esp_srp_free(hd); - return ESP_FAIL; + return NULL; } void esp_srp_free(esp_srp_handle_t *hd) { - if (hd->allocated != 1) { + if (!hd) { return; } - if (hd->ctx) { esp_mpi_ctx_free(hd->ctx); } @@ -138,7 +173,7 @@ void esp_srp_free(esp_srp_handle_t *hd) if (hd->session_key) { free(hd->session_key); } - memset(hd, 0, sizeof(*hd)); + free(hd); } static esp_mpi_t *calculate_x(char *bytes_salt, int salt_len, const char *username, int username_len, const char *pass, int pass_len) @@ -223,7 +258,7 @@ static esp_mpi_t *calculate_u(esp_srp_handle_t *hd, char *A, int len_A) return calculate_padded_hash(hd, A, len_A, hd->bytes_B, hd->len_B); } -esp_err_t __esp_srp_srv_pubkey(esp_srp_handle_t *hd, char **bytes_B, int *len_B) +static esp_err_t __esp_srp_srv_pubkey(esp_srp_handle_t *hd, char **bytes_B, int *len_B) { esp_mpi_t *k = calculate_k(hd); esp_mpi_t *kv = NULL; @@ -279,47 +314,46 @@ error: return ESP_FAIL; } -esp_err_t esp_srp_srv_pubkey(esp_srp_handle_t *hd, const char *username, int username_len, const char *pass, int pass_len, int salt_len, - char **bytes_B, int *len_B, char **bytes_salt) +static esp_err_t _esp_srp_gen_salt_verifier(esp_srp_handle_t *hd, const char *username, int username_len, + const char *pass, int pass_len, int salt_len) { /* Get Salt */ int str_salt_len; esp_mpi_t *x = NULL; hd->s = esp_mpi_new(); - if (! hd->s) { + if (!hd->s) { + ESP_LOGE(TAG, "Failed to allocate bignum s"); goto error; } esp_mpi_get_rand(hd->s, 8 * salt_len, -1, 0); - *bytes_salt = esp_mpi_to_bin(hd->s, &str_salt_len); - if (! *bytes_salt) { + hd->bytes_s = esp_mpi_to_bin(hd->s, &str_salt_len); + if (!hd->bytes_s) { + ESP_LOGE(TAG, "Failed to generate salt of len %d", salt_len); goto error; } - hd->bytes_s = *bytes_salt; hd->len_s = salt_len; ESP_LOGD(TAG, "Salt ->"); - ESP_LOG_BUFFER_HEX_LEVEL(TAG, *bytes_salt, str_salt_len, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, hd->bytes_s, str_salt_len, ESP_LOG_DEBUG); /* Calculate X which is simply a hash for all these things */ - x = calculate_x(*bytes_salt, str_salt_len, username, username_len, pass, pass_len); - if (! x) { + x = calculate_x(hd->bytes_s, str_salt_len, username, username_len, pass, pass_len); + if (!x) { + ESP_LOGE(TAG, "Failed to calculate x"); goto error; } hexdump_mpi("x", x); /* v = g^x % N */ hd->v = esp_mpi_new(); - if (! hd->v) { + if (!hd->v) { + ESP_LOGE(TAG, "Failed to allocate bignum v"); goto error; } esp_mpi_a_exp_b_mod_c(hd->v, hd->g, x, hd->n, hd->ctx); hexdump_mpi("Verifier", hd->v); - if (__esp_srp_srv_pubkey(hd, bytes_B, len_B) < 0 ) { - goto error; - } - esp_mpi_free(x); return ESP_OK; @@ -328,9 +362,8 @@ error: esp_mpi_free(hd->s); hd->s = NULL; } - if (*bytes_salt) { - free(*bytes_salt); - *bytes_salt = NULL; + if (hd->bytes_s) { + free(hd->bytes_s); hd->bytes_s = NULL; hd->len_s = 0; } @@ -345,11 +378,86 @@ error: return ESP_FAIL; } +esp_err_t esp_srp_srv_pubkey(esp_srp_handle_t *hd, const char *username, int username_len, + const char *pass, int pass_len, int salt_len, + char **bytes_B, int *len_B, char **bytes_salt) +{ + if (!hd || !username || !pass) { + return ESP_ERR_INVALID_ARG; + } + if (ESP_OK != _esp_srp_gen_salt_verifier(hd, username, username_len, pass, pass_len, salt_len)) { + goto error; + } + *bytes_salt = hd->bytes_s; + + if (__esp_srp_srv_pubkey(hd, bytes_B, len_B) < 0 ) { + goto error; + } + return ESP_OK; + +error: + if (hd->s) { + esp_mpi_free(hd->s); + hd->s = NULL; + } + if (*bytes_salt) { + free(*bytes_salt); + *bytes_salt = NULL; + hd->bytes_s = NULL; + hd->len_s = 0; + } + if (hd->v) { + esp_mpi_free(hd->v); + hd->v = NULL; + } + return ESP_FAIL; +} + esp_err_t esp_srp_srv_pubkey_from_salt_verifier(esp_srp_handle_t *hd, char **bytes_B, int *len_B) { + if (!hd || !bytes_B || !len_B) { + return ESP_ERR_INVALID_ARG; + } return __esp_srp_srv_pubkey(hd, bytes_B, len_B); } +/* Generate salt-verifier pair for given username and password */ +esp_err_t esp_srp_gen_salt_verifier(const char *username, int username_len, + const char *pass, int pass_len, + char **bytes_salt, int salt_len, + char **verifier, int *verifier_len) +{ + esp_err_t ret = ESP_FAIL; + + /* allocate and init temporary SRP handle */ + esp_srp_handle_t *srp_hd = esp_srp_init(ESP_NG_3072); + if (!srp_hd) { + ESP_LOGE(TAG, "Failed to initialise security context!"); + return ESP_ERR_NO_MEM; + } + + // get salt and verifier + if (ESP_OK != _esp_srp_gen_salt_verifier(srp_hd, username, username_len, pass, pass_len, salt_len)) { + goto cleanup; + } + + // convert to verifier bytes + *verifier = esp_mpi_to_bin(srp_hd->v, verifier_len); + if (!*verifier) { + ESP_LOGE(TAG, "Failed to allocate verifier bytes!"); + ret = ESP_ERR_NO_MEM; + goto cleanup; + } + + *bytes_salt = srp_hd->bytes_s; + srp_hd->bytes_s = NULL; // so that it won't be freed in `esp_srp_free` step + ret = ESP_OK; + +cleanup: + esp_srp_free(srp_hd); + return ret; +} + esp_err_t esp_srp_set_salt_verifier(esp_srp_handle_t *hd, const char *salt, int salt_len, const char *verifier, int verifier_len) { diff --git a/components/protocomm/src/crypto/srp6a/include/esp_srp_mpi.h b/components/protocomm/src/crypto/srp6a/esp_srp_mpi.h similarity index 100% rename from components/protocomm/src/crypto/srp6a/include/esp_srp_mpi.h rename to components/protocomm/src/crypto/srp6a/esp_srp_mpi.h diff --git a/components/protocomm/src/crypto/srp6a/include/esp_srp.h b/components/protocomm/src/crypto/srp6a/include/esp_srp.h deleted file mode 100644 index 972704f038..0000000000 --- a/components/protocomm/src/crypto/srp6a/include/esp_srp.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include -#include "esp_srp_mpi.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - /* SRP specific: - * N = 3072 bit large safe prime, - * g = generator */ - ESP_NG_3072 = 0, -} esp_ng_type_t; - -typedef struct esp_srp_handle { - int allocated; - esp_ng_type_t type; - esp_mpi_ctx_t *ctx; - - /* N - * the bytes_n simply points to the static array - */ - esp_mpi_t *n; - const char *bytes_n; - int len_n; - - /* g - * the bytes_g simply points to the static array - */ - esp_mpi_t *g; - const char *bytes_g; - int len_g; - - /* Salt */ - esp_mpi_t *s; - char *bytes_s; - int len_s; - /* Verifier */ - esp_mpi_t *v; - /* B */ - esp_mpi_t *B; - char *bytes_B; - int len_B; - /* b */ - esp_mpi_t *b; - /* A */ - esp_mpi_t *A; - char *bytes_A; - int len_A; - /* K - session key*/ - char *session_key; -} esp_srp_handle_t; - -int esp_srp_init(esp_srp_handle_t *hd, esp_ng_type_t ng); - -void esp_srp_free(esp_srp_handle_t *hd); - -/* Returns B (pub key) and salt - * - * *bytes_B MUST NOT BE FREED BY THE CALLER - * *bytes_salt MUST NOT BE FREE BY THE CALLER - * - */ -esp_err_t esp_srp_srv_pubkey(esp_srp_handle_t *hd, const char *username, int username_len, const char *pass, int pass_len, int salt_len, - char **bytes_B, int *len_B, char **bytes_salt); - -/* Set the Salt and Verifier pre-generated for a given password. - * This should be used only if the actual password is not available. - * The public key can then be generated using esp_srp_srv_pubkey_from_salt_verifier() - * and not esp_srp_srv_pubkey() - */ -esp_err_t esp_srp_set_salt_verifier(esp_srp_handle_t *hd, const char *salt, int salt_len, - const char *verifier, int verifier_len); - -/* Returns B (pub key) when the salt and verifier are set using esp_srp_set_salt_verifier() - * - * *bytes_B MUST NOT BE FREED BY THE CALLER - */ -esp_err_t esp_srp_srv_pubkey_from_salt_verifier(esp_srp_handle_t *hd, char **bytes_B, int *len_B); - -/* Returns bytes_key - * *bytes_key MUST NOT BE FREED BY THE CALLER - */ -esp_err_t esp_srp_get_session_key(esp_srp_handle_t *hd, char *bytes_A, int len_A, char **bytes_key, uint16_t *len_key); - -/* Exchange proofs - * Returns 1 if user's proof is ok. Also 1 when is returned, bytes_host_proof contains our proof. - * - * bytes_user_proof is parameter in - * bytes_host_proof is parameter out (should be SHA512_DIGEST_LENGTH) bytes in size - */ -esp_err_t esp_srp_exchange_proofs(esp_srp_handle_t *hd, char *username, uint16_t username_len, char *bytes_user_proof, char *bytes_host_proof); - -#ifdef __cplusplus -} -#endif diff --git a/components/protocomm/src/security/security2.c b/components/protocomm/src/security/security2.c index 8256114ad7..73d104d47c 100644 --- a/components/protocomm/src/security/security2.c +++ b/components/protocomm/src/security/security2.c @@ -109,15 +109,9 @@ static esp_err_t handle_session_command0(session_t *cur_session, hexdump("Client Public Key", (char *) in->sc0->client_pubkey.data, PUBLIC_KEY_LEN); /* Initialize mu srp context */ - cur_session->srp_hd = calloc(1, sizeof(esp_srp_handle_t)); - if (!cur_session->srp_hd) { - ESP_LOGE(TAG, "Failed to allocate security context!"); - return ESP_ERR_NO_MEM; - } - - if (esp_srp_init(cur_session->srp_hd, ESP_NG_3072) != ESP_OK) { + cur_session->srp_hd = esp_srp_init(ESP_NG_3072); + if (cur_session->srp_hd == NULL) { ESP_LOGE(TAG, "Failed to initialise security context!"); - free(cur_session->srp_hd); return ESP_FAIL; } @@ -131,14 +125,15 @@ static esp_err_t handle_session_command0(session_t *cur_session, ESP_LOGI(TAG, "Using salt and verifier to generate public key..."); if (sv->salt != NULL && sv->salt_len != 0 && sv->verifier != NULL && sv->verifier_len != 0) { - if (esp_srp_set_salt_verifier(cur_session->srp_hd, cur_session->salt, cur_session->salt_len, cur_session->verifier, cur_session->verifier_len) != ESP_OK) { + if (esp_srp_set_salt_verifier(cur_session->srp_hd, cur_session->salt, + cur_session->salt_len, cur_session->verifier, cur_session->verifier_len) != ESP_OK) { ESP_LOGE(TAG, "Failed to set salt and verifier!"); - free(cur_session->srp_hd); + esp_srp_free(cur_session->srp_hd); return ESP_FAIL; } if (esp_srp_srv_pubkey_from_salt_verifier(cur_session->srp_hd, &device_pubkey, &device_pubkey_len) != ESP_OK) { ESP_LOGE(TAG, "Failed to device public key!"); - free(cur_session->srp_hd); + esp_srp_free(cur_session->srp_hd); return ESP_FAIL; } } @@ -147,7 +142,7 @@ static esp_err_t handle_session_command0(session_t *cur_session, if (esp_srp_get_session_key(cur_session->srp_hd, (char *) in->sc0->client_pubkey.data, PUBLIC_KEY_LEN, &cur_session->session_key, &cur_session->session_key_len) != ESP_OK) { ESP_LOGE(TAG, "Failed to generate device session key!"); - free(cur_session->srp_hd); + esp_srp_free(cur_session->srp_hd); return ESP_FAIL; } hexdump("Session Key", cur_session->session_key, cur_session->session_key_len); @@ -156,7 +151,7 @@ static esp_err_t handle_session_command0(session_t *cur_session, S2SessionResp0 *out_resp = (S2SessionResp0 *) malloc(sizeof(S2SessionResp0)); if (!out || !out_resp) { ESP_LOGE(TAG, "Error allocating memory for response0"); - free(cur_session->srp_hd); + esp_srp_free(cur_session->srp_hd); free(out); free(out_resp); return ESP_ERR_NO_MEM; @@ -185,7 +180,7 @@ static esp_err_t handle_session_command0(session_t *cur_session, cur_session->username = malloc(cur_session->username_len); if (!cur_session->username) { ESP_LOGE(TAG, "Failed to allocate memory!"); - free(cur_session->srp_hd); + esp_srp_free(cur_session->srp_hd); return ESP_ERR_NO_MEM; } memcpy(cur_session->username, in->sc0->client_username.data, in->sc0->client_username.len); @@ -365,7 +360,6 @@ static esp_err_t sec2_close_session(protocomm_security_handle_t handle, uint32_t if (cur_session->srp_hd) { esp_srp_free(cur_session->srp_hd); - free(cur_session->srp_hd); } memset(cur_session, 0, sizeof(session_t)); diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 289b2e001c..3945ede97c 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -279,9 +279,11 @@ INPUT = \ $(PROJECT_PATH)/components/protocomm/include/security/protocomm_security.h \ $(PROJECT_PATH)/components/protocomm/include/security/protocomm_security0.h \ $(PROJECT_PATH)/components/protocomm/include/security/protocomm_security1.h \ + $(PROJECT_PATH)/components/protocomm/include/security/protocomm_security2.h \ $(PROJECT_PATH)/components/protocomm/include/transports/protocomm_ble.h \ $(PROJECT_PATH)/components/protocomm/include/transports/protocomm_console.h \ $(PROJECT_PATH)/components/protocomm/include/transports/protocomm_httpd.h \ + $(PROJECT_PATH)/components/protocomm/include/crypto/srp6a/esp_srp.h \ $(PROJECT_PATH)/components/pthread/include/esp_pthread.h \ $(PROJECT_PATH)/components/sdmmc/include/sdmmc_cmd.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/adc_channel.h \ diff --git a/docs/en/api-reference/provisioning/protocomm.rst b/docs/en/api-reference/provisioning/protocomm.rst index 04cfe3f9ce..a196bd4375 100644 --- a/docs/en/api-reference/provisioning/protocomm.rst +++ b/docs/en/api-reference/provisioning/protocomm.rst @@ -43,7 +43,7 @@ The protocomm component provides a project configuration menu to enable/disable * Support ``protocomm_security2`` with SRP6a-based key exchange + AES-GCM encryption/decryption: :ref:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2`. .. note:: - + Enabling multiple security versions at once offers the ability to control them dynamically but also increases the firmware size. .. only:: SOC_WIFI_SUPPORTED @@ -299,5 +299,7 @@ API Reference .. include-build-file:: inc/protocomm_security.inc .. include-build-file:: inc/protocomm_security0.inc .. include-build-file:: inc/protocomm_security1.inc +.. include-build-file:: inc/protocomm_security2.inc +.. include-build-file:: inc/esp_srp.inc .. include-build-file:: inc/protocomm_httpd.inc .. include-build-file:: inc/protocomm_ble.inc diff --git a/docs/zh_CN/api-reference/provisioning/protocomm.rst b/docs/zh_CN/api-reference/provisioning/protocomm.rst index 4293496fa5..bc4dcd5dac 100644 --- a/docs/zh_CN/api-reference/provisioning/protocomm.rst +++ b/docs/zh_CN/api-reference/provisioning/protocomm.rst @@ -40,10 +40,10 @@ Protocomm 为以下各种传输提供框架: * 支持 ``protocomm_security0``,该版本无安全功能::ref:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0`,该选项默认启用。 * 支持 ``protocomm_security1``,使用 Curve25519 密钥交换和 AES-CTR 加密/解密::ref:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1`,该选项默认启用。 - * 支持 ``protocomm_security2``,使用基于 SRP6a 的密钥交换和 AES-GCM 加密/解密::ref:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2`。 + * 支持 ``protocomm_security2``,使用基于 SRP6a 的密钥交换和 AES-GCM 加密/解密::ref:`CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2`。 + +.. note:: -.. note:: - 启用多个安全版本后可以动态控制安全版本,但也会增加固件大小。 .. only:: SOC_WIFI_SUPPORTED @@ -241,7 +241,7 @@ Protocomm 为以下各种传输提供框架: 使用 Security 0 的低功耗蓝牙传输方案示例 ------------------------------------------- - + 示例用法请参阅 :component_file:`wifi_provisioning/src/scheme_ble.c`。 .. highlight:: c @@ -299,5 +299,7 @@ API 参考 .. include-build-file:: inc/protocomm_security.inc .. include-build-file:: inc/protocomm_security0.inc .. include-build-file:: inc/protocomm_security1.inc +.. include-build-file:: inc/protocomm_security2.inc +.. include-build-file:: inc/esp_srp.inc .. include-build-file:: inc/protocomm_httpd.inc .. include-build-file:: inc/protocomm_ble.inc