From 4a658a01c6511f02c82efd9d1e80901e8fef2fac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 14 Oct 2019 11:06:47 +0200 Subject: [PATCH 01/30] Add projective coordinates randomization in ECDSA Why: this protects against potential side-channels attacks. This counter-measure is for example effective against Template SPA. Also, the bignum arithmetic as implemented in TinyCrypt isn't entirely regular, which could in principle be exploited by an attacker; randomizing the coordinates makes this less likely to happen. Randomizing projective coordinates is also a well-known countermeasure to DPA. In the context of the scalar multiplication in ECDSA, DPA isn't a concern since it requires multiple measurements with various base points and the same scalar, and the scalar mult in ECDSA is the opposite: the base point's always the same and the scalar is always unique. But we want protection against the other attacks as well. How: we use the same code fragment as in uECC_shared_secret in ecc_dh.c, adapted as follows: (1) replace p2 with k2 as that's how it's called in this function; (2) adjust how errors are handled. The code might not be immediately clear so here are a few more details: regularize_k() takes two arrays as outputs, and the return value says which one should be passed to ECCPoint_mult(). The other one is free for us to re-use to generate a random number to be used as the initial Z value for randomizing coordinates (otherwise the initial Z value is 1), thus avoiding the use of an extra stack buffer. --- tinycrypt/ecc_dsa.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index a3893d37f..e8c0e0b2b 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -116,6 +116,7 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, 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); @@ -127,8 +128,20 @@ 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); - EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, 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)) { return 0; } From 6ee7a4e01c587072b88cf9bcb4c7566f614bda9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 14 Oct 2019 14:02:07 +0200 Subject: [PATCH 02/30] Validate peer's public key in ECDH This protects against invalid curve attacks. (It's also a tiny step in the direction of protecting against some fault injection attacks.) --- tinycrypt/ecc_dh.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tinycrypt/ecc_dh.c b/tinycrypt/ecc_dh.c index 54b9a8ab4..853c50dca 100644 --- a/tinycrypt/ecc_dh.c +++ b/tinycrypt/ecc_dh.c @@ -169,6 +169,12 @@ int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key, wordcount_t num_bytes = curve->num_bytes; int r; + /* Protect against invalid curve attacks */ + if (uECC_valid_public_key(public_key, curve) != 0) { + r = 0; + goto clear_and_out; + } + /* Converting buffers to correct bit order: */ uECC_vli_bytesToNative(_private, private_key, From 14ab9c287946dbb899734937d0d909b770a9bea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 22 Oct 2019 09:49:53 +0200 Subject: [PATCH 03/30] Add random delays to multi-precision multiplication This is a counter-measure to make horizontal attacks harder. Horizontal attacks work with a single trace by noticing when intermediate computations within that trace happen on the same operands. We'll try to make that harder for an attacker to achieve that by introducing random delays based on extra computation and extra random accesses to input in the multi-precision multiplication (which is the dominant operation and the target of horizontal attacks known so far). This should make it hard for the attacker to compare two multiplications. This first commit introduces the new function for multiplication with random delay - future commits will ensure it is used all the way up to the top-level scalar multiplication routine. --- tinycrypt/ecc.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 116 insertions(+), 3 deletions(-) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index cef1469ee..9ca2b6772 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -253,6 +253,12 @@ static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) } } +/* Compute (r2, r1, r0) = a * b + (r1, r0): + * [in] a, b: operands to be multiplied + * [in] r0, r1: low and high-order words of operand to add + * [out] r0, r1: low and high-order words of the result + * [out] r2: carry + */ static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0, uECC_word_t *r1, uECC_word_t *r2) { @@ -266,15 +272,71 @@ static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0, } -/* Computes result = left * right. Result must be 2 * num_words long. */ -static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words) +/* State for implementing random delays in uECC_vli_mult_rnd(). + * + * The state is initialised by randomizing delays and setting i = 0. + * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i. + * + * A scalar muliplication uses 14 field multiplications per bit of exponent. + */ +typedef struct { + uint8_t delays[14 * 256]; + uint16_t i; +} wait_state_t; + +#if 0 +static void wait_init(wait_state_t *s) +{ + g_rng_function(s->delays, sizeof(s->delays)); + s->i = 0; +} +#endif + +/* Computes result = left * right. Result must be 2 * num_words long. + * + * As a counter-measure against horizontal attacks, add noise by performing + * a random number of extra computations performing random additional accesses + * to limbs of the input. + * + * Each of the two actual computation loops is surrounded by two + * similar-looking waiting loops, to make the beginning and end of the actual + * computation harder to spot. + * + * We add 4 waiting loops of between 0 and 3 calls to muladd() each. That + * makes an average of 6 extra calls. Compared to the main computation which + * makes 64 such calls, this represents an average performance degradation of + * less than 10%. + * + * Compared to the original uECC_vli_mult(), loose the num_words argument as we + * know it's always 8. This saves a bit of code size and execution speed. + */ +static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wait_state_t *s) { uECC_word_t r0 = 0; uECC_word_t r1 = 0; uECC_word_t r2 = 0; wordcount_t i, k; + const uint8_t num_words = 8; + + /* Fetch 8 bit worth of delay from the state; 0 if we have no state */ + uint8_t delays = s ? s->delays[s->i++] : 0; + uECC_word_t rr0 = 0, rr1 = 0; + volatile uECC_word_t r; + + /* Mimic start of next loop: k in [0, 3] */ + k = 0 + (delays & 0x03); + delays >>= 2; + /* k = 0 -> i in [1, 0] -> 0 extra muladd; + * k = 3 -> i in [1, 3] -> 3 extra muladd */ + for (i = 0; i <= k; ++i) { + muladd(left[i], right[k - i], &rr0, &rr1, &r2); + } + r = rr0; + rr0 = rr1; + rr1 = r2; + r2 = 0; /* Compute each digit of result in sequence, maintaining the carries. */ for (k = 0; k < num_words; ++k) { @@ -289,6 +351,32 @@ static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left, r2 = 0; } + /* Mimic end of previous loop: k in [4, 7] */ + k = 4 + (delays & 0x03); + delays >>= 2; + /* k = 4 -> i in [5, 4] -> 0 extra muladd; + * k = 7 -> i in [5, 7] -> 3 extra muladd */ + for (i = 5; i <= k; ++i) { + muladd(left[i], right[k - i], &rr0, &rr1, &r2); + } + r = rr0; + rr0 = rr1; + rr1 = r2; + r2 = 0; + + /* Mimic start of next loop: k in [8, 11] */ + k = 11 - (delays & 0x03); + delays >>= 2; + /* k = 8 -> i in [5, 7] -> 3 extra muladd; + * k = 11 -> i in [8, 7] -> 0 extra muladd */ + for (i = (k + 5) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], &rr0, &rr1, &r2); + } + r = rr0; + rr0 = rr1; + rr1 = r2; + r2 = 0; + for (k = num_words; k < num_words * 2 - 1; ++k) { for (i = (k + 1) - num_words; i < num_words; ++i) { @@ -299,7 +387,32 @@ static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left, r1 = r2; r2 = 0; } + result[num_words * 2 - 1] = r0; + + /* Mimic end of previous loop: k in [12, 15] */ + k = 15 - (delays & 0x03); + delays >>= 2; + /* k = 12 -> i in [5, 7] -> 3 extra muladd; + * k = 15 -> i in [8, 7] -> 0 extra muladd */ + for (i = (k + 1) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], &rr0, &rr1, &r2); + } + r = rr0; + rr0 = rr1; + rr1 = r2; + r2 = 0; + + /* avoid warning that r is set but not used */ + (void) r; +} + +/* Computes result = left * right. Result must be 2 * num_words long. */ +static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wordcount_t num_words) +{ + (void) num_words; + uECC_vli_mult_rnd(result, left, right, NULL); } void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, From 938f53f1fbb23d9b4f653dded3f1a3a1606f6786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 29 Oct 2019 11:23:43 +0100 Subject: [PATCH 04/30] Actually use randomized mult when relevant While at it, loose the 'curve' argument in internal randomized functions, for the same reasons we lost 'num_words' in uECC_vli_mult_rnd(): we only have one curve so we don't need this, and hardcoding it saves a bit of code size and speed, which is welcome to slightly reduce the impact of the counter-measure on both of them. --- tinycrypt/ecc.c | 93 +++++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 34 deletions(-) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 9ca2b6772..6e983692f 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -284,14 +284,6 @@ typedef struct { uint16_t i; } wait_state_t; -#if 0 -static void wait_init(wait_state_t *s) -{ - g_rng_function(s->delays, sizeof(s->delays)); - s->i = 0; -} -#endif - /* Computes result = left * right. Result must be 2 * num_words long. * * As a counter-measure against horizontal attacks, add noise by performing @@ -494,6 +486,15 @@ void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, uECC_vli_mmod(result, product, mod, num_words); } +static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left, + const uECC_word_t *right, wait_state_t *s) +{ + uECC_word_t product[2 * NUM_ECC_WORDS]; + uECC_vli_mult_rnd(product, left, right, s); + + vli_mmod_fast_secp256r1(result, product); +} + void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, uECC_Curve curve) { @@ -503,6 +504,13 @@ void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, curve->mmod_fast(result, product); } +static void uECC_vli_modSquare_rnd(uECC_word_t *result, + const uECC_word_t *left, + wait_state_t *s) +{ + uECC_vli_modMult_rnd(result, left, left, s); +} + static void uECC_vli_modSquare_fast(uECC_word_t *result, const uECC_word_t *left, uECC_Curve curve) @@ -782,68 +790,78 @@ static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, apply_z(X2, Y2, z, curve); } -void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * X2, uECC_word_t * Y2, - uECC_Curve curve) +static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + wait_state_t *s) { /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ uECC_word_t t5[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; + const uECC_Curve curve = &curve_secp256r1; + const wordcount_t num_words = 8; uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ - uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ - uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modSquare_rnd(t5, t5, s); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ + uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ - uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */ + uECC_vli_modSquare_rnd(t5, Y2, s); /* t5 = (y2 - y1)^2 = D */ uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ - uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */ + uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */ uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ - uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ uECC_vli_set(X2, t5, num_words); } +void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + uECC_Curve curve) +{ + (void) curve; + XYcZ_add_rnd(X1, Y1, X2, Y2, NULL); +} + /* Input P = (x1, y1, Z), Q = (x2, y2, Z) Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3) or P => P - Q, Q => P + Q */ -static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1, - uECC_word_t * X2, uECC_word_t * Y2, - uECC_Curve curve) +static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, + uECC_word_t * X2, uECC_word_t * Y2, + wait_state_t *s) { /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ uECC_word_t t5[NUM_ECC_WORDS]; uECC_word_t t6[NUM_ECC_WORDS]; uECC_word_t t7[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; + const uECC_Curve curve = &curve_secp256r1; + const wordcount_t num_words = 8; uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ - uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ - uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modSquare_rnd(t5, t5, s); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ + uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ - uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */ + uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */ uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */ - uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */ + uECC_vli_modSquare_rnd(X2, Y2, s); /* t3 = (y2 - y1)^2 = D */ uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */ - uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */ /* t4 = (y2 - y1)*(B - x3) - E = y3: */ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); - uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */ + uECC_vli_modSquare_rnd(t7, t5, s); /* t7 = (y2 + y1)^2 = F */ uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */ uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */ - uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */ + uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */ /* t2 = (y2+y1)*(x3' - B) - E = y3': */ uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); @@ -862,6 +880,13 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, bitcount_t i; uECC_word_t nb; wordcount_t num_words = curve->num_words; + wait_state_t wait_state, *ws = NULL; + + if (g_rng_function) { + ws = &wait_state; + g_rng_function(ws->delays, sizeof(ws->delays)); + ws->i = 0; + } uECC_vli_set(Rx[1], point, num_words); uECC_vli_set(Ry[1], point + num_words, num_words); @@ -870,12 +895,12 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, for (i = num_bits - 2; i > 0; --i) { nb = !uECC_vli_testBit(scalar, i); - XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); - XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); + XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); } nb = !uECC_vli_testBit(scalar, 0); - XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); /* Find final 1/Z value. */ uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ @@ -888,7 +913,7 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); /* End 1/Z calculation */ - XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); apply_z(Rx[0], Ry[0], z, curve); uECC_vli_set(result, Rx[0], num_words); From d467116e5945502b70096f2ca50236a03e1575d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 31 Oct 2019 11:26:26 +0100 Subject: [PATCH 05/30] Make wait_state smaller Previous size was 3584 bytes which is not acceptable on constrained systems (especially on the stack). This was a misguided attempt at minimizing the number of calls to the RNG function in order to minimize impact on performance, but clearly this does not justify using that much RAM and a compromise had to be found. --- tinycrypt/ecc.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 6e983692f..233d5eec7 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -274,16 +274,37 @@ static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0, /* State for implementing random delays in uECC_vli_mult_rnd(). * - * The state is initialised by randomizing delays and setting i = 0. + * The state is initialized by randomizing delays and setting i = 0. * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i. * - * A scalar muliplication uses 14 field multiplications per bit of exponent. + * Randomized vli multiplication is used only for point operations + * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication + * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to + * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(), + * indirectly through uECC_vli_modMult_rnd() or uECC_vli_modSquare_rnd()). + * + * Considering this, in order to minimize the number of calls to the RNG + * (which impact performance) while keeping the size of the structure low, + * make room for 14 randomized vli mults, which corresponds to one step in the + * scalar multiplication routine. */ typedef struct { - uint8_t delays[14 * 256]; - uint16_t i; + uint8_t i; + uint8_t delays[14]; } wait_state_t; +/* + * Reset wait_state so that it's ready to be used. + */ +void wait_state_reset(wait_state_t *ws) +{ + if (ws == NULL) + return; + + ws->i = 0; + g_rng_function(ws->delays, sizeof(ws->delays)); +} + /* Computes result = left * right. Result must be 2 * num_words long. * * As a counter-measure against horizontal attacks, add noise by performing @@ -880,13 +901,8 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, bitcount_t i; uECC_word_t nb; wordcount_t num_words = curve->num_words; - wait_state_t wait_state, *ws = NULL; - - if (g_rng_function) { - ws = &wait_state; - g_rng_function(ws->delays, sizeof(ws->delays)); - ws->i = 0; - } + wait_state_t wait_state; + wait_state_t * const ws = g_rng_function ? &wait_state : NULL; uECC_vli_set(Rx[1], point, num_words); uECC_vli_set(Ry[1], point + num_words, num_words); @@ -894,11 +910,13 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); for (i = num_bits - 2; i > 0; --i) { + wait_state_reset(ws); nb = !uECC_vli_testBit(scalar, i); XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); } + wait_state_reset(ws); nb = !uECC_vli_testBit(scalar, 0); XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); From d5e503ec3396551bda8b19dc068a2ca3dcf67df0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 31 Oct 2019 12:53:44 +0100 Subject: [PATCH 06/30] Rename wait_state_t to ecc_wait_state_t Even though this is type name is purely internal to a single C file, let's reduce the potential for clashes with other wait state types which might be added elsewhere in the library and become visible here (for example through platform_util.h). --- tinycrypt/ecc.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 233d5eec7..45a01dc5e 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -291,12 +291,12 @@ static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0, typedef struct { uint8_t i; uint8_t delays[14]; -} wait_state_t; +} ecc_wait_state_t; /* * Reset wait_state so that it's ready to be used. */ -void wait_state_reset(wait_state_t *ws) +void ecc_wait_state_reset(ecc_wait_state_t *ws) { if (ws == NULL) return; @@ -324,7 +324,7 @@ void wait_state_reset(wait_state_t *ws) * know it's always 8. This saves a bit of code size and execution speed. */ static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wait_state_t *s) + const uECC_word_t *right, ecc_wait_state_t *s) { uECC_word_t r0 = 0; @@ -508,7 +508,7 @@ void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, } static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wait_state_t *s) + const uECC_word_t *right, ecc_wait_state_t *s) { uECC_word_t product[2 * NUM_ECC_WORDS]; uECC_vli_mult_rnd(product, left, right, s); @@ -527,7 +527,7 @@ void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, static void uECC_vli_modSquare_rnd(uECC_word_t *result, const uECC_word_t *left, - wait_state_t *s) + ecc_wait_state_t *s) { uECC_vli_modMult_rnd(result, left, left, s); } @@ -813,7 +813,7 @@ static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2, uECC_word_t * Y2, - wait_state_t *s) + ecc_wait_state_t *s) { /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ uECC_word_t t5[NUM_ECC_WORDS]; @@ -852,7 +852,7 @@ void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, */ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2, uECC_word_t * Y2, - wait_state_t *s) + ecc_wait_state_t *s) { /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ uECC_word_t t5[NUM_ECC_WORDS]; @@ -901,8 +901,8 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, bitcount_t i; uECC_word_t nb; wordcount_t num_words = curve->num_words; - wait_state_t wait_state; - wait_state_t * const ws = g_rng_function ? &wait_state : NULL; + ecc_wait_state_t wait_state; + ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL; uECC_vli_set(Rx[1], point, num_words); uECC_vli_set(Ry[1], point + num_words, num_words); @@ -910,13 +910,13 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); for (i = num_bits - 2; i > 0; --i) { - wait_state_reset(ws); + ecc_wait_state_reset(ws); nb = !uECC_vli_testBit(scalar, i); XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); } - wait_state_reset(ws); + ecc_wait_state_reset(ws); nb = !uECC_vli_testBit(scalar, 0); XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); From 86c4f81408a516f65e2f4d672e023ed68a055ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 31 Oct 2019 13:02:03 +0100 Subject: [PATCH 07/30] Improve documentation of internal function --- tinycrypt/ecc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 45a01dc5e..8eaa1e749 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -253,7 +253,11 @@ static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) } } -/* Compute (r2, r1, r0) = a * b + (r1, r0): +/* Compute a * b + r, where r is a double-word with high-order word r1 and + * low-order word r0, and store the result in the same double-word (r1, r0), + * with the carry bit stored in r2. + * + * (r2, r1, r0) = a * b + (r1, r0): * [in] a, b: operands to be multiplied * [in] r0, r1: low and high-order words of operand to add * [out] r0, r1: low and high-order words of the result From c78d86b4991c260ff59fe06d54ae350f5f7720af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 10:18:42 +0100 Subject: [PATCH 08/30] Remove some internal functions that aren't needed This saves 10 bytes of code size, and makes it a bit easier to remove unused parameters later (fewer prototypes to change). --- tinycrypt/ecc.c | 53 ++++++++++++++----------------------------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 8eaa1e749..f7a6f0665 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -285,7 +285,7 @@ static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0, * (XYcZ_add_rnd() * and XYcZ_addC_rnd()) in scalar multiplication * (ECCPoint_mult()). Those go in pair, and each pair does 14 calls to * uECC_vli_mult_rnd() (6 in XYcZ_add_rnd() and 8 in XYcZ_addC_rnd(), - * indirectly through uECC_vli_modMult_rnd() or uECC_vli_modSquare_rnd()). + * indirectly through uECC_vli_modMult_rnd(). * * Considering this, in order to minimize the number of calls to the RNG * (which impact performance) while keeping the size of the structure low, @@ -424,14 +424,6 @@ static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left, (void) r; } -/* Computes result = left * right. Result must be 2 * num_words long. */ -static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words) -{ - (void) num_words; - uECC_vli_mult_rnd(result, left, right, NULL); -} - 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) @@ -507,7 +499,7 @@ void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words) { uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult(product, left, right, num_words); + uECC_vli_mult_rnd(product, left, right, NULL); uECC_vli_mmod(result, product, mod, num_words); } @@ -524,26 +516,11 @@ void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, const uECC_word_t *right, uECC_Curve curve) { uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult(product, left, right, curve->num_words); + uECC_vli_mult_rnd(product, left, right, NULL); curve->mmod_fast(result, product); } -static void uECC_vli_modSquare_rnd(uECC_word_t *result, - const uECC_word_t *left, - ecc_wait_state_t *s) -{ - uECC_vli_modMult_rnd(result, left, left, s); -} - -static void uECC_vli_modSquare_fast(uECC_word_t *result, - const uECC_word_t *left, - uECC_Curve curve) -{ - uECC_vli_modMult_fast(result, left, left, curve); -} - - #define EVEN(vli) (!(vli[0] & 1)) static void vli_modInv_update(uECC_word_t *uv, @@ -621,11 +598,11 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, return; } - uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */ + uECC_vli_modMult_fast(t4, Y1, Y1, curve); /* t4 = y1^2 */ uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */ - uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */ + uECC_vli_modMult_fast(t4, t4, t4, curve); /* t4 = y1^4 */ uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */ - uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */ + uECC_vli_modMult_fast(Z1, Z1, Z1, curve); /* t3 = z1^2 */ uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */ uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */ @@ -643,7 +620,7 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, } /* t1 = 3/2*(x1^2 - z1^4) = B */ - uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */ + uECC_vli_modMult_fast(Z1, X1, X1, curve); /* t3 = B^2 */ uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */ uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */ uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */ @@ -663,7 +640,7 @@ void x_side_default(uECC_word_t *result, uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */ wordcount_t num_words = curve->num_words; - uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ + uECC_vli_modMult_fast(result, x, x, curve); /* r = x^2 */ uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */ /* r = x^3 - 3x + b: */ @@ -786,7 +763,7 @@ void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, { uECC_word_t t1[NUM_ECC_WORDS]; - uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */ + uECC_vli_modMult_fast(t1, Z, Z, curve); /* z^2 */ uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */ uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */ uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ @@ -825,11 +802,11 @@ static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1, const wordcount_t num_words = 8; uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ - uECC_vli_modSquare_rnd(t5, t5, s); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ - uECC_vli_modSquare_rnd(t5, Y2, s); /* t5 = (y2 - y1)^2 = D */ + uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */ uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ @@ -866,7 +843,7 @@ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, const wordcount_t num_words = 8; uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ - uECC_vli_modSquare_rnd(t5, t5, s); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ @@ -875,7 +852,7 @@ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */ uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */ - uECC_vli_modSquare_rnd(X2, Y2, s); /* t3 = (y2 - y1)^2 = D */ + uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */ uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */ @@ -883,7 +860,7 @@ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, /* t4 = (y2 - y1)*(B - x3) - E = y3: */ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); - uECC_vli_modSquare_rnd(t7, t5, s); /* t7 = (y2 + y1)^2 = F */ + uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */ uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */ uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */ uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */ @@ -1048,7 +1025,7 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) return -2; } - uECC_vli_modSquare_fast(tmp1, point + num_words, curve); + uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words, curve); curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ /* Make sure that y^2 == x^3 + ax + b */ From ef238283d55fff7b4ae8601013596f5639a56988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 11:19:30 +0100 Subject: [PATCH 09/30] Add ECCPoint_mult_safer() function This avoids the need for each calling site to manually regularize the scalar and randomize coordinates, which makes for simpler safe use and saves 50 bytes of code size in the library. --- include/tinycrypt/ecc.h | 14 ++++++++++++++ tinycrypt/ecc.c | 41 ++++++++++++++++++++++++++++++++++++++++- tinycrypt/ecc_dh.c | 32 +++----------------------------- tinycrypt/ecc_dsa.c | 23 ++++------------------- 4 files changed, 61 insertions(+), 49 deletions(-) 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 +#include "mbedtls/platform_util.h" #include /* 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 #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; } From 27926d63b70e5e89e9b4be76dfdb73b1e7478852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 11:26:46 +0100 Subject: [PATCH 10/30] Remove less-safe mult function from public API This doesn't change code size, but makes it easier to remove unneeded parameters later (less possible entry points). --- include/tinycrypt/ecc.h | 27 --------------------------- tinycrypt/ecc.c | 4 ++-- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 3996cd4b2..7a0b0bb7e 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -282,33 +282,6 @@ int uECC_compute_public_key(const uint8_t *private_key, uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, uECC_word_t *private_key, uECC_Curve curve); -/* - * @brief Regularize the bitcount for the private key so that attackers cannot - * use a side channel attack to learn the number of leading zeros. - * @return Regularized k - * @param k IN -- private-key - * @param k0 IN/OUT -- regularized k - * @param k1 IN/OUT -- regularized k - * @param curve IN -- elliptic curve - */ -uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, - uECC_word_t *k1, uECC_Curve curve); - -/* - * @brief Point multiplication algorithm using Montgomery's ladder with co-Z - * coordinates. See http://eprint.iacr.org/2011/338.pdf. - * @note Result may overlap point. - * @param result OUT -- returns scalar*point - * @param point IN -- elliptic curve point - * @param scalar IN -- scalar - * @param initial_Z IN -- initial value for z - * @param num_bits IN -- number of bits in scalar - * @param curve IN -- elliptic curve - */ -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. diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 91bec5604..a95ad28b8 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -871,7 +871,7 @@ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, uECC_vli_set(X1, t7, num_words); } -void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, +static 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) @@ -920,7 +920,7 @@ void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, uECC_vli_set(result + num_words, Ry[0], num_words); } -uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, +static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, uECC_word_t *k1, uECC_Curve curve) { From 3645ac93f5aae072831b365115afb14e045a5f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 11:39:18 +0100 Subject: [PATCH 11/30] Start hardcoding curve in internal functions Saves 68 byte of code size. --- tinycrypt/ecc.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index a95ad28b8..a6bbcf7f4 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -873,8 +873,7 @@ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, static 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) + const uECC_word_t * initial_Z) { /* R0 and R1 */ uECC_word_t Rx[2][NUM_ECC_WORDS]; @@ -882,7 +881,9 @@ static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, uECC_word_t z[NUM_ECC_WORDS]; bitcount_t i; uECC_word_t nb; - wordcount_t num_words = curve->num_words; + const wordcount_t num_words = 8; + const bitcount_t num_bits = 256 + 1; /* from regularize_k */ + const uECC_Curve curve = uECC_secp256r1(); ecc_wait_state_t wait_state; ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL; @@ -921,12 +922,12 @@ static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, } static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, - uECC_word_t *k1, uECC_Curve curve) + uECC_word_t *k1) { - wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); - - bitcount_t num_n_bits = curve->num_n_bits; + wordcount_t num_n_words = 8; + bitcount_t num_n_bits = 256; + const uECC_Curve curve = uECC_secp256r1(); 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) && @@ -943,15 +944,17 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, 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; + wordcount_t num_words = 8; uECC_word_t carry; uECC_word_t *initial_Z = 0; int r; + if (curve != uECC_secp256r1()) + 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(scalar, tmp, s, curve); + carry = regularize_k(scalar, tmp, s); /* If an RNG function was specified, get a random initial Z value to * protect against side-channel attacks such as Template SPA */ @@ -963,7 +966,7 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, initial_Z = k2[carry]; } - EccPoint_mult(result, point, k2[!carry], initial_Z, num_n_bits + 1, curve); + EccPoint_mult(result, point, k2[!carry], initial_Z); r = 1; clear_and_out: @@ -985,11 +988,14 @@ uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, uECC_word_t *p2[2] = {tmp1, tmp2}; uECC_word_t carry; + if (curve != uECC_secp256r1()) + 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(private_key, tmp1, tmp2, curve); + carry = regularize_k(private_key, tmp1, tmp2); - EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve); + EccPoint_mult(result, curve->G, p2[!carry], 0); if (EccPoint_isZero(result, curve)) { return 0; From c3ec14c87f40de6dec25f4c110df02286df0f769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 12:12:00 +0100 Subject: [PATCH 12/30] Harcode curve in semi-internal modMult function Saves 80 bytes of code size. --- include/tinycrypt/ecc.h | 5 ++-- tinycrypt/ecc.c | 54 +++++++++++++++++++---------------------- tinycrypt/ecc_dsa.c | 8 +++--- 3 files changed, 31 insertions(+), 36 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 7a0b0bb7e..ac3e3ad0b 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -367,8 +367,7 @@ void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2, * @param Z IN -- z value * @param curve IN -- elliptic curve */ -void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, - uECC_Curve curve); +void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z); /* * @brief Check if bit is set. @@ -399,7 +398,7 @@ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, * @param curve IN -- elliptic curve */ void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, uECC_Curve curve); + const uECC_word_t *right); /* * @brief Computes result = left - right. diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index a6bbcf7f4..08e24dd57 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -514,12 +514,9 @@ static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left, } void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, uECC_Curve curve) + const uECC_word_t *right) { - uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult_rnd(product, left, right, NULL); - - curve->mmod_fast(result, product); + uECC_vli_modMult_rnd(result, left, right, NULL); } #define EVEN(vli) (!(vli[0] & 1)) @@ -599,16 +596,16 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, return; } - uECC_vli_modMult_fast(t4, Y1, Y1, curve); /* t4 = y1^2 */ - uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */ - uECC_vli_modMult_fast(t4, t4, t4, curve); /* t4 = y1^4 */ - uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */ - uECC_vli_modMult_fast(Z1, Z1, Z1, curve); /* t3 = z1^2 */ + uECC_vli_modMult_fast(t4, Y1, Y1); /* t4 = y1^2 */ + uECC_vli_modMult_fast(t5, X1, t4); /* t5 = x1*y1^2 = A */ + uECC_vli_modMult_fast(t4, t4, t4); /* t4 = y1^4 */ + uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */ + uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */ uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */ uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */ uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */ - uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */ + uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */ uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */ uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ @@ -621,11 +618,11 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, } /* t1 = 3/2*(x1^2 - z1^4) = B */ - uECC_vli_modMult_fast(Z1, X1, X1, curve); /* t3 = B^2 */ + uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */ uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */ uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */ uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */ + uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */ /* t4 = B * (A - x3) - y1^4 = y3: */ uECC_vli_modSub(t4, X1, t4, curve->p, num_words); @@ -641,9 +638,9 @@ void x_side_default(uECC_word_t *result, uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */ wordcount_t num_words = curve->num_words; - uECC_vli_modMult_fast(result, x, x, curve); /* r = x^2 */ + uECC_vli_modMult_fast(result, x, x); /* r = x^2 */ uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ - uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */ + uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */ /* r = x^3 - 3x + b: */ uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); } @@ -759,15 +756,14 @@ uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve) return uECC_vli_isZero(point, curve->num_words * 2); } -void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z, - uECC_Curve curve) +void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z) { uECC_word_t t1[NUM_ECC_WORDS]; - uECC_vli_modMult_fast(t1, Z, Z, curve); /* z^2 */ - uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */ - uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */ - uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ + uECC_vli_modMult_fast(t1, Z, Z); /* z^2 */ + uECC_vli_modMult_fast(X1, X1, t1); /* x1 * z^2 */ + uECC_vli_modMult_fast(t1, t1, Z); /* z^3 */ + uECC_vli_modMult_fast(Y1, Y1, t1); /* y1 * z^3 */ } /* P = (x1, y1) => 2P, (x2, y2) => P' */ @@ -788,9 +784,9 @@ static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, uECC_vli_set(X2, X1, num_words); uECC_vli_set(Y2, Y1, num_words); - apply_z(X1, Y1, z, curve); + apply_z(X1, Y1, z); curve->double_jacobian(X1, Y1, z, curve); - apply_z(X2, Y2, z, curve); + apply_z(X2, Y2, z); } static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1, @@ -905,17 +901,17 @@ static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, /* Find final 1/Z value. */ uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ - uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */ - uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */ + uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */ + uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */ uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/ /* yP / (xP * Yb * (X1 - X0)) */ - uECC_vli_modMult_fast(z, z, point + num_words, curve); + uECC_vli_modMult_fast(z, z, point + num_words); /* Xb * yP / (xP * Yb * (X1 - X0)) */ - uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); + uECC_vli_modMult_fast(z, z, Rx[1 - nb]); /* End 1/Z calculation */ XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); - apply_z(Rx[0], Ry[0], z, curve); + apply_z(Rx[0], Ry[0], z); uECC_vli_set(result, Rx[0], num_words); uECC_vli_set(result + num_words, Ry[0], num_words); @@ -1070,7 +1066,7 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) return -2; } - uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words, curve); + uECC_vli_modMult_fast(tmp1, point + num_words, point + num_words); curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ /* Make sure that y^2 == x^3 + ax + b */ diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 8462860c6..2df89a504 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -257,7 +257,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ XYcZ_add(tx, ty, sum, sum + num_words, curve); uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ - apply_z(sum, sum + num_words, z, curve); + apply_z(sum, sum + num_words, z); /* Use Shamir's trick to calculate u1*G + u2*Q */ points[0] = 0; @@ -283,15 +283,15 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, if (point) { uECC_vli_set(tx, point, num_words); uECC_vli_set(ty, point + num_words, num_words); - apply_z(tx, ty, z, curve); + apply_z(tx, ty, z); uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ XYcZ_add(tx, ty, rx, ry, curve); - uECC_vli_modMult_fast(z, z, tz, curve); + uECC_vli_modMult_fast(z, z, tz); } } uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */ - apply_z(rx, ry, z, curve); + apply_z(rx, ry, z); /* v = x1 (mod n) */ if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { From 78a7e351fe0fc7bd65490c88c0247d636f177b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 12:31:06 +0100 Subject: [PATCH 13/30] Use macros for number of bits and words --- include/tinycrypt/ecc.h | 1 + tinycrypt/ecc.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index ac3e3ad0b..026febcb0 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -111,6 +111,7 @@ typedef uint64_t uECC_dword_t; #define NUM_ECC_WORDS 8 /* Number of bytes to represent an element of the the curve p-256: */ #define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS) +#define NUM_ECC_BITS 256 /* structure that represents an elliptic curve (e.g. p256):*/ struct uECC_Curve_t; diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 08e24dd57..a5145bc79 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -336,7 +336,7 @@ static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left, uECC_word_t r1 = 0; uECC_word_t r2 = 0; wordcount_t i, k; - const uint8_t num_words = 8; + const uint8_t num_words = NUM_ECC_WORDS; /* Fetch 8 bit worth of delay from the state; 0 if we have no state */ uint8_t delays = s ? s->delays[s->i++] : 0; @@ -796,7 +796,7 @@ static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1, /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ uECC_word_t t5[NUM_ECC_WORDS]; const uECC_Curve curve = &curve_secp256r1; - const wordcount_t num_words = 8; + const wordcount_t num_words = NUM_ECC_WORDS; uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ @@ -837,7 +837,7 @@ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t t6[NUM_ECC_WORDS]; uECC_word_t t7[NUM_ECC_WORDS]; const uECC_Curve curve = &curve_secp256r1; - const wordcount_t num_words = 8; + const wordcount_t num_words = NUM_ECC_WORDS; uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ @@ -877,8 +877,8 @@ static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, uECC_word_t z[NUM_ECC_WORDS]; bitcount_t i; uECC_word_t nb; - const wordcount_t num_words = 8; - const bitcount_t num_bits = 256 + 1; /* from regularize_k */ + const wordcount_t num_words = NUM_ECC_WORDS; + const bitcount_t num_bits = NUM_ECC_BITS + 1; /* from regularize_k */ const uECC_Curve curve = uECC_secp256r1(); ecc_wait_state_t wait_state; ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL; @@ -921,8 +921,8 @@ static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, uECC_word_t *k1) { - wordcount_t num_n_words = 8; - bitcount_t num_n_bits = 256; + wordcount_t num_n_words = NUM_ECC_WORDS; + bitcount_t num_n_bits = NUM_ECC_BITS; const uECC_Curve curve = uECC_secp256r1(); uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || @@ -940,7 +940,7 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, 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 = 8; + wordcount_t num_words = NUM_ECC_WORDS; uECC_word_t carry; uECC_word_t *initial_Z = 0; int r; From 02d9d21fd691ab6614c60f5f1e0bfd29248a2f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 12:37:08 +0100 Subject: [PATCH 14/30] Hardcode numwords in internal vli_add Saves 40 bytes --- tinycrypt/ecc.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index a5145bc79..b9b55bc6e 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -218,11 +218,11 @@ uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, /* Computes result = left + right, returning carry, in constant time. * Can modify in place. */ static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words) + const uECC_word_t *right) { uECC_word_t carry = 0; wordcount_t i; - for (i = 0; i < num_words; ++i) { + for (i = 0; i < NUM_ECC_WORDS; ++i) { uECC_word_t sum = left[i] + right[i] + carry; uECC_word_t val = (sum < left[i]); carry = cond_set(val, carry, (sum != left[i])); @@ -429,7 +429,7 @@ 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) { - uECC_word_t carry = uECC_vli_add(result, left, right, num_words); + uECC_word_t carry = uECC_vli_add(result, left, right); if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { /* result > mod (result = mod + remainder), so subtract mod to get * remainder. */ @@ -445,7 +445,7 @@ void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, 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(result, result, mod); } } @@ -529,7 +529,7 @@ static void vli_modInv_update(uECC_word_t *uv, uECC_word_t carry = 0; if (!EVEN(uv)) { - carry = uECC_vli_add(uv, uv, mod, num_words); + carry = uECC_vli_add(uv, uv, mod); } uECC_vli_rshift1(uv, num_words); if (carry) { @@ -565,7 +565,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, uECC_vli_sub(a, a, b, num_words); uECC_vli_rshift1(a, num_words); if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) { - uECC_vli_add(u, u, mod, num_words); + uECC_vli_add(u, u, mod); } uECC_vli_sub(u, u, v, num_words); vli_modInv_update(u, mod, num_words); @@ -573,7 +573,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, uECC_vli_sub(b, b, a, num_words); uECC_vli_rshift1(b, num_words); if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) { - uECC_vli_add(v, v, mod, num_words); + uECC_vli_add(v, v, mod); } uECC_vli_sub(v, v, u, num_words); vli_modInv_update(v, mod, num_words); @@ -610,7 +610,7 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */ uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ if (uECC_vli_testBit(X1, 0)) { - uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words); + uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p); uECC_vli_rshift1(X1, num_words); X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); } else { @@ -665,8 +665,8 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) tmp[5] = product[13]; tmp[6] = product[14]; tmp[7] = product[15]; - carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS); - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + carry = uECC_vli_add(tmp, tmp, tmp); + carry += uECC_vli_add(result, result, tmp); /* s2 */ tmp[3] = product[12]; @@ -674,8 +674,8 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) tmp[5] = product[14]; tmp[6] = product[15]; tmp[7] = 0; - carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS); - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + carry += uECC_vli_add(tmp, tmp, tmp); + carry += uECC_vli_add(result, result, tmp); /* s3 */ tmp[0] = product[8]; @@ -684,7 +684,7 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) tmp[3] = tmp[4] = tmp[5] = 0; tmp[6] = product[14]; tmp[7] = product[15]; - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + carry += uECC_vli_add(result, result, tmp); /* s4 */ tmp[0] = product[9]; @@ -695,7 +695,7 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) tmp[5] = product[15]; tmp[6] = product[13]; tmp[7] = product[8]; - carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS); + carry += uECC_vli_add(result, result, tmp); /* d1 */ tmp[0] = product[11]; @@ -740,7 +740,7 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) if (carry < 0) { do { - carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS); + carry += uECC_vli_add(result, result, curve_secp256r1.p); } while (carry < 0); } else { @@ -925,11 +925,11 @@ static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, bitcount_t num_n_bits = NUM_ECC_BITS; const uECC_Curve curve = uECC_secp256r1(); - uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || + uECC_word_t carry = uECC_vli_add(k0, k, curve->n) || (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && uECC_vli_testBit(k0, num_n_bits)); - uECC_vli_add(k1, k0, curve->n, num_n_words); + uECC_vli_add(k1, k0, curve->n); return carry; } From f3899fc0ea485f0180f16e81cbdca89827435e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 12:44:43 +0100 Subject: [PATCH 15/30] hardcode numwords in semi-internal vli_isZero --- include/tinycrypt/ecc.h | 2 +- tinycrypt/ecc.c | 17 +++++++++-------- tinycrypt/ecc_dsa.c | 6 +++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 026febcb0..1205eb1c2 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -303,7 +303,7 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, * @param num_words IN -- number of words in the vli * @return 1 if vli == 0, 0 otherwise. */ -uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words); +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli); /* * @brief Check if 'point' is the point at infinity diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index b9b55bc6e..28463999f 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -104,11 +104,11 @@ void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) } } -uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli) { uECC_word_t bits = 0; wordcount_t i; - for (i = 0; i < num_words; ++i) { + for (i = 0; i < NUM_ECC_WORDS; ++i) { bits |= vli[i]; } return (bits == 0); @@ -236,7 +236,7 @@ cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, { uECC_word_t tmp[NUM_ECC_WORDS]; uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); - uECC_word_t equal = uECC_vli_isZero(tmp, num_words); + uECC_word_t equal = uECC_vli_isZero(tmp); return (!equal - 2 * neg); } @@ -544,7 +544,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS]; cmpresult_t cmpResult; - if (uECC_vli_isZero(input, num_words)) { + if (uECC_vli_isZero(input)) { uECC_vli_clear(result, num_words); return; } @@ -592,7 +592,7 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t t5[NUM_ECC_WORDS]; wordcount_t num_words = curve->num_words; - if (uECC_vli_isZero(Z1, num_words)) { + if (uECC_vli_isZero(Z1)) { return; } @@ -753,7 +753,8 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve) { - return uECC_vli_isZero(point, curve->num_words * 2); + (void) curve; + return uECC_vli_isZero(point); } void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z) @@ -1040,7 +1041,7 @@ int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, } random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); - if (!uECC_vli_isZero(random, num_words) && + if (!uECC_vli_isZero(random) && uECC_vli_cmp(top, random, num_words) == 1) { return 1; } @@ -1107,7 +1108,7 @@ int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, BITS_TO_BYTES(curve->num_n_bits)); /* Make sure the private key is in the range [1, n-1]. */ - if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) { + if (uECC_vli_isZero(_private)) { return 0; } diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 2df89a504..8c32ee87f 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -121,13 +121,13 @@ 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, num_words) || + if (uECC_vli_isZero(k) || uECC_vli_cmp(curve->n, k, num_n_words) != 1) { return 0; } r = EccPoint_mult_safer(p, curve->G, k, curve); - if (r == 0 || uECC_vli_isZero(p, num_words)) { + if (r == 0 || uECC_vli_isZero(p)) { return 0; } @@ -232,7 +232,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes); /* r, s must not be 0. */ - if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) { + if (uECC_vli_isZero(r) || uECC_vli_isZero(s)) { return 0; } From 94e48498ef3372d36364ad412836402497881c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 12:47:28 +0100 Subject: [PATCH 16/30] Hardcode numwords in semi-internal vli_clear() --- include/tinycrypt/ecc.h | 2 +- tinycrypt/ecc.c | 16 ++++++++-------- tinycrypt/ecc_dsa.c | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 1205eb1c2..59a7a89c2 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -484,7 +484,7 @@ bitcount_t uECC_vli_numBits(const uECC_word_t *vli, * @param vli IN -- very long integer * @param num_words IN -- number of words */ -void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words); +void uECC_vli_clear(uECC_word_t *vli); /* * @brief check if it is a valid point in the curve diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 28463999f..0039d2f81 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -96,10 +96,10 @@ int uECC_curve_public_key_size(uECC_Curve curve) return 2 * curve->num_bytes; } -void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) +void uECC_vli_clear(uECC_word_t *vli) { wordcount_t i; - for (i = 0; i < num_words; ++i) { + for (i = 0; i < NUM_ECC_WORDS; ++i) { vli[i] = 0; } } @@ -465,7 +465,7 @@ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, wordcount_t word_shift = shift / uECC_WORD_BITS; wordcount_t bit_shift = shift % uECC_WORD_BITS; uECC_word_t carry = 0; - uECC_vli_clear(mod_multiple, word_shift); + uECC_vli_clear(mod_multiple); if (bit_shift > 0) { for(index = 0; index < (uECC_word_t)num_words; ++index) { mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; @@ -545,15 +545,15 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, cmpresult_t cmpResult; if (uECC_vli_isZero(input)) { - uECC_vli_clear(result, num_words); + uECC_vli_clear(result); return; } uECC_vli_set(a, input, num_words); uECC_vli_set(b, mod, num_words); - uECC_vli_clear(u, num_words); + uECC_vli_clear(u); u[0] = 1; - uECC_vli_clear(v, num_words); + uECC_vli_clear(v); while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) { if (EVEN(a)) { uECC_vli_rshift1(a, num_words); @@ -778,7 +778,7 @@ static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, if (initial_Z) { uECC_vli_set(z, initial_Z, num_words); } else { - uECC_vli_clear(z, num_words); + uECC_vli_clear(z); z[0] = 1; } @@ -1016,7 +1016,7 @@ void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes, int num_bytes) { wordcount_t i; - uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); + uECC_vli_clear(native); for (i = 0; i < num_bytes; ++i) { unsigned b = num_bytes - 1 - i; native[b / uECC_WORD_SIZE] |= diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 8c32ee87f..67b4ac7ff 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -87,7 +87,7 @@ static void bits2int(uECC_word_t *native, const uint8_t *bits, bits_size = num_n_bytes; } - uECC_vli_clear(native, num_n_words); + uECC_vli_clear(native); uECC_vli_bytesToNative(native, bits, bits_size); if (bits_size * 8 <= (unsigned)curve->num_n_bits) { return; @@ -134,7 +134,7 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, /* If an RNG function was specified, get a random number to prevent side channel analysis of k. */ if (!g_rng_function) { - uECC_vli_clear(tmp, num_n_words); + uECC_vli_clear(tmp); tmp[0] = 1; } else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) { @@ -271,7 +271,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; uECC_vli_set(rx, point, num_words); uECC_vli_set(ry, point + num_words, num_words); - uECC_vli_clear(z, num_words); + uECC_vli_clear(z); z[0] = 1; for (i = num_bits - 2; i >= 0; --i) { From 2bf5a129cf41971885af269bbf8bfc29f0f28ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 12:56:59 +0100 Subject: [PATCH 17/30] Hardcode numwords in semi-internal vli_numBits() --- include/tinycrypt/ecc.h | 3 +-- tinycrypt/ecc.c | 14 ++++++-------- tinycrypt/ecc_dsa.c | 6 +++--- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 59a7a89c2..50d93d240 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -476,8 +476,7 @@ void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, * @param max_words IN -- number of words * @return number of bits in given vli */ -bitcount_t uECC_vli_numBits(const uECC_word_t *vli, - const wordcount_t max_words); +bitcount_t uECC_vli_numBits(const uECC_word_t *vli); /* * @brief Erases (set to 0) vli diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 0039d2f81..cbc024acd 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -121,27 +121,25 @@ uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) } /* Counts the number of words in vli. */ -static wordcount_t vli_numDigits(const uECC_word_t *vli, - const wordcount_t max_words) +static wordcount_t vli_numDigits(const uECC_word_t *vli) { wordcount_t i; /* Search from the end until we find a non-zero digit. We do it in reverse * because we expect that most digits will be nonzero. */ - for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) { + for (i = NUM_ECC_WORDS - 1; i >= 0 && vli[i] == 0; --i) { } return (i + 1); } -bitcount_t uECC_vli_numBits(const uECC_word_t *vli, - const wordcount_t max_words) +bitcount_t uECC_vli_numBits(const uECC_word_t *vli) { uECC_word_t i; uECC_word_t digit; - wordcount_t num_digits = vli_numDigits(vli, max_words); + wordcount_t num_digits = vli_numDigits(vli); if (num_digits == 0) { return 0; } @@ -461,7 +459,7 @@ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, /* 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); + uECC_vli_numBits(mod); wordcount_t word_shift = shift / uECC_WORD_BITS; wordcount_t bit_shift = shift % uECC_WORD_BITS; uECC_word_t carry = 0; @@ -1029,7 +1027,7 @@ int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, { uECC_word_t mask = (uECC_word_t)-1; uECC_word_t tries; - bitcount_t num_bits = uECC_vli_numBits(top, num_words); + bitcount_t num_bits = uECC_vli_numBits(top); if (!g_rng_function) { return 0; diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 67b4ac7ff..4fe4343be 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -159,7 +159,7 @@ 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_numBits(s) > (bitcount_t)curve->num_bytes * 8) { return 0; } @@ -264,8 +264,8 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, points[1] = curve->G; points[2] = _public; points[3] = sum; - num_bits = smax(uECC_vli_numBits(u1, num_n_words), - uECC_vli_numBits(u2, num_n_words)); + num_bits = smax(uECC_vli_numBits(u1), + uECC_vli_numBits(u2)); point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; From cbbb0f034b3735bc2d11252c6fa8c48a158af7d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 13:02:04 +0100 Subject: [PATCH 18/30] Hardcode numwords in vli_set() --- include/tinycrypt/ecc.h | 3 +-- tinycrypt/ecc.c | 42 ++++++++++++++++++++--------------------- tinycrypt/ecc_dsa.c | 19 +++++++++---------- 3 files changed, 30 insertions(+), 34 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 50d93d240..ba5dffc58 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -453,8 +453,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, * @param src IN -- origin buffer * @param num_words IN -- number of words */ -void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, - wordcount_t num_words); +void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src); /* * @brief Computes (left + right) % mod. diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index cbc024acd..60b565e3c 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -152,12 +152,11 @@ bitcount_t uECC_vli_numBits(const uECC_word_t *vli) return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); } -void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, - wordcount_t num_words) +void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src) { wordcount_t i; - for (i = 0; i < num_words; ++i) { + for (i = 0; i < NUM_ECC_WORDS; ++i) { dest[i] = src[i]; } } @@ -470,7 +469,7 @@ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, carry = mod[index] >> (uECC_WORD_BITS - bit_shift); } } else { - uECC_vli_set(mod_multiple + word_shift, mod, num_words); + uECC_vli_set(mod_multiple + word_shift, mod); } for (index = 1; shift >= 0; --shift) { @@ -490,7 +489,7 @@ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, (uECC_WORD_BITS - 1); uECC_vli_rshift1(mod_multiple + num_words, num_words); } - uECC_vli_set(result, v[index], num_words); + uECC_vli_set(result, v[index]); } void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, @@ -547,8 +546,8 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, return; } - uECC_vli_set(a, input, num_words); - uECC_vli_set(b, mod, num_words); + uECC_vli_set(a, input); + uECC_vli_set(b, mod); uECC_vli_clear(u); u[0] = 1; uECC_vli_clear(v); @@ -577,7 +576,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, vli_modInv_update(v, mod, num_words); } } - uECC_vli_set(result, u, num_words); + uECC_vli_set(result, u); } /* ------ Point operations ------ */ @@ -624,9 +623,9 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, /* t4 = B * (A - x3) - y1^4 = y3: */ uECC_vli_modSub(t4, X1, t4, curve->p, num_words); - uECC_vli_set(X1, Z1, num_words); - uECC_vli_set(Z1, Y1, num_words); - uECC_vli_set(Y1, t4, num_words); + uECC_vli_set(X1, Z1); + uECC_vli_set(Z1, Y1); + uECC_vli_set(Y1, t4); } void x_side_default(uECC_word_t *result, @@ -654,7 +653,7 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) int carry; /* t */ - uECC_vli_set(result, product, NUM_ECC_WORDS); + uECC_vli_set(result, product); /* s1 */ tmp[0] = tmp[1] = tmp[2] = 0; @@ -772,16 +771,15 @@ static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1, uECC_Curve curve) { uECC_word_t z[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; if (initial_Z) { - uECC_vli_set(z, initial_Z, num_words); + uECC_vli_set(z, initial_Z); } else { uECC_vli_clear(z); z[0] = 1; } - uECC_vli_set(X2, X1, num_words); - uECC_vli_set(Y2, Y1, num_words); + uECC_vli_set(X2, X1); + uECC_vli_set(Y2, Y1); apply_z(X1, Y1, z); curve->double_jacobian(X1, Y1, z, curve); @@ -812,7 +810,7 @@ static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1, uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ - uECC_vli_set(X2, t5, num_words); + uECC_vli_set(X2, t5); } void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, @@ -863,7 +861,7 @@ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, /* t2 = (y2+y1)*(x3' - B) - E = y3': */ uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); - uECC_vli_set(X1, t7, num_words); + uECC_vli_set(X1, t7); } static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, @@ -882,8 +880,8 @@ static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, ecc_wait_state_t wait_state; ecc_wait_state_t * const ws = g_rng_function ? &wait_state : NULL; - uECC_vli_set(Rx[1], point, num_words); - uECC_vli_set(Ry[1], point + num_words, num_words); + uECC_vli_set(Rx[1], point); + uECC_vli_set(Ry[1], point + num_words); XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); @@ -912,8 +910,8 @@ static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, XYcZ_add_rnd(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], ws); apply_z(Rx[0], Ry[0], z); - uECC_vli_set(result, Rx[0], num_words); - uECC_vli_set(result + num_words, Ry[0], num_words); + uECC_vli_set(result, Rx[0]); + uECC_vli_set(result + num_words, Ry[0]); } static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 4fe4343be..e302e04ce 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -115,7 +115,6 @@ 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 p[NUM_ECC_WORDS * 2]; - wordcount_t num_words = curve->num_words; wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); int r; @@ -153,7 +152,7 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); s[num_n_words - 1] = 0; - uECC_vli_set(s, p, num_words); + uECC_vli_set(s, p); uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */ bits2int(tmp, message_hash, hash_size, curve); @@ -250,10 +249,10 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */ /* Calculate sum = G + Q. */ - uECC_vli_set(sum, _public, num_words); - uECC_vli_set(sum + num_words, _public + num_words, num_words); - uECC_vli_set(tx, curve->G, num_words); - uECC_vli_set(ty, curve->G + num_words, num_words); + uECC_vli_set(sum, _public); + uECC_vli_set(sum + num_words, _public + num_words); + uECC_vli_set(tx, curve->G); + uECC_vli_set(ty, curve->G + num_words); uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ XYcZ_add(tx, ty, sum, sum + num_words, curve); uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ @@ -269,8 +268,8 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; - uECC_vli_set(rx, point, num_words); - uECC_vli_set(ry, point + num_words, num_words); + uECC_vli_set(rx, point); + uECC_vli_set(ry, point + num_words); uECC_vli_clear(z); z[0] = 1; @@ -281,8 +280,8 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); point = points[index]; if (point) { - uECC_vli_set(tx, point, num_words); - uECC_vli_set(ty, point + num_words, num_words); + uECC_vli_set(tx, point); + uECC_vli_set(ty, point + num_words); apply_z(tx, ty, z); uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ XYcZ_add(tx, ty, rx, ry, curve); From a752191191c2367c927a3e7af4cfa3c1acfac13c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 14:31:35 +0100 Subject: [PATCH 19/30] Hardcode numwords in vli_cpm_unsafe --- include/tinycrypt/ecc.h | 3 +-- tinycrypt/ecc.c | 21 ++++++++++----------- tinycrypt/ecc_dsa.c | 8 ++++---- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index ba5dffc58..57c156aae 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -331,8 +331,7 @@ cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, * @param num_words IN -- number of words * @return the sign of left - right */ -cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words); +cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right); /* * @brief Computes result = (left - right) % mod. diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 60b565e3c..c223ff509 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -162,12 +162,11 @@ void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src) } cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, - const uECC_word_t *right, - wordcount_t num_words) + const uECC_word_t *right) { wordcount_t i; - for (i = num_words - 1; i >= 0; --i) { + for (i = NUM_ECC_WORDS - 1; i >= 0; --i) { if (left[i] > right[i]) { return 1; } else if (left[i] < right[i]) { @@ -427,7 +426,7 @@ void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words) { uECC_word_t carry = uECC_vli_add(result, left, right); - if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { + if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) { /* result > mod (result = mod + remainder), so subtract mod to get * remainder. */ uECC_vli_sub(result, result, mod, num_words); @@ -551,7 +550,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, uECC_vli_clear(u); u[0] = 1; uECC_vli_clear(v); - while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) { + while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) { if (EVEN(a)) { uECC_vli_rshift1(a, num_words); vli_modInv_update(u, mod, num_words); @@ -561,7 +560,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, } else if (cmpResult > 0) { uECC_vli_sub(a, a, b, num_words); uECC_vli_rshift1(a, num_words); - if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) { + if (uECC_vli_cmp_unsafe(u, v) < 0) { uECC_vli_add(u, u, mod); } uECC_vli_sub(u, u, v, num_words); @@ -569,7 +568,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, } else { uECC_vli_sub(b, b, a, num_words); uECC_vli_rshift1(b, num_words); - if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) { + if (uECC_vli_cmp_unsafe(v, u) < 0) { uECC_vli_add(v, v, mod); } uECC_vli_sub(v, v, u, num_words); @@ -742,7 +741,7 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) while (carry < 0); } else { while (carry || - uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) { + uECC_vli_cmp_unsafe(curve_secp256r1.p, result) != 1) { carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS); } } @@ -1058,8 +1057,8 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) } /* x and y must be smaller than p. */ - if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 || - uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) { + if (uECC_vli_cmp_unsafe(curve->p, point) != 1 || + uECC_vli_cmp_unsafe(curve->p, point + num_words) != 1) { return -2; } @@ -1084,7 +1083,7 @@ int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) public_key + curve->num_bytes, curve->num_bytes); - if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) { + if (memcmp(_public, curve->G, NUM_ECC_WORDS * 2) == 0) { return -4; } diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index e302e04ce..7d4053401 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -102,7 +102,7 @@ static void bits2int(uECC_word_t *native, const uint8_t *bits, } /* Reduce mod curve_n */ - if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) { + if (uECC_vli_cmp_unsafe(curve->n, native) != 1) { uECC_vli_sub(native, native, curve->n, num_n_words); } } @@ -236,8 +236,8 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, } /* r, s must be < n. */ - if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 || - uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) { + if (uECC_vli_cmp_unsafe(curve->n, r) != 1 || + uECC_vli_cmp_unsafe(curve->n, s) != 1) { return 0; } @@ -293,7 +293,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, apply_z(rx, ry, z); /* v = x1 (mod n) */ - if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { + if (uECC_vli_cmp_unsafe(curve->n, rx) != 1) { uECC_vli_sub(rx, rx, curve->n, num_n_words); } From 2eca3d367b283003204fcacb42f74b449b0000a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 14:33:09 +0100 Subject: [PATCH 20/30] Hardcode numwords in vli_equal --- include/tinycrypt/ecc.h | 3 +-- tinycrypt/ecc.c | 7 +++---- tinycrypt/ecc_dsa.c | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 57c156aae..55e450ee8 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -419,8 +419,7 @@ uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, * @param num_words IN -- number of words * @return Returns 0 if left == right, 1 otherwise. */ -uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words); +uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right); /* * @brief Computes (left * right) % mod diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index c223ff509..0b7b41af3 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -176,14 +176,13 @@ cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, return 0; } -uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words) +uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right) { uECC_word_t diff = 0; wordcount_t i; - for (i = num_words - 1; i >= 0; --i) { + for (i = NUM_ECC_WORDS - 1; i >= 0; --i) { diff |= (left[i] ^ right[i]); } return !(diff == 0); @@ -1066,7 +1065,7 @@ int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ /* Make sure that y^2 == x^3 + ax + b */ - if (uECC_vli_equal(tmp1, tmp2, num_words) != 0) + if (uECC_vli_equal(tmp1, tmp2) != 0) return -3; return 0; diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 7d4053401..6a937058e 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -298,7 +298,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, } /* Accept only if v == r. */ - return (int)(uECC_vli_equal(rx, r, num_words) == 0); + return (int)(uECC_vli_equal(rx, r) == 0); } #else typedef int mbedtls_dummy_tinycrypt_def; From 129b42ea2ece4efaab3d77e7de6f0a6236a50af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 14:41:45 +0100 Subject: [PATCH 21/30] Hardcode numwords in vli_sub --- include/tinycrypt/ecc.h | 2 +- tinycrypt/ecc.c | 31 +++++++++++++++++-------------- tinycrypt/ecc_dsa.c | 4 ++-- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 55e450ee8..74c096053 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -410,7 +410,7 @@ void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, * @return borrow */ uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words); + const uECC_word_t *right); /* * @brief Constant-time comparison function(secure way to compare long ints) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 0b7b41af3..47acf2a70 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -196,11 +196,11 @@ uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond) /* Computes result = left - right, returning borrow, in constant time. * Can modify in place. */ uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left, - const uECC_word_t *right, wordcount_t num_words) + const uECC_word_t *right) { uECC_word_t borrow = 0; wordcount_t i; - for (i = 0; i < num_words; ++i) { + for (i = 0; i < NUM_ECC_WORDS; ++i) { uECC_word_t diff = left[i] - right[i] - borrow; uECC_word_t val = (diff > left[i]); borrow = cond_set(val, borrow, (diff != left[i])); @@ -230,8 +230,9 @@ cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, wordcount_t num_words) { uECC_word_t tmp[NUM_ECC_WORDS]; - uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); + uECC_word_t neg = !!uECC_vli_sub(tmp, left, right); uECC_word_t equal = uECC_vli_isZero(tmp); + (void) num_words; return (!equal - 2 * neg); } @@ -425,10 +426,11 @@ void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words) { uECC_word_t carry = uECC_vli_add(result, left, right); + (void) num_words; if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) { /* result > mod (result = mod + remainder), so subtract mod to get * remainder. */ - uECC_vli_sub(result, result, mod, num_words); + uECC_vli_sub(result, result, mod); } } @@ -436,7 +438,8 @@ 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) { - uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words); + uECC_word_t l_borrow = uECC_vli_sub(result, left, right); + (void) 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). */ @@ -557,20 +560,20 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, uECC_vli_rshift1(b, num_words); vli_modInv_update(v, mod, num_words); } else if (cmpResult > 0) { - uECC_vli_sub(a, a, b, num_words); + uECC_vli_sub(a, a, b); uECC_vli_rshift1(a, num_words); if (uECC_vli_cmp_unsafe(u, v) < 0) { uECC_vli_add(u, u, mod); } - uECC_vli_sub(u, u, v, num_words); + uECC_vli_sub(u, u, v); vli_modInv_update(u, mod, num_words); } else { - uECC_vli_sub(b, b, a, num_words); + uECC_vli_sub(b, b, a); uECC_vli_rshift1(b, num_words); if (uECC_vli_cmp_unsafe(v, u) < 0) { uECC_vli_add(v, v, mod); } - uECC_vli_sub(v, v, u, num_words); + uECC_vli_sub(v, v, u); vli_modInv_update(v, mod, num_words); } } @@ -699,7 +702,7 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) tmp[3] = tmp[4] = tmp[5] = 0; tmp[6] = product[8]; tmp[7] = product[10]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + carry -= uECC_vli_sub(result, result, tmp); /* d2 */ tmp[0] = product[12]; @@ -709,7 +712,7 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) tmp[4] = tmp[5] = 0; tmp[6] = product[9]; tmp[7] = product[11]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + carry -= uECC_vli_sub(result, result, tmp); /* d3 */ tmp[0] = product[13]; @@ -720,7 +723,7 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) tmp[5] = product[10]; tmp[6] = 0; tmp[7] = product[12]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + carry -= uECC_vli_sub(result, result, tmp); /* d4 */ tmp[0] = product[14]; @@ -731,7 +734,7 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) tmp[5] = product[11]; tmp[6] = 0; tmp[7] = product[13]; - carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS); + carry -= uECC_vli_sub(result, result, tmp); if (carry < 0) { do { @@ -741,7 +744,7 @@ void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product) } else { while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result) != 1) { - carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS); + carry -= uECC_vli_sub(result, result, curve_secp256r1.p); } } } diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 6a937058e..1685c208a 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -103,7 +103,7 @@ static void bits2int(uECC_word_t *native, const uint8_t *bits, /* Reduce mod curve_n */ if (uECC_vli_cmp_unsafe(curve->n, native) != 1) { - uECC_vli_sub(native, native, curve->n, num_n_words); + uECC_vli_sub(native, native, curve->n); } } @@ -294,7 +294,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, /* v = x1 (mod n) */ if (uECC_vli_cmp_unsafe(curve->n, rx) != 1) { - uECC_vli_sub(rx, rx, curve->n, num_n_words); + uECC_vli_sub(rx, rx, curve->n); } /* Accept only if v == r. */ From 2cb3eea92244ce03eedc617c09e776565f1a77fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 14:43:35 +0100 Subject: [PATCH 22/30] Hardcode numwords in vli_cmp --- include/tinycrypt/ecc.h | 3 +-- tinycrypt/ecc.c | 8 +++----- tinycrypt/ecc_dsa.c | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 74c096053..c4dad0bb6 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -320,8 +320,7 @@ uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve); * @param num_words IN -- number of words * @return the sign of left - right */ -cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words); +cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right); /* * @brief computes sign of left - right, not in constant time. diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 47acf2a70..10d3972b6 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -226,13 +226,11 @@ static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left, return carry; } -cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, - wordcount_t num_words) +cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right) { uECC_word_t tmp[NUM_ECC_WORDS]; uECC_word_t neg = !!uECC_vli_sub(tmp, left, right); uECC_word_t equal = uECC_vli_isZero(tmp); - (void) num_words; return (!equal - 2 * neg); } @@ -1039,7 +1037,7 @@ int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top, random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); if (!uECC_vli_isZero(random) && - uECC_vli_cmp(top, random, num_words) == 1) { + uECC_vli_cmp(top, random) == 1) { return 1; } } @@ -1109,7 +1107,7 @@ int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, return 0; } - if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) { + if (uECC_vli_cmp(curve->n, _private) != 1) { return 0; } diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 1685c208a..8cc09c76f 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -121,7 +121,7 @@ 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, num_n_words) != 1) { + uECC_vli_cmp(curve->n, k) != 1) { return 0; } From 5e3baf23036d7cec078223ea4f39550f8a545fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 14:46:10 +0100 Subject: [PATCH 23/30] Hardcode numwords in vli_rshift1 --- tinycrypt/ecc.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 10d3972b6..3ec4e2f02 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -235,12 +235,12 @@ cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right) } /* Computes vli = vli >> 1. */ -static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) +static void uECC_vli_rshift1(uECC_word_t *vli) { uECC_word_t *end = vli; uECC_word_t carry = 0; - vli += num_words; + vli += NUM_ECC_WORDS; while (vli-- > end) { uECC_word_t temp = *vli; *vli = (temp >> 1) | carry; @@ -483,10 +483,10 @@ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, } /* Swap the index if there was no borrow */ index = !(index ^ borrow); - uECC_vli_rshift1(mod_multiple, num_words); + uECC_vli_rshift1(mod_multiple); mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); - uECC_vli_rshift1(mod_multiple + num_words, num_words); + uECC_vli_rshift1(mod_multiple + num_words); } uECC_vli_set(result, v[index]); } @@ -527,7 +527,7 @@ static void vli_modInv_update(uECC_word_t *uv, if (!EVEN(uv)) { carry = uECC_vli_add(uv, uv, mod); } - uECC_vli_rshift1(uv, num_words); + uECC_vli_rshift1(uv); if (carry) { uv[num_words - 1] |= HIGH_BIT_SET; } @@ -552,14 +552,14 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, uECC_vli_clear(v); while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) { if (EVEN(a)) { - uECC_vli_rshift1(a, num_words); + uECC_vli_rshift1(a); vli_modInv_update(u, mod, num_words); } else if (EVEN(b)) { - uECC_vli_rshift1(b, num_words); + uECC_vli_rshift1(b); vli_modInv_update(v, mod, num_words); } else if (cmpResult > 0) { uECC_vli_sub(a, a, b); - uECC_vli_rshift1(a, num_words); + uECC_vli_rshift1(a); if (uECC_vli_cmp_unsafe(u, v) < 0) { uECC_vli_add(u, u, mod); } @@ -567,7 +567,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, vli_modInv_update(u, mod, num_words); } else { uECC_vli_sub(b, b, a); - uECC_vli_rshift1(b, num_words); + uECC_vli_rshift1(b); if (uECC_vli_cmp_unsafe(v, u) < 0) { uECC_vli_add(v, v, mod); } @@ -607,10 +607,10 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ if (uECC_vli_testBit(X1, 0)) { uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p); - uECC_vli_rshift1(X1, num_words); + uECC_vli_rshift1(X1); X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); } else { - uECC_vli_rshift1(X1, num_words); + uECC_vli_rshift1(X1); } /* t1 = 3/2*(x1^2 - z1^4) = B */ From 0779be7f317dab58754fb5fd764557a308c737af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 14:48:22 +0100 Subject: [PATCH 24/30] Hardcode numwords in vli_modAdd --- include/tinycrypt/ecc.h | 3 +-- tinycrypt/ecc.c | 18 ++++++++---------- tinycrypt/ecc_dsa.c | 2 +- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index c4dad0bb6..68952940d 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -463,8 +463,7 @@ void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src); * @param num_words IN -- number of words */ 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); + const uECC_word_t *right, const uECC_word_t *mod); /* * @brief Counts the number of bits required to represent vli. diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 3ec4e2f02..e4e2b4509 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -420,11 +420,9 @@ static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left, } 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) + const uECC_word_t *right, const uECC_word_t *mod) { uECC_word_t carry = uECC_vli_add(result, left, right); - (void) num_words; if (carry || uECC_vli_cmp_unsafe(mod, result) != 1) { /* result > mod (result = mod + remainder), so subtract mod to get * remainder. */ @@ -598,13 +596,13 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, uECC_vli_modMult_fast(Y1, Y1, Z1); /* t2 = y1*z1 = z3 */ uECC_vli_modMult_fast(Z1, Z1, Z1); /* t3 = z1^2 */ - uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */ - uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */ + uECC_vli_modAdd(X1, X1, Z1, curve->p); /* t1 = x1 + z1^2 */ + uECC_vli_modAdd(Z1, Z1, Z1, curve->p); /* t3 = 2*z1^2 */ uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */ uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */ - uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */ - uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ + uECC_vli_modAdd(Z1, X1, X1, curve->p); /* t3 = 2*(x1^2 - z1^4) */ + uECC_vli_modAdd(X1, X1, Z1, curve->p); /* t1 = 3*(x1^2 - z1^4) */ if (uECC_vli_testBit(X1, 0)) { uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p); uECC_vli_rshift1(X1); @@ -638,7 +636,7 @@ void x_side_default(uECC_word_t *result, uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */ /* r = x^3 - 3x + b: */ - uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); + uECC_vli_modAdd(result, result, curve->b, curve->p); } uECC_Curve uECC_secp256r1(void) @@ -839,12 +837,12 @@ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ - uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ + uECC_vli_modAdd(t5, Y2, Y1, curve->p); /* t5 = y2 + y1 */ uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */ - uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */ + uECC_vli_modAdd(t6, X1, X2, curve->p); /* t6 = B + C */ uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */ uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 8cc09c76f..e6ce7fc5a 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -156,7 +156,7 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */ bits2int(tmp, message_hash, hash_size, curve); - uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */ + uECC_vli_modAdd(s, tmp, s, curve->n); /* 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) > (bitcount_t)curve->num_bytes * 8) { return 0; From 1b0875d8635c5ae674c0b6a646026823d6eed07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 14:50:54 +0100 Subject: [PATCH 25/30] Hardcode numwords in vli_modSub --- include/tinycrypt/ecc.h | 3 +-- tinycrypt/ecc.c | 53 +++++++++++++++++++---------------------- tinycrypt/ecc_dsa.c | 4 ++-- 3 files changed, 27 insertions(+), 33 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 68952940d..3d60267cc 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -343,8 +343,7 @@ cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *righ * @param num_words IN -- number of words */ 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); + const uECC_word_t *right, const uECC_word_t *mod); /* * @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index e4e2b4509..e7558e9a0 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -431,11 +431,9 @@ void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left, } 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) + const uECC_word_t *right, const uECC_word_t *mod) { uECC_word_t l_borrow = uECC_vli_sub(result, left, right); - (void) 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). */ @@ -598,7 +596,7 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, uECC_vli_modAdd(X1, X1, Z1, curve->p); /* t1 = x1 + z1^2 */ uECC_vli_modAdd(Z1, Z1, Z1, curve->p); /* t3 = 2*z1^2 */ - uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */ + uECC_vli_modSub(Z1, X1, Z1, curve->p); /* t3 = x1 - z1^2 */ uECC_vli_modMult_fast(X1, X1, Z1); /* t1 = x1^2 - z1^4 */ uECC_vli_modAdd(Z1, X1, X1, curve->p); /* t3 = 2*(x1^2 - z1^4) */ @@ -613,12 +611,12 @@ void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1, /* t1 = 3/2*(x1^2 - z1^4) = B */ uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */ - uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */ - uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */ - uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */ + uECC_vli_modSub(Z1, Z1, t5, curve->p); /* t3 = B^2 - A */ + uECC_vli_modSub(Z1, Z1, t5, curve->p); /* t3 = B^2 - 2A = x3 */ + uECC_vli_modSub(t5, t5, Z1, curve->p); /* t5 = A - x3 */ uECC_vli_modMult_fast(X1, X1, t5); /* t1 = B * (A - x3) */ /* t4 = B * (A - x3) - y1^4 = y3: */ - uECC_vli_modSub(t4, X1, t4, curve->p, num_words); + uECC_vli_modSub(t4, X1, t4, curve->p); uECC_vli_set(X1, Z1); uECC_vli_set(Z1, Y1); @@ -630,10 +628,9 @@ void x_side_default(uECC_word_t *result, uECC_Curve curve) { uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */ - wordcount_t num_words = curve->num_words; uECC_vli_modMult_fast(result, x, x); /* r = x^2 */ - uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ + uECC_vli_modSub(result, result, _3, curve->p); /* r = x^2 - 3 */ uECC_vli_modMult_fast(result, result, x); /* r = x^3 - 3x */ /* r = x^3 - 3x + b: */ uECC_vli_modAdd(result, result, curve->b, curve->p); @@ -790,22 +787,21 @@ static void XYcZ_add_rnd(uECC_word_t * X1, uECC_word_t * Y1, /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ uECC_word_t t5[NUM_ECC_WORDS]; const uECC_Curve curve = &curve_secp256r1; - const wordcount_t num_words = NUM_ECC_WORDS; - uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSub(t5, X2, X1, curve->p); /* t5 = x2 - x1 */ uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p); /* t4 = y2 - y1 */ uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */ - uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ - uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ - uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ + uECC_vli_modSub(t5, t5, X1, curve->p); /* t5 = D - B */ + uECC_vli_modSub(t5, t5, X2, curve->p); /* t5 = D - B - C = x3 */ + uECC_vli_modSub(X2, X2, X1, curve->p); /* t3 = C - B */ uECC_vli_modMult_rnd(Y1, Y1, X2, s); /* t2 = y1*(C - B) */ - uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ + uECC_vli_modSub(X2, X1, t5, curve->p); /* t3 = B - x3 */ uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p); /* t4 = y3 */ uECC_vli_set(X2, t5); } @@ -831,32 +827,31 @@ static void XYcZ_addC_rnd(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t t6[NUM_ECC_WORDS]; uECC_word_t t7[NUM_ECC_WORDS]; const uECC_Curve curve = &curve_secp256r1; - const wordcount_t num_words = NUM_ECC_WORDS; - uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSub(t5, X2, X1, curve->p); /* t5 = x2 - x1 */ uECC_vli_modMult_rnd(t5, t5, t5, s); /* t5 = (x2 - x1)^2 = A */ uECC_vli_modMult_rnd(X1, X1, t5, s); /* t1 = x1*A = B */ uECC_vli_modMult_rnd(X2, X2, t5, s); /* t3 = x2*A = C */ uECC_vli_modAdd(t5, Y2, Y1, curve->p); /* t5 = y2 + y1 */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p); /* t4 = y2 - y1 */ - uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ + uECC_vli_modSub(t6, X2, X1, curve->p); /* t6 = C - B */ uECC_vli_modMult_rnd(Y1, Y1, t6, s); /* t2 = y1 * (C - B) = E */ uECC_vli_modAdd(t6, X1, X2, curve->p); /* t6 = B + C */ uECC_vli_modMult_rnd(X2, Y2, Y2, s); /* t3 = (y2 - y1)^2 = D */ - uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ + uECC_vli_modSub(X2, X2, t6, curve->p); /* t3 = D - (B + C) = x3 */ - uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */ + uECC_vli_modSub(t7, X1, X2, curve->p); /* t7 = B - x3 */ uECC_vli_modMult_rnd(Y2, Y2, t7, s); /* t4 = (y2 - y1)*(B - x3) */ /* t4 = (y2 - y1)*(B - x3) - E = y3: */ - uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); + uECC_vli_modSub(Y2, Y2, Y1, curve->p); uECC_vli_modMult_rnd(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */ - uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */ - uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */ + uECC_vli_modSub(t7, t7, t6, curve->p); /* t7 = F - (B + C) = x3' */ + uECC_vli_modSub(t6, t7, X1, curve->p); /* t6 = x3' - B */ uECC_vli_modMult_rnd(t6, t6, t5, s); /* t6 = (y2+y1)*(x3' - B) */ /* t2 = (y2+y1)*(x3' - B) - E = y3': */ - uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); + uECC_vli_modSub(Y1, t6, Y1, curve->p); uECC_vli_set(X1, t7); } @@ -894,7 +889,7 @@ static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, XYcZ_addC_rnd(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], ws); /* Find final 1/Z value. */ - uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ + uECC_vli_modSub(z, Rx[1], Rx[0], curve->p); /* X1 - X0 */ uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */ uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */ uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/ diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index e6ce7fc5a..77e3efee7 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -253,7 +253,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, uECC_vli_set(sum + num_words, _public + num_words); uECC_vli_set(tx, curve->G); uECC_vli_set(ty, curve->G + num_words); - uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ + uECC_vli_modSub(z, sum, tx, curve->p); /* z = x2 - x1 */ XYcZ_add(tx, ty, sum, sum + num_words, curve); uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ apply_z(sum, sum + num_words, z); @@ -283,7 +283,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, uECC_vli_set(tx, point); uECC_vli_set(ty, point + num_words); apply_z(tx, ty, z); - uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ + uECC_vli_modSub(tz, rx, tx, curve->p); /* Z = x2 - x1 */ XYcZ_add(tx, ty, rx, ry, curve); uECC_vli_modMult_fast(z, z, tz); } From 10349e49128d8b25bf6e8315f345aba94db1b943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 14:57:53 +0100 Subject: [PATCH 26/30] Hardcode numwords in vli_mmod --- include/tinycrypt/ecc.h | 2 +- tinycrypt/ecc.c | 6 ++++-- tinycrypt/ecc_dh.c | 2 +- tinycrypt/ecc_dsa.c | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 3d60267cc..e016c696b 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -386,7 +386,7 @@ uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit); * @warning Currently only designed to work for curve_p or curve_n. */ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, - const uECC_word_t *mod, wordcount_t num_words); + const uECC_word_t *mod); /* * @brief Computes modular product (using curve->mmod_fast) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index e7558e9a0..508831cb2 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -444,12 +444,13 @@ void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left, /* Computes result = product % mod, where product is 2N words long. */ /* Currently only designed to work for curve_p or curve_n. */ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, - const uECC_word_t *mod, wordcount_t num_words) + const uECC_word_t *mod) { uECC_word_t mod_multiple[2 * NUM_ECC_WORDS]; uECC_word_t tmp[2 * NUM_ECC_WORDS]; uECC_word_t *v[2] = {tmp, product}; uECC_word_t index; + const wordcount_t num_words = NUM_ECC_WORDS; /* Shift mod so its highest set bit is at the maximum position. */ bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - @@ -493,7 +494,8 @@ void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, { uECC_word_t product[2 * NUM_ECC_WORDS]; uECC_vli_mult_rnd(product, left, right, NULL); - uECC_vli_mmod(result, product, mod, num_words); + uECC_vli_mmod(result, product, mod); + (void) num_words; } static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left, diff --git a/tinycrypt/ecc_dh.c b/tinycrypt/ecc_dh.c index 52208ad9d..71c51f5a8 100644 --- a/tinycrypt/ecc_dh.c +++ b/tinycrypt/ecc_dh.c @@ -123,7 +123,7 @@ int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve) } /* computing modular reduction of _random (see FIPS 186.4 B.4.1): */ - uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits)); + uECC_vli_mmod(_private, _random, curve->n); /* Computing public-key from private: */ if (EccPoint_compute_public_key(_public, _private, curve)) { diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 77e3efee7..ca07eb191 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -182,7 +182,7 @@ int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash, } // computing k as modular reduction of _random (see FIPS 186.4 B.5.1): - uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits)); + uECC_vli_mmod(k, _random, curve->n); if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature, curve)) { From 3e20adf53310a607b960a61dbc0a69a64e530bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 15:00:43 +0100 Subject: [PATCH 27/30] Hardcode numwords in vli_modMult --- include/tinycrypt/ecc.h | 3 +-- tinycrypt/ecc.c | 4 +--- tinycrypt/ecc_dsa.c | 12 ++++++------ 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index e016c696b..d6f2c9dfc 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -428,8 +428,7 @@ uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right); * @param num_words IN -- number of words */ 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); + const uECC_word_t *right, const uECC_word_t *mod); /* * @brief Computes (1 / input) % mod diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 508831cb2..81464e1e0 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -489,13 +489,11 @@ void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product, } 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) + const uECC_word_t *right, const uECC_word_t *mod) { uECC_word_t product[2 * NUM_ECC_WORDS]; uECC_vli_mult_rnd(product, left, right, NULL); uECC_vli_mmod(result, product, mod); - (void) num_words; } static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left, diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index ca07eb191..09b2b848e 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -142,9 +142,9 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, /* Prevent side channel analysis of uECC_vli_modInv() to determine bits of k / the private key by premultiplying by a random number */ - uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */ + uECC_vli_modMult(k, k, tmp, curve->n); /* k' = rand * k */ uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */ - uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */ + uECC_vli_modMult(k, k, tmp, curve->n); /* k = 1 / k */ uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */ @@ -153,11 +153,11 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, s[num_n_words - 1] = 0; uECC_vli_set(s, p); - uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */ + uECC_vli_modMult(s, tmp, s, curve->n); /* s = r*d */ bits2int(tmp, message_hash, hash_size, curve); uECC_vli_modAdd(s, tmp, s, curve->n); /* s = e + r*d */ - uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */ + uECC_vli_modMult(s, s, k, curve->n); /* s = (e + r*d) / k */ if (uECC_vli_numBits(s) > (bitcount_t)curve->num_bytes * 8) { return 0; } @@ -245,8 +245,8 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ u1[num_n_words - 1] = 0; bits2int(u1, message_hash, hash_size, curve); - uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */ - uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */ + uECC_vli_modMult(u1, u1, z, curve->n); /* u1 = e/s */ + uECC_vli_modMult(u2, r, z, curve->n); /* u2 = r/s */ /* Calculate sum = G + Q. */ uECC_vli_set(sum, _public); From 913534837a2015e8dba9733866c32051e4572205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 15:04:20 +0100 Subject: [PATCH 28/30] Hardcode numwords in vli_modInv --- include/tinycrypt/ecc.h | 2 +- tinycrypt/ecc.c | 17 ++++++++--------- tinycrypt/ecc_dsa.c | 8 ++++---- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index d6f2c9dfc..2da74b3c0 100644 --- a/include/tinycrypt/ecc.h +++ b/include/tinycrypt/ecc.h @@ -440,7 +440,7 @@ void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left, * @param num_words -- number of words */ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, - const uECC_word_t *mod, wordcount_t num_words); + const uECC_word_t *mod); /* * @brief Sets dest = src. diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 81464e1e0..674037519 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -514,8 +514,7 @@ void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left, #define EVEN(vli) (!(vli[0] & 1)) static void vli_modInv_update(uECC_word_t *uv, - const uECC_word_t *mod, - wordcount_t num_words) + const uECC_word_t *mod) { uECC_word_t carry = 0; @@ -525,12 +524,12 @@ static void vli_modInv_update(uECC_word_t *uv, } uECC_vli_rshift1(uv); if (carry) { - uv[num_words - 1] |= HIGH_BIT_SET; + uv[NUM_ECC_WORDS - 1] |= HIGH_BIT_SET; } } void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, - const uECC_word_t *mod, wordcount_t num_words) + const uECC_word_t *mod) { uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS]; uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS]; @@ -549,10 +548,10 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, while ((cmpResult = uECC_vli_cmp_unsafe(a, b)) != 0) { if (EVEN(a)) { uECC_vli_rshift1(a); - vli_modInv_update(u, mod, num_words); + vli_modInv_update(u, mod); } else if (EVEN(b)) { uECC_vli_rshift1(b); - vli_modInv_update(v, mod, num_words); + vli_modInv_update(v, mod); } else if (cmpResult > 0) { uECC_vli_sub(a, a, b); uECC_vli_rshift1(a); @@ -560,7 +559,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, uECC_vli_add(u, u, mod); } uECC_vli_sub(u, u, v); - vli_modInv_update(u, mod, num_words); + vli_modInv_update(u, mod); } else { uECC_vli_sub(b, b, a); uECC_vli_rshift1(b); @@ -568,7 +567,7 @@ void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input, uECC_vli_add(v, v, mod); } uECC_vli_sub(v, v, u); - vli_modInv_update(v, mod, num_words); + vli_modInv_update(v, mod); } } uECC_vli_set(result, u); @@ -892,7 +891,7 @@ static void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point, uECC_vli_modSub(z, Rx[1], Rx[0], curve->p); /* X1 - X0 */ uECC_vli_modMult_fast(z, z, Ry[1 - nb]); /* Yb * (X1 - X0) */ uECC_vli_modMult_fast(z, z, point); /* xP * Yb * (X1 - X0) */ - uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/ + uECC_vli_modInv(z, z, curve->p); /* 1 / (xP * Yb * (X1 - X0))*/ /* yP / (xP * Yb * (X1 - X0)) */ uECC_vli_modMult_fast(z, z, point + num_words); /* Xb * yP / (xP * Yb * (X1 - X0)) */ diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 09b2b848e..b3a08cf1f 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -143,7 +143,7 @@ int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash, /* Prevent side channel analysis of uECC_vli_modInv() to determine bits of k / the private key by premultiplying by a random number */ uECC_vli_modMult(k, k, tmp, curve->n); /* k' = rand * k */ - uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */ + uECC_vli_modInv(k, k, curve->n); /* k = 1 / k' */ uECC_vli_modMult(k, k, tmp, curve->n); /* k = 1 / k */ uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */ @@ -242,7 +242,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, } /* Calculate u1 and u2. */ - uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ + uECC_vli_modInv(z, s, curve->n); /* z = 1/s */ u1[num_n_words - 1] = 0; bits2int(u1, message_hash, hash_size, curve); uECC_vli_modMult(u1, u1, z, curve->n); /* u1 = e/s */ @@ -255,7 +255,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, uECC_vli_set(ty, curve->G + num_words); uECC_vli_modSub(z, sum, tx, curve->p); /* z = x2 - x1 */ XYcZ_add(tx, ty, sum, sum + num_words, curve); - uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ + uECC_vli_modInv(z, z, curve->p); /* z = 1/z */ apply_z(sum, sum + num_words, z); /* Use Shamir's trick to calculate u1*G + u2*Q */ @@ -289,7 +289,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, } } - uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */ + uECC_vli_modInv(z, z, curve->p); /* Z = 1/Z */ apply_z(rx, ry, z); /* v = x1 (mod n) */ From ad166d8db783a4731948ff60ad09ca427fcc3f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 4 Nov 2019 15:37:42 +0100 Subject: [PATCH 29/30] Also check curve in verify() This is the only function that performs computations without calling EccPoint_mult_safer() and that didn't have that guard yet. --- tinycrypt/ecc_dsa.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index b3a08cf1f..04b1bfabd 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -220,6 +220,9 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, wordcount_t num_words = curve->num_words; wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + if (curve != uECC_secp256r1()) + return 0; + rx[num_n_words - 1] = 0; r[num_n_words - 1] = 0; s[num_n_words - 1] = 0; From c881486bb2597aa29a22225beeeec1d65881ff82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 5 Nov 2019 10:32:37 +0100 Subject: [PATCH 30/30] Fix off-by-one number of extra operations This caused a performance issue. --- tinycrypt/ecc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 674037519..d01c67617 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -342,7 +342,7 @@ static void uECC_vli_mult_rnd(uECC_word_t *result, const uECC_word_t *left, delays >>= 2; /* k = 0 -> i in [1, 0] -> 0 extra muladd; * k = 3 -> i in [1, 3] -> 3 extra muladd */ - for (i = 0; i <= k; ++i) { + for (i = 1; i <= k; ++i) { muladd(left[i], right[k - i], &rr0, &rr1, &r2); } r = rr0;