Skip to content

Commit 295d906

Browse files
authored
Merge pull request #8929 from SparkiDev/regression_fixes_18
Regression testing
2 parents edacf04 + f1cb4d5 commit 295d906

6 files changed

Lines changed: 191 additions & 170 deletions

File tree

wolfcrypt/src/dh.c

Lines changed: 72 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -2058,44 +2058,19 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
20582058
#endif
20592059

20602060
#ifdef WOLFSSL_HAVE_SP_DH
2061+
if (0
20612062
#ifndef WOLFSSL_SP_NO_2048
2062-
if (mp_count_bits(&key->p) == 2048) {
2063-
if (mp_init(y) != MP_OKAY)
2064-
ret = MP_INIT_E;
2065-
2066-
if (ret == 0) {
2067-
SAVE_VECTOR_REGISTERS(ret = _svr_ret;);
2068-
2069-
if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY)
2070-
ret = MP_READ_E;
2071-
2072-
if (ret == 0)
2073-
ret = sp_DhExp_2048(y, priv, privSz, &key->p, agree, agreeSz);
2074-
2075-
mp_clear(y);
2076-
2077-
RESTORE_VECTOR_REGISTERS();
2078-
}
2079-
2080-
/* make sure agree is > 1 (SP800-56A, 5.7.1.1) */
2081-
if ((ret == 0) &&
2082-
((*agreeSz == 0) || ((*agreeSz == 1) && (agree[0] == 1))))
2083-
{
2084-
ret = MP_VAL;
2085-
}
2086-
2087-
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
2088-
#if !defined(WOLFSSL_SP_MATH)
2089-
XFREE(z, key->heap, DYNAMIC_TYPE_DH);
2090-
XFREE(x, key->heap, DYNAMIC_TYPE_DH);
2091-
#endif
2092-
XFREE(y, key->heap, DYNAMIC_TYPE_DH);
2093-
#endif
2094-
return ret;
2095-
}
2063+
|| mp_count_bits(&key->p) == 2048
20962064
#endif
20972065
#ifndef WOLFSSL_SP_NO_3072
2098-
if (mp_count_bits(&key->p) == 3072) {
2066+
|| mp_count_bits(&key->p) == 3072
2067+
#endif
2068+
#ifdef WOLFSSL_SP_4096
2069+
|| mp_count_bits(&key->p) == 4096
2070+
#endif
2071+
) {
2072+
int i = (int)*agreeSz - 1;
2073+
20992074
if (mp_init(y) != MP_OKAY)
21002075
ret = MP_INIT_E;
21012076

@@ -2105,8 +2080,26 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
21052080
if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY)
21062081
ret = MP_READ_E;
21072082

2108-
if (ret == 0)
2109-
ret = sp_DhExp_3072(y, priv, privSz, &key->p, agree, agreeSz);
2083+
if (ret == 0) {
2084+
#ifndef WOLFSSL_SP_NO_2048
2085+
if (mp_count_bits(&key->p) == 2048) {
2086+
ret = sp_DhExp_2048(y, priv, privSz, &key->p, agree,
2087+
agreeSz);
2088+
}
2089+
#endif
2090+
#ifndef WOLFSSL_SP_NO_3072
2091+
if (mp_count_bits(&key->p) == 3072) {
2092+
ret = sp_DhExp_3072(y, priv, privSz, &key->p, agree,
2093+
agreeSz);
2094+
}
2095+
#endif
2096+
#ifdef WOLFSSL_SP_4096
2097+
if (mp_count_bits(&key->p) == 4096) {
2098+
ret = sp_DhExp_4096(y, priv, privSz, &key->p, agree,
2099+
agreeSz);
2100+
}
2101+
#endif
2102+
}
21102103

21112104
mp_clear(y);
21122105

@@ -2120,40 +2113,16 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
21202113
ret = MP_VAL;
21212114
}
21222115

