diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 9c53f3e7e..3996cd4b2 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -309,6 +309,20 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, const uECC_word_t * scalar, const uECC_word_t * initial_Z, bitcount_t num_bits, uECC_Curve curve); +/* + * @brief Point multiplication algorithm using Montgomery's ladder with co-Z + * coordinates. See http://eprint.iacr.org/2011/338.pdf. + * Uses scalar regularization and coordinate randomization (if a global RNG + * function is set) in order to protect against some side channel attacks. + * @note Result may overlap point. + * @param result OUT -- returns scalar*point + * @param point IN -- elliptic curve point + * @param scalar IN -- scalar + * @param curve IN -- elliptic curve + */ +int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, + const uECC_word_t * scalar, uECC_Curve curve); + /* * @brief Constant-time comparison to zero - secure way to compare long integers * @param vli IN -- very long integer diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index f7a6f0665..91bec5604 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -65,6 +65,7 @@ #if defined(MBEDTLS_USE_TINYCRYPT) #include <tinycrypt/ecc.h> +#include "mbedtls/platform_util.h" #include <string.h> /* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform @@ -873,7 +874,7 @@ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, const uECC_word_t * scalar, const uECC_word_t * initial_Z, - bitcount_t num_bits, uECC_Curve curve) + bitcount_t num_bits, uECC_Curve curve) { /* R0 and R1 */ uECC_word_t Rx[2][NUM_ECC_WORDS]; @@ -936,6 +937,44 @@ uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, return carry; } +int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, + const uECC_word_t * scalar, uECC_Curve curve) +{ + uECC_word_t tmp[NUM_ECC_WORDS]; + uECC_word_t s[NUM_ECC_WORDS]; + uECC_word_t *k2[2] = {tmp, s}; + wordcount_t num_words = curve->num_words; + bitcount_t num_n_bits = curve->num_n_bits; + uECC_word_t carry; + uECC_word_t *initial_Z = 0; + int r; + + /* 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(scalar, tmp, s, curve); + + /* If an RNG function was specified, get a random initial Z value to + * 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; + goto clear_and_out; + } + initial_Z = k2[carry]; + } + + EccPoint_mult(result, point, k2[!carry], initial_Z, num_n_bits + 1, curve); + r = 1; + +clear_and_out: + /* erasing temporary buffer used to store secret: */ + mbedtls_platform_zeroize(k2, sizeof(k2)); + mbedtls_platform_zeroize(tmp, sizeof(tmp)); + mbedtls_platform_zeroize(s, sizeof(s)); + + return r; +} + uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, uECC_word_t *private_key, uECC_Curve curve) diff --git a/tinycrypt/ecc_dh.c b/tinycrypt/ecc_dh.c index 853c50dca..52208ad9d 100644 --- a/tinycrypt/ecc_dh.c +++ b/tinycrypt/ecc_dh.c @@ -72,12 +72,6 @@ #include <string.h> #include "mbedtls/platform_util.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) { @@ -160,11 +154,6 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, uECC_word_t _public[NUM_ECC_WORDS * 2]; uECC_word_t _private[NUM_ECC_WORDS]; - - uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t *p2[2] = {_private, tmp}; - uECC_word_t *initial_Z = 0; - uECC_word_t carry; wordcount_t num_words = curve->num_words; wordcount_t num_bytes = curve->num_bytes; int r; @@ -186,30 +175,15 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, public_key + num_bytes, num_bytes); - /* 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) { - if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) { - r = 0; - goto clear_and_out; - } - initial_Z = p2[carry]; - } - - EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1, - curve); + r = EccPoint_mult_safer(_public, _public, _private, curve); + if (r == 0) + goto clear_and_out; uECC_vli_nativeToBytes(secret, num_bytes, _public); r = !EccPoint_isZero(_public, curve); clear_and_out: /* erasing temporary buffer used to store secret: */ - mbedtls_platform_zeroize(p2, sizeof(p2)); - mbedtls_platform_zeroize(tmp, sizeof(tmp)); mbedtls_platform_zeroize(_private, sizeof(_private)); return r; diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index e8c0e0b2b..8462860c6 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -114,13 +114,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]; - uECC_word_t *k2[2] = {tmp, s}; uECC_word_t p[NUM_ECC_WORDS * 2]; - uECC_word_t *initial_Z = 0; - uECC_word_t carry; 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; + int r; + /* Make sure 0 < k < curve_n */ if (uECC_vli_isZero(k, num_words) || @@ -128,21 +126,8 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, return 0; } - /* 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(k, tmp, s, curve); - - /* If an RNG function was specified, get a random initial Z value to - * protect against side-channel attacks such as Template SPA */ - if (g_rng_function) { - if (!uECC_generate_random_int(k2[carry], curve->p, num_words)) { - return 0; - } - initial_Z = k2[carry]; - } - - EccPoint_mult(p, curve->G, k2[!carry], initial_Z, num_n_bits + 1, curve); - if (uECC_vli_isZero(p, num_words)) { + r = EccPoint_mult_safer(p, curve->G, k, curve); + if (r == 0 || uECC_vli_isZero(p, num_words)) { return 0; }