mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2026-05-11 06:28:17 +02:00
Return and propagate UECC_FAULT_DETECTED
This commit first changes the return convention of EccPoint_mult_safer() so
that it properly reports when faults are detected. Then all functions that
call it need to be changed to (1) follow the same return convention and (2)
properly propagate UECC_FAULT_DETECTED when it occurs.
Here's the reverse call graph from EccPoint_mult_safer() to the rest of the
library (where return values are translated to the MBEDTLS_ERR_ space) and test
functions (where expected return values are asserted explicitly).
EccPoint_mult_safer()
EccPoint_compute_public_key()
uECC_compute_public_key()
pkparse.c
tests/suites/test_suite_pkparse.function
uECC_make_key_with_d()
uECC_make_key()
ssl_cli.c
ssl_srv.c
tests/suites/test_suite_pk.function
tests/suites/test_suite_tinycrypt.function
uECC_shared_secret()
ssl_tls.c
tests/suites/test_suite_tinycrypt.function
uECC_sign_with_k()
uECC_sign()
pk.c
tests/suites/test_suite_tinycrypt.function
Note: in uECC_sign_with_k() a test for uECC_vli_isZero(p) is suppressed
because it is redundant with a more thorough test (point validity) done at the
end of EccPoint_mult_safer(). This redundancy was introduced in a previous
commit but not noticed earlier.
This commit is contained in:
@@ -1021,16 +1021,16 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
|
||||
wordcount_t num_words = NUM_ECC_WORDS;
|
||||
uECC_word_t carry;
|
||||
uECC_word_t *initial_Z = 0;
|
||||
int r;
|
||||
int r = UECC_FAULT_DETECTED;
|
||||
|
||||
/* Protect against faults modifying curve paremeters in flash */
|
||||
if (uECC_check_curve_integrity() != 0) {
|
||||
return 0;
|
||||
return UECC_FAULT_DETECTED;
|
||||
}
|
||||
|
||||
/* Protects against invalid curves attacks */
|
||||
/* Protects against invalid curve attacks */
|
||||
if (uECC_valid_point(point) != 0 ) {
|
||||
return 0;
|
||||
return UECC_FAILURE;
|
||||
}
|
||||
|
||||
/* Regularize the bitcount for the private key so that attackers cannot use a
|
||||
@@ -1041,7 +1041,7 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
|
||||
* protect against side-channel attacks such as Template SPA */
|
||||
if (g_rng_function) {
|
||||
if (!uECC_generate_random_int(k2[carry], curve_p, num_words)) {
|
||||
r = 0;
|
||||
r = UECC_FAILURE;
|
||||
goto clear_and_out;
|
||||
}
|
||||
initial_Z = k2[carry];
|
||||
@@ -1052,17 +1052,17 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point,
|
||||
/* Protect against fault injections that would make the resulting
|
||||
* point not lie on the intended curve */
|
||||
if (uECC_valid_point(result) != 0 ) {
|
||||
r = 0;
|
||||
r = UECC_FAULT_DETECTED;
|
||||
goto clear_and_out;
|
||||
}
|
||||
|
||||
/* Protect against faults modifying curve paremeters in flash */
|
||||
if (uECC_check_curve_integrity() != 0) {
|
||||
r = 0;
|
||||
r = UECC_FAULT_DETECTED;
|
||||
goto clear_and_out;
|
||||
}
|
||||
|
||||
r = 1;
|
||||
r = UECC_SUCCESS;
|
||||
|
||||
clear_and_out:
|
||||
/* erasing temporary buffer used to store secret: */
|
||||
@@ -1176,7 +1176,7 @@ int uECC_valid_public_key(const uint8_t *public_key)
|
||||
|
||||
int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
|
||||
{
|
||||
|
||||
int ret;
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
|
||||
@@ -1187,23 +1187,24 @@ int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key)
|
||||
|
||||
/* Make sure the private key is in the range [1, n-1]. */
|
||||
if (uECC_vli_isZero(_private)) {
|
||||
return 0;
|
||||
return UECC_FAILURE;
|
||||
}
|
||||
|
||||
if (uECC_vli_cmp(curve_n, _private) != 1) {
|
||||
return 0;
|
||||
return UECC_FAILURE;
|
||||
}
|
||||
|
||||
/* Compute public key. */
|
||||
if (!EccPoint_compute_public_key(_public, _private)) {
|
||||
return 0;
|
||||
ret = EccPoint_compute_public_key(_public, _private);
|
||||
if (ret != UECC_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
uECC_vli_nativeToBytes(public_key, NUM_ECC_BYTES, _public);
|
||||
uECC_vli_nativeToBytes(
|
||||
public_key +
|
||||
NUM_ECC_BYTES, NUM_ECC_BYTES, _public + NUM_ECC_WORDS);
|
||||
return 1;
|
||||
return UECC_SUCCESS;
|
||||
}
|
||||
#else
|
||||
typedef int mbedtls_dummy_tinycrypt_def;
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
|
||||
unsigned int *d)
|
||||
{
|
||||
|
||||
int ret;
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
|
||||
@@ -85,30 +85,32 @@ int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
|
||||
mbedtls_platform_memcpy (_private, d, NUM_ECC_BYTES);
|
||||
|
||||
/* Computing public-key from private: */
|
||||
if (EccPoint_compute_public_key(_public, _private)) {
|
||||
|
||||
/* Converting buffers to correct bit order: */
|
||||
uECC_vli_nativeToBytes(private_key,
|
||||
BITS_TO_BYTES(NUM_ECC_BITS),
|
||||
_private);
|
||||
uECC_vli_nativeToBytes(public_key,
|
||||
NUM_ECC_BYTES,
|
||||
_public);
|
||||
uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES,
|
||||
NUM_ECC_BYTES,
|
||||
_public + NUM_ECC_WORDS);
|
||||
|
||||
/* erasing temporary buffer used to store secret: */
|
||||
mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES);
|
||||
|
||||
return 1;
|
||||
ret = EccPoint_compute_public_key(_public, _private);
|
||||
if (ret != UECC_SUCCESS) {
|
||||
goto exit;
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* Converting buffers to correct bit order: */
|
||||
uECC_vli_nativeToBytes(private_key,
|
||||
BITS_TO_BYTES(NUM_ECC_BITS),
|
||||
_private);
|
||||
uECC_vli_nativeToBytes(public_key,
|
||||
NUM_ECC_BYTES,
|
||||
_public);
|
||||
uECC_vli_nativeToBytes(public_key + NUM_ECC_BYTES,
|
||||
NUM_ECC_BYTES,
|
||||
_public + NUM_ECC_WORDS);
|
||||
|
||||
exit:
|
||||
/* erasing temporary buffer used to store secret: */
|
||||
mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uECC_make_key(uint8_t *public_key, uint8_t *private_key)
|
||||
{
|
||||
|
||||
int ret;
|
||||
uECC_word_t _random[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
@@ -119,14 +121,19 @@ int uECC_make_key(uint8_t *public_key, uint8_t *private_key)
|
||||
uECC_RNG_Function rng_function = uECC_get_rng();
|
||||
if (!rng_function ||
|
||||
!rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) {
|
||||
return 0;
|
||||
return UECC_FAILURE;
|
||||
}
|
||||
|
||||
/* computing modular reduction of _random (see FIPS 186.4 B.4.1): */
|
||||
uECC_vli_mmod(_private, _random, curve_n);
|
||||
|
||||
/* Computing public-key from private: */
|
||||
if (EccPoint_compute_public_key(_public, _private)) {
|
||||
ret = EccPoint_compute_public_key(_public, _private);
|
||||
/* don't try again if a fault was detected */
|
||||
if (ret == UECC_FAULT_DETECTED) {
|
||||
return ret;
|
||||
}
|
||||
if (ret == UECC_SUCCESS) {
|
||||
|
||||
/* Converting buffers to correct bit order: */
|
||||
uECC_vli_nativeToBytes(private_key,
|
||||
@@ -142,10 +149,10 @@ int uECC_make_key(uint8_t *public_key, uint8_t *private_key)
|
||||
/* erasing temporary buffer that stored secret: */
|
||||
mbedtls_platform_memset(_private, 0, NUM_ECC_BYTES);
|
||||
|
||||
return 1;
|
||||
return UECC_SUCCESS;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return UECC_FAILURE;
|
||||
}
|
||||
|
||||
int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
||||
|
||||
@@ -122,12 +122,12 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
/* Make sure 0 < k < curve_n */
|
||||
if (uECC_vli_isZero(k) ||
|
||||
uECC_vli_cmp(curve_n, k) != 1) {
|
||||
return 0;
|
||||
return UECC_FAILURE;
|
||||
}
|
||||
|
||||
r = EccPoint_mult_safer(p, curve_G, k);
|
||||
if (r == 0 || uECC_vli_isZero(p)) {
|
||||
return 0;
|
||||
if (r != UECC_SUCCESS) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* If an RNG function was specified, get a random number
|
||||
@@ -137,7 +137,7 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
tmp[0] = 1;
|
||||
}
|
||||
else if (!uECC_generate_random_int(tmp, curve_n, num_n_words)) {
|
||||
return 0;
|
||||
return UECC_FAILURE;
|
||||
}
|
||||
|
||||
/* Prevent side channel analysis of uECC_vli_modInv() to determine
|
||||
@@ -159,16 +159,17 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
uECC_vli_modAdd(s, tmp, s, curve_n); /* s = e + r*d */
|
||||
uECC_vli_modMult(s, s, k, curve_n); /* s = (e + r*d) / k */
|
||||
if (uECC_vli_numBits(s) > (bitcount_t)NUM_ECC_BYTES * 8) {
|
||||
return 0;
|
||||
return UECC_FAILURE;
|
||||
}
|
||||
|
||||
uECC_vli_nativeToBytes(signature + NUM_ECC_BYTES, NUM_ECC_BYTES, s);
|
||||
return 1;
|
||||
return UECC_SUCCESS;
|
||||
}
|
||||
|
||||
int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, uint8_t *signature)
|
||||
{
|
||||
int r;
|
||||
uECC_word_t _random[2*NUM_ECC_WORDS];
|
||||
uECC_word_t k[NUM_ECC_WORDS];
|
||||
uECC_word_t tries;
|
||||
@@ -178,17 +179,23 @@ int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
uECC_RNG_Function rng_function = uECC_get_rng();
|
||||
if (!rng_function ||
|
||||
!rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) {
|
||||
return 0;
|
||||
return UECC_FAILURE;
|
||||
}
|
||||
|
||||
// computing k as modular reduction of _random (see FIPS 186.4 B.5.1):
|
||||
uECC_vli_mmod(k, _random, curve_n);
|
||||
|
||||
if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature)) {
|
||||
return 1;
|
||||
r = uECC_sign_with_k(private_key, message_hash, hash_size, k, signature);
|
||||
/* don't keep trying if a fault was detected */
|
||||
if (r == UECC_FAULT_DETECTED) {
|
||||
return r;
|
||||
}
|
||||
if (r == UECC_SUCCESS) {
|
||||
return UECC_SUCCESS;
|
||||
}
|
||||
/* else keep trying */
|
||||
}
|
||||
return 0;
|
||||
return UECC_FAILURE;
|
||||
}
|
||||
|
||||
static bitcount_t smax(bitcount_t a, bitcount_t b)
|
||||
|
||||
Reference in New Issue
Block a user