2123-
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
2124-
#if !defined(WOLFSSL_SP_MATH)
2125-
XFREE(z, key->heap, DYNAMIC_TYPE_DH);
2126-
XFREE(x, key->heap, DYNAMIC_TYPE_DH);
2127-
#endif
2128-
XFREE(y, key->heap, DYNAMIC_TYPE_DH);
2129-
#endif
2130-
return ret;
2131-
}
2132-
#endif
2133-
#ifdef WOLFSSL_SP_4096
2134-
if (mp_count_bits(&key->p) == 4096) {
2135-
if (mp_init(y) != MP_OKAY)
2136-
ret = MP_INIT_E;
2137-
2138-
if (ret == 0) {
2139-
SAVE_VECTOR_REGISTERS(ret = _svr_ret;);
2140-
2141-
if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY)
2142-
ret = MP_READ_E;
2143-
2144-
if (ret == 0)
2145-
ret = sp_DhExp_4096(y, priv, privSz, &key->p, agree, agreeSz);
2146-
2147-
mp_clear(y);
2148-
2149-
RESTORE_VECTOR_REGISTERS();
2150-
}
2116+
if ((ret == 0) && ct) {
2117+
word16 mask = 0xff;
2118+
sword16 o = (sword16)(*agreeSz - 1);
21512119

2152-
/* make sure agree is > 1 (SP800-56A, 5.7.1.1) */
2153-
if ((ret == 0) &&
2154-
((*agreeSz == 0) || ((*agreeSz == 1) && (agree[0] == 1))))
2155-
{
2156-
ret = MP_VAL;
2120+
*agreeSz = (word32)(i + 1);
2121+
for (; i >= 0 ; i--) {
2122+
agree[i] = agree[o] & (byte)mask;
2123+
mask = ctMask16LT(0, (int)o);
2124+
o = (sword16)(o + (sword16)mask);
2125+
}
21572126
}
21582127

21592128
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
@@ -2166,16 +2135,8 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
21662135
return ret;
21672136
}
21682137
#endif
2169-
#endif
21702138

21712139
#if !defined(WOLFSSL_SP_MATH)
2172-
if (ct) {
2173-
/* for the constant-time variant, we will probably use more bits in x for
2174-
* the modexp than we read from the private key, and those extra bits need
2175-
* to be zeroed.
2176-
*/
2177-
XMEMSET(x, 0, sizeof *x);
2178-
}
21792140
if (mp_init_multi(x, y, z, 0, 0, 0) != MP_OKAY) {
21802141
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
21812142
XFREE(z, key->heap, DYNAMIC_TYPE_DH);
@@ -2184,6 +2145,14 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
21842145
#endif
21852146
return MP_INIT_E;
21862147
}
2148+
#if defined(WOLFSSL_SP_MATH_ALL)
2149+
if (ct) {
2150+
/* TFM and Integer implementations keep high words zero.
2151+
* SP math implementation needs all words set to zero as it doesn't
2152+
* ensure unused words are zero. */
2153+
mp_forcezero(x);
2154+
}
2155+
#endif
21872156

21882157
SAVE_VECTOR_REGISTERS(ret = _svr_ret;);
21892158

@@ -2198,12 +2167,24 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
21982167
ret = MP_READ_E;
21992168

