Skip to content

Commit 21f53f3

Browse files
committed
ECC: generate values in range of order by rejection
When generating private key and nonce for ECDSA, use rejection sampling. Note: SP uses this algorithm
1 parent 6125e59 commit 21f53f3

File tree

7 files changed

+217
-18
lines changed

7 files changed

+217
-18
lines changed

wolfcrypt/src/ecc.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ Possible ECC enable options:
9292
* Enables implementations that protect data that is in
9393
* encrypted memory.
9494
* default: off
95+
* WOLFSSL_ECC_GEN_REJECT_SAMPLING
96+
* Enables generation of scalar (private key and ECDSA
97+
* nonce) to be performed using reject sampling algorithm.
98+
* Use this when CPU state can be closely observered by
99+
* attacker.
100+
* default: off
95101
*/
96102

97103
/*
@@ -5135,6 +5141,7 @@ int wc_ecc_point_is_at_infinity(ecc_point* p)
51355141
int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order)
51365142
{
51375143
#ifndef WC_NO_RNG
5144+
#ifndef WOLFSSL_ECC_GEN_REJECT_SAMPLING
51385145
int err;
51395146
byte buf[ECC_MAXSIZE_GEN];
51405147

@@ -5176,6 +5183,54 @@ int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order)
51765183
#endif
51775184

51785185
return err;
5186+
#else
5187+
int err;
5188+
byte buf[ECC_MAXSIZE_GEN];
5189+
int bits;
5190+
5191+
if ((rng == NULL) || (size < 0) || (size + 8 > ECC_MAXSIZE_GEN) ||
5192+
(k == NULL) || (order == NULL)) {
5193+
return BAD_FUNC_ARG;
5194+
}
5195+
5196+
/* Get actual bit count of order. */
5197+
bits = mp_count_bits(order);
5198+
size = (bits + 7) >> 3;
5199+
5200+
/* generate number in range of order through rejection sampling. */
5201+
/* see section A.2.2 and A.4.2 in FIPS 186-5 */
5202+
do {
5203+
/* A.2.2 step 3: make up random string */
5204+
err = wc_RNG_GenerateBlock(rng, buf, (word32)size);
5205+
#ifdef WOLFSSL_CHECK_MEM_ZERO
5206+
wc_MemZero_Add("wc_ecc_gen_k buf", buf, size);
5207+
#endif
5208+
/* Generated multiple of 8 bits but now make it size of order. */
5209+
if ((bits & 0x7) > 0) {
5210+
buf[0] &= (1 << (bits & 0x7)) - 1;
5211+
}
5212+
5213+
/* A.2.2 step 4: convert to integer. */
5214+
/* A.4.2 step 3: Convert the bit string to integer x. */
5215+
if (err == 0) {
5216+
err = mp_read_unsigned_bin(k, buf, (word32)size);
5217+
}
5218+
5219+
/* A.4.2 step 4, 5: x must be in range [1, n-1] */
5220+
if ((err == MP_OKAY) && !mp_iszero(k) &&
5221+
(mp_cmp_ct(k, order, order->used) == MP_LT)) {
5222+
break;
5223+
}
5224+
}
5225+
while (err == MP_OKAY);
5226+
5227+
ForceZero(buf, ECC_MAXSIZE_GEN);
5228+
#ifdef WOLFSSL_CHECK_MEM_ZERO
5229+
wc_MemZero_Check(buf, ECC_MAXSIZE_GEN);
5230+
#endif
5231+
5232+
return err;
5233+
#endif
51795234
#else
51805235
(void)rng;
51815236
(void)size;

wolfcrypt/src/sp_int.c

Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4780,7 +4780,7 @@ static void _sp_mont_setup(const sp_int* m, sp_int_digit* rho);
47804780

