@@ -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,
22962301int 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