cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ssl_cry.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib SSL v3/TLS Crypto Routines *
4 * Copyright Peter Gutmann 1998-2010 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "misc_rw.h"
11  #include "session.h"
12  #include "ssl.h"
13 #else
14  #include "crypt.h"
15  #include "enc_dec/misc_rw.h"
16  #include "session/session.h"
17  #include "session/ssl.h"
18 #endif /* Compiler-specific includes */
19 
20 /* Proto-HMAC padding data */
21 
22 #define PROTOHMAC_PAD1_VALUE 0x36
23 #define PROTOHMAC_PAD2_VALUE 0x5C
24 #define PROTOHMAC_PAD1 "\x36\x36\x36\x36\x36\x36\x36\x36" \
25  "\x36\x36\x36\x36\x36\x36\x36\x36" \
26  "\x36\x36\x36\x36\x36\x36\x36\x36" \
27  "\x36\x36\x36\x36\x36\x36\x36\x36" \
28  "\x36\x36\x36\x36\x36\x36\x36\x36" \
29  "\x36\x36\x36\x36\x36\x36\x36\x36"
30 #define PROTOHMAC_PAD2 "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" \
31  "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" \
32  "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" \
33  "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" \
34  "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C" \
35  "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C"
36 
37 #ifdef USE_SSL
38 
39 /****************************************************************************
40 * *
41 * Utility Functions *
42 * *
43 ****************************************************************************/
44 
45 /* Write packet metadata for input to the MAC/ICV authentication process:
46 
47  seq_num || type || version || length */
48 
49 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
50 static int writePacketMetadata( OUT_BUFFER( dataMaxLength, *dataLength ) \
51  void *data,
52  IN_LENGTH_SHORT_MIN( 16 ) const int dataMaxLength,
54  IN_RANGE( 0, 255 ) const int type,
55  IN_INT_Z const long seqNo,
57  SSL_MINOR_VERSION_TLS12 ) const int version,
58  IN_LENGTH_Z const int payloadLength )
59  {
60  STREAM stream;
61  int status;
62 
63  assert( isWritePtr( data, dataMaxLength ) );
64  assert( isWritePtr( dataLength, sizeof( int ) ) );
65 
66  REQUIRES( dataMaxLength >= 16 && dataMaxLength < MAX_INTLENGTH_SHORT );
67  REQUIRES( type >= 0 && type <= 255 );
68  REQUIRES( seqNo >= 0 );
69  REQUIRES( version >= SSL_MINOR_VERSION_TLS && \
70  version <= SSL_MINOR_VERSION_TLS12 );
71  REQUIRES( payloadLength > 0 && payloadLength <= MAX_PACKET_SIZE );
72 
73  /* Clear return values */
74  memset( data, 0, min( 16, dataMaxLength ) );
75  *dataLength = 0;
76 
77  /* Write the sequence number, packet type, version, and length
78  information to the output buffer */
79  sMemOpen( &stream, data, dataMaxLength );
80  writeUint64( &stream, seqNo );
81  sputc( &stream, type );
82  sputc( &stream, SSL_MAJOR_VERSION );
83  sputc( &stream, version );
84  status = writeUint16( &stream, payloadLength );
85  if( cryptStatusOK( status ) )
86  *dataLength = stell( &stream );
87  sMemDisconnect( &stream );
88  return( status );
89  }
90 
91 /****************************************************************************
92 * *
93 * Encrypt/Decrypt Functions *
94 * *
95 ****************************************************************************/
96 
97 /* Encrypt/decrypt a data block (in mose cases this also includes the MAC,
98  which has been added to the data by the caller). The handling of length
99  arguments for these is a bit tricky, for encryption the input is { data,
100  payloadLength } which is padded (if necessary) and the padded length
101  returned in '*dataLength', for decryption the entire data block will be
102  processed but only 'processedDataLength' bytes of result are valid
103  output */
104 
105 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
106 int encryptData( const SESSION_INFO *sessionInfoPtr,
107  INOUT_BUFFER( dataMaxLength, *dataLength ) \
108  BYTE *data,
109  IN_LENGTH const int dataMaxLength,
110  OUT_LENGTH_Z int *dataLength,
111  IN_LENGTH const int payloadLength )
112  {
113  int length = payloadLength, status;
114 
115  assert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
116  assert( isWritePtr( data, dataMaxLength ) );
117  assert( isWritePtr( dataLength, sizeof( int ) ) );
118 
119  REQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_INTLENGTH );
120  REQUIRES( payloadLength > 0 && \
121  payloadLength <= MAX_PACKET_SIZE + 20 && \
122  payloadLength <= sessionInfoPtr->sendBufSize && \
123  payloadLength <= dataMaxLength );
124 
125  /* Clear return value */
126  *dataLength = 0;
127 
128  /* If it's a block cipher then we need to add end-of-block padding */
129  if( sessionInfoPtr->cryptBlocksize > 1 )
130  {
131  const int padSize = ( sessionInfoPtr->cryptBlocksize - 1 ) - \
132  ( payloadLength & ( sessionInfoPtr->cryptBlocksize - 1 ) );
133  int i;
134 
135  ENSURES( padSize >= 0 && padSize <= CRYPT_MAX_IVSIZE && \
136  length + padSize + 1 <= dataMaxLength );
137 
138  /* Add the PKCS #5-style padding (PKCS #5 uses n, TLS uses n-1) */
139  for( i = 0; i < padSize + 1; i++ )
140  data[ length++ ] = intToByte( padSize );
141  }
142 
143  /* Encrypt the data and optional padding */
144  status = krnlSendMessage( sessionInfoPtr->iCryptOutContext,
145  IMESSAGE_CTX_ENCRYPT, data, length );
146  if( cryptStatusError( status ) )
147  return( status );
148  *dataLength = length;
149 
150  /* If we're using GCM then we have to append the ICV to the data */
151  if( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM )
152  {
154 
155  REQUIRES( length + sessionInfoPtr->authBlocksize <= dataMaxLength );
156 
157  setMessageData( &msgData, data + length,
158  sessionInfoPtr->authBlocksize );
159  status = krnlSendMessage( sessionInfoPtr->iCryptOutContext,
160  IMESSAGE_GETATTRIBUTE_S, &msgData,
161  CRYPT_IATTRIBUTE_ICV );
162  if( cryptStatusError( status ) )
163  return( status );
164  *dataLength += sessionInfoPtr->authBlocksize;
165  }
166 
167  return( CRYPT_OK );
168  }
169 
170 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
171 int decryptData( SESSION_INFO *sessionInfoPtr,
172  INOUT_BUFFER_FIXED( dataLength ) \
173  BYTE *data,
174  IN_LENGTH const int dataLength,
176  {
177  int length = dataLength, padSize, status;
178 
179  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
180  assert( isWritePtr( data, dataLength ) );
181  assert( isWritePtr( processedDataLength, sizeof( int ) ) );
182 
183  REQUIRES( dataLength > 0 && \
184  dataLength <= sessionInfoPtr->receiveBufEnd && \
185  dataLength < MAX_INTLENGTH );
186 
187  /* Clear return value */
188  *processedDataLength = 0;
189 
190  /* Decrypt the data */
191  status = krnlSendMessage( sessionInfoPtr->iCryptInContext,
192  IMESSAGE_CTX_DECRYPT, data, length );
193  if( cryptStatusError( status ) )
194  {
195  retExt( status,
196  ( status, SESSION_ERRINFO,
197  "Packet decryption failed" ) );
198  }
199 
200  /* If we're using GCM then we have to check the ICV that follows the
201  data */
202  if( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM )
203  {
205 
206  setMessageData( &msgData, data + length,
207  sessionInfoPtr->authBlocksize );
208  status = krnlSendMessage( sessionInfoPtr->iCryptInContext,
209  IMESSAGE_COMPARE, &msgData,
211  if( cryptStatusError( status ) )
212  {
215  "Bad message ICV for packet type %d, length %d",
216  data[ 0 ], length ) );
217  }
218  }
219 
220  /* If it's a stream cipher then there's no padding present */
221  if( sessionInfoPtr->cryptBlocksize <= 1 )
222  {
223  *processedDataLength = length;
224 
225  return( CRYPT_OK );
226  }
227 
228  /* If it's a block cipher, we need to remove end-of-block padding. Up
229  until TLS 1.1 the spec was silent about any requirement to check the
230  padding (and for SSLv3 it didn't specify the padding format at all)
231  so it's not really safe to reject an SSL message if we don't find the
232  correct padding because many SSL implementations didn't process the
233  padded data space in any way, leaving it containing whatever was
234  there before (which can include old plaintext (!!)). Almost all TLS
235  implementations get it right (even though in TLS 1.0 there was only a
236  requirement to generate, but not to check, the PKCS #5-style
237  padding). Because of this we only check the padding bytes if we're
238  talking TLS.
239 
240  First we make sure that the padding information looks OK. TLS allows
241  up to 256 bytes of padding (only GnuTLS actually seems to use this
242  capability though) so we can't check for a sensible (small) padding
243  length, however we can check this for SSL, which is good because for
244  that we can't check the padding itself */
245  padSize = byteToInt( data[ dataLength - 1 ] );
246  if( padSize < 0 || padSize > 255 || \
247  ( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL && \
248  padSize > sessionInfoPtr->cryptBlocksize - 1 ) )
249  {
252  "Invalid encryption padding value 0x%02X (%d)",
253  padSize, padSize ) );
254  }
255  length -= padSize + 1;
256  if( length < 0 || length > MAX_INTLENGTH )
257  {
260  "Encryption padding adjustment value %d is greater "
261  "than packet length %d", padSize, dataLength ) );
262  }
263 
264  /* Check for PKCS #5-type padding (PKCS #5 uses n, TLS uses n-1) if
265  necessary */
266  if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS )
267  {
268  int i;
269 
270  for( i = 0; i < padSize; i++ )
271  {
272  if( data[ length + i ] != padSize )
273  {
276  "Invalid encryption padding byte 0x%02X at "
277  "position %d, should be 0x%02X",
278  data[ length + i ], length + i, padSize ) );
279  }
280  }
281  }
282  *processedDataLength = length;
283 
284  return( CRYPT_OK );
285  }
286 
287 /****************************************************************************
288 * *
289 * SSL MAC Functions *
290 * *
291 ****************************************************************************/
292 
293 /* Perform an SSL MAC of a data block. We have to provide special-case
294  handling of zero-length blocks since some versions of OpenSSL send these
295  as a kludge in SSL/TLS 1.0 to work around chosen-IV attacks.
296 
297  In the following functions we don't check the return value of every
298  single component MAC operation since it would lead to endless sequences
299  of 'status = x; if( cSOK( x ) ) ...' chains, on the remote chance that
300  there's some transient failure in a single component operation it'll be
301  picked up at the end anyway when the overall MAC check fails */
302 
304 static int macDataSSL( IN_HANDLE const CRYPT_CONTEXT iHashContext,
306  IN_BUFFER( macSecretLength ) \
307  const void *macSecret,
308  IN_LENGTH_SHORT const int macSecretLength,
309  IN_INT_Z const long seqNo,
310  IN_BUFFER_OPT( dataLength ) const void *data,
311  IN_LENGTH_Z const int dataLength,
312  IN_RANGE( 0, 255 ) const int type )
313  {
315  STREAM stream;
316  BYTE buffer[ 128 + 8 ];
317  const int padSize = ( hashAlgo == CRYPT_ALGO_MD5 ) ? 48 : 40;
318  int length = DUMMY_INIT, status;
319 
320  assert( isReadPtr( macSecret, macSecretLength ) );
321  assert( ( data == NULL && dataLength == 0 ) || \
322  isReadPtr( data, dataLength ) );
323 
324  REQUIRES( isHandleRangeValid( iHashContext ) );
325  REQUIRES( hashAlgo == CRYPT_ALGO_MD5 || \
326  hashAlgo == CRYPT_ALGO_SHA1 );
327  REQUIRES( macSecretLength > 0 && \
328  macSecretLength < MAX_INTLENGTH_SHORT );
329  REQUIRES( seqNo >= 0 );
330  REQUIRES( ( data == NULL && dataLength == 0 ) || \
331  ( data != NULL && \
332  dataLength > 0 && dataLength <= MAX_PACKET_SIZE ) );
333  REQUIRES( type >= 0 && type <= 255 );
334 
335  /* Set up the sequence number and length data */
336  memset( buffer, PROTOHMAC_PAD1_VALUE, padSize );
337  sMemOpen( &stream, buffer + padSize, 128 - padSize );
338  writeUint64( &stream, seqNo );
339  sputc( &stream, type );
340  status = writeUint16( &stream, dataLength );
341  if( cryptStatusOK( status ) )
342  length = stell( &stream );
343  sMemDisconnect( &stream );
344  if( cryptStatusError( status ) )
345  return( status );
346 
347  /* Reset the hash context and generate the inner portion of the MAC:
348 
349  hash( MAC_secret || pad1 || seq_num || type || length || data ) */
350  krnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,
352  krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
353  ( MESSAGE_CAST ) macSecret, macSecretLength );
354  krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer,
355  padSize + length );
356  if( dataLength > 0 )
357  krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
358  ( MESSAGE_CAST ) data, dataLength );
359  status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 );
360  if( cryptStatusError( status ) )
361  return( status );
362 
363  /* Extract the inner hash value */
364  memset( buffer, PROTOHMAC_PAD2_VALUE, padSize );
365  setMessageData( &msgData, buffer + padSize, CRYPT_MAX_HASHSIZE );
366  status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,
367  &msgData, CRYPT_CTXINFO_HASHVALUE );
368  if( cryptStatusError( status ) )
369  return( status );
370 
371  /* Generate the outer portion of the handshake message's MAC:
372 
373  hash( MAC_secret || pad2 || inner_hash ) */
374  krnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,
376  krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
377  ( MESSAGE_CAST ) macSecret, macSecretLength );
378  krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer,
379  padSize + msgData.length );
380  return( krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 ) );
381  }
382 
383 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
384 int createMacSSL( INOUT SESSION_INFO *sessionInfoPtr,
385  INOUT_BUFFER( dataMaxLength, *dataLength ) void *data,
386  IN_LENGTH const int dataMaxLength,
387  OUT_LENGTH_Z int *dataLength,
388  IN_LENGTH const int payloadLength,
389  IN_RANGE( 0, 255 ) const int type )
390  {
391  SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
393  int status;
394 
395  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
396  assert( isWritePtr( data, dataMaxLength ) );
397  assert( isWritePtr( dataLength, sizeof( int ) ) );
398 
399  REQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_INTLENGTH );
400  REQUIRES( payloadLength > 0 && payloadLength <= MAX_PACKET_SIZE && \
401  payloadLength + sessionInfoPtr->authBlocksize <= dataMaxLength );
402  REQUIRES( type >= 0 && type <= 255 );
403 
404  /* Clear return value */
405  *dataLength = 0;
406 
407  /* MAC the payload */
408  status = macDataSSL( sessionInfoPtr->iAuthOutContext,
409  sessionInfoPtr->integrityAlgo,
410  sslInfo->macWriteSecret,
411  sessionInfoPtr->authBlocksize, sslInfo->writeSeqNo,
412  data, payloadLength, type );
413  if( cryptStatusError( status ) )
414  return( status );
415  sslInfo->writeSeqNo++;
416 
417  /* Append the MAC value to the end of the packet */
418  ENSURES( rangeCheck( payloadLength, sessionInfoPtr->authBlocksize,
419  dataMaxLength ) );
420  setMessageData( &msgData, ( BYTE * ) data + payloadLength,
421  sessionInfoPtr->authBlocksize );
422  status = krnlSendMessage( sessionInfoPtr->iAuthOutContext,
423  IMESSAGE_GETATTRIBUTE_S, &msgData,
425  if( cryptStatusError( status ) )
426  return( status );
427  *dataLength = payloadLength + msgData.length;
428 
429  return( CRYPT_OK );
430  }
431 
432 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
433 int checkMacSSL( INOUT SESSION_INFO *sessionInfoPtr,
434  IN_BUFFER( dataLength ) const void *data,
435  IN_LENGTH const int dataLength,
436  IN_LENGTH_Z const int payloadLength,
437  IN_RANGE( 0, 255 ) const int type,
438  const BOOLEAN noReportError )
439  {
440  SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
442  int status;
443 
444  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
445  assert( isReadPtr( data, dataLength ) );
446 
447  REQUIRES( dataLength > 0 && dataLength < MAX_INTLENGTH );
448  REQUIRES( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE && \
449  payloadLength + sessionInfoPtr->authBlocksize <= dataLength );
450  REQUIRES( type >= 0 && type <= 255 );
451 
452  /* MAC the payload. If the payload length is zero then there's no data
453  payload, this can happen with some versions of OpenSSL that send
454  zero-length blocks as a kludge to work around pre-TLS 1.1 chosen-IV
455  attacks */
456  if( payloadLength <= 0 )
457  {
458  status = macDataSSL( sessionInfoPtr->iAuthInContext,
459  sessionInfoPtr->integrityAlgo,
460  sslInfo->macReadSecret,
461  sessionInfoPtr->authBlocksize,
462  sslInfo->readSeqNo, NULL, 0, type );
463  }
464  else
465  {
466  status = macDataSSL( sessionInfoPtr->iAuthInContext,
467  sessionInfoPtr->integrityAlgo,
468  sslInfo->macReadSecret,
469  sessionInfoPtr->authBlocksize,
470  sslInfo->readSeqNo, data, payloadLength, type );
471  }
472  if( cryptStatusError( status ) )
473  return( status );
474  sslInfo->readSeqNo++;
475 
476  /* Compare the calculated MAC to the MAC present at the end of the
477  data */
478  ENSURES( rangeCheckZ( payloadLength, sessionInfoPtr->authBlocksize,
479  dataLength ) );
480  setMessageData( &msgData, ( BYTE * ) data + payloadLength,
481  sessionInfoPtr->authBlocksize );
482  status = krnlSendMessage( sessionInfoPtr->iAuthInContext,
483  IMESSAGE_COMPARE, &msgData,
485  if( cryptStatusError( status ) )
486  {
487  /* If the error message has already been set at a higher level,
488  don't update the error information */
489  if( noReportError )
490  return( CRYPT_ERROR_SIGNATURE );
491 
494  "Bad message MAC for packet type %d, length %d",
495  type, dataLength ) );
496  }
497 
498  return( CRYPT_OK );
499  }
500 
501 /****************************************************************************
502 * *
503 * TLS MAC Functions *
504 * *
505 ****************************************************************************/
506 
507 /* Perform a TLS MAC of a data block. We have to provide special-case
508  handling of zero-length blocks since some versions of OpenSSL send these
509  as a kludge in SSL/TLS 1.0 to work around chosen-IV attacks.
510 
511  In the following functions we don't check the return value of every
512  single component MAC operation since it would lead to endless sequences
513  of 'status = x; if( cSOK( x ) ) ...' chains, on the remote chance that
514  there's some transient failure in a single component operation it'll be
515  picked up at the end anyway when the overall MAC check fails */
516 
517 CHECK_RETVAL \
518 static int macDataTLS( IN_HANDLE const CRYPT_CONTEXT iHashContext,
519  IN_INT_Z const long seqNo,
521  SSL_MINOR_VERSION_TLS12 ) const int version,
522  IN_BUFFER_OPT( dataLength ) const void *data,
523  IN_LENGTH_Z const int dataLength,
524  IN_RANGE( 0, 255 ) const int type )
525  {
526  BYTE buffer[ 64 + 8 ];
527  int length, status;
528 
529  assert( ( data == NULL && dataLength == 0 ) || \
530  isReadPtr( data, dataLength ) );
531 
532  REQUIRES( isHandleRangeValid( iHashContext ) );
533  REQUIRES( seqNo >= 0 );
534  REQUIRES( version >= SSL_MINOR_VERSION_TLS && \
535  version <= SSL_MINOR_VERSION_TLS12 );
536  REQUIRES( ( data == NULL && dataLength == 0 ) || \
537  ( data != NULL && \
538  dataLength > 0 && dataLength <= MAX_PACKET_SIZE ) );
539  REQUIRES( type >= 0 && type <= 255 );
540 
541  /* Set up the packet metadata to be MACed */
542  status = writePacketMetadata( buffer, 64, &length, type, seqNo, version,
543  dataLength );
544  if( cryptStatusError( status ) )
545  return( status );
546 
547  /* Reset the hash context and generate the MAC:
548 
549  HMAC( metadata || data ) */
550  krnlSendMessage( iHashContext, IMESSAGE_DELETEATTRIBUTE, NULL,
552  krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, buffer, length );
553  if( dataLength > 0 )
554  {
555  krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
556  ( MESSAGE_CAST ) data, dataLength );
557  }
558  return( krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 ) );
559  }
560 
561 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
562 int createMacTLS( INOUT SESSION_INFO *sessionInfoPtr,
563  OUT_BUFFER( dataMaxLength, *dataLength ) void *data,
564  IN_LENGTH const int dataMaxLength,
565  OUT_LENGTH_Z int *dataLength,
566  IN_LENGTH const int payloadLength,
567  IN_RANGE( 0, 255 ) const int type )
568  {
569  SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
571  int status;
572 
573  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
574  assert( isWritePtr( data, dataMaxLength ) );
575  assert( isWritePtr( dataLength, sizeof( int ) ) );
576 
577  REQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_INTLENGTH );
578  REQUIRES( payloadLength > 0 && payloadLength <= MAX_PACKET_SIZE && \
579  payloadLength + sessionInfoPtr->authBlocksize <= dataMaxLength );
580  REQUIRES( type >= 0 && type <= 255 );
581 
582  /* Clear return value */
583  *dataLength = 0;
584 
585  /* MAC the payload */
586  status = macDataTLS( sessionInfoPtr->iAuthOutContext, sslInfo->writeSeqNo,
587  sessionInfoPtr->version, data, payloadLength, type );
588  if( cryptStatusError( status ) )
589  return( status );
590  sslInfo->writeSeqNo++;
591 
592  /* Append the MAC value to the end of the packet */
593  ENSURES( rangeCheck( payloadLength, sessionInfoPtr->authBlocksize,
594  dataMaxLength ) );
595  setMessageData( &msgData, ( BYTE * ) data + payloadLength,
596  sessionInfoPtr->authBlocksize );
597  status = krnlSendMessage( sessionInfoPtr->iAuthOutContext,
598  IMESSAGE_GETATTRIBUTE_S, &msgData,
600  if( cryptStatusError( status ) )
601  return( status );
602  *dataLength = payloadLength + msgData.length;
603 
604  return( CRYPT_OK );
605  }
606 
607 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
608 int checkMacTLS( INOUT SESSION_INFO *sessionInfoPtr,
609  IN_BUFFER( dataLength ) const void *data,
610  IN_LENGTH const int dataLength,
611  IN_LENGTH_Z const int payloadLength,
612  IN_RANGE( 0, 255 ) const int type,
613  const BOOLEAN noReportError )
614  {
615  SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
617  int status;
618 
619  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
620  assert( isReadPtr( data, dataLength ) );
621 
622  REQUIRES( dataLength > 0 && dataLength < MAX_INTLENGTH );
623  REQUIRES( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE && \
624  payloadLength + sessionInfoPtr->authBlocksize <= dataLength );
625  REQUIRES( type >= 0 && type <= 255 );
626 
627  /* MAC the payload. If the payload length is zero then there's no data
628  payload, this can happen with some versions of OpenSSL that send
629  zero-length blocks as a kludge to work around pre-TLS 1.1 chosen-IV
630  attacks */
631  if( payloadLength <= 0 )
632  {
633  status = macDataTLS( sessionInfoPtr->iAuthInContext,
634  sslInfo->readSeqNo, sessionInfoPtr->version,
635  NULL, 0, type );
636  }
637  else
638  {
639  status = macDataTLS( sessionInfoPtr->iAuthInContext,
640  sslInfo->readSeqNo, sessionInfoPtr->version,
641  data, payloadLength, type );
642  }
643  if( cryptStatusError( status ) )
644  return( status );
645  sslInfo->readSeqNo++;
646 
647  /* Compare the calculated MAC to the MAC present at the end of the
648  data */
649  ENSURES( rangeCheckZ( payloadLength, sessionInfoPtr->authBlocksize,
650  dataLength ) );
651  setMessageData( &msgData, ( BYTE * ) data + payloadLength,
652  sessionInfoPtr->authBlocksize );
653  status = krnlSendMessage( sessionInfoPtr->iAuthInContext,
654  IMESSAGE_COMPARE, &msgData,
656  if( cryptStatusError( status ) )
657  {
658  /* If the error message has already been set at a higher level,
659  don't update the error information */
660  if( noReportError )
661  return( CRYPT_ERROR_SIGNATURE );
662 
665  "Bad message MAC for packet type %d, length %d",
666  type, dataLength ) );
667  }
668 
669  return( CRYPT_OK );
670  }
671 
672 /****************************************************************************
673 * *
674 * TLS GCM Functions *
675 * *
676 ****************************************************************************/
677 
678 /* Perform a TLS GCM integrity check of a data block. This differs somewhat
679  from the more conventional MACing routines because GCM combines the ICV
680  generation with encryption, so all that we're actually doing is
681  generating the initial stage of the ICV over the packet metadata handled
682  as GCM AAD */
683 
684 CHECK_RETVAL \
686  IN_INT_Z const long seqNo,
688  SSL_MINOR_VERSION_TLS12 ) const int version,
689  IN_LENGTH_Z const int payloadLength,
690  IN_RANGE( 0, 255 ) const int type )
691  {
693  BYTE buffer[ 64 + 8 ];
694  int length, status;
695 
696  REQUIRES( isHandleRangeValid( iCryptContext ) );
697  REQUIRES( seqNo >= 0 );
698  REQUIRES( version >= SSL_MINOR_VERSION_TLS && \
699  version <= SSL_MINOR_VERSION_TLS12 );
700  REQUIRES( payloadLength >= 0 && payloadLength <= MAX_PACKET_SIZE );
701  REQUIRES( type >= 0 && type <= 255 );
702 
703  /* Set up the packet metadata to be MACed */
704  status = writePacketMetadata( buffer, 64, &length, type, seqNo,
705  version, payloadLength );
706  if( cryptStatusError( status ) )
707  return( status );
708 
709  /* Send the AAD to the GCM context for inclusion in the ICV
710  calculation */
711  setMessageData( &msgData, buffer, length );
712  return( krnlSendMessage( iCryptContext, IMESSAGE_SETATTRIBUTE_S,
713  &msgData, CRYPT_IATTRIBUTE_AAD ) );
714  }
715 
716 /****************************************************************************
717 * *
718 * Handshake Message Hash/MAC Functions *
719 * *
720 ****************************************************************************/
721 
722 /* Perform assorted hashing of a data block, a dual dual MD5+SHA-1 hash for
723  SSL or straight SHA-2 hash for TLS 1.2+. Since this is part of an
724  ongoing message exchange (in other words a failure potentially won't be
725  detected for some time) we check each return value. This processing was
726  originally done using a dual MD5+SHA-1 hash, however TLS 1.2+ switched to
727  using a single SHA-2 hash, because of this we have to explicitly check
728  which hashing option we're using (in some cases it might be both since we
729  have to speculatively hash initial messages until we've agreed on a
730  version) and only use that hash.
731 
732  In addition to the overall hashing we may also be running a separate hash
733  of the messages that stops before the other hashing does if certificate-
734  based client authentication is being used. This would add even more
735  overhead to the whole process, however since it's only used with TLS 1.2+
736  and in that case is restricted to using SHA-2 via hashing preferences
737  sent in the hello messages, we can obtain the necessary hash value by
738  cloning the SHA-2 context when we have to generate or verify the client
739  signature */
740 
741 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
742 static int hashHSData( const SSL_HANDSHAKE_INFO *handshakeInfo,
743  IN_BUFFER( dataLength ) const void *data,
744  IN_LENGTH const int dataLength )
745  {
746  int status;
747 
748  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
749  assert( isReadPtr( data, dataLength ) );
750 
751  REQUIRES( dataLength > 0 && dataLength < MAX_INTLENGTH );
752 
753  if( handshakeInfo->md5context != CRYPT_ERROR )
754  {
755  status = krnlSendMessage( handshakeInfo->md5context,
757  dataLength );
758  if( cryptStatusOK( status ) )
759  status = krnlSendMessage( handshakeInfo->sha1context,
761  dataLength );
762  if( cryptStatusError( status ) )
763  return( status );
764  }
765  if( handshakeInfo->sha2context != CRYPT_ERROR )
766  {
767  status = krnlSendMessage( handshakeInfo->sha2context,
769  dataLength );
770  if( cryptStatusError( status ) )
771  return( status );
772  }
773 #ifdef CONFIG_SUITEB
774  if( handshakeInfo->sha384context != CRYPT_ERROR )
775  {
776  status = krnlSendMessage( handshakeInfo->sha384context,
778  dataLength );
779  if( cryptStatusError( status ) )
780  return( status );
781  }
782 #endif /* CONFIG_SUITEB */
783 
784  return( CRYPT_OK );
785  }
786 
787 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
788 int hashHSPacketRead( const SSL_HANDSHAKE_INFO *handshakeInfo,
789  INOUT STREAM *stream )
790  {
791  const int dataLength = sMemDataLeft( stream );
792  void *data;
793  int status;
794 
795  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
796  assert( isWritePtr( stream, sizeof( STREAM ) ) );
797 
798  REQUIRES( dataLength > 0 && dataLength < MAX_INTLENGTH );
799 
800  /* On a read we've just processed the packet header and everything
801  that's left in the stream is the data to be MACd. Note that we can't
802  use sMemGetDataBlockRemaining() for this because that returns the
803  entire available buffer, not just the amount of data in the buffer */
804  status = sMemGetDataBlock( stream, &data, dataLength );
805  if( cryptStatusOK( status ) )
806  {
807  ANALYSER_HINT( data != NULL );
808  status = hashHSData( handshakeInfo, data, dataLength );
809  }
810  return( status );
811  }
812 
813 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
814 int hashHSPacketWrite( const SSL_HANDSHAKE_INFO *handshakeInfo,
815  INOUT STREAM *stream,
816  IN_LENGTH_Z const int offset )
817  {
818  const int dataStart = offset + SSL_HEADER_SIZE;
819  const int dataLength = stell( stream ) - dataStart;
820  void *data;
821  int status;
822 
823  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
824  assert( isWritePtr( stream, sizeof( STREAM ) ) );
825 
826  REQUIRES( offset >= 0 && offset < MAX_INTLENGTH );
827  REQUIRES( dataLength > 0 && dataLength < MAX_INTLENGTH );
828 
829  /* On a write we've just finished writing the packet and everything but
830  the header needs to be MACd */
831  status = sMemGetDataBlockAbs( stream, dataStart, &data, dataLength );
832  if( cryptStatusOK( status ) )
833  {
834  ANALYSER_HINT( data != NULL );
835  status = hashHSData( handshakeInfo, data, dataLength );
836  }
837  return( status );
838  }
839 
840 /* Complete the dual MD5/SHA1 hash/MAC or SHA2 MAC that's used in the
841  finished message. There are no less than three variations of this, one
842  for SSL's dual MAC, one for TLS 1.0 - 1.1's IPsec cargo cult 96-bit
843  PRF'd dual MAC, and one for TLS 1.2's similarly cargo-cult 96-bit PRF'd
844  single MAC.
845 
846  We don't check the return value of every single component MAC operation
847  since it would lead to endless sequences of 'status = x;
848  if( cSOK( x ) ) ...' chains, on the remote chance that there's some
849  transient failure in a single component operation it'll be picked up at
850  the end anyway when the overall MAC check fails */
851 
852 CHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 6, 8 ) ) \
853 int completeSSLDualMAC( IN_HANDLE const CRYPT_CONTEXT md5context,
855  OUT_BUFFER( hashValuesMaxLen, *hashValuesLen )
856  BYTE *hashValues,
858  const int hashValuesMaxLen,
860  IN_BUFFER( labelLength ) const char *label,
861  IN_RANGE( 1, 64 ) const int labelLength,
862  IN_BUFFER( masterSecretLen ) const BYTE *masterSecret,
863  IN_LENGTH_SHORT const int masterSecretLen )
864  {
866  int status;
867 
868  assert( isWritePtr( hashValues, hashValuesMaxLen ) );
869  assert( isWritePtr( hashValuesLen, sizeof( int ) ) );
870  assert( isReadPtr( label, labelLength ) );
871  assert( isReadPtr( masterSecret, masterSecretLen ) );
872 
873  REQUIRES( isHandleRangeValid( md5context ) );
874  REQUIRES( isHandleRangeValid( sha1context ) );
875  REQUIRES( hashValuesMaxLen >= MD5MAC_SIZE + SHA1MAC_SIZE && \
876  hashValuesMaxLen < MAX_INTLENGTH_SHORT );
877  REQUIRES( labelLength > 0 && labelLength <= 64 );
878  REQUIRES( masterSecretLen > 0 && masterSecretLen < MAX_INTLENGTH_SHORT );
879 
880  /* Clear return value */
881  *hashValuesLen = 0;
882 
883  /* Generate the inner portion of the handshake message's MAC:
884 
885  hash( handshake_messages || cl/svr_label || master_secret || pad1 )
886 
887  Note that the SHA-1 pad size is 40 bytes and not 44 (to get a total
888  length of 64 bytes), this is due to an error in the spec */
889  krnlSendMessage( md5context, IMESSAGE_CTX_HASH,
890  ( MESSAGE_CAST ) label, labelLength );
891  krnlSendMessage( sha1context, IMESSAGE_CTX_HASH,
892  ( MESSAGE_CAST ) label, labelLength );
893  krnlSendMessage( md5context, IMESSAGE_CTX_HASH,
894  ( MESSAGE_CAST ) masterSecret, masterSecretLen );
895  krnlSendMessage( sha1context, IMESSAGE_CTX_HASH,
896  ( MESSAGE_CAST ) masterSecret, masterSecretLen );
898  krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD1, 40 );
899  krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
900  krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
901  setMessageData( &msgData, hashValues, MD5MAC_SIZE );
902  status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
903  &msgData, CRYPT_CTXINFO_HASHVALUE );
904  if( cryptStatusOK( status ) )
905  {
906  setMessageData( &msgData, hashValues + MD5MAC_SIZE, SHA1MAC_SIZE );
907  status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
908  &msgData, CRYPT_CTXINFO_HASHVALUE );
909  }
910  if( cryptStatusError( status ) )
911  return( status );
912 
913  /* Reset the hash contexts */
914  krnlSendMessage( md5context, IMESSAGE_DELETEATTRIBUTE, NULL,
916  krnlSendMessage( sha1context, IMESSAGE_DELETEATTRIBUTE, NULL,
918 
919  /* Generate the outer portion of the handshake message's MAC:
920 
921  hash( master_secret || pad2 || inner_hash ) */
922  krnlSendMessage( md5context, IMESSAGE_CTX_HASH,
923  ( MESSAGE_CAST ) masterSecret, masterSecretLen );
924  krnlSendMessage( sha1context, IMESSAGE_CTX_HASH,
925  ( MESSAGE_CAST ) masterSecret, masterSecretLen );
927  krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, PROTOHMAC_PAD2, 40 );
928  krnlSendMessage( md5context, IMESSAGE_CTX_HASH, hashValues,
929  MD5MAC_SIZE );
930  krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, hashValues + MD5MAC_SIZE,
931  SHA1MAC_SIZE );
932  krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
933  krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
934  setMessageData( &msgData, hashValues, MD5MAC_SIZE );
935  status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
936  &msgData, CRYPT_CTXINFO_HASHVALUE );
937  if( cryptStatusError( status ) )
938  return( status );
939  setMessageData( &msgData, hashValues + MD5MAC_SIZE, SHA1MAC_SIZE );
940  status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
941  &msgData, CRYPT_CTXINFO_HASHVALUE );
942  if( cryptStatusOK( status ) )
943  *hashValuesLen = MD5MAC_SIZE + SHA1MAC_SIZE;
944  return( status );
945  }
946 
947 CHECK_RETVAL STDC_NONNULL_ARG( ( 3, 5, 6, 8 ) ) \
948 int completeTLSHashedMAC( IN_HANDLE const CRYPT_CONTEXT md5context,
949  IN_HANDLE const CRYPT_CONTEXT sha1context,
950  OUT_BUFFER( hashValuesMaxLen, *hashValuesLen )
951  BYTE *hashValues,
953  const int hashValuesMaxLen,
954  OUT_LENGTH_SHORT_Z int *hashValuesLen,
955  IN_BUFFER( labelLength ) const char *label,
956  IN_RANGE( 1, 64 ) const int labelLength,
957  IN_BUFFER( masterSecretLen ) const BYTE *masterSecret,
958  IN_LENGTH_SHORT const int masterSecretLen )
959  {
962  BYTE hashBuffer[ 64 + ( CRYPT_MAX_HASHSIZE * 2 ) + 8 ];
963  int status;
964 
965  assert( isWritePtr( hashValues, hashValuesMaxLen ) );
966  assert( isWritePtr( hashValuesLen, sizeof( int ) ) );
967  assert( isReadPtr( label, labelLength ) );
968  assert( isReadPtr( masterSecret, masterSecretLen ) );
969 
970  REQUIRES( isHandleRangeValid( md5context ) );
971  REQUIRES( isHandleRangeValid( sha1context ) );
972  REQUIRES( hashValuesMaxLen >= TLS_HASHEDMAC_SIZE && \
973  hashValuesMaxLen < MAX_INTLENGTH_SHORT );
974  REQUIRES( labelLength > 0 && labelLength <= 64 && \
975  labelLength + MD5MAC_SIZE + SHA1MAC_SIZE <= \
976  64 + ( CRYPT_MAX_HASHSIZE * 2 ) );
977 
978  /* Clear return value */
979  *hashValuesLen = 0;
980 
981  memcpy( hashBuffer, label, labelLength );
982 
983  /* Complete the hashing and get the MD5 and SHA-1 hashes */
984  krnlSendMessage( md5context, IMESSAGE_CTX_HASH, "", 0 );
985  krnlSendMessage( sha1context, IMESSAGE_CTX_HASH, "", 0 );
986  setMessageData( &msgData, hashBuffer + labelLength, MD5MAC_SIZE );
987  status = krnlSendMessage( md5context, IMESSAGE_GETATTRIBUTE_S,
988  &msgData, CRYPT_CTXINFO_HASHVALUE );
989  if( cryptStatusOK( status ) )
990  {
991  setMessageData( &msgData, hashBuffer + labelLength + MD5MAC_SIZE,
992  SHA1MAC_SIZE );
993  status = krnlSendMessage( sha1context, IMESSAGE_GETATTRIBUTE_S,
994  &msgData, CRYPT_CTXINFO_HASHVALUE );
995  }
996  if( cryptStatusError( status ) )
997  return( status );
998 
999  /* Generate the TLS check value. This isn't really a hash or a MAC but
1000  is generated by feeding the MD5 and SHA1 hashes of the handshake
1001  messages into the TLS key derivation (PRF) function and truncating
1002  the result to 12 bytes (96 bits) IPsec cargo cult protocol design
1003  purposes:
1004 
1005  TLS_PRF( label || MD5_hash || SHA1_hash ) */
1006  setMechanismDeriveInfo( &mechanismInfo, hashValues,
1007  TLS_HASHEDMAC_SIZE, ( MESSAGE_CAST ) masterSecret,
1008  masterSecretLen, CRYPT_USE_DEFAULT, hashBuffer,
1009  labelLength + MD5MAC_SIZE + SHA1MAC_SIZE, 1 );
1011  &mechanismInfo, MECHANISM_DERIVE_TLS );
1012  if( cryptStatusOK( status ) )
1013  *hashValuesLen = TLS_HASHEDMAC_SIZE;
1014  return( status );
1015  }
1016 
1017 CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 4, 5, 7 ) ) \
1018 int completeTLS12HashedMAC( IN_HANDLE const CRYPT_CONTEXT sha2context,
1019  OUT_BUFFER( hashValuesMaxLen, *hashValuesLen ) \
1020  BYTE *hashValues,
1022  const int hashValuesMaxLen,
1023  OUT_LENGTH_SHORT_Z int *hashValuesLen,
1024  IN_BUFFER( labelLength ) const char *label,
1025  IN_RANGE( 1, 64 ) const int labelLength,
1026  IN_BUFFER( masterSecretLen ) const BYTE *masterSecret,
1027  IN_LENGTH_SHORT const int masterSecretLen )
1028  {
1031  BYTE hashBuffer[ 64 + ( CRYPT_MAX_HASHSIZE * 2 ) + 8 ];
1032  int macSize, status;
1033 
1034  assert( isWritePtr( hashValues, hashValuesMaxLen ) );
1035  assert( isWritePtr( hashValuesLen, sizeof( int ) ) );
1036  assert( isReadPtr( label, labelLength ) );
1037  assert( isReadPtr( masterSecret, masterSecretLen ) );
1038 
1039  REQUIRES( isHandleRangeValid( sha2context ) );
1040  REQUIRES( hashValuesMaxLen >= TLS_HASHEDMAC_SIZE && \
1041  hashValuesMaxLen < MAX_INTLENGTH_SHORT );
1042  REQUIRES( labelLength > 0 && labelLength <= 64 && \
1043  labelLength + CRYPT_MAX_HASHSIZE <= 64 + ( CRYPT_MAX_HASHSIZE ) );
1044 
1045  /* Clear return value */
1046  *hashValuesLen = 0;
1047 
1048  memcpy( hashBuffer, label, labelLength );
1049 
1050  /* Get the MAC size */
1051  status = krnlSendMessage( sha2context, IMESSAGE_GETATTRIBUTE, &macSize,
1053  if( cryptStatusError( status ) )
1054  return( status );
1055 
1056  /* Complete the hashing and get the SHA-2 hash */
1057  krnlSendMessage( sha2context, IMESSAGE_CTX_HASH, "", 0 );
1058  setMessageData( &msgData, hashBuffer + labelLength, macSize );
1059  status = krnlSendMessage( sha2context, IMESSAGE_GETATTRIBUTE_S,
1060  &msgData, CRYPT_CTXINFO_HASHVALUE );
1061  if( cryptStatusError( status ) )
1062  return( status );
1063 
1064  /* Generate the TLS check value. This isn't really a hash or a MAC but
1065  is generated by feeding the SHA-2 hash of the handshake messages into
1066  the TLS key derivation (PRF) function and truncating the result to 12
1067  bytes (96 bits) for IPsec cargo cult protocol design purposes:
1068 
1069  TLS_PRF( label || SHA2_hash ) */
1070  setMechanismDeriveInfo( &mechanismInfo, hashValues,
1071  TLS_HASHEDMAC_SIZE, ( MESSAGE_CAST ) masterSecret,
1072  masterSecretLen, CRYPT_ALGO_SHA2, hashBuffer,
1073  labelLength + macSize, 1 );
1074  if( macSize != bitsToBytes( 256 ) )
1075  mechanismInfo.hashParam = macSize;
1077  &mechanismInfo, MECHANISM_DERIVE_TLS12 );
1078  if( cryptStatusOK( status ) )
1079  *hashValuesLen = TLS_HASHEDMAC_SIZE;
1080  return( status );
1081  }
1082 
1083 /****************************************************************************
1084 * *
1085 * Client-Auth Signature Functions *
1086 * *
1087 ****************************************************************************/
1088 
1089 /* Create/check the signature on an SSL certificate verify message.
1090  SSLv3/TLS use a weird signature format that dual-MACs (SSLv3) or hashes
1091  (TLS) all of the handshake messages exchanged to date (SSLv3 additionally
1092  hashes in further data like the master secret), then signs them using
1093  nonstandard PKCS #1 RSA without the ASN.1 wrapper (that is, it uses the
1094  raw concatenated SHA-1 and MD5 MAC (SSL) or hash (TLS) of the handshake
1095  messages with PKCS #1 padding prepended), unless we're using DSA in which
1096  case it drops the MD5 MAC/hash and uses only the SHA-1 one.
1097 
1098  This is an incredible pain to support because it requires running a
1099  parallel hash of handshake messages that terminates before the main
1100  hashing does, further hashing/MAC'ing of additional data, and the use of
1101  weird nonstandard data formats and signature mechanisms that aren't
1102  normally supported by anything. For example if the signing is to be done
1103  via a smart card then we can't use the standard PKCS #1 sig mechanism, we
1104  can't even use raw RSA and kludge the format together ourselves because
1105  some PKCS #11 implementations don't support the _X509 (raw) mechanism,
1106  what we have to do is tunnel the nonstandard sig.format information down
1107  through several cryptlib layers and then hope that the PKCS #11
1108  implementation that we're using (a) supports this format and (b) gets it
1109  right.
1110 
1111  Another problem (which only occurs for SSLv3) is that the MAC requires
1112  the use of the master secret, which isn't available for several hundred
1113  more lines of code, so we have to delay producing any more data packets
1114  until the master secret is available (either that or squirrel all packets
1115  away in some buffer somewhere so that they can be hashed later), which
1116  severely screws up the handshake processing flow. TLS is slightly better
1117  here since it simply signs MD5-hash || SHA1-hash without requiring the
1118  use of the master secret, but even then it requires speculatively running
1119  an MD5 and SHA-1 hash of all messages on every exchange on the remote
1120  chance that the client will be using client certificates. TLS 1.2
1121  finally moved to using standard signatures (PKCS #1 for RSA, conventional
1122  signatures for DSA/ECDSA), but still requires the speculative hashing of
1123  handshake messages.
1124 
1125  The chances of all of this custom data and signature handling working
1126  correctly are fairly low, and in any case there's no advantage to the
1127  weird mechanism and format used in SSL/TLS, all that we actually need to
1128  do is sign the client and server nonces to ensure signature freshness.
1129  Because of this what we actually do is just this, after which we create a
1130  standard PKCS #1 signature via the normal cryptlib mechanisms, which
1131  guarantees that it'll work with native cryptlib as well as any crypto
1132  hardware implementation. Since client certificates are hardly ever used
1133  and when they are it's in a closed environment, it's extremely unlikely
1134  that anyone will ever notice. There'll be far more problems in trying to
1135  use the nonstandard SSL/TLS signature mechanism than there are with using
1136  a standard (but not-in-the-spec) one.
1137 
1138  The one exception to this is, as already mentioned above, TLS 1.2+, for
1139  which we can finally use a standard signature. In this case we take
1140  a clone of the SHA-2 context that's been used to hash the handshake
1141  messages so far (the use of SHA-2 for this is enforced by the judicious
1142  use of TLS extensions, see the comments in ssl_ext.c for more on this)
1143  and sign that */
1144 
1145 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1146 static int createCertVerifyAltHash( const SSL_HANDSHAKE_INFO *handshakeInfo,
1147  OUT_HANDLE_OPT CRYPT_CONTEXT *iHashContext )
1148  {
1149  MESSAGE_CREATEOBJECT_INFO createInfo;
1150  BYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];
1151  int status;
1152 
1153  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1154  assert( isWritePtr( iHashContext, sizeof( CRYPT_CONTEXT ) ) );
1155 
1156  /* Clear return value */
1157  *iHashContext = CRYPT_ERROR;
1158 
1159  /* Hash the client and server nonces */
1162  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
1164  if( cryptStatusError( status ) )
1165  return( status );
1166  memcpy( nonceBuffer, "certificate verify", 18 );
1167  memcpy( nonceBuffer + 18, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
1168  memcpy( nonceBuffer + 18 + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
1169  SSL_NONCE_SIZE );
1170  status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_CTX_HASH,
1171  nonceBuffer,
1172  18 + SSL_NONCE_SIZE + SSL_NONCE_SIZE );
1173  if( cryptStatusOK( status ) )
1174  status = krnlSendMessage( createInfo.cryptHandle,
1175  IMESSAGE_CTX_HASH, nonceBuffer, 0 );
1176  if( cryptStatusError( status ) )
1177  {
1179  return( status );
1180  }
1181  *iHashContext = createInfo.cryptHandle;
1182 
1183  return( CRYPT_OK );
1184  }
1185 
1186 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
1187 int createCertVerifyHash( const SESSION_INFO *sessionInfoPtr,
1188  INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
1189  {
1191  int status;
1192 
1193  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1194 
1195  /* SSL and TLS 1.0 and 1.1 use a different signature strategy than
1196  TLS 1.2+ (see the long comment above) so this call is a no-op */
1197  if( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )
1198  return( CRYPT_OK );
1199 
1200  /* Clone the current hash state and complete the hashing for the cloned
1201  context */
1202  status = cloneHashContext( handshakeInfo->sha2context, &iHashContext );
1203  if( cryptStatusError( status ) )
1204  return( status );
1205  status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 );
1206  if( cryptStatusError( status ) )
1207  {
1208  krnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );
1209  return( status );
1210  }
1211  handshakeInfo->certVerifyContext = iHashContext;
1212 
1213  return( CRYPT_OK );
1214  }
1215 
1216 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
1217 int createCertVerify( const SESSION_INFO *sessionInfoPtr,
1218  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
1219  INOUT STREAM *stream )
1220  {
1221  void *dataPtr;
1222  int dataLength, length = DUMMY_INIT, status;
1223 
1224  assert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1225  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1226  assert( isWritePtr( stream, sizeof( STREAM ) ) );
1227 
1228  /* Get a pointer to the signature data block */
1229  status = sMemGetDataBlockRemaining( stream, &dataPtr, &dataLength );
1230  if( cryptStatusError( status ) )
1231  return( status );
1232 
1233  /* Create the signature. The reason for the min() part of the
1234  expression is that iCryptCreateSignature() gets suspicious of very
1235  large buffer sizes, for example when the user has specified the use
1236  of a huge send buffer */
1237  if( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )
1238  {
1240 
1241  /* Create the hash of the data to sign if necessary */
1242  status = createCertVerifyAltHash( handshakeInfo, &iHashContext );
1243  if( cryptStatusError( status ) )
1244  return( status );
1245 
1246  status = iCryptCreateSignature( dataPtr,
1247  min( dataLength, MAX_INTLENGTH_SHORT - 1 ), &length,
1248  CRYPT_FORMAT_CRYPTLIB, sessionInfoPtr->privateKey,
1249  iHashContext, NULL );
1250  krnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );
1251  }
1252  else
1253  {
1254  status = iCryptCreateSignature( dataPtr,
1255  min( dataLength, MAX_INTLENGTH_SHORT - 1 ), &length,
1256  CRYPT_IFORMAT_TLS12, sessionInfoPtr->privateKey,
1257  handshakeInfo->certVerifyContext, NULL );
1258  krnlSendNotifier( handshakeInfo->certVerifyContext,
1260  handshakeInfo->certVerifyContext = CRYPT_ERROR;
1261  }
1262  if( cryptStatusOK( status ) )
1263  status = sSkip( stream, length );
1264  return( status );
1265  }
1266 
1267 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
1268 int checkCertVerify( const SESSION_INFO *sessionInfoPtr,
1269  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
1270  INOUT STREAM *stream,
1272  const int sigLength )
1273  {
1274  void *dataPtr;
1275  int status;
1276 
1277  assert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1278  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1279  assert( isWritePtr( stream, sizeof( STREAM ) ) );
1280 
1281  REQUIRES( sigLength >= MIN_CRYPT_OBJECTSIZE && \
1282  sigLength < MAX_INTLENGTH_SHORT );
1283 
1284  /* Get a pointer to the signature data block */
1285  status = sMemGetDataBlock( stream, &dataPtr, sigLength );
1286  if( cryptStatusError( status ) )
1287  return( status );
1288  ANALYSER_HINT( dataPtr != NULL );
1289 
1290  /* Verify the signature. The reason for the min() part of the
1291  expression is that iCryptCheckSignature() gets suspicious of very
1292  large buffer sizes, for example when the user has specified the use
1293  of a huge send buffer */
1294  if( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )
1295  {
1297 
1298  /* Create the hash of the data to verify if necessary */
1299  status = createCertVerifyAltHash( handshakeInfo, &iHashContext );
1300  if( cryptStatusError( status ) )
1301  return( status );
1302 
1303  status = iCryptCheckSignature( dataPtr,
1304  min( sigLength, MAX_INTLENGTH_SHORT - 1 ),
1305  CRYPT_FORMAT_CRYPTLIB, sessionInfoPtr->iKeyexAuthContext,
1306  iHashContext, CRYPT_UNUSED, NULL );
1307  krnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );
1308  }
1309  else
1310  {
1311  status = iCryptCheckSignature( dataPtr,
1312  min( sigLength, MAX_INTLENGTH_SHORT - 1 ),
1313  CRYPT_IFORMAT_TLS12, sessionInfoPtr->iKeyexAuthContext,
1314  handshakeInfo->certVerifyContext, CRYPT_UNUSED, NULL );
1315  krnlSendNotifier( handshakeInfo->certVerifyContext,
1317  handshakeInfo->certVerifyContext = CRYPT_ERROR;
1318 #ifdef CONFIG_SUITEB_TESTS
1319  if( cryptStatusOK( status ) )
1320  {
1321  int sigKeySize;
1322 
1323  status = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext,
1324  IMESSAGE_GETATTRIBUTE, &sigKeySize,
1326  if( cryptStatusOK( status ) )
1327  {
1328  DEBUG_PRINT(( "Verified client's P%d authentication.\n",
1329  bytesToBits( sigKeySize ) ));
1330  }
1331  }
1332 #endif /* CONFIG_SUITEB_TESTS */
1333  }
1334  return( status );
1335  }
1336 
1337 /****************************************************************************
1338 * *
1339 * Keyex Signature Functions *
1340 * *
1341 ****************************************************************************/
1342 
1343 /* Create/check the signature on the server key data */
1344 
1345 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 5 ) ) \
1346 static int createKeyexHash( const SSL_HANDSHAKE_INFO *handshakeInfo,
1348  IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
1349  IN_INT_SHORT_Z const int hashParam,
1350  IN_BUFFER( keyDataLength ) const void *keyData,
1351  IN_LENGTH_SHORT const int keyDataLength )
1352  {
1354  MESSAGE_CREATEOBJECT_INFO createInfo;
1355  BYTE nonceBuffer[ SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];
1356  int status;
1357 
1358  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1359  assert( isWritePtr( hashContext, sizeof( CRYPT_CONTEXT ) ) );
1360  assert( isReadPtr( keyData, keyDataLength ) );
1361 
1362  REQUIRES( hashAlgo >= CRYPT_ALGO_FIRST_HASH && \
1363  hashAlgo <= CRYPT_ALGO_LAST_HASH );
1364  REQUIRES( hashParam >= 0 && hashParam < MAX_INTLENGTH_SHORT );
1365  REQUIRES( keyDataLength > 0 && keyDataLength < MAX_INTLENGTH_SHORT );
1366 
1367  /* Clear return value */
1368  *hashContext = CRYPT_ERROR;
1369 
1370  /* Create the hash context */
1371  setMessageCreateObjectInfo( &createInfo, hashAlgo );
1373  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
1375  if( cryptStatusError( status ) )
1376  return( status );
1377  iHashContext = createInfo.cryptHandle;
1378  if( hashParam != 0 )
1379  {
1380  status = krnlSendMessage( createInfo.cryptHandle,
1382  ( MESSAGE_CAST ) &hashParam,
1384  if( cryptStatusError( status ) )
1385  {
1386  krnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );
1387  return( status );
1388  }
1389  }
1390 
1391  /* Hash the client and server nonces and key data */
1392  memcpy( nonceBuffer, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
1393  memcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
1394  SSL_NONCE_SIZE );
1395  status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
1396  nonceBuffer, SSL_NONCE_SIZE + SSL_NONCE_SIZE );
1397  if( cryptStatusOK( status ) )
1398  status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
1399  ( MESSAGE_CAST ) keyData, keyDataLength );
1400  if( cryptStatusOK( status ) )
1401  status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
1402  nonceBuffer, 0 );
1403  if( cryptStatusError( status ) )
1404  {
1405  krnlSendNotifier( iHashContext, IMESSAGE_DECREFCOUNT );
1406  return( status );
1407  }
1408 
1409  *hashContext = iHashContext;
1410  return( CRYPT_OK );
1411  }
1412 
1413 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
1414 int createKeyexSignature( INOUT SESSION_INFO *sessionInfoPtr,
1415  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
1416  INOUT STREAM *stream,
1417  IN_BUFFER( keyDataLength ) const void *keyData,
1418  IN_LENGTH_SHORT const int keyDataLength )
1419  {
1420  CRYPT_CONTEXT md5Context = DUMMY_INIT, shaContext;
1421  void *dataPtr;
1422  int dataLength, sigLength = DUMMY_INIT, status;
1423 
1424  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1425  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1426  assert( isWritePtr( stream, sizeof( STREAM ) ) );
1427  assert( isReadPtr( keyData, keyDataLength ) );
1428 
1429  REQUIRES( keyDataLength > 0 && keyDataLength < MAX_INTLENGTH_SHORT );
1430 
1431  /* Hash the data to be signed */
1432  status = createKeyexHash( handshakeInfo, &shaContext,
1433  ( handshakeInfo->keyexSigHashAlgo != CRYPT_ALGO_NONE ) ? \
1434  handshakeInfo->keyexSigHashAlgo : CRYPT_ALGO_SHA1,
1435  handshakeInfo->keyexSigHashAlgoParam, keyData, keyDataLength );
1436  if( cryptStatusError( status ) )
1437  return( status );
1438  if( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )
1439  {
1440  status = createKeyexHash( handshakeInfo, &md5Context,
1441  CRYPT_ALGO_MD5, 0, keyData, keyDataLength );
1442  if( cryptStatusError( status ) )
1443  {
1444  krnlSendNotifier( shaContext, IMESSAGE_DECREFCOUNT );
1445  return( status );
1446  }
1447  }
1448 
1449  /* Sign the hashes. The reason for the min() part of the expression is
1450  that iCryptCreateSignature() gets suspicious of very large buffer
1451  sizes, for example when the user has specified the use of a huge send
1452  buffer */
1453  status = sMemGetDataBlockRemaining( stream, &dataPtr, &dataLength );
1454  if( cryptStatusOK( status ) )
1455  {
1456  if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
1457  {
1458  status = iCryptCreateSignature( dataPtr,
1459  min( dataLength, \
1460  MAX_INTLENGTH_SHORT - 1 ),
1461  &sigLength, CRYPT_IFORMAT_TLS12,
1462  sessionInfoPtr->privateKey,
1463  shaContext, NULL );
1464  }
1465  else
1466  {
1468 
1469  initSigParams( &sigParams );
1470  sigParams.iSecondHash = shaContext;
1471  status = iCryptCreateSignature( dataPtr,
1472  min( dataLength, \
1473  MAX_INTLENGTH_SHORT - 1 ),
1474  &sigLength, CRYPT_IFORMAT_SSL,
1475  sessionInfoPtr->privateKey,
1476  md5Context, &sigParams );
1477  }
1478  }
1479  if( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )
1480  krnlSendNotifier( md5Context, IMESSAGE_DECREFCOUNT );
1481  krnlSendNotifier( shaContext, IMESSAGE_DECREFCOUNT );
1482  if( cryptStatusError( status ) )
1483  return( status );
1484 
1485  return( sSkip( stream, sigLength ) );
1486  }
1487 
1488 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
1489 int checkKeyexSignature( INOUT SESSION_INFO *sessionInfoPtr,
1490  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
1491  INOUT STREAM *stream,
1492  IN_BUFFER( keyDataLength ) const void *keyData,
1493  IN_LENGTH_SHORT const int keyDataLength,
1494  const BOOLEAN isECC )
1495  {
1496  CRYPT_CONTEXT md5Context = DUMMY_INIT, shaContext;
1497  CRYPT_ALGO_TYPE hashAlgo = CRYPT_ALGO_SHA1;
1498  void *dataPtr;
1499  int dataLength, keyexKeySize, sigKeySize = DUMMY_INIT, hashParam = 0;
1500  int status;
1501 
1502  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1503  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1504  assert( isWritePtr( stream, sizeof( STREAM ) ) );
1505  assert( isReadPtr( keyData, keyDataLength ) );
1506 
1507  REQUIRES( keyDataLength > 0 && keyDataLength < MAX_INTLENGTH_SHORT );
1508 
1509  /* Make sure that there's enough data present for at least a minimal-
1510  length signature and get a pointer to the signature data */
1511  if( sMemDataLeft( stream ) < ( isECC ? \
1513  return( CRYPT_ERROR_BADDATA );
1514  status = sMemGetDataBlockRemaining( stream, &dataPtr, &dataLength );
1515  if( cryptStatusError( status ) )
1516  return( status );
1517  ANALYSER_HINT( dataPtr != NULL );
1518 
1519  /* TLS 1.2+ precedes the signature itself with an indication of the hash
1520  and signature algorithm that's required to verify it, so if we're
1521  using this format then we have to process the identifiers before we
1522  can create the signature-verification hashes */
1523  if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
1524  {
1525  static const MAP_TABLE hashAlgoIDTbl[] = {
1526 #ifdef CONFIG_SUITEB
1528 #endif /* CONFIG_SUITEB */
1532  { CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 }
1533  };
1534  int cryptHashAlgo, tlsHashAlgo;
1535 
1536  /* Get the hash algorithm that we need to use. We don't care about
1537  the signature algorithm since we've already been given the public
1538  key for it */
1539  status = tlsHashAlgo = sgetc( stream );
1540  if( cryptStatusError( status ) )
1541  return( status );
1542  ( void ) sgetc( stream );
1543  status = mapValue( tlsHashAlgo, &cryptHashAlgo, hashAlgoIDTbl,
1544  FAILSAFE_ARRAYSIZE( hashAlgoIDTbl, MAP_TABLE ) );
1545  if( cryptStatusError( status ) )
1546  return( CRYPT_ERROR_NOTAVAIL );
1547  hashAlgo = cryptHashAlgo; /* int vs.enum */
1548  if( tlsHashAlgo == TLS_HASHALGO_SHA384 )
1549  hashParam = bitsToBytes( 384 );
1550  }
1551 
1552  /* Hash the data to be signed */
1553  status = createKeyexHash( handshakeInfo, &shaContext, hashAlgo,
1554  hashParam, keyData, keyDataLength );
1555  if( cryptStatusError( status ) )
1556  return( status );
1557  if( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )
1558  {
1559  status = createKeyexHash( handshakeInfo, &md5Context,
1560  CRYPT_ALGO_MD5, 0, keyData, keyDataLength );
1561  if( cryptStatusError( status ) )
1562  {
1563  krnlSendNotifier( shaContext, IMESSAGE_DECREFCOUNT );
1564  return( status );
1565  }
1566  }
1567 
1568  /* Check the signature on the hashes. The reason for the min() part of
1569  the expression is that iCryptCheckSignature() gets suspicious of
1570  very large buffer sizes, for example when the user has specified the
1571  use of a huge send buffer */
1572  if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
1573  {
1574  status = iCryptCheckSignature( dataPtr,
1575  min( dataLength, MAX_INTLENGTH_SHORT - 1 ),
1576  CRYPT_IFORMAT_TLS12,
1577  sessionInfoPtr->iKeyexCryptContext,
1578  shaContext, CRYPT_UNUSED, NULL );
1579  }
1580  else
1581  {
1582  status = iCryptCheckSignature( dataPtr,
1583  min( dataLength, MAX_INTLENGTH_SHORT - 1 ),
1584  CRYPT_IFORMAT_SSL,
1585  sessionInfoPtr->iKeyexCryptContext,
1586  md5Context, shaContext, NULL );
1587  }
1588  if( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )
1589  krnlSendNotifier( md5Context, IMESSAGE_DECREFCOUNT );
1590  krnlSendNotifier( shaContext, IMESSAGE_DECREFCOUNT );
1591  if( cryptStatusError( status ) )
1592  return( status );
1593 
1594  /* Make sure that the relative strengths of the keyex and signature keys
1595  match. This is just a general precaution for RSA/DSA, but is
1596  mandated for ECC with Suite B in order to make the appropriate
1597  fashion statement (see the comment below). When performing the check
1598  we allow a small amount of wiggle room to deal with keygen
1599  differences */
1600  status = krnlSendMessage( handshakeInfo->dhContext,
1601  IMESSAGE_GETATTRIBUTE, &keyexKeySize,
1603  if( cryptStatusOK( status ) )
1604  status = krnlSendMessage( sessionInfoPtr->iKeyexCryptContext,
1605  IMESSAGE_GETATTRIBUTE, &sigKeySize,
1607  if( cryptStatusError( status ) )
1608  return( status );
1609  if( isECC )
1610  {
1611  /* For ECC with Suite B the signature key size has to match the
1612  keyex key size otherwise fashion dictums are violated (if you
1613  could just sign size n with size n+1 then you wouldn't need
1614  hashsize n/n+1 and keysize n/n+1 and whatnot) */
1615  if( sigKeySize < keyexKeySize - bitsToBytes( 8 ) )
1616  return( CRYPT_ERROR_NOSECURE );
1617 #ifdef CONFIG_SUITEB
1618  if( ( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB ) && \
1619  sigKeySize > keyexKeySize + bitsToBytes( 8 ) )
1620  return( CRYPT_ERROR_NOSECURE );
1621  #ifdef CONFIG_SUITEB_TESTS
1622  DEBUG_PRINT(( "Verified server's P%d keyex with P%d signature.\n",
1623  bytesToBits( keyexKeySize ),
1624  bytesToBits( sigKeySize ) ));
1625  #endif /* CONFIG_SUITEB_TESTS */
1626 #endif /* CONFIG_SUITEB */
1627  }
1628  else
1629  {
1630  /* For conventional keyex/signatures the bounds are a bit looser
1631  because non-ECC keygen mechanisms can result in a wider variation
1632  of actual vs. nominal key size */
1633  if( sigKeySize < keyexKeySize - bitsToBytes( 32 ) )
1634  return( CRYPT_ERROR_NOSECURE );
1635  }
1636 
1637  /* Skip the signature data */
1638  return( readUniversal16( stream ) );
1639  }
1640 #endif /* USE_SSL */