cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ssl_suites.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib SSL v3/TLS Cipher Suites *
4 * Copyright Peter Gutmann 1998-2010 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "session.h"
11  #include "ssl.h"
12 #else
13  #include "crypt.h"
14  #include "session/session.h"
15  #include "session/ssl.h"
16 #endif /* Compiler-specific includes */
17 
18 #ifdef USE_SSL
19 
20 /****************************************************************************
21 * *
22 * Cipher Suite Definitions *
23 * *
24 ****************************************************************************/
25 
26 /* The monster list of cryptlib's SSL/TLS cipher suites (the full list is
27  even longer than this). There are a pile of DH cipher suites, in
28  practice only DHE is used, DH requires the use of X9.42 DH certificates
29  (there aren't any) and DH_anon uses unauthenticated DH which implementers
30  seem to have an objection to even though it's not much different in
31  effect from the way RSA cipher suites are used in practice.
32 
33  To keep things simple for the caller we only allow RSA auth for DH key
34  agreement and not DSA, since the former also automatically works for the
35  far more common RSA key exchange that's usually used for key setup.
36  Similarly we only allow ECDSA for ECDH, since anyone who wants to make
37  the ECC fashion statement isn't going to then fall back to RSA for the
38  server authentication. In both cases the actions for the unused suites
39  are present in the table but commented out.
40 
41  We prefer AES-128 to AES-256 since -256 has a weaker key schedule than
42  -128, so if anyone's going to attack it they'll go for the key schedule
43  rather than the (mostly irrelevant) -128 vs. -256.
44 
45  Some buggy older versions of IIS that only support crippled crypto drop
46  the connection when they see a client hello advertising strong crypto
47  rather than sending an alert as they should. To work around this we
48  advertise a dummy cipher suite SSL_RSA_EXPORT_WITH_RC4_40_MD5 as a canary
49  to force IIS to send back a response that we can then turn into an error
50  message. The need to do this is somewhat unfortunate since it will
51  appear to an observer that cryptlib will use crippled crypto (in fact it
52  won't even load such a key) but there's no other way to detect the buggy
53  IIS apart from completely restarting the session activation at the
54  session level with crippled-crypto advertised in the restarted session.
55 
56  The number of suites and different configuration options are sufficiently
57  complex that we can't use a fixed table for them but have to dynamically
58  build them up at runtime from the following sub-tables */
59 
60 #define MAX_CIPHERSUITE_TBLSIZE 64
61 
62 static const CIPHERSUITE_INFO cipherSuiteDH[] = {
63  /* 3DES with DH */
65  DESCRIPTION( "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA" )
69 /* { TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
70  DESCRIPTION( "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA" )
71  CRYPT_ALGO_DH, CRYPT_ALGO_DSA, CRYPT_ALGO_3DES,
72  CRYPT_ALGO_HMAC_SHA1, 0, 24, SHA1MAC_SIZE,
73  CIPHERSUITE_FLAG_DH }, */
74 
75  /* AES with DH */
77  DESCRIPTION( "TLS_DHE_RSA_WITH_AES_128_CBC_SHA" )
82  DESCRIPTION( "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256" )
86 /* { TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
87  DESCRIPTION( "TLS_DHE_DSS_WITH_AES_128_CBC_SHA" )
88  CRYPT_ALGO_RSA, CRYPT_ALGO_DSA, CRYPT_ALGO_AES,
89  CRYPT_ALGO_HMAC_SHA1, 0, 16, SHA1MAC_SIZE, CIPHERSUITE_FLAG_DH },
90  { TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
91  DESCRIPTION( "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256" )
92  CRYPT_ALGO_RSA, CRYPT_ALGO_DSA, CRYPT_ALGO_AES,
93  CRYPT_ALGO_HMAC_SHA2, 0, 16, SHA2MAC_SIZE,
94  CIPHERSUITE_FLAG_DH | CIPHERSUITE_FLAG_TLS12 }, */
96  DESCRIPTION( "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" )
100  DESCRIPTION( "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" )
103  CIPHERSUITE_FLAG_DH | CIPHERSUITE_FLAG_TLS12 },
104 /* { TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
105  DESCRIPTION( "TLS_DHE_DSS_WITH_AES_256_CBC_SHA" )
106  CRYPT_ALGO_DH, CRYPT_ALGO_DSA, CRYPT_ALGO_AES,
107  CRYPT_ALGO_HMAC_SHA1, 0, 32, SHA1MAC_SIZE, CIPHERSUITE_FLAG_DH },
108  { TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
109  DESCRIPTION( "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256" )
110  CRYPT_ALGO_DH, CRYPT_ALGO_DSA, CRYPT_ALGO_AES,
111  CRYPT_ALGO_HMAC_SHA2, 0, 32, SHA2MAC_SIZE,
112  CIPHERSUITE_FLAG_DH | CIPHERSUITE_FLAG_TLS12 }, */
113 
114  /* End-of-list marker */
116  DESCRIPTION( "End-of-list marker" )
120  DESCRIPTION( "End-of-list marker" )
123  };
124 
125 static const CIPHERSUITE_INFO cipherSuiteECC[] = {
126  /* ECDH with ECDSA */
128  DESCRIPTION( "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA" )
133  DESCRIPTION( "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" )
136  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_TLS12 },
137 /* { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
138  DESCRIPTION( "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" )
139  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,
140  CRYPT_ALGO_HMAC_SHA2, 0, 32, SHA2MAC_SIZE,
141  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_TLS12 }, */
143  DESCRIPTION( "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA" )
148  DESCRIPTION( "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" )
153  DESCRIPTION( "TLS_ECDHE_RSA_WITH_RC4_128_SHA" )
157 
158  /* ECDH with RSA */
159 /* { TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
160  DESCRIPTION( "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA" )
161  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_3DES,
162  CRYPT_ALGO_HMAC_SHA1, 0, 24, SHA1MAC_SIZE,
163  CIPHERSUITE_FLAG_ECC },
164  { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
165  DESCRIPTION( "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA" )
166  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,
167  CRYPT_ALGO_HMAC_SHA1, 0, 16, SHA1MAC_SIZE,
168  CIPHERSUITE_FLAG_ECC },
169  { TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
170  DESCRIPTION( "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" )
171  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,
172  CRYPT_ALGO_HMAC_SHA1, 0, 32, SHA1MAC_SIZE,
173  CIPHERSUITE_FLAG_ECC }, */
174 
175  /* End-of-list marker */
177  DESCRIPTION( "End-of-list marker" )
181  DESCRIPTION( "End-of-list marker" )
184  };
185 
186 static const CIPHERSUITE_INFO cipherSuiteGCM[] = {
187  /* ECDH with ECDSA and AES-GCM */
189  DESCRIPTION( "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" )
192  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 },
193 /* { TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
194  DESCRIPTION( "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" )
195  CRYPT_ALGO_ECDH, CRYPT_ALGO_RSA, CRYPT_ALGO_AES,
196  CRYPT_ALGO_HMAC_SHA2, 0, 16, GCMICV_SIZE,
197  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 }, */
198 
199  /* AES-GCM with DH */
201  DESCRIPTION( "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256" )
204  CIPHERSUITE_FLAG_DH | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 },
205 /* { TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,
206  DESCRIPTION( "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256" )
207  CRYPT_ALGO_DH, CRYPT_ALGO_DSA, CRYPT_ALGO_AES,
208  CRYPT_ALGO_HMAC_SHA2, 0, 16, GCMICV_SIZE,
209  CIPHERSUITE_FLAG_DH | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 }, */
210 
211  /* AES-GCM with RSA */
213  DESCRIPTION( "TLS_RSA_WITH_AES_128_GCM_SHA256" )
216  CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12 },
217 
218  /* End-of-list marker */
220  DESCRIPTION( "End-of-list marker" )
224  DESCRIPTION( "End-of-list marker" )
227  };
228 
229 static const CIPHERSUITE_INFO cipherSuiteMisc[] = {
230  /* RC4 + RSA */
232  DESCRIPTION( "SSL_RSA_WITH_RC4_128_SHA" )
237  DESCRIPTION( "SSL_RSA_WITH_RC4_128_MD5" )
241 
242  /* DES + RSA */
244  DESCRIPTION( "SSL_RSA_WITH_DES_CBC_SHA" )
249  DESCRIPTION( "TLS_DHE_RSA_WITH_DES_CBC_SHA" )
253 /* { TLS_DHE_DSS_WITH_DES_CBC_SHA,
254  DESCRIPTION( "TLS_DHE_DSS_WITH_DES_CBC_SHA" )
255  CRYPT_ALGO_DH, CRYPT_ALGO_DSA, CRYPT_ALGO_DES,
256  CRYPT_ALGO_HMAC_SHA1, 0, 8, SHA1MAC_SIZE,
257  CIPHERSUITE_FLAG_NONE }, */
258 
259  /* End-of-list marker */
261  DESCRIPTION( "End-of-list marker" )
265  DESCRIPTION( "End-of-list marker" )
268  };
269 
270 static const CIPHERSUITE_INFO cipherSuitePSK[] = {
271  /* PSK */
273  DESCRIPTION( "TLS_PSK_WITH_3DES_EDE_CBC_SHA" )
278  DESCRIPTION( "TLS_PSK_WITH_AES_128_CBC_SHA" )
283  DESCRIPTION( "TLS_PSK_WITH_AES_256_CBC_SHA" )
288  DESCRIPTION( "TLS_PSK_WITH_RC4_128_SHA" )
292 
293  /* End-of-list marker */
295  DESCRIPTION( "End-of-list marker" )
299  DESCRIPTION( "End-of-list marker" )
302  };
303 
304 static const CIPHERSUITE_INFO cipherSuiteRSA[] = {
305  /* 3DES with RSA */
307  DESCRIPTION( "SSL_RSA_WITH_3DES_EDE_CBC_SHA" )
311 
312  /* AES with RSA */
314  DESCRIPTION( "TLS_RSA_WITH_AES_128_CBC_SHA" )
319  DESCRIPTION( "TLS_RSA_WITH_AES_256_CBC_SHA" )
324  DESCRIPTION( "TLS_RSA_WITH_AES_128_CBC_SHA256" )
327  CIPHERSUITE_FLAG_TLS12 },
329  DESCRIPTION( "TLS_RSA_WITH_AES_256_CBC_SHA256" )
332  CIPHERSUITE_FLAG_TLS12 },
333 
334  /* End-of-list marker */
336  DESCRIPTION( "End-of-list marker" )
340  DESCRIPTION( "End-of-list marker" )
343  };
344 
345 static const CIPHERSUITE_INFO cipherSuiteCanary[] = {
346  /* Canary used to detect the use of weak ciphers by the peer (where the
347  peer in this case would be "older versions of IIS") */
349  DESCRIPTION( "SSL_RSA_EXPORT_WITH_RC4_40_MD5" )
353 
354  /* End-of-list marker */
356  DESCRIPTION( "End-of-list marker" )
360  DESCRIPTION( "End-of-list marker" )
363  };
364 
365 /* Tables defining the arrangement of the above sets of suites into a
366  single monster list. The order of adding suites is as follows:
367 
368  [ Optional special-case suites, for testing or custom configurations ].
369  PSK suites, since they provide proper mutual authentication.
370  ECC suites if PREFER_ECC is defined, since anyone wanting to make this
371  particular fashion statement probably wants to actually use the
372  suites rather than having them ignored as the 25th-ranked
373  option. (GCM with ECC is a variant of this, this is even more
374  of a fashion statement and really only makes sense with ECC).
375  DH suites unless PREFER_RSA_TO_DH is defined, since these provide
376  PFS, are secure against factoring attacks, and in many cases
377  are the same as RSA when employed in anon-DH-equivalent mode.
378  RSA suites with strong ciphers.
379  Misc RSA suites with also-ran ciphers.
380  Canary used to detect broken older version of MSIE */
381 
382 typedef struct {
383  const CIPHERSUITE_INFO *cipherSuites;
384  const int cipherSuiteCount;
385  } CIPHERSUITES_LIST;
386 
387 static const CIPHERSUITES_LIST cipherSuitesList[] = {
388  { cipherSuitePSK, FAILSAFE_ARRAYSIZE( cipherSuitePSK, CIPHERSUITE_INFO ) },
389 #if defined( PREFER_ECC ) && defined( USE_ECDH ) && defined( USE_ECDSA )
390  #ifdef USE_GCM
391  { cipherSuiteGCM, FAILSAFE_ARRAYSIZE( cipherSuiteGCM, CIPHERSUITE_INFO ) },
392  #endif /* USE_GCM */
393  { cipherSuiteECC, FAILSAFE_ARRAYSIZE( cipherSuiteECC, CIPHERSUITE_INFO ) },
394 #endif /* PREFER_ECC && USE_ECDH && USE_ECDSA */
395 #ifdef PREFER_RSA_TO_DH
396  { cipherSuiteRSA, FAILSAFE_ARRAYSIZE( cipherSuiteRSA, CIPHERSUITE_INFO ) },
397  { cipherSuiteDH, FAILSAFE_ARRAYSIZE( cipherSuiteDH, CIPHERSUITE_INFO ) },
398 #else
399  { cipherSuiteDH, FAILSAFE_ARRAYSIZE( cipherSuiteDH, CIPHERSUITE_INFO ) },
400  { cipherSuiteRSA, FAILSAFE_ARRAYSIZE( cipherSuiteRSA, CIPHERSUITE_INFO ) },
401 #endif /* PREFER_RSA_TO_DH */
402 #if !defined( PREFER_ECC ) && defined( USE_ECDH ) && defined( USE_ECDSA )
403  #ifdef USE_GCM
404  { cipherSuiteGCM, FAILSAFE_ARRAYSIZE( cipherSuiteGCM, CIPHERSUITE_INFO ) },
405  #endif /* USE_GCM */
406  { cipherSuiteECC, FAILSAFE_ARRAYSIZE( cipherSuiteECC, CIPHERSUITE_INFO ) },
407 #endif /* !PREFER_ECC && USE_ECDH && USE_ECDSA */
408  { cipherSuiteMisc, FAILSAFE_ARRAYSIZE( cipherSuiteMisc, CIPHERSUITE_INFO ) },
409  { cipherSuiteCanary, FAILSAFE_ARRAYSIZE( cipherSuiteCanary, CIPHERSUITE_INFO ) },
410  { NULL, 0 }, { NULL, 0 }
411  };
412 
413 /****************************************************************************
414 * *
415 * Cipher Suite Definitions for Suite B *
416 * *
417 ****************************************************************************/
418 
419 /* If we're running in a Suite B configuration then we don't bother with any
420  of the standard cipher suites but only provide Suite B suites */
421 
422 #if defined( CONFIG_SUITEB )
423 
424 #if defined( _MSC_VER )
425  #pragma message( " Building with custom suite: Suite B" )
426  #if defined( CONFIG_SUITEB_TESTS )
427  #pragma message( " Building with custom suite: Suite B test suites" )
428  #endif /* Suite B special test suites */
429 #endif /* VC++ */
430 
431 /* 256-bit Suite B suites */
432 
433 static const CIPHERSUITE_INFO suiteBP384GCM = {
435  DESCRIPTION( "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" )
438  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12
439  };
440 
441 /* 128-bit Suite B suites */
442 
443 static const CIPHERSUITE_INFO suiteBP256GCM = {
445  DESCRIPTION( "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" )
448  CIPHERSUITE_FLAG_ECC | CIPHERSUITE_FLAG_GCM | CIPHERSUITE_FLAG_TLS12
449  };
450 
451 /* End-of-list marker */
452 
453 static const CIPHERSUITE_INFO suiteBEOL = {
455  DESCRIPTION( "End-of-list marker" )
458  };
459 
460 /* Since the only suites that we're enabling are the Suite B ones, we
461  override the default getCipherSuiteInfo() with our own one */
462 
463 CHECK_RETVAL \
464 int getSuiteBCipherSuiteInfo( OUT const CIPHERSUITE_INFO ***cipherSuiteInfoPtrPtrPtr,
465  OUT_INT_Z int *noSuiteEntries,
467  IN_FLAGS_Z( SSL ) const int suiteBinfo )
468  {
469  static const CIPHERSUITE_INFO *cipherSuite192InfoTbl[] = \
470  { &suiteBP384GCM, &suiteBEOL, &suiteBEOL };
471  static const CIPHERSUITE_INFO *cipherSuite128InfoTbl[] = \
472  { &suiteBP256GCM, &suiteBP384GCM, &suiteBEOL, &suiteBEOL };
473  BOOLEAN is128bitLevel = ( ( suiteBinfo & SSL_PFLAG_SUITEB ) == \
475 
476  assert( isReadPtr( cipherSuiteInfoPtrPtrPtr, \
477  sizeof( CIPHERSUITE_INFO ** ) ) );
478  assert( isWritePtr( noSuiteEntries, sizeof( int ) ) );
479 
480  REQUIRES( suiteBinfo >= SSL_PFLAG_NONE && suiteBinfo < SSL_PFLAG_MAX );
481 
482  /* Depending on the security level that we're configured for we either
483  prefer the 128-bit suites or the 192-bit suites */
484  if( is128bitLevel )
485  {
486  *cipherSuiteInfoPtrPtrPtr = ( const CIPHERSUITE_INFO ** ) \
487  cipherSuite128InfoTbl; /* For gcc */
488  *noSuiteEntries = FAILSAFE_ARRAYSIZE( cipherSuite128InfoTbl, \
489  CIPHERSUITE_INFO * );
490  }
491  else
492  {
493  *cipherSuiteInfoPtrPtrPtr = ( const CIPHERSUITE_INFO ** ) \
494  cipherSuite192InfoTbl; /* For gcc */
495  *noSuiteEntries = FAILSAFE_ARRAYSIZE( cipherSuite192InfoTbl, \
496  CIPHERSUITE_INFO * );
497  }
498  return( CRYPT_OK );
499  }
500 
501 /* Remap the usual getCipherSuiteInfo() into an alternative name that
502  doesn't clash with the Suite B replacement */
503 
504 #undef getCipherSuiteInfo
505 #define getCipherSuiteInfo getCipherSuiteInfoOriginal
506 
507 #endif /* CONFIG_SUITEB */
508 
509 /****************************************************************************
510 * *
511 * Cipher Suite Functions *
512 * *
513 ****************************************************************************/
514 
515 /* Build the single unified list of ciphers suites in preferred-algorithm
516  order */
517 
518 CHECK_RETVAL \
519 static int addCipherSuiteInfo( INOUT CIPHERSUITE_INFO **cipherSuiteTbl,
520  IN_RANGE( 0, MAX_CIPHERSUITE_TBLSIZE ) \
521  const int cipherSuiteTblCount,
522  OUT_RANGE( 0, MAX_CIPHERSUITE_TBLSIZE ) \
523  int *newCipherSuiteTblCount,
524  const CIPHERSUITE_INFO *cipherSuites,
525  IN_RANGE( 0, MAX_CIPHERSUITE_TBLSIZE / 2 ) \
526  const int cipherSuitesCount )
527  {
528  int srcIndex, destIndex;
529 
530  assert( isReadPtr( cipherSuiteTbl, \
531  sizeof( CIPHERSUITE_INFO * ) * MAX_CIPHERSUITE_TBLSIZE ) );
532  assert( isWritePtr( newCipherSuiteTblCount, sizeof( int ) ) );
533  assert( isReadPtr( cipherSuites,
534  sizeof( CIPHERSUITE_INFO * ) * 2 ) );
535 
536  REQUIRES( cipherSuiteTblCount >= 0 && \
537  cipherSuiteTblCount < MAX_CIPHERSUITE_TBLSIZE );
538  REQUIRES( cipherSuitesCount >= 0 && \
539  cipherSuitesCount < MAX_CIPHERSUITE_TBLSIZE / 2 );
540 
541  /* Clear return value. Unlike standard practice this doesn't set it to
542  zero but to the existing count, making the call a no-op */
543  *newCipherSuiteTblCount = cipherSuiteTblCount;
544 
545  /* Add any new suites to the existing table */
546  for( srcIndex = 0, destIndex = cipherSuiteTblCount;
547  cipherSuites[ srcIndex ].cipherSuite != SSL_NULL_WITH_NULL && \
548  srcIndex < cipherSuitesCount && destIndex < MAX_CIPHERSUITE_TBLSIZE;
549  srcIndex++, destIndex++ )
550  {
551  cipherSuiteTbl[ destIndex ] = ( CIPHERSUITE_INFO * ) \
552  &cipherSuites[ srcIndex ];
553  }
554  ENSURES( srcIndex < cipherSuitesCount );
555  ENSURES( destIndex < MAX_CIPHERSUITE_TBLSIZE );
556 
557  *newCipherSuiteTblCount = destIndex;
558 
559  return( CRYPT_OK );
560  }
561 
562 CHECK_RETVAL \
563 int getCipherSuiteInfo( OUT const CIPHERSUITE_INFO ***cipherSuiteInfoPtrPtrPtr,
564  OUT_INT_Z int *noSuiteEntries,
565  STDC_UNUSED const BOOLEAN isServer )
566  {
567  static CIPHERSUITE_INFO *cipherSuiteInfoTbl[ MAX_CIPHERSUITE_TBLSIZE + 8 ];
568  static BOOLEAN cipherSuitInfoInited = FALSE;
569  static int cipherSuiteCount = 0;
570  int status;
571 
572  assert( isReadPtr( cipherSuiteInfoPtrPtrPtr, \
573  sizeof( CIPHERSUITE_INFO ** ) ) );
574  assert( isWritePtr( noSuiteEntries, sizeof( int ) ) );
575 
576  /* Dynamically set up the monster table of cipher suites. Note that
577  this isn't thread-safe, but since it performs the setup in a
578  completely deterministic manner it doesn't matter if the extremely
579  unlikely situation of two threads initialising the array at the same
580  time occurs, since they're initialising it identically */
581  if( !cipherSuitInfoInited )
582  {
583  static const CIPHERSUITE_INFO endOfList = {
585  DESCRIPTION( "End-of-list marker" )
588  int i;
589 
590  /* Build the unified list of cipher suites */
591  for( i = 0;
592  cipherSuitesList[ i ].cipherSuites != NULL && \
593  i < FAILSAFE_ARRAYSIZE( cipherSuitesList, CIPHERSUITES_LIST );
594  i++ )
595  {
596  status = addCipherSuiteInfo( cipherSuiteInfoTbl, cipherSuiteCount,
597  &cipherSuiteCount, cipherSuitesList[ i ].cipherSuites,
598  cipherSuitesList[ i ].cipherSuiteCount );
599  if( cryptStatusError( status ) )
600  return( status );
601  }
602  ENSURES( i < FAILSAFE_ARRAYSIZE( cipherSuitesList, CIPHERSUITES_LIST ) );
603 
604  /* Add the end-of-list marker suites. Note that we don't increment
605  the suite count when the second one is added to match the
606  behaviour of FAILSAFE_ARRAYSIZE() */
607  REQUIRES( cipherSuiteCount + 2 < MAX_CIPHERSUITE_TBLSIZE );
608  cipherSuiteInfoTbl[ cipherSuiteCount++ ] = \
609  ( CIPHERSUITE_INFO * ) &endOfList;
610  cipherSuiteInfoTbl[ cipherSuiteCount ] = \
611  ( CIPHERSUITE_INFO * ) &endOfList;
612 
613  cipherSuitInfoInited = TRUE;
614  }
615 
616  *cipherSuiteInfoPtrPtrPtr = ( const CIPHERSUITE_INFO ** ) \
617  cipherSuiteInfoTbl; /* For gcc */
618  *noSuiteEntries = cipherSuiteCount;
619 
620  return( CRYPT_OK );
621  }
622 #endif /* USE_SSL */