Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECC: generate values in range of order by rejection #7020

Merged
merged 2 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions wolfcrypt/src/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 observered by
cconlon marked this conversation as resolved.
Show resolved Hide resolved
* attacker.
* default: off
*/

/*
Expand Down Expand Up @@ -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];

Expand Down Expand Up @@ -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;
Expand Down
104 changes: 87 additions & 17 deletions wolfcrypt/src/sp_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
*************************/
Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -17771,7 +17841,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;
Expand Down
6 changes: 6 additions & 0 deletions wolfcrypt/src/tfm.c
Original file line number Diff line number Diff line change
Expand Up @@ -4859,6 +4859,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)
{
Expand Down
61 changes: 61 additions & 0 deletions wolfcrypt/test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -46040,6 +46040,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;
}

Expand Down
1 change: 1 addition & 0 deletions wolfssl/wolfcrypt/integer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 5 additions & 1 deletion wolfssl/wolfcrypt/sp_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions wolfssl/wolfcrypt/tfm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down