diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index b9e2e84356..c4ad9e8a61 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -92,6 +92,12 @@ Possible ECC enable options: * Enables implementations that protect data that is in * encrypted memory. * default: off + * WOLFSSL_ECC_GEN_REJECT_SAMPLING + * Enables generation of scalar (private key and ECDSA + * nonce) to be performed using reject sampling algorithm. + * Use this when CPU state can be closely observed by + * attacker. + * default: off */ /* @@ -5135,6 +5141,7 @@ int wc_ecc_point_is_at_infinity(ecc_point* p) int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) { #ifndef WC_NO_RNG +#ifndef WOLFSSL_ECC_GEN_REJECT_SAMPLING int err; byte buf[ECC_MAXSIZE_GEN]; @@ -5176,6 +5183,54 @@ int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) #endif return err; +#else + int err; + byte buf[ECC_MAXSIZE_GEN]; + int bits; + + if ((rng == NULL) || (size < 0) || (size + 8 > ECC_MAXSIZE_GEN) || + (k == NULL) || (order == NULL)) { + return BAD_FUNC_ARG; + } + + /* Get actual bit count of order. */ + bits = mp_count_bits(order); + size = (bits + 7) >> 3; + + /* generate number in range of order through rejection sampling. */ + /* see section A.2.2 and A.4.2 in FIPS 186-5 */ + do { + /* A.2.2 step 3: make up random string */ + err = wc_RNG_GenerateBlock(rng, buf, (word32)size); + #ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Add("wc_ecc_gen_k buf", buf, size); + #endif + /* Generated multiple of 8 bits but now make it size of order. */ + if ((bits & 0x7) > 0) { + buf[0] &= (1 << (bits & 0x7)) - 1; + } + + /* A.2.2 step 4: convert to integer. */ + /* A.4.2 step 3: Convert the bit string to integer x. */ + if (err == 0) { + err = mp_read_unsigned_bin(k, buf, (word32)size); + } + + /* A.4.2 step 4, 5: x must be in range [1, n-1] */ + if ((err == MP_OKAY) && !mp_iszero(k) && + (mp_cmp_ct(k, order, order->used) == MP_LT)) { + break; + } + } + while (err == MP_OKAY); + + ForceZero(buf, ECC_MAXSIZE_GEN); +#ifdef WOLFSSL_CHECK_MEM_ZERO + wc_MemZero_Check(buf, ECC_MAXSIZE_GEN); +#endif + + return err; +#endif #else (void)rng; (void)size; diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index cb1364535c..94fc01c358 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -4780,7 +4780,7 @@ static void _sp_mont_setup(const sp_int* m, sp_int_digit* rho); /* Determine when mp_add_d is required. */ #if !defined(NO_PWDBASED) || defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || \ - !defined(NO_DSA) || (defined(HAVE_ECC) && defined(HAVE_COMP_KEY)) || \ + !defined(NO_DSA) || defined(HAVE_ECC) || \ (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ defined(OPENSSL_EXTRA) #define WOLFSSL_SP_ADD_D @@ -5327,8 +5327,8 @@ int sp_abs(const sp_int* a, sp_int* r) (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) /* Compare absolute value of two multi-precision numbers. * - * @param [in] a SP integer. - * @param [in] b SP integer. + * @param [in] a SP integer. + * @param [in] b SP integer. * * @return MP_GT when a is greater than b. * @return MP_LT when a is less than b. @@ -5373,8 +5373,8 @@ static int _sp_cmp_abs(const sp_int* a, const sp_int* b) * * Pointers are compared such that NULL is less than not NULL. * - * @param [in] a SP integer. - * @param [in] b SP integer. + * @param [in] a SP integer. + * @param [in] b SP integer. * * @return MP_GT when a is greater than b. * @return MP_LT when a is less than b. @@ -5413,8 +5413,8 @@ int sp_cmp_mag(const sp_int* a, const sp_int* b) * * Assumes a and b are not NULL. * - * @param [in] a SP integer. - * @param [in] a SP integer. + * @param [in] a SP integer. + * @param [in] b SP integer. * * @return MP_GT when a is greater than b. * @return MP_LT when a is less than b. @@ -5457,8 +5457,8 @@ static int _sp_cmp(const sp_int* a, const sp_int* b) * * Pointers are compared such that NULL is less than not NULL. * - * @param [in] a SP integer. - * @param [in] a SP integer. + * @param [in] a SP integer. + * @param [in] b SP integer. * * @return MP_GT when a is greater than b. * @return MP_LT when a is less than b. @@ -5490,6 +5490,80 @@ int sp_cmp(const sp_int* a, const sp_int* b) } #endif +#if defined(HAVE_ECC) && !defined(WC_NO_RNG) && \ + defined(WOLFSSL_ECC_GEN_REJECT_SAMPLING) +/* Compare two multi-precision numbers in constant time. + * + * Assumes a and b are not NULL. + * Assumes a and b are positive. + * + * @param [in] a SP integer. + * @param [in] b SP integer. + * @param [in] n Number of digits to compare. + * + * @return MP_GT when a is greater than b. + * @return MP_LT when a is less than b. + * @return MP_EQ when a is equals b. + */ +static int _sp_cmp_ct(const sp_int* a, const sp_int* b, unsigned int n) +{ + int ret = MP_EQ; + int i; + int mask = -1; + + for (i = n - 1; i >= 0; i--) { + sp_int_digit ad = a->dp[i] & ((sp_int_digit)0 - (i < (int)a->used)); + sp_int_digit bd = b->dp[i] & ((sp_int_digit)0 - (i < (int)b->used)); + + ret |= mask & ((0 - (ad < bd)) & MP_LT); + mask &= 0 - (ret == MP_EQ); + ret |= mask & ((0 - (ad > bd)) & MP_GT); + mask &= 0 - (ret == MP_EQ); + } + + return ret; +} + +/* Compare two multi-precision numbers in constant time. + * + * Pointers are compared such that NULL is less than not NULL. + * Assumes a and b are positive. + * Assumes a and b have n digits set at sometime. + * + * @param [in] a SP integer. + * @param [in] b SP integer. + * @param [in] n Number of digits to compare. + * + * @return MP_GT when a is greater than b. + * @return MP_LT when a is less than b. + * @return MP_EQ when a is equals b. + */ +int sp_cmp_ct(const sp_int* a, const sp_int* b, unsigned int n) +{ + int ret; + + /* Check pointers first. Both NULL returns equal. */ + if (a == b) { + ret = MP_EQ; + } + /* Nothing is smaller than something. */ + else if (a == NULL) { + ret = MP_LT; + } + /* Something is larger than nothing. */ + else if (b == NULL) { + ret = MP_GT; + } + else + { + /* Compare values - a and b are not NULL. */ + ret = _sp_cmp_ct(a, b, n); + } + + return ret; +} +#endif /* HAVE_ECC && !WC_NO_RNG && WOLFSSL_ECC_GEN_REJECT_SAMPLING */ + /************************* * Bit check/set functions *************************/ @@ -7673,10 +7747,6 @@ int sp_submod(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r) } #endif /* WOLFSSL_SP_MATH_ALL */ -#if (defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)) || \ - (defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \ - defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE) || \ - defined(OPENSSL_ALL)) /* Constant time clamping/ * * @param [in, out] a SP integer to clamp. @@ -7693,7 +7763,6 @@ static void sp_clamp_ct(sp_int* a) } a->used = used; } -#endif #if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC) /* Add two value and reduce: r = (a + b) % m @@ -14362,7 +14431,8 @@ int sp_div_2d(const sp_int* a, int e, sp_int* r, sp_int* rem) } #endif /* WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY */ -#if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) +#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ + defined(HAVE_ECC) /* The bottom e bits: r = a & ((1 << e) - 1) * * @param [in] a SP integer to reduce. @@ -14432,7 +14502,7 @@ int sp_mod_2d(const sp_int* a, int e, sp_int* r) return err; } -#endif /* WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY */ +#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY)) || HAVE_ECC */ #if (defined(WOLFSSL_SP_MATH_ALL) && (!defined(WOLFSSL_RSA_VERIFY_ONLY) || \ !defined(NO_DH))) || defined(OPENSSL_ALL) @@ -17780,7 +17850,7 @@ int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz) #endif /* LITTLE_ENDIAN_ORDER */ } #endif - sp_clamp(a); + sp_clamp_ct(a); } return err; diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 373c9e85c4..1b07f5d597 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -4863,6 +4863,12 @@ int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d) return MP_OKAY; } +int mp_mod_2d(fp_int* a, int b, fp_int* c) +{ + fp_mod_2d(a, b, c); + return MP_OKAY; +} + /* copy (src = a) to (dst = b) */ void fp_copy(const fp_int *a, fp_int *b) { diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 6e7fb5e3ce..b32179e332 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -46174,6 +46174,67 @@ static wc_test_ret_t mp_test_cmp(mp_int* a, mp_int* b) return WC_TEST_RET_ENC_NC; #endif +#if defined(HAVE_ECC) && !defined(WC_NO_RNG) && \ + defined(WOLFSSL_ECC_GEN_REJECT_SAMPLING) + mp_zero(a); + mp_zero(b); + ret = mp_cmp_ct(a, b, 1); + if (ret != MP_EQ) + return WC_TEST_RET_ENC_EC(ret); + ret = mp_cmp_ct(a, a, a->used); + if (ret != MP_EQ) + return WC_TEST_RET_ENC_EC(ret); + +#ifdef WOLFSSL_SP_MATH_ALL + ret = mp_cmp_ct(a, NULL, a->used); + if (ret != MP_GT) + return WC_TEST_RET_ENC_EC(ret); + ret = mp_cmp_ct(NULL, a, a->used); + if (ret != MP_LT) + return WC_TEST_RET_ENC_EC(ret); +#endif + + mp_read_radix(a, "1", MP_RADIX_HEX); + ret = mp_cmp_ct(a, b, 1); + if (ret != MP_GT) + return WC_TEST_RET_ENC_EC(ret); + ret = mp_cmp_ct(b, a, 1); + if (ret != MP_LT) + return WC_TEST_RET_ENC_EC(ret); + + mp_read_radix(a, "0123456789abcdef0123456789abcdef", MP_RADIX_HEX); + ret = mp_cmp_ct(a, b, a->used); + if (ret != MP_GT) + return WC_TEST_RET_ENC_EC(ret); + ret = mp_cmp_ct(b, a, a->used); + if (ret != MP_LT) + return WC_TEST_RET_ENC_EC(ret); + + mp_read_radix(b, "1123456789abcdef0123456789abcdef", MP_RADIX_HEX); + ret = mp_cmp_ct(b, a, a->used); + if (ret != MP_GT) + return WC_TEST_RET_ENC_EC(ret); + ret = mp_cmp_ct(a, b, a->used); + if (ret != MP_LT) + return WC_TEST_RET_ENC_EC(ret); + + mp_read_radix(b, "0123456789abcdef0123456789abcdf0", MP_RADIX_HEX); + ret = mp_cmp_ct(b, a, a->used); + if (ret != MP_GT) + return WC_TEST_RET_ENC_EC(ret); + ret = mp_cmp_ct(a, b, a->used); + if (ret != MP_LT) + return WC_TEST_RET_ENC_EC(ret); + + mp_read_radix(b, "0123456789abcdf0", MP_RADIX_HEX); + ret = mp_cmp_ct(a, b, a->used); + if (ret != MP_GT) + return WC_TEST_RET_ENC_EC(ret); + ret = mp_cmp_ct(b, a, a->used); + if (ret != MP_LT) + return WC_TEST_RET_ENC_EC(ret); +#endif + return 0; } diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index 75dc614381..243d3f0d13 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -344,6 +344,7 @@ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c); MP_API int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); MP_API int mp_cmp_mag (mp_int * a, mp_int * b); MP_API int mp_cmp (mp_int * a, mp_int * b); +#define mp_cmp_ct(a, b, n) mp_cmp(a, b) MP_API int mp_cmp_d(mp_int * a, mp_digit b); MP_API int mp_set (mp_int * a, mp_digit b); MP_API int mp_is_bit_set (mp_int * a, mp_digit b); diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h index f0b4789451..e768d0cd5f 100644 --- a/wolfssl/wolfcrypt/sp_int.h +++ b/wolfssl/wolfcrypt/sp_int.h @@ -945,6 +945,7 @@ MP_API int sp_abs(const sp_int* a, sp_int* r); MP_API int sp_cmp_mag(const sp_int* a, const sp_int* b); #endif MP_API int sp_cmp(const sp_int* a, const sp_int* b); +MP_API int sp_cmp_ct(const sp_int* a, const sp_int* b, unsigned int n); MP_API int sp_is_bit_set(const sp_int* a, unsigned int b); MP_API int sp_count_bits(const sp_int* a); @@ -1030,9 +1031,11 @@ MP_API int sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, #if defined(WOLFSSL_SP_MATH_ALL) || defined(OPENSSL_ALL) MP_API int sp_div_2d(const sp_int* a, int e, sp_int* r, sp_int* rem); -MP_API int sp_mod_2d(const sp_int* a, int e, sp_int* r); MP_API int sp_mul_2d(const sp_int* a, int e, sp_int* r); #endif +#if defined(WOLFSSL_SP_MATH_ALL) || defined(HAVE_ECC) || defined(OPENSSL_ALL) +MP_API int sp_mod_2d(const sp_int* a, int e, sp_int* r); +#endif MP_API int sp_sqr(const sp_int* a, sp_int* r); MP_API int sp_sqrmod(const sp_int* a, const sp_int* m, sp_int* r); @@ -1119,6 +1122,7 @@ WOLFSSL_LOCAL void sp_memzero_check(sp_int* sp); #define mp_cond_swap_ct_ex sp_cond_swap_ct_ex #define mp_cmp_mag sp_cmp_mag #define mp_cmp sp_cmp +#define mp_cmp_ct sp_cmp_ct #define mp_count_bits sp_count_bits #define mp_cnt_lsb sp_cnt_lsb #define mp_leading_bit sp_leading_bit diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index 8099a17006..dc6d55a1c1 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -838,6 +838,7 @@ MP_API int mp_2expt(mp_int* a, int b); MP_API int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); MP_API int mp_cmp(mp_int *a, mp_int *b); +#define mp_cmp_ct(a, b, n) mp_cmp(a, b) MP_API int mp_cmp_d(mp_int *a, mp_digit b); MP_API int mp_unsigned_bin_size(const mp_int * a); @@ -908,6 +909,7 @@ MP_API int mp_cond_swap_ct(mp_int* a, mp_int* b, int c, int m); MP_API int mp_cnt_lsb(fp_int *a); MP_API int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); +MP_API int mp_mod_2d(fp_int *a, int b, fp_int *c); MP_API int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c); MP_API int mp_lshd (mp_int * a, int b); MP_API int mp_abs(mp_int* a, mp_int* b);