47814781
/* Determine when mp_add_d is required. */
47824782
#if !defined(NO_PWDBASED) || defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || \
4783-
!defined(NO_DSA) || (defined(HAVE_ECC) && defined(HAVE_COMP_KEY)) || \
4783+
!defined(NO_DSA) || defined(HAVE_ECC) || \
47844784
(!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
47854785
defined(OPENSSL_EXTRA)
47864786
#define WOLFSSL_SP_ADD_D
@@ -5327,8 +5327,8 @@ int sp_abs(const sp_int* a, sp_int* r)
53275327
(!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY))
53285328
/* Compare absolute value of two multi-precision numbers.
53295329
*
5330-
* @param [in] a SP integer.
5331-
* @param [in] b SP integer.
5330+
* @param [in] a SP integer.
5331+
* @param [in] b SP integer.
53325332
*
53335333
* @return MP_GT when a is greater than b.
53345334
* @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)
53735373
*
53745374
* Pointers are compared such that NULL is less than not NULL.
53755375
*
5376-
* @param [in] a SP integer.
5377-
* @param [in] b SP integer.
5376+
* @param [in] a SP integer.
5377+
* @param [in] b SP integer.
53785378
*
53795379
* @return MP_GT when a is greater than b.
53805380
* @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)
54135413
*
54145414
* Assumes a and b are not NULL.
54155415
*
5416-
* @param [in] a SP integer.
5417-
* @param [in] a SP integer.
5416+
* @param [in] a SP integer.
5417+
* @param [in] b SP integer.
54185418
*
54195419
* @return MP_GT when a is greater than b.
54205420
* @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)
54575457
*
54585458
* Pointers are compared such that NULL is less than not NULL.
54595459
*
5460-
* @param [in] a SP integer.
5461-
* @param [in] a SP integer.
5460+
* @param [in] a SP integer.
5461+
* @param [in] b SP integer.
54625462
*
54635463
* @return MP_GT when a is greater than b.
54645464
* @return MP_LT when a is less than b.
@@ -5490,6 +5490,80 @@ int sp_cmp(const sp_int* a, const sp_int* b)
54905490
}
54915491
#endif
54925492

5493+
#if defined(HAVE_ECC) && !defined(WC_NO_RNG) && \
5494+
defined(WOLFSSL_ECC_GEN_REJECT_SAMPLING)
5495+
/* Compare two multi-precision numbers in constant time.
5496+
*
5497+
* Assumes a and b are not NULL.
5498+
* Assumes a and b are positive.
5499+
*
5500+
* @param [in] a SP integer.
5501+
* @param [in] b SP integer.
5502+
* @param [in] n Number of digits to compare.
5503+
*
5504+
* @return MP_GT when a is greater than b.
5505+
* @return MP_LT when a is less than b.
5506+
* @return MP_EQ when a is equals b.
5507+
*/
5508+
static int _sp_cmp_ct(const sp_int* a, const sp_int* b, unsigned int n)
5509+
{
5510+
int ret = MP_EQ;
5511+
int i;
5512+
int mask = -1;
5513+
5514+
for (i = n - 1; i >= 0; i--) {
5515+
sp_int_digit ad = a->dp[i] & ((sp_int_digit)0 - (i < (int)a->used));
5516+
sp_int_digit bd = b->dp[i] & ((sp_int_digit)0 - (i < (int)b->used));
5517+
5518+
ret |= mask & ((0 - (ad < bd)) & MP_LT);
5519+
mask &= 0 - (ret == MP_EQ);
5520+
ret |= mask & ((0 - (ad > bd)) & MP_GT);
5521+
mask &= 0 - (ret == MP_EQ);
5522+
}
5523+
5524+
return ret;
5525+
}
5526+
5527+
/* Compare two multi-precision numbers in constant time.
5528+
*
5529+
* Pointers are compared such that NULL is less than not NULL.
5530+
* Assumes a and b are positive.
5531+
* Assumes a and b have n digits set at sometime.
5532+
*
5533+
* @param [in] a SP integer.
5534+
* @param [in] b SP integer.
5535+
* @param [in] n Number of digits to compare.
5536+
*
5537+
* @return MP_GT when a is greater than b.
5538+
* @return MP_LT when a is less than b.
5539+
* @return MP_EQ when a is equals b.
5540+
*/
5541+
int sp_cmp_ct(const sp_int* a, const sp_int* b, unsigned int n)
5542+
{
5543+
int ret;
5544+
5545+
/* Check pointers first. Both NULL returns equal. */
5546+
if (a == b) {
5547+
ret = MP_EQ;
5548+
}
5549+
/* Nothing is smaller than something. */
5550+
else if (a == NULL) {
5551+
ret = MP_LT;
5552+
}
5553+
/* Something is larger than nothing. */
5554+
else if (b == NULL) {
5555+
ret = MP_GT;
5556+
}
5557+
else
5558+
{
5559+
/* Compare values - a and b are not NULL. */
5560+
ret = _sp_cmp_ct(a, b, n);
5561+
}
5562+
5563+
return ret;
5564+
}
5565+
#endif /* HAVE_ECC && !WC_NO_RNG && WOLFSSL_ECC_GEN_REJECT_SAMPLING */
5566+
54935567
/*************************
54945568
* Bit check/set functions
54955569
*************************/
@@ -7673,10 +7747,6 @@ int sp_submod(const sp_int* a, const sp_int* b, const sp_int* m, sp_int* r)
76737747
}
76747748
#endif /* WOLFSSL_SP_MATH_ALL */
76757749

