diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h index 9c53f3e7e..2da74b3c0 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; @@ -282,32 +283,19 @@ 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. + * 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 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); +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 @@ -315,7 +303,7 @@ void EccPoint_mult(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 @@ -332,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. @@ -343,8 +330,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. @@ -357,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 @@ -380,8 +365,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. @@ -402,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) @@ -412,7 +396,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. @@ -424,7 +408,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) @@ -433,8 +417,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 @@ -445,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 @@ -458,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. @@ -466,8 +448,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. @@ -480,8 +461,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. @@ -489,15 +469,14 @@ 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 * @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 cef1469ee..d01c67617 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 @@ -95,19 +96,19 @@ 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; } } -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); @@ -120,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; } @@ -153,23 +152,21 @@ 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]; } } 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]) { @@ -179,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); @@ -200,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])); @@ -217,11 +213,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])); @@ -230,22 +226,21 @@ 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, num_words); - uECC_word_t equal = uECC_vli_isZero(tmp, num_words); + uECC_word_t neg = !!uECC_vli_sub(tmp, left, right); + uECC_word_t equal = uECC_vli_isZero(tmp); return (!equal - 2 * neg); } /* 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; @@ -253,6 +248,16 @@ static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) } } +/* 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 + * [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 +271,84 @@ 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 initialized by randomizing delays and setting i = 0. + * Each call to uECC_vli_mult_rnd() uses one byte of delays and increments i. + * + * 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(). + * + * 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 i; + uint8_t delays[14]; +} ecc_wait_state_t; + +/* + * Reset wait_state so that it's ready to be used. + */ +void ecc_wait_state_reset(ecc_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 + * 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, ecc_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 = 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; + 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 = 1; 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 +363,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,57 +399,73 @@ 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; } 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, num_words); - if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { + uECC_word_t carry = uECC_vli_add(result, left, right); + 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); } } 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, num_words); + uECC_word_t l_borrow = uECC_vli_sub(result, left, right); 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); } } /* 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) - - 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; - 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; 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) { @@ -364,101 +480,97 @@ 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], num_words); + uECC_vli_set(result, v[index]); } 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(product, left, right, num_words); - uECC_vli_mmod(result, product, mod, num_words); + uECC_vli_mult_rnd(product, left, right, NULL); + uECC_vli_mmod(result, product, mod); +} + +static void uECC_vli_modMult_rnd(uECC_word_t *result, const uECC_word_t *left, + 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); + + 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) + const uECC_word_t *right) { - uECC_word_t product[2 * NUM_ECC_WORDS]; - uECC_vli_mult(product, left, right, curve->num_words); - - curve->mmod_fast(result, product); + uECC_vli_modMult_rnd(result, left, right, NULL); } -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, - const uECC_word_t *mod, - wordcount_t num_words) + const uECC_word_t *mod) { 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); + 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]; cmpresult_t cmpResult; - if (uECC_vli_isZero(input, num_words)) { - uECC_vli_clear(result, num_words); + if (uECC_vli_isZero(input)) { + 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_set(a, input); + uECC_vli_set(b, mod); + uECC_vli_clear(u); u[0] = 1; - uECC_vli_clear(v, num_words); - while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) { + uECC_vli_clear(v); + 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); + uECC_vli_rshift1(a); + vli_modInv_update(u, mod); } else if (EVEN(b)) { - uECC_vli_rshift1(b, num_words); - vli_modInv_update(v, mod, num_words); + uECC_vli_rshift1(b); + vli_modInv_update(v, mod); } 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) { - uECC_vli_add(u, u, mod, num_words); + uECC_vli_sub(a, a, b); + uECC_vli_rshift1(a); + if (uECC_vli_cmp_unsafe(u, v) < 0) { + uECC_vli_add(u, u, mod); } - uECC_vli_sub(u, u, v, num_words); - vli_modInv_update(u, mod, num_words); + uECC_vli_sub(u, u, v); + vli_modInv_update(u, mod); } 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) { - uECC_vli_add(v, v, mod, num_words); + uECC_vli_sub(b, b, a); + uECC_vli_rshift1(b); + if (uECC_vli_cmp_unsafe(v, u) < 0) { + uECC_vli_add(v, v, mod); } - uECC_vli_sub(v, v, u, num_words); - vli_modInv_update(v, mod, num_words); + uECC_vli_sub(v, v, u); + vli_modInv_update(v, mod); } } - uECC_vli_set(result, u, num_words); + uECC_vli_set(result, u); } /* ------ Point operations ------ */ @@ -471,43 +583,43 @@ 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; } - uECC_vli_modSquare_fast(t4, 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(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */ - uECC_vli_modSquare_fast(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_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); /* 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, num_words); - uECC_vli_rshift1(X1, num_words); + uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p); + 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 */ - uECC_vli_modSquare_fast(Z1, 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 */ - uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */ + uECC_vli_modMult_fast(Z1, X1, X1); /* t3 = B^2 */ + 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, 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, @@ -515,13 +627,12 @@ 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_modSquare_fast(result, 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 */ + uECC_vli_modMult_fast(result, x, x); /* r = x^2 */ + 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, num_words); + uECC_vli_modAdd(result, result, curve->b, curve->p); } uECC_Curve uECC_secp256r1(void) @@ -535,7 +646,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; @@ -544,8 +655,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]; @@ -553,8 +664,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]; @@ -563,7 +674,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]; @@ -574,7 +685,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]; @@ -583,7 +694,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]; @@ -593,7 +704,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]; @@ -604,7 +715,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]; @@ -615,35 +726,35 @@ 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 { - 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 { while (carry || - uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) { - carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS); + uECC_vli_cmp_unsafe(curve_secp256r1.p, result) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp256r1.p); } } } 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, - 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_modSquare_fast(t1, 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' */ @@ -653,94 +764,100 @@ 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, num_words); + 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); + 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, + uECC_word_t * X2, uECC_word_t * Y2, + ecc_wait_state_t *s) +{ + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[NUM_ECC_WORDS]; + const uECC_Curve curve = &curve_secp256r1; + + 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); /* t4 = y2 - y1 */ + uECC_vli_modMult_rnd(t5, Y2, Y2, s); /* t5 = (y2 - y1)^2 = D */ + + 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); /* t3 = B - x3 */ + uECC_vli_modMult_rnd(Y2, Y2, X2, s); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p); /* t4 = y3 */ + + uECC_vli_set(X2, t5); } void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2, uECC_word_t * Y2, uECC_Curve curve) { - /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ - uECC_word_t t5[NUM_ECC_WORDS]; - wordcount_t num_words = curve->num_words; - - 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_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_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_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_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ - - uECC_vli_set(X2, t5, num_words); + (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, + ecc_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; - 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_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(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); /* 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_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_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ + 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); /* 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_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_modSquare_fast(t7, t5, curve); /* 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(t7, t5, t5, s); /* t7 = (y2 + y1)^2 = F */ + 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, num_words); + uECC_vli_set(X1, t7); } -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) + const uECC_word_t * initial_Z) { /* R0 and R1 */ uECC_word_t Rx[2][NUM_ECC_WORDS]; @@ -748,57 +865,103 @@ 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 = 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; - 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); for (i = num_bits - 2; i > 0; --i) { + ecc_wait_state_reset(ws); 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); } + ecc_wait_state_reset(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 */ - 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_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (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); /* 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(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); - apply_z(Rx[0], Ry[0], z, curve); + 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]); } -uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0, - uECC_word_t *k1, uECC_Curve curve) +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 = BITS_TO_WORDS(curve->num_n_bits); + wordcount_t num_n_words = NUM_ECC_WORDS; + bitcount_t num_n_bits = NUM_ECC_BITS; + const uECC_Curve curve = uECC_secp256r1(); - bitcount_t num_n_bits = curve->num_n_bits; - - 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; } +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 = NUM_ECC_WORDS; + 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); + + /* 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); + 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) @@ -809,11 +972,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; @@ -837,7 +1003,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] |= @@ -850,7 +1016,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; @@ -862,8 +1028,8 @@ 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) && - uECC_vli_cmp(top, random, num_words) == 1) { + if (!uECC_vli_isZero(random) && + uECC_vli_cmp(top, random) == 1) { return 1; } } @@ -883,16 +1049,16 @@ 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; } - uECC_vli_modSquare_fast(tmp1, 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 */ - if (uECC_vli_equal(tmp1, tmp2, num_words) != 0) + if (uECC_vli_equal(tmp1, tmp2) != 0) return -3; return 0; @@ -909,7 +1075,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; } @@ -929,11 +1095,11 @@ 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; } - 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_dh.c b/tinycrypt/ecc_dh.c index 54b9a8ab4..71c51f5a8 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) { @@ -129,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)) { @@ -160,15 +154,16 @@ 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; + /* 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, @@ -180,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 a3893d37f..04b1bfabd 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; @@ -102,8 +102,8 @@ 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) { - uECC_vli_sub(native, native, curve->n, num_n_words); + if (uECC_vli_cmp_unsafe(curve->n, native) != 1) { + uECC_vli_sub(native, native, curve->n); } } @@ -114,29 +114,26 @@ 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 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) || - uECC_vli_cmp(curve->n, k, num_n_words) != 1) { + if (uECC_vli_isZero(k) || + uECC_vli_cmp(curve->n, k) != 1) { return 0; } - carry = regularize_k(k, tmp, s, curve); - EccPoint_mult(p, curve->G, k2[!carry], 0, 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)) { return 0; } /* 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)) { @@ -145,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_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' = rand * 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 */ @@ -155,13 +152,13 @@ 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_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */ + uECC_vli_set(s, p); + 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, 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) { + uECC_vli_modAdd(s, tmp, s, curve->n); /* s = e + r*d */ + uECC_vli_modMult(s, s, k, curve->n); /* s = (e + r*d) / k */ + if (uECC_vli_numBits(s) > (bitcount_t)curve->num_bytes * 8) { return 0; } @@ -185,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)) { @@ -223,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; @@ -234,46 +234,46 @@ 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; } /* 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; } /* 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, 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, 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_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ + 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); /* 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); + 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 */ points[0] = 0; 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)]; - uECC_vli_set(rx, point, num_words); - uECC_vli_set(ry, point + num_words, num_words); - uECC_vli_clear(z, num_words); + uECC_vli_set(rx, point); + uECC_vli_set(ry, point + num_words); + uECC_vli_clear(z); z[0] = 1; for (i = num_bits - 2; i >= 0; --i) { @@ -283,25 +283,25 @@ 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); - apply_z(tx, ty, z, curve); - uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ + 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); /* 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); + uECC_vli_modInv(z, z, curve->p); /* Z = 1/Z */ + apply_z(rx, ry, z); /* v = x1 (mod n) */ - if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { - uECC_vli_sub(rx, rx, curve->n, num_n_words); + if (uECC_vli_cmp_unsafe(curve->n, rx) != 1) { + uECC_vli_sub(rx, rx, curve->n); } /* 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;