22002169
if (ret == 0) {
2201-
if (ct)
2202-
ret = mp_exptmod_ex(y, x,
2203-
((int)*agreeSz + DIGIT_BIT - 1) / DIGIT_BIT,
2170+
if (ct) {
2171+
int bits;
2172+
2173+
/* x is mod q but if q not available, use p (> q). */
2174+
if (mp_iszero(&key->q) == MP_NO) {
2175+
bits = mp_count_bits(&key->q);
2176+
}
2177+
else {
2178+
bits = mp_count_bits(&key->p);
2179+
}
2180+
/* Exponentiate to the maximum words of a valid x to ensure a
2181+
* constant time operation. */
2182+
ret = mp_exptmod_ex(y, x, (bits + DIGIT_BIT - 1) / DIGIT_BIT,
22042183
&key->p, z);
2205-
else
2184+
}
2185+
else {
22062186
ret = mp_exptmod(y, x, &key->p, z);
2187+
}
22072188
if (ret != MP_OKAY)
22082189
ret = MP_EXPTMOD_E;
22092190
}
@@ -2219,6 +2200,7 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
22192200

22202201
if (ret == 0) {
22212202
if (ct) {
2203+
/* Put the secret into a buffer in constant time. */
22222204
ret = mp_to_unsigned_bin_len_ct(z, agree, (int)*agreeSz);
22232205
}
22242206
else {
@@ -2316,7 +2298,8 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,
23162298
#else
23172299
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH)
23182300
if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) {
2319-
ret = wc_DhAgree_Async(key, agree, agreeSz, priv, privSz, otherPub, pubSz);
2301+
ret = wc_DhAgree_Async(key, agree, agreeSz, priv, privSz, otherPub,
2302+
pubSz);
23202303
}
23212304
else
23222305
#endif
@@ -2332,56 +2315,21 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,
23322315
int wc_DhAgree_ct(DhKey* key, byte* agree, word32 *agreeSz, const byte* priv,
23332316
word32 privSz, const byte* otherPub, word32 pubSz)
23342317
{
2335-
int ret;
23362318
word32 requested_agreeSz;
2337-
#ifndef WOLFSSL_NO_MALLOC
2338-
byte *agree_buffer = NULL;
2339-
#else
2340-
byte agree_buffer[DH_MAX_SIZE / 8];
2341-
#endif
23422319

23432320
if (key == NULL || agree == NULL || agreeSz == NULL || priv == NULL ||
23442321
otherPub == NULL) {
23452322
return BAD_FUNC_ARG;
23462323
}
23472324

2348-
requested_agreeSz = *agreeSz;
2349-
2350-
#ifndef WOLFSSL_NO_MALLOC
2351-
agree_buffer = (byte *)XMALLOC(requested_agreeSz, key->heap,
2352-
DYNAMIC_TYPE_DH);
2353-
if (agree_buffer == NULL)
2354-
return MEMORY_E;
2355-
#endif
2356-
2357-
XMEMSET(agree_buffer, 0, requested_agreeSz);
2358-
2359-
ret = wc_DhAgree_Sync(key, agree_buffer, agreeSz, priv, privSz, otherPub,
2360-
pubSz, 1);
2361-
2362-
if (ret == 0) {
2363-
/* Arrange for correct fixed-length, right-justified key, even if the
2364-
* crypto back end doesn't support it. This assures that the key is
2365-
* unconditionally agreed correctly. With some crypto back ends,
2366-
* e.g. heapmath, there are no provisions for actual constant time, but
2367-
* with others the key computation and clamping is constant time, and
2368-
* the unclamping here is also constant time.
2369-
*/
2370-
byte *agree_src = agree_buffer + *agreeSz - 1,
2371-
*agree_dst = agree + requested_agreeSz - 1;
2372-
while (agree_dst >= agree) {
2373-
word32 mask = (agree_src >= agree_buffer) - 1U;
2374-
agree_src += (mask & requested_agreeSz);
2375-
*agree_dst-- = *agree_src--;
2376-
}
2377-
*agreeSz = requested_agreeSz;
2325+
requested_agreeSz = (word32)mp_unsigned_bin_size(&key->p);
2326+
if (requested_agreeSz > *agreeSz) {
2327+
return BUFFER_E;
23782328
}
2329+
*agreeSz = requested_agreeSz;
23792330

2380-
#ifndef WOLFSSL_NO_MALLOC
2381-
XFREE(agree_buffer, key->heap, DYNAMIC_TYPE_DH);
2382-
#endif
2383-
2384-
return ret;
2331+
return wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz,
2332+
1);
23852333
}
23862334

23872335
#ifdef WOLFSSL_DH_EXTRA

wolfcrypt/src/sp_int.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5241,7 +5241,7 @@ int sp_grow(sp_int* a, int l)
52415241
#endif /* (!NO_RSA && !WOLFSSL_RSA_VERIFY_ONLY) || !NO_DH || HAVE_ECC */
52425242

52435243
#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
5244-
defined(HAVE_ECC)
5244+
defined(HAVE_ECC) || defined(WOLFSSL_PUBLIC_MP)
52455245
/* Set the multi-precision number to zero.
52465246
*
52475247
* @param [out] a SP integer to set to zero.
@@ -5826,7 +5826,7 @@ int sp_cmp_ct(const sp_int* a, const sp_int* b, unsigned int n)
58265826

58275827
#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \
58285828
((defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_SP_SM2)) && \
5829-
defined(HAVE_ECC)) || defined(OPENSSL_EXTRA)
5829+
defined(HAVE_ECC)) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_PUBLIC_MP)
58305830
/* Check if a bit is set
58315831
*
58325832
* When a is NULL, result is 0.

wolfcrypt/src/tfm.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4198,6 +4198,58 @@ int fp_to_unsigned_bin(fp_int *a, unsigned char *b)
41984198
return FP_OKAY;
41994199
}
42004200

4201+
int fp_to_unsigned_bin_len_ct(fp_int *a, unsigned char *out, int outSz)
4202+
{
4203+
int err = MP_OKAY;
4204+
4205+
/* Validate parameters. */
4206+
if ((a == NULL) || (out == NULL) || (outSz < 0)) {
4207+
err = MP_VAL;
4208+
}
4209+
4210+
#if DIGIT_BIT > 8
4211+
if (err == MP_OKAY) {
4212+
/* Start at the end of the buffer - least significant byte. */
4213+
int j;
4214+
unsigned int i;
4215+
fp_digit mask = (fp_digit)-1;
4216+
fp_digit d;
4217+
4218+
/* Put each digit in. */
4219+
i = 0;
4220+
for (j = outSz - 1; j >= 0; ) {
4221+
unsigned int b;
4222+
d = a->dp[i];
4223+
/* Place each byte of a digit into the buffer. */
4224+
for (b = 0; (j >= 0) && (b < (DIGIT_BIT / 8)); b++) {
4225+
out[j--] = (byte)(d & mask);
4226+
d >>= 8;
4227+
}
4228+
mask &= (fp_digit)0 - (i < (unsigned int)a->used - 1);
4229+
i += (unsigned int)(1 & mask);
4230+
}
4231+
}
4232+
#else
4233+
if ((err == MP_OKAY) && ((unsigned int)outSz < a->used)) {
4234+
err = MP_VAL;
4235+
}
4236+
if (err == MP_OKAY) {
4237+
unsigned int i;
4238+
int j;
4239+
fp_digit mask = (fp_digit)-1;
4240+
4241+
i = 0;
4242+
for (j = outSz - 1; j >= 0; j--) {
4243+
out[j] = a->dp[i] & mask;
4244+
mask &= (fp_digit)0 - (i < (unsigned int)a->used - 1);
4245+
i += (unsigned int)(1 & mask);
4246+
}
4247+
}
4248+
#endif
4249+
4250+
return err;
4251+
}
4252+
42014253
int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c)
42024254
{
42034255
#if DIGIT_BIT == 64 || DIGIT_BIT == 32 || DIGIT_BIT == 16
@@ -4823,6 +4875,11 @@ int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
48234875
return fp_to_unsigned_bin(a,b);
48244876
}
48254877

4878+
int mp_to_unsigned_bin_len_ct(mp_int * a, unsigned char *b, int c)
4879+
{
4880+
return fp_to_unsigned_bin_len_ct(a, b, c);
4881+
}
4882+
48264883
int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c)
48274884
{
48284885
return fp_to_unsigned_bin_len(a, b, c);

0 commit comments

Comments
 (0)