fix(nimble): Address review fixes for tinycrypt / and blufi code

This commit is contained in:
Rahul Tank
2026-04-14 11:22:10 +05:30
parent 17f8e9c6d5
commit 02b57e7e77
12 changed files with 224 additions and 69 deletions
@@ -49,6 +49,7 @@ int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
/* input sanity check: */
if (out == (uint8_t *) 0 ||
in == (const uint8_t *) 0 ||
iv == (const uint8_t *) 0 ||
sched == (TCAesKeySched_t) 0 ||
inlen == 0 ||
outlen == 0 ||
@@ -90,6 +91,7 @@ int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
/* sanity check the inputs */
if (out == (uint8_t *) 0 ||
in == (const uint8_t *) 0 ||
iv == (const uint8_t *) 0 ||
sched == (TCAesKeySched_t) 0 ||
inlen == 0 ||
outlen == 0 ||
@@ -105,7 +107,7 @@ int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
* that would not otherwise be possible.
*/
p = iv;
for (n = m = 0; n < inlen; ++n) {
for (n = m = 0; n < outlen; ++n) {
if ((n % TC_AES_BLOCK_SIZE) == 0) {
(void)tc_aes_decrypt(buffer, in, sched);
in += TC_AES_BLOCK_SIZE;
+26 -2
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -115,6 +115,9 @@ static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const pr
/* 10.2.1.2 step 6 */
memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE);
/* Clear transient key material from stack */
_set(temp, 0, sizeof(temp));
}
}
@@ -162,6 +165,11 @@ int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
result = TC_CRYPTO_SUCCESS;
}
_set(personalization_buf, 0, sizeof(personalization_buf));
_set(seed_material, 0, sizeof(seed_material));
_set(zeroArr, 0, sizeof(zeroArr));
return result;
}
@@ -203,6 +211,10 @@ int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
result = TC_CRYPTO_SUCCESS;
}
_set(additional_input_buf, 0, sizeof(additional_input_buf));
_set(seed_material, 0, sizeof(seed_material));
return result;
}
@@ -220,7 +232,19 @@ int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
unsigned int result = TC_CRYPTO_FAIL;
if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) {
if (0 == ctx) {
return TC_CRYPTO_FAIL;
}
if (0U == outlen) {
return TC_CRYPTO_SUCCESS;
}
if ((0 == out) || (outlen >= MAX_BYTES_PER_REQ)) {
return TC_CRYPTO_FAIL;
}
{
/* 10.2.1.5.1 step 1 */
if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) {
result = TC_CTR_PRNG_RESEED_REQ;
+60 -21
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -303,11 +303,19 @@ void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words)
{
wordcount_t i;
uECC_word_t tmp[NUM_ECC_WORDS];
if (num_words <= 0 || num_words > NUM_ECC_WORDS) {
return;
}
uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
/* result > mod (result = mod + remainder), so subtract mod to get
* remainder. */
uECC_vli_sub(result, result, mod, num_words);
uECC_word_t borrow = uECC_vli_sub(tmp, result, mod, num_words);
uECC_word_t do_reduce = (uECC_word_t)(carry || !borrow);
for (i = 0; i < num_words; ++i) {
result[i] = cond_set(tmp[i], result[i], do_reduce);
}
}
@@ -315,11 +323,17 @@ void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words)
{
wordcount_t i;
uECC_word_t tmp[NUM_ECC_WORDS];
if (num_words <= 0 || num_words > NUM_ECC_WORDS) {
return;
}
uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
if (l_borrow) {
/* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
* we can get the correct result from result + mod (with overflow). */
uECC_vli_add(result, result, mod, num_words);
uECC_vli_add(tmp, result, mod, num_words);
for (i = 0; i < num_words; ++i) {
result[i] = cond_set(tmp[i], result[i], l_borrow);
}
}
@@ -333,6 +347,10 @@ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
uECC_word_t *v[2] = {tmp, product};
uECC_word_t index;
if (num_words <= 0 || num_words > NUM_ECC_WORDS) {
return;
}
/* Shift mod so its highest set bit is at the maximum position. */
bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
uECC_vli_numBits(mod, num_words);
@@ -354,9 +372,8 @@ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
wordcount_t i;
for (i = 0; i < num_words * 2; ++i) {
uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
if (diff != v[index][i]) {
borrow = (diff > v[index][i]);
}
uECC_word_t val = (diff > v[index][i]);
borrow = cond_set(val, borrow, (diff != v[index][i]));
v[1 - index][i] = diff;
}
/* Swap the index if there was no borrow */
@@ -373,6 +390,10 @@ void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
const uECC_word_t *right, const uECC_word_t *mod,
wordcount_t num_words)
{
if (num_words <= 0 || num_words > NUM_ECC_WORDS) {
return;
}
uECC_word_t product[2 * NUM_ECC_WORDS];
uECC_vli_mult(product, left, right, num_words);
uECC_vli_mmod(result, product, mod, num_words);
@@ -643,7 +664,8 @@ void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
}
#if !SOC_ECC_SUPPORTED
#if !SOC_ECC_SUPPORTED || SOC_ESP_NIMBLE_CONTROLLER
/* Keep ESP32-C6 on the software micro-ecc path for BLE SC compatibility. */
/* P = (x1, y1) => 2P, (x2, y2) => P' */
static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
uECC_word_t * X2, uECC_word_t * Y2,
@@ -677,7 +699,7 @@ static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1,
uECC_Curve curve)
{
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
uECC_word_t t5[NUM_ECC_WORDS];
uECC_word_t t5[NUM_ECC_WORDS] = {0};
uECC_word_t t6[NUM_ECC_WORDS];
uECC_word_t t7[NUM_ECC_WORDS];
wordcount_t num_words = curve->num_words;
@@ -716,7 +738,7 @@ void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
uECC_Curve curve)
{
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
uECC_word_t t5[NUM_ECC_WORDS];
uECC_word_t t5[NUM_ECC_WORDS] = {0};
wordcount_t num_words = curve->num_words;
uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
@@ -742,7 +764,7 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
const uECC_word_t * initial_Z,
bitcount_t num_bits, uECC_Curve curve)
{
#if SOC_ECC_SUPPORTED
#if SOC_ECC_SUPPORTED && !SOC_ESP_NIMBLE_CONTROLLER
wordcount_t num_words = curve->num_words;
/* Only p256r1 is supported currently. */
@@ -800,10 +822,22 @@ uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
bitcount_t num_n_bits = curve->num_n_bits;
uECC_word_t carry;
uECC_word_t bit = 0;
bitcount_t max_n_bits;
uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
(num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
uECC_vli_testBit(k0, num_n_bits));
if (num_n_words <= 0 || num_n_words > NUM_ECC_WORDS) {
return 0;
}
max_n_bits = (bitcount_t)num_n_words * uECC_WORD_SIZE * 8;
carry = uECC_vli_add(k0, k, curve->n, num_n_words);
if (num_n_bits < max_n_bits) {
bit = (uECC_vli_testBit(k0, num_n_bits) != 0);
}
carry |= bit;
uECC_vli_add(k1, k0, curve->n, num_n_words);
@@ -814,17 +848,22 @@ uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
uECC_word_t *private_key,
uECC_Curve curve)
{
#if !SOC_ECC_SUPPORTED || SOC_ESP_NIMBLE_CONTROLLER
uECC_word_t tmp1[NUM_ECC_WORDS];
uECC_word_t tmp2[NUM_ECC_WORDS];
uECC_word_t *p2[2] = {tmp1, tmp2};
uECC_word_t carry;
#endif
#if SOC_ECC_SUPPORTED && !SOC_ESP_NIMBLE_CONTROLLER
EccPoint_mult(result, curve->G, private_key, 0, curve->num_n_bits, curve);
#else
/* Regularize the bitcount for the private key so that attackers cannot
* use a side channel attack to learn the number of leading zeros. */
carry = regularize_k(private_key, tmp1, tmp2, curve);
EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
#endif
if (EccPoint_isZero(result, curve)) {
return 0;
@@ -863,7 +902,7 @@ int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
uECC_word_t tries;
bitcount_t num_bits = uECC_vli_numBits(top, num_words);
if (!g_rng_function) {
if (!g_rng_function || num_words <= 0 || num_words > NUM_ECC_WORDS) {
return 0;
}
+13 -8
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -63,12 +63,6 @@
#include <tinycrypt/ecc_dh.h>
#include <string.h>
#if default_RNG_defined
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
#else
static uECC_RNG_Function g_rng_function = 0;
#endif
int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
unsigned int *d, uECC_Curve curve)
{
@@ -153,9 +147,11 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
uECC_word_t _private[NUM_ECC_WORDS];
uECC_word_t tmp[NUM_ECC_WORDS];
#if !SOC_ECC_SUPPORTED
uECC_word_t *p2[2] = {_private, tmp};
uECC_word_t *initial_Z = 0;
uECC_word_t carry;
#endif
wordcount_t num_words = curve->num_words;
wordcount_t num_bytes = curve->num_bytes;
int r;
@@ -171,13 +167,17 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
public_key + num_bytes,
num_bytes);
#if SOC_ECC_SUPPORTED
EccPoint_mult(_public, _public, _private, 0, curve->num_n_bits, curve);
#else
/* Regularize the bitcount for the private key so that attackers cannot use a
* side channel attack to learn the number of leading zeros. */
carry = regularize_k(_private, _private, tmp, curve);
/* If an RNG function was specified, try to get a random initial Z value to
* improve protection against side-channel attacks. */
if (g_rng_function) {
uECC_RNG_Function rng_function = uECC_get_rng();
if (rng_function) {
if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
r = 0;
goto clear_and_out;
@@ -187,14 +187,19 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1,
curve);
#endif
uECC_vli_nativeToBytes(secret, num_bytes, _public);
r = !EccPoint_isZero(_public, curve);
clear_and_out:
/* erasing temporary buffer used to store secret: */
#if !SOC_ECC_SUPPORTED
memset(p2, 0, sizeof(p2));
__asm__ __volatile__("" :: "g"(p2) : "memory");
#endif
memset(_public, 0, sizeof(_public));
__asm__ __volatile__("" :: "g"(_public) : "memory");
memset(tmp, 0, sizeof(tmp));
__asm__ __volatile__("" :: "g"(tmp) : "memory");
memset(_private, 0, sizeof(_private));
+12 -10
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -61,12 +61,6 @@
#include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_dsa.h>
#if default_RNG_defined
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
#else
static uECC_RNG_Function g_rng_function = 0;
#endif
static void bits2int(uECC_word_t *native, const uint8_t *bits,
unsigned bits_size, uECC_Curve curve)
{
@@ -107,9 +101,11 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
uECC_word_t tmp[NUM_ECC_WORDS];
uECC_word_t s[NUM_ECC_WORDS];
#if !SOC_ECC_SUPPORTED
uECC_word_t *k2[2] = {tmp, s};
uECC_word_t p[NUM_ECC_WORDS * 2];
uECC_word_t carry;
#endif
uECC_word_t p[NUM_ECC_WORDS * 2];
wordcount_t num_words = curve->num_words;
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
bitcount_t num_n_bits = curve->num_n_bits;
@@ -120,15 +116,20 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
return 0;
}
#if SOC_ECC_SUPPORTED
EccPoint_mult(p, curve->G, k, 0, num_n_bits, curve);
#else
carry = regularize_k(k, tmp, s, curve);
EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
#endif
if (uECC_vli_isZero(p, num_words)) {
return 0;
}
/* If an RNG function was specified, get a random number
to prevent side channel analysis of k. */
if (!g_rng_function) {
uECC_RNG_Function rng_function = uECC_get_rng();
if (!rng_function) {
uECC_vli_clear(tmp, num_n_words);
tmp[0] = 1;
}
@@ -154,7 +155,8 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
bits2int(tmp, message_hash, hash_size, curve);
uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */
if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
if (uECC_vli_isZero(s, num_n_words) ||
uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
return 0;
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -86,6 +86,9 @@ static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len)
const uint8_t separator0 = 0x00;
const uint8_t separator1 = 0x01;
/* tc_hmac_final wipes the HMAC context, so reload key before init */
(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
/* use current state, e and separator 0 to compute a new prng key: */
(void)tc_hmac_init(&prng->h);
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
@@ -101,6 +104,7 @@ static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len)
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
/* use current state, e and separator 1 to compute a new prng key: */
(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
(void)tc_hmac_init(&prng->h);
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
(void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1));
@@ -113,6 +117,9 @@ static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len)
(void)tc_hmac_init(&prng->h);
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
/* keep HMAC context prepared for callers that reuse prng->h */
(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
}
int tc_hmac_prng_init(TCHmacPrng_t prng,
@@ -198,6 +205,7 @@ int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng)
while (outlen != 0) {
/* operate HMAC in OFB mode to create "random" outputs */
(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
(void)tc_hmac_init(&prng->h);
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);