diff options
author | Flavio Santes <flavio.santes@intel.com> | 2017-03-10 20:08:21 -0600 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2017-04-19 18:44:06 -0400 |
commit | c6588695ee74374439aeefede137dd40b33d43e8 (patch) | |
tree | 29a89f479d243ab75143855da666ec7ce4ec77c9 | |
parent | 2421e11f25a297f3bf86a72d9cdf14a6927bdeaf (diff) |
ext/lib/crypto: Update TinyCrypt to version 0.2.6
Update TinyCrypt to version 0.2.6.
Origin: https://github.com/01org/tinycrypt/releases/tag/v0.2.6
Jira: ZEP-749
Change-Id: I62be0c134236d4a5dcae14bee86692c0fd6dc381
Signed-off-by: Flavio Santes <flavio.santes@intel.com>
-rw-r--r-- | ext/lib/crypto/tinycrypt/include/tinycrypt/constants.h | 4 | ||||
-rw-r--r-- | ext/lib/crypto/tinycrypt/include/tinycrypt/ecc.h | 41 | ||||
-rw-r--r-- | ext/lib/crypto/tinycrypt/include/tinycrypt/ecc_dh.h | 20 | ||||
-rw-r--r-- | ext/lib/crypto/tinycrypt/include/tinycrypt/hmac.h | 1 | ||||
-rw-r--r-- | ext/lib/crypto/tinycrypt/source/ecc.c | 27 | ||||
-rw-r--r-- | ext/lib/crypto/tinycrypt/source/ecc_dh.c | 19 | ||||
-rw-r--r-- | ext/lib/crypto/tinycrypt/source/ecc_dsa.c | 14 | ||||
-rw-r--r-- | ext/lib/crypto/tinycrypt/source/utils.c | 7 |
8 files changed, 96 insertions, 37 deletions
diff --git a/ext/lib/crypto/tinycrypt/include/tinycrypt/constants.h b/ext/lib/crypto/tinycrypt/include/tinycrypt/constants.h index 25f03616c..1a7c9df36 100644 --- a/ext/lib/crypto/tinycrypt/include/tinycrypt/constants.h +++ b/ext/lib/crypto/tinycrypt/include/tinycrypt/constants.h @@ -47,10 +47,6 @@ extern "C" { #define NULL ((void *)0) #endif -#ifndef bool -enum {false, true} bool; -#endif - #define TC_CRYPTO_SUCCESS 1 #define TC_CRYPTO_FAIL 0 diff --git a/ext/lib/crypto/tinycrypt/include/tinycrypt/ecc.h b/ext/lib/crypto/tinycrypt/include/tinycrypt/ecc.h index 71194758c..74324f91b 100644 --- a/ext/lib/crypto/tinycrypt/include/tinycrypt/ecc.h +++ b/ext/lib/crypto/tinycrypt/include/tinycrypt/ecc.h @@ -79,10 +79,12 @@ extern "C" { #endif +/* Word size (4 bytes considering 32-bits architectures) */ +#define WORD_SIZE 4 /* Number of words of 32 bits to represent an element of the the curve p-256: */ #define NUM_ECC_DIGITS 8 /* Number of bytes to represent an element of the the curve p-256: */ -#define NUM_ECC_BYTES (4*NUM_ECC_DIGITS) +#define NUM_ECC_BYTES (WORD_SIZE*NUM_ECC_DIGITS) /* struct to represent a point of the curve (uses X and Y coordinates): */ typedef struct EccPoint { @@ -218,6 +220,8 @@ void vli_modSquare_fast(uint32_t *p_result, uint32_t *p_left); * @param p_right IN -- buffer p_right in (p_left * p_right) % p_mod. * @param p_mod IN -- module. * @param p_barrett IN -- used for Barrett reduction. + * @note Side-channel countermeasure: algorithm strengthened against timing + * attack. */ void vli_modMult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right, uint32_t *p_mod, uint32_t *p_barrett); @@ -229,11 +233,28 @@ void vli_modMult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right, * @param p_input IN -- buffer p_input in (1/p_intput) % p_mod. * @param p_mod IN -- module. * @param p_barrett IN -- used for Barrett reduction. + * @note Side-channel countermeasure: algorithm strengthened against timing + * attack. */ void vli_modInv(uint32_t *p_result, uint32_t *p_input, uint32_t *p_mod, uint32_t *p_barrett); /* + * @brief modular reduction based on Barrett's method + * @param p_result OUT -- p_product % p_mod. + * @param p_product IN -- buffer p_product in (p_product % p_mod). + * @param p_mod IN -- buffer p_mod in (p_product % p_mod). + * @param p_barrett -- used for Barrett reduction. + * @note Side-channel countermeasure: algorithm strengthened against timing + * attack. + */ +void vli_mmod_barrett( + uint32_t *p_result, + uint32_t *p_product, + uint32_t *p_mod, + uint32_t *p_barrett); + +/* * @brief Check if a point is zero. * @return Returns 1 if p_point is the point at infinity, 0 otherwise. * @@ -271,11 +292,27 @@ void EccPoint_add(EccPointJacobi *P1, EccPointJacobi *P2); * @param p_result OUT -- Product of p_point by p_scalar. * @param p_point IN -- Elliptic curve point * @param p_scalar IN -- Scalar integer + * @note Side-channel countermeasure: algorithm strengthened against timing + * attack. */ -void EccPoint_mult(EccPointJacobi *p_result, EccPoint *p_point, +void EccPoint_mult_safe(EccPointJacobi *p_result, EccPoint *p_point, uint32_t *p_scalar); /* + * @brief Fast elliptic curve scalar multiplication with result in Jacobi + * coordinates + * @note non constant time + * @param p_result OUT -- Product of p_point by p_scalar. + * @param p_point IN -- Elliptic curve point + * @param p_scalar IN -- Scalar integer + * @note algorithm NOT strengthened against timing attack. + */ +void EccPoint_mult_unsafe( + EccPointJacobi *p_result, + EccPoint *p_point, + uint32_t *p_scalar); + +/* * @brief Convert an integer in standard octet representation to native format. * @return returns TC_CRYPTO_SUCCESS (1) * returns TC_CRYPTO_FAIL (0) if: diff --git a/ext/lib/crypto/tinycrypt/include/tinycrypt/ecc_dh.h b/ext/lib/crypto/tinycrypt/include/tinycrypt/ecc_dh.h index b31477b1f..778fee272 100644 --- a/ext/lib/crypto/tinycrypt/include/tinycrypt/ecc_dh.h +++ b/ext/lib/crypto/tinycrypt/include/tinycrypt/ecc_dh.h @@ -80,7 +80,7 @@ extern "C" { /** * @brief Create a public/private key pair. - * @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully + * @return returns TC_CRYPTO_SUCCESS (1) if key pair was generated successfully * returns TC_CRYPTO_FAIL (0) if: * the private key is 0 * @@ -90,13 +90,15 @@ extern "C" { * * @note You must use a new non-predictable random number to generate each * new key pair. + * @note p_random must have NUM_ECC_DIGITS*2 bits of entropy to eliminate + * bias in keys. * * @note side-channel countermeasure: algorithm strengthened against timing * attack. */ int32_t ecc_make_key(EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS], - uint32_t p_random[NUM_ECC_DIGITS]); + uint32_t p_random[2 * NUM_ECC_DIGITS]); /** * @brief Determine whether or not a given point is on the chosen elliptic curve @@ -106,7 +108,8 @@ int32_t ecc_make_key(EccPoint *p_publicKey, * returns -2 if: curve_p - p_publicKey->x != 1 or * curve_p - p_publicKey->y != 1 * returns -3 if: y^2 != x^3 + ax + b - + * returns -4 if: public key is the group generator + * * @param p_publicKey IN -- The point to be checked. */ int32_t ecc_valid_public_key(EccPoint *p_publicKey); @@ -114,7 +117,7 @@ int32_t ecc_valid_public_key(EccPoint *p_publicKey); /** * @brief Compute a shared secret given your secret key and someone else's * public key. - * @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully + * @return returns TC_CRYPTO_SUCCESS (1) if the secret was computed successfully * returns TC_CRYPTO_FAIL (0) otherwise * * @param p_secret OUT -- The shared secret value. @@ -125,12 +128,9 @@ int32_t ecc_valid_public_key(EccPoint *p_publicKey); * attacks. The random multiplier should probably be different for each * invocation of ecdh_shared_secret(). * - * @note It is recommended that you hash the result of ecdh_shared_secret before - * using it for symmetric encryption or HMAC. If you do not hash the shared - * secret, you must call ecc_valid_public_key() to verify that the remote side's - * public key is valid. If this is not done, an attacker could create a public - * key that would cause your use of the shared secret to leak information about - * the private key. + * @warning It is recommended to use the output of ecdh_shared_secret() as the + * input of a recommended Key Derivation Function (see NIST SP 800-108) in + * order to produce a symmetric key. */ int32_t ecdh_shared_secret(uint32_t p_secret[NUM_ECC_DIGITS], EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS]); diff --git a/ext/lib/crypto/tinycrypt/include/tinycrypt/hmac.h b/ext/lib/crypto/tinycrypt/include/tinycrypt/hmac.h index 41e712a39..26f6cfe68 100644 --- a/ext/lib/crypto/tinycrypt/include/tinycrypt/hmac.h +++ b/ext/lib/crypto/tinycrypt/include/tinycrypt/hmac.h @@ -125,6 +125,7 @@ int32_t tc_hmac_update(TCHmacState_t ctx, * ctx == NULL or * key == NULL or * taglen != TC_SHA256_DIGEST_SIZE + * @note 'ctx' is erased before exiting (this must never be changed/removed). * @note Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes * state has been initialized by tc_hmac_init * @param tag IN/OUT -- buffer to receive computed HMAC tag diff --git a/ext/lib/crypto/tinycrypt/source/ecc.c b/ext/lib/crypto/tinycrypt/source/ecc.c index 357139b9b..bfe6c5f13 100644 --- a/ext/lib/crypto/tinycrypt/source/ecc.c +++ b/ext/lib/crypto/tinycrypt/source/ecc.c @@ -97,7 +97,9 @@ static void vli_clear(uint32_t *p_vli) } } -/* Returns nonzero if bit p_bit of p_vli is set. */ +/* Returns nonzero if bit p_bit of p_vli is set. + * It is assumed that the value provided in 'bit' is within + * the boundaries of the word-array 'p_vli'.*/ static uint32_t vli_testBit(uint32_t *p_vli, uint32_t p_bit) { return (p_vli[p_bit / 32] & (1 << (p_bit % 32))); @@ -235,7 +237,7 @@ static void vli_square(uint32_t *p_result, uint32_t *p_left) } /* Computes p_result = p_product % curve_p using Barrett reduction. */ -static void vli_mmod_barrett(uint32_t *p_result, uint32_t *p_product, +void vli_mmod_barrett(uint32_t *p_result, uint32_t *p_product, uint32_t *p_mod, uint32_t *p_barrett) { uint32_t i; @@ -547,7 +549,7 @@ void EccPoint_add(EccPointJacobi *P1, EccPointJacobi *P2) * * p_result = p_scalar * p_point. */ -void EccPoint_mult(EccPointJacobi *p_result, EccPoint *p_point, uint32_t *p_scalar) +void EccPoint_mult_safe(EccPointJacobi *p_result, EccPoint *p_point, uint32_t *p_scalar) { int32_t i; @@ -568,6 +570,25 @@ void EccPoint_mult(EccPointJacobi *p_result, EccPoint *p_point, uint32_t *p_scal } } +/* Ellptic curve scalar multiplication with result in Jacobi coordinates */ +/* p_result = p_scalar * p_point */ +void EccPoint_mult_unsafe(EccPointJacobi *p_result, EccPoint *p_point, uint32_t *p_scalar) +{ + int i; + EccPointJacobi p_point_jacobi; + EccPoint_fromAffine(p_result, p_point); + EccPoint_fromAffine(&p_point_jacobi, p_point); + + for(i = vli_numBits(p_scalar) - 2; i >= 0; i--) + { + EccPoint_double(p_result); + if (vli_testBit(p_scalar, i)) + { + EccPoint_add(p_result, &p_point_jacobi); + } + } +} + /* -------- Conversions between big endian and little endian: -------- */ void ecc_bytes2native(uint32_t p_native[NUM_ECC_DIGITS], diff --git a/ext/lib/crypto/tinycrypt/source/ecc_dh.c b/ext/lib/crypto/tinycrypt/source/ecc_dh.c index 965394b23..861001d43 100644 --- a/ext/lib/crypto/tinycrypt/source/ecc_dh.c +++ b/ext/lib/crypto/tinycrypt/source/ecc_dh.c @@ -35,31 +35,36 @@ extern uint32_t curve_p[NUM_ECC_DIGITS]; extern uint32_t curve_b[NUM_ECC_DIGITS]; extern uint32_t curve_n[NUM_ECC_DIGITS]; +extern uint32_t curve_pb[NUM_ECC_DIGITS + 1]; extern EccPoint curve_G; int32_t ecc_make_key(EccPoint *p_publicKey, uint32_t p_privateKey[NUM_ECC_DIGITS], - uint32_t p_random[NUM_ECC_DIGITS]) + uint32_t p_random[NUM_ECC_DIGITS * 2]) { + /* computing modular reduction of p_random (see FIPS 186.4 B.4.1): */ + vli_mmod_barrett(p_privateKey, p_random, curve_p, curve_pb); /* Make sure the private key is in the range [1, n-1]. * For the supported curve, n is always large enough * that we only need to subtract once at most. */ uint32_t p_tmp[NUM_ECC_DIGITS]; - - vli_set(p_privateKey, p_random); vli_sub(p_tmp, p_privateKey, curve_n, NUM_ECC_DIGITS); vli_cond_set(p_privateKey, p_privateKey, p_tmp, vli_cmp(curve_n, p_privateKey, NUM_ECC_DIGITS) == 1); + /* erasing temporary buffer used to store secret: */ + for (uint32_t i = 0; i < NUM_ECC_DIGITS; i++) + p_tmp[i] = 0; + if (vli_isZero(p_privateKey)) { return TC_CRYPTO_FAIL; /* The private key cannot be 0 (mod p). */ } EccPointJacobi P; - EccPoint_mult(&P, &curve_G, p_privateKey); + EccPoint_mult_safe(&P, &curve_G, p_privateKey); EccPoint_toAffine(p_publicKey, &P); return TC_CRYPTO_SUCCESS; @@ -102,6 +107,10 @@ int32_t ecc_valid_public_key(EccPoint *p_publicKey) return -3; } + if (vli_cmp(p_publicKey->x, curve_G.x, NUM_ECC_DIGITS) == 0 && + vli_cmp(p_publicKey->y, curve_G.y, NUM_ECC_DIGITS) == 0 ) + return -4; + return 0; } @@ -112,7 +121,7 @@ int32_t ecdh_shared_secret(uint32_t p_secret[NUM_ECC_DIGITS], EccPoint p_point; EccPointJacobi P; - EccPoint_mult(&P, p_publicKey, p_privateKey); + EccPoint_mult_safe(&P, p_publicKey, p_privateKey); if (EccPointJacobi_isZero(&P)) { return TC_CRYPTO_FAIL; } diff --git a/ext/lib/crypto/tinycrypt/source/ecc_dsa.c b/ext/lib/crypto/tinycrypt/source/ecc_dsa.c index 8636fa18e..dd84a1834 100644 --- a/ext/lib/crypto/tinycrypt/source/ecc_dsa.c +++ b/ext/lib/crypto/tinycrypt/source/ecc_dsa.c @@ -56,7 +56,7 @@ int32_t ecdsa_sign(uint32_t r[NUM_ECC_DIGITS], uint32_t s[NUM_ECC_DIGITS], vli_cond_set(k, k, tmp, vli_cmp(curve_n, k, NUM_ECC_DIGITS) == 1); /* tmp = k * G */ - EccPoint_mult(&P, &curve_G, k); + EccPoint_mult_safe(&P, &curve_G, k); EccPoint_toAffine(&p_point, &P); /* r = x1 (mod n) */ @@ -101,17 +101,15 @@ int32_t ecdsa_verify(EccPoint *p_publicKey, uint32_t p_hash[NUM_ECC_DIGITS], vli_modMult(u2, r, z, curve_n, curve_nb); /* u2 = r/s */ /* calculate P = u1*G + u2*Q */ - EccPoint_mult(&P, &curve_G, u1); - EccPoint_mult(&R, p_publicKey, u2); + EccPoint_mult_unsafe(&P, &curve_G, u1); + EccPoint_mult_unsafe(&R, p_publicKey, u2); EccPoint_add(&P, &R); EccPoint_toAffine(&p_point, &P); /* Accept only if P.x == r. */ - vli_cond_set( - p_point.x, - p_point.x, - z, - vli_sub(z, p_point.x, curve_n, NUM_ECC_DIGITS)); + if (!vli_sub(z, p_point.x, curve_n, NUM_ECC_DIGITS)) { + vli_set(p_point.x, z); + } return (vli_cmp(p_point.x, r, NUM_ECC_DIGITS) == 0); } diff --git a/ext/lib/crypto/tinycrypt/source/utils.c b/ext/lib/crypto/tinycrypt/source/utils.c index 3338e0ca4..147d8d407 100644 --- a/ext/lib/crypto/tinycrypt/source/utils.c +++ b/ext/lib/crypto/tinycrypt/source/utils.c @@ -55,14 +55,11 @@ void _set(void *to, uint8_t val, uint32_t len) } /* - * Doubles the value of a byte for values up to 127. Original 'return - * ((a<<1) ^ ((a>>7) * 0x1b))' re-written to avoid extra multiplication which - * the compiler won't be able to optimize + * Doubles the value of a byte for values up to 127. */ uint8_t _double_byte(uint8_t a) { - return (a & MASK_MOST_SIG_BIT) ? - ((a << 1) ^ MASK_TWENTY_SEVEN) : (a << 1); + return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN)); } int32_t _compare(const uint8_t *a, const uint8_t *b, size_t size) |