7676-
#if (defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)) || \
7677-
(defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_HAVE_SP_DH) || \
7678-
defined(WOLFCRYPT_HAVE_ECCSI) || defined(WOLFCRYPT_HAVE_SAKKE) || \
7679-
defined(OPENSSL_ALL))
76807750
/* Constant time clamping/
76817751
*
76827752
* @param [in, out] a SP integer to clamp.
@@ -7693,7 +7763,6 @@ static void sp_clamp_ct(sp_int* a)
76937763
}
76947764
a->used = used;
76957765
}
7696-
#endif
76977766

76987767
#if defined(WOLFSSL_SP_MATH_ALL) && defined(HAVE_ECC)
76997768
/* 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)
1436214431
}
1436314432
#endif /* WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY */
1436414433

14365-
#if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)
14434+
#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
14435+
defined(HAVE_ECC)
1436614436
/* The bottom e bits: r = a & ((1 << e) - 1)
1436714437
*
1436814438
* @param [in] a SP integer to reduce.
@@ -14432,7 +14502,7 @@ int sp_mod_2d(const sp_int* a, int e, sp_int* r)
1443214502

1443314503
return err;
1443414504
}
14435-
#endif /* WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY */
14505+
#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY)) || HAVE_ECC */
1443614506

1443714507
#if (defined(WOLFSSL_SP_MATH_ALL) && (!defined(WOLFSSL_RSA_VERIFY_ONLY) || \
1443814508
!defined(NO_DH))) || defined(OPENSSL_ALL)
@@ -17771,7 +17841,7 @@ int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz)
1777117841
#endif /* LITTLE_ENDIAN_ORDER */
1777217842
}
1777317843
#endif
17774-
sp_clamp(a);
17844+
sp_clamp_ct(a);
1777517845
}
1777617846

1777717847
return err;

wolfcrypt/src/tfm.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4859,6 +4859,12 @@ int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d)
48594859
return MP_OKAY;
48604860
}
48614861

4862+
int mp_mod_2d(fp_int* a, int b, fp_int* c)
4863+
{
4864+
fp_mod_2d(a, b, c);
4865+
return MP_OKAY;
4866+
}
4867+
48624868
/* copy (src = a) to (dst = b) */
48634869
void fp_copy(const fp_int *a, fp_int *b)
48644870
{

wolfcrypt/test/test.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46040,6 +46040,67 @@ static wc_test_ret_t mp_test_cmp(mp_int* a, mp_int* b)
4604046040
return WC_TEST_RET_ENC_NC;
4604146041
#endif
4604246042

46043+
#if defined(HAVE_ECC) && !defined(WC_NO_RNG) && \
46044+
defined(WOLFSSL_ECC_GEN_REJECT_SAMPLING)
46045+
mp_zero(a);
46046+
mp_zero(b);
46047+
ret = mp_cmp_ct(a, b, 1);
46048+
if (ret != MP_EQ)
46049+
return WC_TEST_RET_ENC_EC(ret);
46050+
ret = mp_cmp_ct(a, a, a->used);
46051+
if (ret != MP_EQ)
46052+
return WC_TEST_RET_ENC_EC(ret);
46053+
46054+
#ifdef WOLFSSL_SP_MATH_ALL
46055+
ret = mp_cmp_ct(a, NULL, a->used);
46056+
if (ret != MP_GT)
46057+
return WC_TEST_RET_ENC_EC(ret);
46058+
ret = mp_cmp_ct(NULL, a, a->used);
46059+
if (ret != MP_LT)
46060+
return WC_TEST_RET_ENC_EC(ret);
46061+
#endif
46062+
46063+
mp_read_radix(a, "1", MP_RADIX_HEX);
46064+
ret = mp_cmp_ct(a, b, 1);
46065+
if (ret != MP_GT)
46066+
return WC_TEST_RET_ENC_EC(ret);
46067+
ret = mp_cmp_ct(b, a, 1);
46068+
if (ret != MP_LT)
46069+
return WC_TEST_RET_ENC_EC(ret);
46070+
46071+
mp_read_radix(a, "0123456789abcdef0123456789abcdef", MP_RADIX_HEX);
46072+
ret = mp_cmp_ct(a, b, a->used);
46073+
if (ret != MP_GT)
46074+
return WC_TEST_RET_ENC_EC(ret);
46075+
ret = mp_cmp_ct(b, a, a->used);
46076+
if (ret != MP_LT)
46077+
return WC_TEST_RET_ENC_EC(ret);
46078+
46079+
mp_read_radix(b, "1123456789abcdef0123456789abcdef", MP_RADIX_HEX);
46080+
ret = mp_cmp_ct(b, a, a->used);
46081+
if (ret != MP_GT)
46082+
return WC_TEST_RET_ENC_EC(ret);
46083+
ret = mp_cmp_ct(a, b, a->used);
46084+
if (ret != MP_LT)
46085+
return WC_TEST_RET_ENC_EC(ret);
46086+
46087+
mp_read_radix(b, "0123456789abcdef0123456789abcdf0", MP_RADIX_HEX);
46088+
ret = mp_cmp_ct(b, a, a->used);
46089+
if (ret != MP_GT)
46090+
return WC_TEST_RET_ENC_EC(ret);
46091+
ret = mp_cmp_ct(a, b, a->used);
46092+
if (ret != MP_LT)
46093+
return WC_TEST_RET_ENC_EC(ret);
46094+
46095+
mp_read_radix(b, "0123456789abcdf0", MP_RADIX_HEX);
46096+
ret = mp_cmp_ct(a, b, a->used);
46097+
if (ret != MP_GT)
46098+
return WC_TEST_RET_ENC_EC(ret);
46099+
ret = mp_cmp_ct(b, a, a->used);
46100+
if (ret != MP_LT)
46101+
return WC_TEST_RET_ENC_EC(ret);
46102+
#endif
46103+
4604346104
return 0;
4604446105
}
4604546106

