Skip to content

Commit 5ef617a

Browse files
authored
Merge pull request #7978 from douzzer/20240916-wc_DhAgree_ct-sp-math
20240916-wc_DhAgree_ct-sp-math
2 parents 9666394 + 04c781a commit 5ef617a

2 files changed

Lines changed: 57 additions & 7 deletions

File tree

src/ssl_load.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ static int DataToDerBuffer(const unsigned char* buff, word32 len, int format,
137137
FreeDer(der);
138138
}
139139
#else
140+
(void)algId;
140141
ret = NOT_COMPILED_IN;
141142
#endif
142143
}

wolfcrypt/src/dh.c

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,6 +2138,13 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
21382138
#endif
21392139

21402140
#if !defined(WOLFSSL_SP_MATH)
2141+
if (ct) {
2142+
/* for the constant-time variant, we will probably use more bits in x for
2143+
* the modexp than we read from the private key, and those extra bits need
2144+
* to be zeroed.
2145+
*/
2146+
XMEMSET(x, 0, sizeof *x);
2147+
}
21412148
if (mp_init_multi(x, y, z, 0, 0, 0) != MP_OKAY) {
21422149
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC)
21432150
XFREE(z, key->heap, DYNAMIC_TYPE_DH);
@@ -2181,13 +2188,11 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz,
21812188

21822189
if (ret == 0) {
21832190
if (ct) {
2184-
if (mp_to_unsigned_bin_len_ct(z, agree, (int)*agreeSz) != MP_OKAY)
2185-
ret = MP_TO_E;
2191+
ret = mp_to_unsigned_bin_len_ct(z, agree, (int)*agreeSz);
21862192
}
21872193
else {
2188-
if (mp_to_unsigned_bin(z, agree) != MP_OKAY)
2189-
ret = MP_TO_E;
2190-
if (ret == 0)
2194+
ret = mp_to_unsigned_bin(z, agree);
2195+
if (ret == MP_OKAY)
21912196
*agreeSz = (word32)mp_unsigned_bin_size(z);
21922197
}
21932198
}
@@ -2296,13 +2301,57 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,
22962301
int wc_DhAgree_ct(DhKey* key, byte* agree, word32 *agreeSz, const byte* priv,
22972302
word32 privSz, const byte* otherPub, word32 pubSz)
22982303
{
2304+
int ret;
2305+
word32 requested_agreeSz;
2306+
#ifndef WOLFSSL_NO_MALLOC
2307+
byte *agree_buffer = NULL;
2308+
#else
2309+
byte agree_buffer[DH_MAX_SIZE / 8];
2310+
#endif
2311+
22992312
if (key == NULL || agree == NULL || agreeSz == NULL || priv == NULL ||
23002313
otherPub == NULL) {
23012314
return BAD_FUNC_ARG;
23022315
}
23032316

2304-
return wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz,
2305-
1);
2317+
requested_agreeSz = *agreeSz;
2318+
2319+
#ifndef WOLFSSL_NO_MALLOC
2320+
agree_buffer = (byte *)XMALLOC(requested_agreeSz, key->heap,
2321+
DYNAMIC_TYPE_DH);
2322+
if (agree_buffer == NULL)
2323+
return MEMORY_E;
2324+
#endif
2325+
2326+
XMEMSET(agree, 0, requested_agreeSz);
2327+
XMEMSET(agree_buffer, 0, requested_agreeSz);
2328+
2329+
ret = wc_DhAgree_Sync(key, agree_buffer, agreeSz, priv, privSz, otherPub,
2330+
pubSz, 1);
2331+
2332+
if (ret == 0) {
2333+
/* Arrange for correct fixed-length, right-justified key, even if the
2334+
* crypto back end doesn't support it. This assures that the key is
2335+
* unconditionally agreed correctly. With some crypto back ends,
2336+
* e.g. heapmath, there are no provisions for actual constant time, but
2337+
* with others the key computation and clamping is constant time, and
2338+
* the unclamping here is also constant time.
2339+
*/
2340+
byte *agree_src = agree_buffer + *agreeSz - 1,
2341+
*agree_dst = agree + requested_agreeSz - 1;
2342+
while (agree_dst >= agree) {
2343+
word32 mask = (agree_src >= agree_buffer) - 1U;;
2344+
agree_src += (mask & requested_agreeSz);
2345+
*agree_dst-- = *agree_src--;
2346+
}
2347+
*agreeSz = requested_agreeSz;
2348+
}
2349+
2350+
#ifndef WOLFSSL_NO_MALLOC
2351+
XFREE(agree_buffer, key->heap, DYNAMIC_TYPE_DH);
2352+
#endif
2353+
2354+
return ret;
23062355
}
23072356

23082357
#ifdef WOLFSSL_DH_EXTRA

0 commit comments

Comments
 (0)