@@ -51,6 +51,11 @@ typedef struct wp_HmacCtx {
5151 unsigned char * key ;
5252 /** Length of private key in bytes. */
5353 size_t keyLen ;
54+
55+ /** Length of the padded TLS record including MAC and padding. */
56+ size_t tlsDataSize ;
57+ /** Number of dummy blocks to hash in final to equalize hashing time. */
58+ int tlsDummyBlocks ;
5459} wp_HmacCtx ;
5560
5661
@@ -205,6 +210,8 @@ static wp_HmacCtx* wp_hmac_dup(wp_HmacCtx* src)
205210 dst -> type = src -> type ;
206211 dst -> size = src -> size ;
207212 dst -> provCtx = src -> provCtx ;
213+ dst -> tlsDataSize = src -> tlsDataSize ;
214+ dst -> tlsDummyBlocks = src -> tlsDummyBlocks ;
208215
209216 /* Copy the Hmac struct directly to preserve in-progress state.
210217 * wc_HmacCopy is not available in all wolfSSL versions. */
@@ -258,6 +265,64 @@ static int wp_hmac_init(wp_HmacCtx* macCtx, const unsigned char* key,
258265 return ok ;
259266}
260267
268+ /** Length of the TLS record header hashed before the record data. */
269+ #define WP_TLS_HMAC_HEADER_SZ 13
270+
271+ /**
272+ * Count the blocks a hash processes for a message of the given length.
273+ *
274+ * @param [in] len Length of message in bytes.
275+ * @param [in] blockBits Log base 2 of the hash block size.
276+ * @param [in] blockMask Hash block size minus one.
277+ * @param [in] padSz Bytes of padding the hash appends to the message.
278+ * @return Number of blocks processed.
279+ */
280+ static int wp_hmac_blocks (word32 len , int blockBits , word32 blockMask ,
281+ word32 padSz )
282+ {
283+ return (int )(len >> blockBits ) +
284+ (wp_ct_int_mask_lt ((int )((len + padSz ) & blockMask ), (int )padSz ) & 1 );
285+ }
286+
287+ /**
288+ * Calculate the number of dummy blocks to hash when finalizing a TLS record.
289+ *
290+ * @param [in] hashType wolfSSL digest type.
291+ * @param [in] macSize Output size of the digest in bytes.
292+ * @param [in] tlsDataSize Length of the padded record including MAC and
293+ * padding.
294+ * @param [in] dataLen Length of data passed to update in bytes.
295+ * @return Number of dummy blocks to hash. At least one.
296+ */
297+ int wp_hmac_tls_dummy_blocks (enum wc_HashType hashType , size_t macSize ,
298+ size_t tlsDataSize , size_t dataLen )
299+ {
300+ int blockSizeRet = wc_HashGetBlockSize (hashType );
301+ word32 blockSz ;
302+ word32 blockMask ;
303+ word32 padSz ;
304+ word32 realSz ;
305+ word32 maxSz ;
306+ int blockBits = 0 ;
307+
308+ if ((blockSizeRet <= 0 ) || (tlsDataSize <= macSize )) {
309+ return 1 ;
310+ }
311+
312+ blockSz = (word32 )blockSizeRet ;
313+ blockMask = blockSz - 1 ;
314+ while (((word32 )1 << blockBits ) < blockSz ) {
315+ blockBits ++ ;
316+ }
317+ padSz = blockSz >> 3 ;
318+
319+ realSz = WP_TLS_HMAC_HEADER_SZ + (word32 )dataLen ;
320+ maxSz = WP_TLS_HMAC_HEADER_SZ + (word32 )(tlsDataSize - 1 - macSize );
321+
322+ return 1 + wp_hmac_blocks (maxSz , blockBits , blockMask , padSz ) -
323+ wp_hmac_blocks (realSz , blockBits , blockMask , padSz );
324+ }
325+
261326/**
262327 * Update the MAC state with data.
263328 *
@@ -274,6 +339,11 @@ static int wp_hmac_update(wp_HmacCtx* macCtx, const unsigned char* data,
274339
275340 WOLFPROV_ENTER (WP_LOG_COMP_MAC , "wp_hmac_update" );
276341
342+ if (macCtx -> tlsDataSize > 0 ) {
343+ macCtx -> tlsDummyBlocks = wp_hmac_tls_dummy_blocks (macCtx -> type ,
344+ macCtx -> size , macCtx -> tlsDataSize , dataLen );
345+ }
346+
277347 while (ok && (dataLen > 0 )) {
278348 word32 chunk = (!WP_FITS_WORD32 (dataLen )) ?
279349 0xFFFFFFFFU : (word32 )dataLen ;
@@ -323,6 +393,24 @@ static int wp_hmac_final(wp_HmacCtx* macCtx, unsigned char* out, size_t* outl,
323393 ok = 0 ;
324394 }
325395 }
396+ if (ok && (macCtx -> tlsDataSize > 0 )) {
397+ unsigned char dummy [WC_MAX_BLOCK_SIZE ];
398+ int blockSz = wc_HashGetBlockSize (macCtx -> type );
399+ int i ;
400+
401+ if (blockSz <= 0 ) {
402+ ok = 0 ;
403+ }
404+ XMEMSET (dummy , 0 , sizeof (dummy ));
405+ for (i = 0 ; ok && (i < macCtx -> tlsDummyBlocks ); i ++ ) {
406+ rc = wc_HmacUpdate (& macCtx -> hmac , dummy , (word32 )blockSz );
407+ if (rc != 0 ) {
408+ WOLFPROV_MSG_DEBUG_RETCODE (WP_LOG_LEVEL_DEBUG , "wc_HmacUpdate" ,
409+ rc );
410+ ok = 0 ;
411+ }
412+ }
413+ }
326414 if (ok ) {
327415 * outl = macCtx -> size ;
328416 }
@@ -402,6 +490,7 @@ static const OSSL_PARAM* wp_hmac_settable_ctx_params(wp_HmacCtx* macCtx,
402490 static const OSSL_PARAM wp_hmac_supported_settable_ctx_params [] = {
403491 OSSL_PARAM_utf8_string (OSSL_MAC_PARAM_DIGEST , NULL , 0 ),
404492 OSSL_PARAM_octet_string (OSSL_MAC_PARAM_KEY , NULL , 0 ),
493+ OSSL_PARAM_size_t (OSSL_MAC_PARAM_TLS_DATA_SIZE , NULL ),
405494 OSSL_PARAM_END
406495 };
407496 (void )macCtx ;
@@ -443,6 +532,15 @@ static int wp_hmac_set_ctx_params(wp_HmacCtx* macCtx, const OSSL_PARAM params[])
443532 ok = 0 ;
444533 }
445534 }
535+
536+ if (ok ) {
537+ const OSSL_PARAM * p = OSSL_PARAM_locate_const (params ,
538+ OSSL_MAC_PARAM_TLS_DATA_SIZE );
539+ if ((p != NULL ) && (!OSSL_PARAM_get_size_t (p ,
540+ & macCtx -> tlsDataSize ))) {
541+ ok = 0 ;
542+ }
543+ }
446544 }
447545
448546 WOLFPROV_LEAVE (WP_LOG_COMP_MAC , __FILE__ ":" WOLFPROV_STRINGIZE (__LINE__ ), ok );
0 commit comments