cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ssl_hs.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib SSL v3/TLS Hello Handshake Management *
4 * Copyright Peter Gutmann 1998-2009 *
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 #ifdef USE_SSL
21 
22 /****************************************************************************
23 * *
24 * Utility Functions *
25 * *
26 ****************************************************************************/
27 
28 /* Process a session ID */
29 
30 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
31 static int processSessionID( INOUT SESSION_INFO *sessionInfoPtr,
34  {
35  BYTE sessionID[ MAX_SESSIONID_SIZE + 8 ];
36  int sessionIDlength, status;
37 
38  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
39  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
40  assert( isWritePtr( stream, sizeof( STREAM ) ) );
41 
42  /* Get the session ID information */
43  status = sessionIDlength = sgetc( stream );
44  if( cryptStatusError( status ) )
45  {
48  "Invalid session ID information" ) );
49  }
50  if( sessionIDlength <= 0 )
51  {
52  /* No session ID, we're done */
53  return( CRYPT_OK );
54  }
55  if( sessionIDlength < 1 || sessionIDlength > MAX_SESSIONID_SIZE )
56  {
59  "Invalid session ID length %d, should be 1...%d",
60  sessionIDlength, MAX_SESSIONID_SIZE ) );
61  }
62  status = sread( stream, sessionID, sessionIDlength );
63  if( cryptStatusError( status ) )
64  {
67  "Invalid session ID data" ) );
68  }
69 
70  /* If we're the server and it's not (potentially) one of our sessionIDs,
71  we're done */
72  if( isServer( sessionInfoPtr ) && sessionIDlength != SESSIONID_SIZE )
73  return( CRYPT_OK );
74 
75  /* It's a potentially resumed session, remember the details and let the
76  caller know */
77  memcpy( handshakeInfo->sessionID, sessionID, sessionIDlength );
78  handshakeInfo->sessionIDlength = sessionIDlength;
79  return( OK_SPECIAL );
80  }
81 
82 #ifdef CONFIG_SUITEB
83 
84 /* For Suite B the first suite must be ECDHE/AES128-GCM/SHA256 or
85  ECDHE/AES256-GCM/SHA384 depending on the security level and the second
86  suite, at the 128-bit security level, must be ECDHE/AES256-GCM/SHA384.
87  This is one of those pedantic checks that requires vastly more work to
88  support its nitpicking than the whole check is worth (since the same
89  thing is checked anyway when we check the suite strength), but it's
90  required by the spec */
91 
93 static int checkSuiteBSuiteSelection( IN_RANGE( SSL_FIRST_VALID_SUITE, \
94  SSL_LAST_SUITE - 1 ) \
95  const int cipherSuite,
96  const int flags,
97  const BOOLEAN isFirstSuite,
99  {
100  const char *precedenceString = isFirstSuite ? "First" : "Second";
101  const char *suiteName = NULL;
102 
103  assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );
104 
105  REQUIRES( cipherSuite >= SSL_FIRST_VALID_SUITE && \
106  cipherSuite < SSL_LAST_SUITE );
107  REQUIRES( ( flags & ~( SSL_PFLAG_SUITEB ) ) == 0 );
108 
109  if( isFirstSuite )
110  {
111  switch( flags )
112  {
114  if( cipherSuite != TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 )
115  suiteName = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
116  break;
117 
119  if( cipherSuite != TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 )
120  suiteName = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
121  break;
122 
123  default:
124  retIntError();
125  }
126  }
127  else
128  {
129  switch( flags )
130  {
132  if( cipherSuite != TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 )
133  suiteName = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
134  break;
135 
137  /* For the 256-bit level there are no further requirements */
138  break;
139 
140  default:
141  retIntError();
142  }
143  }
144  if( suiteName != NULL )
145  {
147  ( CRYPT_ERROR_NOTAVAIL, errorInfo,
148  "%s cipher suite for Suite B at the %d-bit security "
149  "level must be %s", precedenceString,
150  ( flags == SSL_PFLAG_SUITEB_128 ) ? 128 : 256,
151  suiteName ) );
152  }
153 
154  /* At the 256-bit level there's an additional requirement that the
155  client not offer any P256 cipher suites, or specifically that it not
156  offer the one P256 cipher suite allowed for Suite B (whether it can
157  offer non-Suite B P256 cipher suites is left ambiguous) */
158  if( flags == SSL_PFLAG_SUITEB_256 && \
160  {
162  ( CRYPT_ERROR_NOTAVAIL, errorInfo,
163  "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 cipher suite "
164  "can't be offered at the 256-bit security level" ) );
165  }
166 
167  return( CRYPT_OK );
168  }
169 #endif /* CONFIG_SUITEB */
170 
171 /****************************************************************************
172 * *
173 * Negotiate a Cipher Suite *
174 * *
175 ****************************************************************************/
176 
177 /* Set up the crypto information based on the cipher suite */
178 
179 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
180 static int setSuiteInfo( INOUT SESSION_INFO *sessionInfoPtr,
181  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
182  const CIPHERSUITE_INFO *cipherSuiteInfoPtr )
183  {
185  int status;
186 
187  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
188  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
189  assert( isReadPtr( cipherSuiteInfoPtr, sizeof( CIPHERSUITE_INFO ) ) );
190 
191  handshakeInfo->cipherSuite = cipherSuiteInfoPtr->cipherSuite;
192  handshakeInfo->keyexAlgo = cipherSuiteInfoPtr->keyexAlgo;
193  handshakeInfo->authAlgo = cipherSuiteInfoPtr->authAlgo;
194  handshakeInfo->cryptKeysize = cipherSuiteInfoPtr->cryptKeySize;
195  sessionInfoPtr->cryptAlgo = cipherSuiteInfoPtr->cryptAlgo;
196  sessionInfoPtr->integrityAlgo = cipherSuiteInfoPtr->macAlgo;
197  handshakeInfo->integrityAlgoParam = cipherSuiteInfoPtr->macParam;
198  if( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL )
199  {
200  /* SSL uses a proto-HMAC which requires that we synthesize it from
201  raw hash functionality */
202  sessionInfoPtr->integrityAlgo = \
203  ( sessionInfoPtr->integrityAlgo == CRYPT_ALGO_HMAC_MD5 ) ? \
205  }
206  sessionInfoPtr->authBlocksize = cipherSuiteInfoPtr->macBlockSize;
207  if( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_GCM )
208  {
209  /* GCM is a stream cipher with special-case requirements */
210  sessionInfoPtr->cryptBlocksize = 1;
211  sessionInfoPtr->protocolFlags |= SSL_PFLAG_GCM;
212  }
213  else
214  {
215  /* It's a standard cipher, get the block size */
217  IMESSAGE_DEV_QUERYCAPABILITY, &queryInfo,
218  sessionInfoPtr->cryptAlgo );
219  if( cryptStatusError( status ) )
220  return( status );
221  sessionInfoPtr->cryptBlocksize = queryInfo.blockSize;
222  }
223 
224  return( CRYPT_OK );
225  }
226 
227 /* Choose the best cipher suite from a list of suites */
228 
229 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
230 static int processCipherSuite( INOUT SESSION_INFO *sessionInfoPtr,
231  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
232  INOUT STREAM *stream,
233  IN_RANGE( 1, MAX_CIPHERSUITES ) \
234  const int noSuites )
235  {
236  const CIPHERSUITE_INFO **cipherSuiteInfo;
237  const BOOLEAN isServer = isServer( sessionInfoPtr ) ? TRUE : FALSE;
238  BOOLEAN allowDH = algoAvailable( CRYPT_ALGO_DH );
239  BOOLEAN allowECC = algoAvailable( CRYPT_ALGO_ECDH ) && \
240  algoAvailable( CRYPT_ALGO_ECDSA );
241  BOOLEAN allowRSA = algoAvailable( CRYPT_ALGO_RSA );
242  BOOLEAN allowTLS12 = \
243  ( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 ) ? TRUE : FALSE;
244 #ifdef CONFIG_SUITEB
245  const int suiteBinfo = sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB;
246 #endif /* CONFIG_SUITEB */
247  int cipherSuiteInfoSize, suiteIndex = 999, altSuiteIndex = 999;
248  int i, status;
249 
250  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
251  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
252  assert( isWritePtr( stream, sizeof( STREAM ) ) );
253 
254  REQUIRES( noSuites > 0 && noSuites <= MAX_CIPHERSUITES );
255 
256  /* Get the information for the supported cipher suites */
257  status = getCipherSuiteInfo( &cipherSuiteInfo, &cipherSuiteInfoSize,
258  isServer );
259  if( cryptStatusError( status ) )
260  return( status );
261 
262  /* If we're the server then our choice of possible suites is constrained
263  by the server key that we're using, figure out what we can use */
264  if( isServer && sessionInfoPtr->privateKey != CRYPT_ERROR )
265  {
266  int pkcAlgo;
267 
268  /* To be usable for DH/ECC the server key has to be signature-
269  capable */
270  status = krnlSendMessage( sessionInfoPtr->privateKey,
271  IMESSAGE_CHECK, NULL,
273  if( cryptStatusError( status ) )
274  allowDH = allowECC = FALSE;
275 
276  /* To be usable for ECC or RSA the server key has to itself be an
277  ECC or RSA key */
278  status = krnlSendMessage( sessionInfoPtr->privateKey,
279  IMESSAGE_GETATTRIBUTE, &pkcAlgo,
281  if( cryptStatusError( status ) )
282  allowECC = allowRSA = FALSE;
283  else
284  {
285  if( !isEccAlgo( pkcAlgo ) )
286  allowECC = FALSE;
287  if( pkcAlgo != CRYPT_ALGO_RSA )
288  allowRSA = FALSE;
289  }
290  }
291 
292  for( i = 0; i < noSuites; i++ )
293  {
294  const CIPHERSUITE_INFO *cipherSuiteInfoPtr = NULL;
295  int newSuite, newSuiteIndex;
296 
297 #ifdef ALLOW_SSLV2_HELLO /* 28/01/08 Disabled since it's now finally
298  removed in MSIE and Firefox (but see also the
299  comment in ssl_rd.c) */
300  /* If we're reading an SSLv2 hello and it's an SSLv2 suite (the high
301  byte is nonzero), skip it and continue */
302  if( handshakeInfo->isSSLv2 )
303  {
304  newSuite = sgetc( stream );
305  if( cryptStatusError( newSuite ) )
306  {
307  retExt( newSuite,
308  ( newSuite, SESSION_ERRINFO,
309  "Invalid cipher suite information" ) );
310  }
311  if( newSuite != 0 )
312  {
313  readUint16( stream );
314  continue;
315  }
316  }
317 #endif /* ALLOW_SSLV2_HELLO */
318 
319  /* Get the cipher suite information */
320  status = newSuite = readUint16( stream );
321  if( cryptStatusError( status ) )
322  {
323  retExt( status,
324  ( status, SESSION_ERRINFO,
325  "Invalid cipher suite information" ) );
326  }
327 
328  /* If we're the client and we got back our canary method-of-last-
329  resort suite from the server without having seen another suite
330  that we can use first, the server is incapable of handling non-
331  crippled crypto. Veni, vidi, volo in domum redire */
332  if( !isServer && suiteIndex >= cipherSuiteInfoSize && \
333  newSuite == SSL_RSA_EXPORT_WITH_RC4_40_MD5 )
334  {
337  "Server rejected attempt to connect using "
338  "non-crippled encryption" ) );
339  }
340 
341  /* If it's an obviously non-valid suite, continue. Note that we
342  have to perform this check after the canary check above since the
343  canary is an invalid suite */
344  if( newSuite < SSL_FIRST_VALID_SUITE || newSuite >= SSL_LAST_SUITE )
345  continue;
346 
347  /* When resuming a cached session the client is required to offer
348  as one of its suites the original suite that was used. There's
349  no good reason for this requirement (it's probable that the spec
350  is intending that there be at least one cipher suite and that if
351  there's only one it should really be the one originally
352  negotiated) and it complicates implementation of shared-secret
353  key sessions so we don't perform this check */
354 
355  /* Try and find the information for the proposed cipher suite */
356  for( newSuiteIndex = 0;
357  newSuiteIndex < cipherSuiteInfoSize && \
358  cipherSuiteInfo[ newSuiteIndex ]->cipherSuite != SSL_NULL_WITH_NULL;
359  newSuiteIndex++ )
360  {
361  if( cipherSuiteInfo[ newSuiteIndex ]->cipherSuite == newSuite )
362  {
363  cipherSuiteInfoPtr = cipherSuiteInfo[ newSuiteIndex ];
364  break;
365  }
366  }
367  ENSURES( newSuiteIndex < cipherSuiteInfoSize );
368 #ifdef CONFIG_SUITEB
369  if( ( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB ) && \
370  ( i == 0 || i == 1 ) )
371  {
372  status = checkSuiteBSuiteSelection( \
373  ( cipherSuiteInfoPtr == NULL ) ? \
374  SSL_FIRST_VALID_SUITE /* Dummy value */ : \
375  cipherSuiteInfoPtr->cipherSuite,
376  sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB,
377  ( i == 0 ) ? TRUE : FALSE, SESSION_ERRINFO );
378  if( cryptStatusError( status ) )
379  return( status );
380  }
381 #endif /* CONFIG_SUITEB */
382  if( cipherSuiteInfoPtr == NULL )
383  continue;
384 
385  /* Perform a short-circuit check, if the new suite is inherently
386  less-preferred than what we've already got then there's no point
387  to performing any of the remaining checks since it'll never be
388  selected */
389  if( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_ECC )
390  {
391  if( newSuiteIndex > altSuiteIndex )
392  continue;
393  }
394  else
395  {
396  if( newSuiteIndex > suiteIndex )
397  continue;
398  }
399 
400  /* Make sure that the required algorithms are available. If we're
401  using TLS-PSK then there's no authentication algorithm because
402  the exchange is authenticated using the PSK. We don't have to
403  check the keyex algorithm because that's handled via the
404  algorithm-class check below except for RSA, which is implicitly
405  checked by the fact that it's also used for the (checked)
406  authentication algorithm */
407  if( cipherSuiteInfoPtr->authAlgo != CRYPT_ALGO_NONE && \
408  !algoAvailable( cipherSuiteInfoPtr->authAlgo ) )
409  continue;
410  if( !algoAvailable( cipherSuiteInfoPtr->cryptAlgo ) )
411  continue;
412  if( !algoAvailable( cipherSuiteInfoPtr->macAlgo ) )
413  continue;
414 
415  /* If it's a suite that's disabled because of external constraints
416  then we can't use it */
417  if( !allowRSA && \
418  ( cipherSuiteInfoPtr->keyexAlgo == CRYPT_ALGO_RSA || \
419  cipherSuiteInfoPtr->authAlgo == CRYPT_ALGO_RSA ) )
420  continue;
421  if( !allowDH && \
422  ( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_DH ) )
423  continue;
424  if( !allowECC && \
425  ( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_ECC ) )
426  continue;
427  if( !allowTLS12 && \
428  ( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_TLS12 ) )
429  continue;
430 
431  /* If we're only able to do basic TLS-PSK because there's no private
432  key present and the suite requires a private key then we can't
433  use this suite */
434  if( isServer && sessionInfoPtr->privateKey == CRYPT_ERROR && \
435  cipherSuiteInfoPtr->keyexAlgo != CRYPT_ALGO_NONE )
436  continue;
437 
438  /* If the new suite is more preferred (i.e. with a lower index) than
439  the existing one, use that. The presence of the ECC suites
440  significantly complicates this process because the ECC curve
441  information sent later on in the handshake can retroactively
442  disable an already-negotiated ECC cipher suite, forcing a fallback
443  to a non-ECC suite (this soft-fail fallback is also nasty for the
444  user since they can't guarantee that they're actually using ECC
445  if they ask for it). To handle this we keep track of both the
446  most-preferred (non-ECC) suite and the most preferred ECC suite
447  so that we can switch later if necessary */
448  if( cipherSuiteInfoPtr->flags & CIPHERSUITE_FLAG_ECC )
449  {
450  if( newSuiteIndex < altSuiteIndex )
451  altSuiteIndex = newSuiteIndex;
452  }
453  else
454  {
455  if( newSuiteIndex < suiteIndex )
456  suiteIndex = newSuiteIndex;
457  }
458  }
459 
460  /* If the only matching suite that we found was an ECC one, set it to
461  the primary suite (which can then be retroactively knocked out as per
462  the comment earlier) */
463  if( suiteIndex >= cipherSuiteInfoSize )
464  {
465  suiteIndex = altSuiteIndex;
466  altSuiteIndex = 999;
467  }
468 
469  /* If we couldn't find anything to use, exit. The range comparison is
470  actually for whether it's still set to the original value of 999 but
471  some source code analysis tools think that it's an index check so we
472  compare to the upper bound of the array size instead */
473  if( suiteIndex >= cipherSuiteInfoSize && \
474  altSuiteIndex >= cipherSuiteInfoSize )
475  {
478  "No encryption mechanism compatible with the remote "
479  "system could be found" ) );
480  }
481 
482  /* We got a cipher suite that we can handle, set up the crypto information */
483  status = setSuiteInfo( sessionInfoPtr, handshakeInfo,
484  cipherSuiteInfo[ suiteIndex ] );
485  if( cryptStatusError( status ) )
486  return( status );
487 
488  /* If we found an ECC suite and it's not already been selected due to
489  there being no other suites available, remember this in case we later
490  find out that we can use it */
491  if( altSuiteIndex < cipherSuiteInfoSize )
492  {
493  REQUIRES( allowECC );
494 
495  handshakeInfo->eccSuiteInfoPtr = cipherSuiteInfo[ altSuiteIndex ];
496  }
497 
498  return( CRYPT_OK );
499  }
500 
501 /****************************************************************************
502 * *
503 * Process Client/Server Hello *
504 * *
505 ****************************************************************************/
506 
507 /* Process the client/server hello:
508 
509  byte ID = SSL_HAND_CLIENT_HELLO / SSL_HAND_SERVER_HELLO
510  uint24 len
511  byte[2] version = { 0x03, 0x0n }
512  byte[32] nonce
513  byte sessIDlen -- May receive nonzero len +
514  byte[] sessID -- <len> bytes data
515 
516  Client Server
517  uint16 suiteLen -
518  uint16[] suites uint16 suite
519  byte coprLen = 1 -
520  byte copr = 0 byte copr = 0
521  [ uint16 extListLen -- RFC 3546/RFC 4366
522  byte extType
523  uint16 extLen
524  byte[] extData ] */
525 
526 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
527 int processHelloSSL( INOUT SESSION_INFO *sessionInfoPtr,
528  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
529  INOUT STREAM *stream, const BOOLEAN isServer )
530  {
531  BOOLEAN potentiallyResumedSession = FALSE;
532  int endPos, length, suiteLength = 1, status;
533 
534  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
535  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
536  assert( isWritePtr( stream, sizeof( STREAM ) ) );
537 
538  /* Check the header and version information */
539  if( isServer )
540  {
541  status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
544  1 + ( UINT16_SIZE * 2 ) + 1 + 1 );
545  }
546  else
547  {
548  status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
551  1 + UINT16_SIZE + 1 );
552  }
553  if( cryptStatusError( status ) )
554  return( status );
555  endPos = stell( stream ) + length;
556  status = processVersionInfo( sessionInfoPtr, stream,
557  isServer ? \
558  &handshakeInfo->clientOfferedVersion : \
559  NULL );
560  if( cryptStatusError( status ) )
561  return( status );
562 
563  /* Since we now know which protocol version we're using, we can turn off
564  any hashing that we don't require any more */
565  if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
566  {
567  if( handshakeInfo->md5context != CRYPT_ERROR )
568  {
569  krnlSendNotifier( handshakeInfo->md5context,
571  handshakeInfo->md5context = CRYPT_ERROR;
572  krnlSendNotifier( handshakeInfo->sha1context,
574  handshakeInfo->sha1context = CRYPT_ERROR;
575  }
576  }
577  else
578  {
579  if( handshakeInfo->sha2context != CRYPT_ERROR )
580  {
581  krnlSendNotifier( handshakeInfo->sha2context,
583  handshakeInfo->sha2context = CRYPT_ERROR;
584  }
585 #ifdef CONFIG_SUITEB
586  if( handshakeInfo->sha384context != CRYPT_ERROR )
587  {
588  krnlSendNotifier( handshakeInfo->sha384context,
590  handshakeInfo->sha384context = CRYPT_ERROR;
591  }
592 #endif /* CONFIG_SUITEB */
593  }
594 
595  /* Process the nonce and session ID */
596  status = sread( stream, isServer ? \
597  handshakeInfo->clientNonce : \
598  handshakeInfo->serverNonce, SSL_NONCE_SIZE );
599  if( cryptStatusOK( status ) )
600  status = processSessionID( sessionInfoPtr, handshakeInfo, stream );
601  if( cryptStatusError( status ) )
602  {
603  if( status == OK_SPECIAL )
604  potentiallyResumedSession = TRUE;
605  else
606  return( status );
607  }
608 
609  /* Process the cipher suite information */
610  if( isServer )
611  {
612  /* We're reading the client hello, the packet contains a
613  selection of suites preceded by a suite count */
614  status = suiteLength = readUint16( stream );
615  if( cryptStatusError( status ) )
616  {
619  "Invalid cipher suite information" ) );
620  }
621  if( suiteLength < UINT16_SIZE || \
622  suiteLength > ( UINT16_SIZE * MAX_CIPHERSUITES ) || \
623  ( suiteLength % UINT16_SIZE ) != 0 )
624  {
627  "Invalid cipher suite length %d",
628  suiteLength ) );
629  }
630  suiteLength /= UINT16_SIZE;
631  }
632  status = processCipherSuite( sessionInfoPtr, handshakeInfo, stream,
633  suiteLength );
634  if( cryptStatusError( status ) )
635  return( status );
636 
637  /* Process the compression suite information. Since we don't implement
638  compression all that we need to do is check that the format is valid
639  and then skip the suite information */
640  if( isServer )
641  {
642  /* We're reading the client hello, the packet contains a selection
643  of suites preceded by a suite count */
644  status = suiteLength = sgetc( stream );
645  if( cryptStatusError( status ) )
646  {
649  "Invalid compression suite information" ) );
650  }
651  if( suiteLength < 1 || suiteLength > 20 )
652  {
655  "Invalid compression suite length %d, should be "
656  "1...20", suiteLength ) );
657  }
658  }
659  status = sSkip( stream, suiteLength );
660  if( cryptStatusError( status ) )
661  {
664  "Invalid compression algorithm information" ) );
665  }
666 
667  /* If there's extra data present at the end of the packet, check for TLS
668  extension data */
669  if( endPos - stell( stream ) > 0 )
670  {
671  const int extensionLength = endPos - stell( stream );
672 
673  if( extensionLength < UINT16_SIZE || \
674  extensionLength >= MAX_INTLENGTH_SHORT )
675  {
678  "TLS hello contains %d bytes extraneous data",
679  extensionLength ) );
680  }
681  status = readExtensions( sessionInfoPtr, handshakeInfo, stream,
682  extensionLength );
683  if( cryptStatusError( status ) )
684  return( status );
685  handshakeInfo->hasExtensions = TRUE;
686  }
687 
688  /* If we're the server, perform any special-case handling required by
689  the fact that the selection of an ECC cipher suite can be
690  retroactively modified by by TLS extensions that disable its use
691  again */
692  if( isServer )
693  {
694  if( handshakeInfo->disableECC )
695  {
696  /* If the only available suite is an ECC one but it's been
697  disabled through an incompatible choice of client-selected
698  algorithm parameters then we can't continue */
699  if( isEccAlgo( handshakeInfo->keyexAlgo ) )
700  {
703  "Client specified use of an ECC cipher suite but "
704  "didn't provide any compatible ECC parameters" ) );
705  }
706  }
707  else
708  {
709  /* If the client has chosen an ECC suite and it hasn't
710  subsequently been disabled by an incompatible choice of
711  client-selected parameters, switch to the ECC suite. If the
712  only available option was an ECC suite then it'll already
713  have been enabled so we don't need to do it */
714  if( handshakeInfo->eccSuiteInfoPtr != NULL )
715  {
716  status = setSuiteInfo( sessionInfoPtr, handshakeInfo,
717  handshakeInfo->eccSuiteInfoPtr );
718  if( cryptStatusError( status ) )
719  return( status );
720  }
721 
722  /* If we're using an ECC cipher suite (either due to it being
723  the only suite available or because it was selected above)
724  and there's no ECC curve selected by the client, default to
725  P256 */
726  if( isEccAlgo( handshakeInfo->keyexAlgo ) && \
727  handshakeInfo->eccCurveID == CRYPT_ECCCURVE_NONE )
728  handshakeInfo->eccCurveID = CRYPT_ECCCURVE_P256;
729  }
730  }
731 
732  /* If we're using Suite B and the MAC algorithm is an extended
733  HMAC-SHA-2 algorithm (which means that the hash algorithm will also
734  be extended SHA-2), replace the straight SHA2 context with the
735  extended version */
736 #ifdef CONFIG_SUITEB
737  if( sessionInfoPtr->integrityAlgo == CRYPT_ALGO_HMAC_SHA2 && \
738  handshakeInfo->integrityAlgoParam == bitsToBytes( 384 ) )
739  {
740  krnlSendNotifier( handshakeInfo->sha2context,
742  handshakeInfo->sha2context = handshakeInfo->sha384context;
743  handshakeInfo->sha384context = CRYPT_ERROR;
744  }
745 #endif /* CONFIG_SUITEB */
746 
747  return( potentiallyResumedSession ? OK_SPECIAL : CRYPT_OK );
748  }
749 #endif /* USE_SSL */