11/* ====================================================================
2- * Copyright (c) 2011 The OpenSSL Project. All rights reserved.
2+ * Copyright (c) 2011-2013 The OpenSSL Project. All rights reserved.
33 *
44 * Redistribution and use in source and binary forms, with or without
55 * modification, are permitted provided that the following conditions
@@ -90,6 +90,10 @@ typedef struct
9090 defined(_M_AMD64 ) || defined(_M_X64 ) || \
9191 defined(__INTEL__ ) )
9292
93+ #if defined(__GNUC__ ) && __GNUC__ >=2 && !defined(PEDANTIC )
94+ # define BSWAP (x ) ({ unsigned int r=(x); asm ("bswapl %0":"=r"(r):"0"(r)); r; })
95+ #endif
96+
9397extern unsigned int OPENSSL_ia32cap_P [2 ];
9498#define AESNI_CAPABLE (1<<(57-32))
9599
@@ -167,6 +171,9 @@ static void sha1_update(SHA_CTX *c,const void *data,size_t len)
167171 SHA1_Update (c ,ptr ,res );
168172}
169173
174+ #ifdef SHA1_Update
175+ #undef SHA1_Update
176+ #endif
170177#define SHA1_Update sha1_update
171178
172179static int aesni_cbc_hmac_sha1_cipher (EVP_CIPHER_CTX * ctx , unsigned char * out ,
@@ -184,6 +191,8 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
184191 sha_off = SHA_CBLOCK - key -> md .num ;
185192#endif
186193
194+ key -> payload_length = NO_PAYLOAD_LENGTH ;
195+
187196 if (len %AES_BLOCK_SIZE ) return 0 ;
188197
189198 if (ctx -> encrypt ) {
@@ -234,47 +243,203 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
234243 & key -> ks ,ctx -> iv ,1 );
235244 }
236245 } else {
237- unsigned char mac [SHA_DIGEST_LENGTH ];
246+ union { unsigned int u [SHA_DIGEST_LENGTH /sizeof (unsigned int )];
247+ unsigned char c [SHA_DIGEST_LENGTH ]; } mac ;
238248
239249 /* decrypt HMAC|padding at once */
240250 aesni_cbc_encrypt (in ,out ,len ,
241251 & key -> ks ,ctx -> iv ,0 );
242252
243253 if (plen ) { /* "TLS" mode of operation */
244- /* figure out payload length */
245- if (len < (size_t )(out [len - 1 ]+ 1 + SHA_DIGEST_LENGTH ))
246- return 0 ;
247-
248- len -= (out [len - 1 ]+ 1 + SHA_DIGEST_LENGTH );
254+ size_t inp_len , mask , j , i ;
255+ unsigned int res , maxpad , pad , bitlen ;
256+ int ret = 1 ;
257+ union { unsigned int u [SHA_LBLOCK ];
258+ unsigned char c [SHA_CBLOCK ]; }
259+ * data = (void * )key -> md .data ;
249260
250261 if ((key -> aux .tls_aad [plen - 4 ]<<8 |key -> aux .tls_aad [plen - 3 ])
251- >= TLS1_1_VERSION ) {
252- len -= AES_BLOCK_SIZE ;
262+ >= TLS1_1_VERSION )
253263 iv = AES_BLOCK_SIZE ;
254- }
255264
256- key -> aux .tls_aad [plen - 2 ] = len >>8 ;
257- key -> aux .tls_aad [plen - 1 ] = len ;
265+ if (len < (iv + SHA_DIGEST_LENGTH + 1 ))
266+ return 0 ;
267+
268+ /* omit explicit iv */
269+ out += iv ;
270+ len -= iv ;
271+
272+ /* figure out payload length */
273+ pad = out [len - 1 ];
274+ maxpad = len - (SHA_DIGEST_LENGTH + 1 );
275+ maxpad |= (255 - maxpad )>>(sizeof (maxpad )* 8 - 8 );
276+ maxpad &= 255 ;
277+
278+ inp_len = len - (SHA_DIGEST_LENGTH + pad + 1 );
279+ mask = (0 - ((inp_len - len )>>(sizeof (inp_len )* 8 - 1 )));
280+ inp_len &= mask ;
281+ ret &= (int )mask ;
258282
259- /* calculate HMAC and verify it */
283+ key -> aux .tls_aad [plen - 2 ] = inp_len >>8 ;
284+ key -> aux .tls_aad [plen - 1 ] = inp_len ;
285+
286+ /* calculate HMAC */
260287 key -> md = key -> head ;
261288 SHA1_Update (& key -> md ,key -> aux .tls_aad ,plen );
262- SHA1_Update (& key -> md ,out + iv ,len );
263- SHA1_Final (mac ,& key -> md );
264289
290+ #if 1
291+ len -= SHA_DIGEST_LENGTH ; /* amend mac */
292+ if (len >=(256 + SHA_CBLOCK )) {
293+ j = (len - (256 + SHA_CBLOCK ))& (0 - SHA_CBLOCK );
294+ j += SHA_CBLOCK - key -> md .num ;
295+ SHA1_Update (& key -> md ,out ,j );
296+ out += j ;
297+ len -= j ;
298+ inp_len -= j ;
299+ }
300+
301+ /* but pretend as if we hashed padded payload */
302+ bitlen = key -> md .Nl + (inp_len <<3 ); /* at most 18 bits */
303+ mac .c [0 ] = 0 ;
304+ mac .c [1 ] = (unsigned char )(bitlen >>16 );
305+ mac .c [2 ] = (unsigned char )(bitlen >>8 );
306+ mac .c [3 ] = (unsigned char )bitlen ;
307+ bitlen = mac .u [0 ];
308+
309+ mac .u [0 ]= 0 ;
310+ mac .u [1 ]= 0 ;
311+ mac .u [2 ]= 0 ;
312+ mac .u [3 ]= 0 ;
313+ mac .u [4 ]= 0 ;
314+
315+ for (res = key -> md .num , j = 0 ;j < len ;j ++ ) {
316+ size_t c = out [j ];
317+ mask = (j - inp_len )>>(sizeof (j )* 8 - 8 );
318+ c &= mask ;
319+ c |= 0x80 & ~mask & ~((inp_len - j )>>(sizeof (j )* 8 - 8 ));
320+ data -> c [res ++ ]= (unsigned char )c ;
321+
322+ if (res != SHA_CBLOCK ) continue ;
323+
324+ mask = 0 - ((inp_len + 8 - j )>>(sizeof (j )* 8 - 1 ));
325+ data -> u [SHA_LBLOCK - 1 ] |= bitlen & mask ;
326+ sha1_block_data_order (& key -> md ,data ,1 );
327+ mask &= 0 - ((j - inp_len - 73 )>>(sizeof (j )* 8 - 1 ));
328+ mac .u [0 ] |= key -> md .h0 & mask ;
329+ mac .u [1 ] |= key -> md .h1 & mask ;
330+ mac .u [2 ] |= key -> md .h2 & mask ;
331+ mac .u [3 ] |= key -> md .h3 & mask ;
332+ mac .u [4 ] |= key -> md .h4 & mask ;
333+ res = 0 ;
334+ }
335+
336+ for (i = res ;i < SHA_CBLOCK ;i ++ ,j ++ ) data -> c [i ]= 0 ;
337+
338+ if (res > SHA_CBLOCK - 8 ) {
339+ mask = 0 - ((inp_len + 8 - j )>>(sizeof (j )* 8 - 1 ));
340+ data -> u [SHA_LBLOCK - 1 ] |= bitlen & mask ;
341+ sha1_block_data_order (& key -> md ,data ,1 );
342+ mask &= 0 - ((j - inp_len - 73 )>>(sizeof (j )* 8 - 1 ));
343+ mac .u [0 ] |= key -> md .h0 & mask ;
344+ mac .u [1 ] |= key -> md .h1 & mask ;
345+ mac .u [2 ] |= key -> md .h2 & mask ;
346+ mac .u [3 ] |= key -> md .h3 & mask ;
347+ mac .u [4 ] |= key -> md .h4 & mask ;
348+
349+ memset (data ,0 ,SHA_CBLOCK );
350+ j += 64 ;
351+ }
352+ data -> u [SHA_LBLOCK - 1 ] = bitlen ;
353+ sha1_block_data_order (& key -> md ,data ,1 );
354+ mask = 0 - ((j - inp_len - 73 )>>(sizeof (j )* 8 - 1 ));
355+ mac .u [0 ] |= key -> md .h0 & mask ;
356+ mac .u [1 ] |= key -> md .h1 & mask ;
357+ mac .u [2 ] |= key -> md .h2 & mask ;
358+ mac .u [3 ] |= key -> md .h3 & mask ;
359+ mac .u [4 ] |= key -> md .h4 & mask ;
360+
361+ #ifdef BSWAP
362+ mac .u [0 ] = BSWAP (mac .u [0 ]);
363+ mac .u [1 ] = BSWAP (mac .u [1 ]);
364+ mac .u [2 ] = BSWAP (mac .u [2 ]);
365+ mac .u [3 ] = BSWAP (mac .u [3 ]);
366+ mac .u [4 ] = BSWAP (mac .u [4 ]);
367+ #else
368+ for (i = 0 ;i < 5 ;i ++ ) {
369+ res = mac .u [i ];
370+ mac .c [4 * i + 0 ]= (unsigned char )(res >>24 );
371+ mac .c [4 * i + 1 ]= (unsigned char )(res >>16 );
372+ mac .c [4 * i + 2 ]= (unsigned char )(res >>8 );
373+ mac .c [4 * i + 3 ]= (unsigned char )res ;
374+ }
375+ #endif
376+ len += SHA_DIGEST_LENGTH ;
377+ #else
378+ SHA1_Update (& key -> md ,out ,inp_len );
379+ res = key -> md .num ;
380+ SHA1_Final (mac .c ,& key -> md );
381+
382+ {
383+ unsigned int inp_blocks , pad_blocks ;
384+
385+ /* but pretend as if we hashed padded payload */
386+ inp_blocks = 1 + ((SHA_CBLOCK - 9 - res )>>(sizeof (res )* 8 - 1 ));
387+ res += (unsigned int )(len - inp_len );
388+ pad_blocks = res / SHA_CBLOCK ;
389+ res %= SHA_CBLOCK ;
390+ pad_blocks += 1 + ((SHA_CBLOCK - 9 - res )>>(sizeof (res )* 8 - 1 ));
391+ for (;inp_blocks < pad_blocks ;inp_blocks ++ )
392+ sha1_block_data_order (& key -> md ,data ,1 );
393+ }
394+ #endif
265395 key -> md = key -> tail ;
266- SHA1_Update (& key -> md ,mac ,SHA_DIGEST_LENGTH );
267- SHA1_Final (mac ,& key -> md );
396+ SHA1_Update (& key -> md ,mac . c ,SHA_DIGEST_LENGTH );
397+ SHA1_Final (mac . c ,& key -> md );
268398
269- if (memcmp (out + iv + len ,mac ,SHA_DIGEST_LENGTH ))
270- return 0 ;
399+ /* verify HMAC */
400+ out += inp_len ;
401+ len -= inp_len ;
402+ #if 1
403+ {
404+ unsigned char * p = out + len - 1 - maxpad - SHA_DIGEST_LENGTH ;
405+ size_t off = out - p ;
406+ unsigned int c , cmask ;
407+
408+ maxpad += SHA_DIGEST_LENGTH ;
409+ for (res = 0 ,i = 0 ,j = 0 ;j < maxpad ;j ++ ) {
410+ c = p [j ];
411+ cmask = ((int )(j - off - SHA_DIGEST_LENGTH ))>>(sizeof (int )* 8 - 1 );
412+ res |= (c ^pad )& ~cmask ; /* ... and padding */
413+ cmask &= ((int )(off - 1 - j ))>>(sizeof (int )* 8 - 1 );
414+ res |= (c ^mac .c [i ])& cmask ;
415+ i += 1 & cmask ;
416+ }
417+ maxpad -= SHA_DIGEST_LENGTH ;
418+
419+ res = 0 - ((0 - res )>>(sizeof (res )* 8 - 1 ));
420+ ret &= (int )~res ;
421+ }
422+ #else
423+ for (res = 0 ,i = 0 ;i < SHA_DIGEST_LENGTH ;i ++ )
424+ res |= out [i ]^mac .c [i ];
425+ res = 0 - ((0 - res )>>(sizeof (res )* 8 - 1 ));
426+ ret &= (int )~res ;
427+
428+ /* verify padding */
429+ pad = (pad & ~res ) | (maxpad & res );
430+ out = out + len - 1 - pad ;
431+ for (res = 0 ,i = 0 ;i < pad ;i ++ )
432+ res |= out [i ]^pad ;
433+
434+ res = (0 - res )>>(sizeof (res )* 8 - 1 );
435+ ret &= (int )~res ;
436+ #endif
437+ return ret ;
271438 } else {
272439 SHA1_Update (& key -> md ,out ,len );
273440 }
274441 }
275442
276- key -> payload_length = NO_PAYLOAD_LENGTH ;
277-
278443 return 1 ;
279444 }
280445
0 commit comments