wolfssl/wolfcrypt/integer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c);
344344
MP_API int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
345345
MP_API int mp_cmp_mag (mp_int * a, mp_int * b);
346346
MP_API int mp_cmp (mp_int * a, mp_int * b);
347+
#define mp_cmp_ct(a, b, n) mp_cmp(a, b)
347348
MP_API int mp_cmp_d(mp_int * a, mp_digit b);
348349
MP_API int mp_set (mp_int * a, mp_digit b);
349350
MP_API int mp_is_bit_set (mp_int * a, mp_digit b);

wolfssl/wolfcrypt/sp_int.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,7 @@ MP_API int sp_abs(const sp_int* a, sp_int* r);
945945
MP_API int sp_cmp_mag(const sp_int* a, const sp_int* b);
946946
#endif
947947
MP_API int sp_cmp(const sp_int* a, const sp_int* b);
948+
MP_API int sp_cmp_ct(const sp_int* a, const sp_int* b, unsigned int n);
948949

949950
MP_API int sp_is_bit_set(const sp_int* a, unsigned int b);
950951
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,
10301031

10311032
#if defined(WOLFSSL_SP_MATH_ALL) || defined(OPENSSL_ALL)
10321033
MP_API int sp_div_2d(const sp_int* a, int e, sp_int* r, sp_int* rem);
1033-
MP_API int sp_mod_2d(const sp_int* a, int e, sp_int* r);
10341034
MP_API int sp_mul_2d(const sp_int* a, int e, sp_int* r);
10351035
#endif
1036+
#if defined(WOLFSSL_SP_MATH_ALL) || defined(HAVE_ECC) || defined(OPENSSL_ALL)
1037+
MP_API int sp_mod_2d(const sp_int* a, int e, sp_int* r);
1038+
#endif
10361039

10371040
MP_API int sp_sqr(const sp_int* a, sp_int* r);
10381041
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);
11191122
#define mp_cond_swap_ct_ex sp_cond_swap_ct_ex
11201123
#define mp_cmp_mag sp_cmp_mag
11211124
#define mp_cmp sp_cmp
1125+
#define mp_cmp_ct sp_cmp_ct
11221126
#define mp_count_bits sp_count_bits
11231127
#define mp_cnt_lsb sp_cnt_lsb
11241128
#define mp_leading_bit sp_leading_bit

wolfssl/wolfcrypt/tfm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,7 @@ MP_API int mp_2expt(mp_int* a, int b);
838838
MP_API int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d);
839839

840840
MP_API int mp_cmp(mp_int *a, mp_int *b);
841+
#define mp_cmp_ct(a, b, n) mp_cmp(a, b)
841842
MP_API int mp_cmp_d(mp_int *a, mp_digit b);
842843

843844
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);
908909

909910
MP_API int mp_cnt_lsb(fp_int *a);
910911
MP_API int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d);
912+
MP_API int mp_mod_2d(fp_int *a, int b, fp_int *c);
911913
MP_API int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c);
912914
MP_API int mp_lshd (mp_int * a, int b);
913915
MP_API int mp_abs(mp_int* a, mp_int* b);

0 commit comments

Comments
 (0)