Skip to content

Commit

Permalink
Merge pull request wolfSSL#7020 from SparkiDev/ecc_gen_k_by_reject
Browse files Browse the repository at this point in the history
ECC: generate values in range of order by rejection
  • Loading branch information
cconlon authored Dec 14, 2023
2 parents f6ef58d + 1cf87ce commit fb6b022
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 18 deletions.
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 observed by
* 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 @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions wolfcrypt/src/tfm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
61 changes: 61 additions & 0 deletions wolfcrypt/test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

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

0 comments on commit fb6b022

Please sign in to comment.