cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ssl_kmgmt.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib SSL v3/TLS Key Management Routines *
4 * Copyright Peter Gutmann 1998-2008 *
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 * Init/Shutdown Functions *
25 * *
26 ****************************************************************************/
27 
28 /* Initialise and destroy the crypto information in the handshake state
29  information */
30 
32 int initHandshakeCryptInfo( INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
33  const BOOLEAN isTLS12 )
34  {
35  MESSAGE_CREATEOBJECT_INFO createInfo;
36  int status;
37 
38  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
39 
40  /* Clear the handshake information contexts */
41  handshakeInfo->md5context = \
42  handshakeInfo->sha1context = \
43  handshakeInfo->sha2context = CRYPT_ERROR;
44 #ifdef CONFIG_SUITEB
45  handshakeInfo->sha384context = CRYPT_ERROR;
46 #endif /* CONFIG_SUITEB */
47  handshakeInfo->dhContext = \
48  handshakeInfo->certVerifyContext = CRYPT_ERROR;
49 
50  /* Create the MAC/dual-hash contexts for incoming and outgoing data.
51  SSL uses a pre-HMAC variant for which we can't use real HMAC but have
52  to construct it ourselves from MD5 and SHA-1, TLS uses a straight dual
53  hash and MACs that once a MAC key becomes available at the end of the
54  handshake */
57  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
59  if( cryptStatusOK( status ) )
60  {
61  handshakeInfo->md5context = createInfo.cryptHandle;
64  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
66  }
67  if( cryptStatusOK( status ) )
68  {
69  handshakeInfo->sha1context = createInfo.cryptHandle;
70  if( !isTLS12 )
71  return( CRYPT_OK );
72  }
73 #ifdef CONFIG_SUITEB
74  if( cryptStatusOK( status ) )
75  {
76  /* Create the additional SHA2-384 context that's needed for Suite
77  B use */
80  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
82  if( cryptStatusOK( status ) )
83  {
84  static const int blockSize = bitsToBytes( 384 );
85 
86  handshakeInfo->sha384context = createInfo.cryptHandle;
87  status = krnlSendMessage( handshakeInfo->sha384context,
89  ( MESSAGE_CAST ) &blockSize,
91  }
92  }
93 #endif /* CONFIG_SUITEB */
94  if( cryptStatusOK( status ) )
95  {
96  /* Create additional contexts that may be needed for TLS 1.2 */
99  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
101  }
102  if( cryptStatusOK( status ) )
103  {
104  handshakeInfo->sha2context = createInfo.cryptHandle;
105  return( CRYPT_OK );
106  }
107 
108  /* One or more of the contexts couldn't be created, destroy all of the
109  contexts that have been created so far */
110  destroyHandshakeCryptInfo( handshakeInfo );
111  return( status );
112  }
113 
114 STDC_NONNULL_ARG( ( 1 ) ) \
115 void destroyHandshakeCryptInfo( INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
116  {
117  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
118 
119  /* Destroy any active contexts. We need to do this here (even though
120  it's also done in the general session code) to provide a clean exit in
121  case the session activation fails, so that a second activation attempt
122  doesn't overwrite still-active contexts */
123  if( handshakeInfo->md5context != CRYPT_ERROR )
124  {
125  krnlSendNotifier( handshakeInfo->md5context,
127  handshakeInfo->md5context = CRYPT_ERROR;
128  }
129  if( handshakeInfo->sha1context != CRYPT_ERROR )
130  {
131  krnlSendNotifier( handshakeInfo->sha1context,
133  handshakeInfo->sha1context = CRYPT_ERROR;
134  }
135  if( handshakeInfo->sha2context != CRYPT_ERROR )
136  {
137  krnlSendNotifier( handshakeInfo->sha2context,
139  handshakeInfo->sha2context = CRYPT_ERROR;
140  }
141 #ifdef CONFIG_SUITEB
142  if( handshakeInfo->sha384context != CRYPT_ERROR )
143  {
144  krnlSendNotifier( handshakeInfo->sha384context,
146  handshakeInfo->sha384context = CRYPT_ERROR;
147  }
148 #endif /* CONFIG_SUITEB */
149  if( handshakeInfo->dhContext != CRYPT_ERROR )
150  {
151  krnlSendNotifier( handshakeInfo->dhContext, IMESSAGE_DECREFCOUNT );
152  handshakeInfo->dhContext = CRYPT_ERROR;
153  }
154  if( handshakeInfo->certVerifyContext != CRYPT_ERROR )
155  {
156  krnlSendNotifier( handshakeInfo->certVerifyContext,
158  handshakeInfo->certVerifyContext = CRYPT_ERROR;
159  }
160  }
161 
162 /* Initialise and destroy the session security contexts */
163 
164 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
165 static int initSecurityContextsSSL( INOUT SESSION_INFO *sessionInfoPtr,
166  INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
167  {
168  MESSAGE_CREATEOBJECT_INFO createInfo;
169  int status;
170 
171  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
172  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
173 
174  /* Create the authentication contexts, unless we're using a combined
175  encryption+authentication mode */
176  if( !( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM ) )
177  {
178  const CRYPT_ALGO_TYPE integrityAlgo = sessionInfoPtr->integrityAlgo;
179 
180  setMessageCreateObjectInfo( &createInfo, integrityAlgo );
182  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
184  if( cryptStatusOK( status ) )
185  {
186  sessionInfoPtr->iAuthInContext = createInfo.cryptHandle;
187  setMessageCreateObjectInfo( &createInfo, integrityAlgo );
189  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
191  }
192  if( cryptStatusError( status ) )
193  {
194  destroySecurityContextsSSL( sessionInfoPtr );
195  return( status );
196  }
197  sessionInfoPtr->iAuthOutContext = createInfo.cryptHandle;
198 #ifdef CONFIG_SUITEB
199  if( cryptStatusOK( status ) && \
200  handshakeInfo->integrityAlgoParam == bitsToBytes( 384 ) )
201  {
202  static const int blockSize = bitsToBytes( 384 );
203 
204  status = krnlSendMessage( sessionInfoPtr->iAuthInContext,
206  ( MESSAGE_CAST ) &blockSize,
208  if( cryptStatusOK( status ) )
209  {
210  status = krnlSendMessage( sessionInfoPtr->iAuthOutContext,
212  ( MESSAGE_CAST ) &blockSize,
214  }
215  if( cryptStatusError( status ) )
216  {
217  destroySecurityContextsSSL( sessionInfoPtr );
218  return( status );
219  }
220  }
221 #endif /* CONFIG_SUITEB */
222  }
223 
224  /* Create the encryption contexts */
225  setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );
227  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
229  if( cryptStatusOK( status ) )
230  {
231  sessionInfoPtr->iCryptInContext = createInfo.cryptHandle;
232  setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );
234  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
236  }
237  if( cryptStatusError( status ) )
238  {
239  destroySecurityContextsSSL( sessionInfoPtr );
240  return( status );
241  }
242  sessionInfoPtr->iCryptOutContext = createInfo.cryptHandle;
243 
244  /* If we're using GCM we also need to change the encryption mode from
245  the default CBC */
246  if( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM )
247  {
248  static const int mode = CRYPT_MODE_GCM; /* int vs.enum */
249 
250  status = krnlSendMessage( sessionInfoPtr->iCryptInContext,
252  ( MESSAGE_CAST ) &mode,
254  if( cryptStatusOK( status ) )
255  {
256  status = krnlSendMessage( sessionInfoPtr->iCryptOutContext,
258  ( MESSAGE_CAST ) &mode,
260  }
261  if( cryptStatusError( status ) )
262  {
263  destroySecurityContextsSSL( sessionInfoPtr );
264  return( status );
265  }
266  }
267 
268  return( CRYPT_OK );
269  }
270 
271 STDC_NONNULL_ARG( ( 1 ) ) \
272 void destroySecurityContextsSSL( INOUT SESSION_INFO *sessionInfoPtr )
273  {
274  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
275 
276  /* Destroy any active contexts */
277  if( sessionInfoPtr->iKeyexCryptContext != CRYPT_ERROR )
278  {
279  krnlSendNotifier( sessionInfoPtr->iKeyexCryptContext,
281  sessionInfoPtr->iKeyexCryptContext = CRYPT_ERROR;
282  }
283  if( sessionInfoPtr->iAuthInContext != CRYPT_ERROR )
284  {
285  krnlSendNotifier( sessionInfoPtr->iAuthInContext,
287  sessionInfoPtr->iAuthInContext = CRYPT_ERROR;
288  }
289  if( sessionInfoPtr->iAuthOutContext != CRYPT_ERROR )
290  {
291  krnlSendNotifier( sessionInfoPtr->iAuthOutContext,
293  sessionInfoPtr->iAuthOutContext = CRYPT_ERROR;
294  }
295  if( sessionInfoPtr->iCryptInContext != CRYPT_ERROR )
296  {
297  krnlSendNotifier( sessionInfoPtr->iCryptInContext,
299  sessionInfoPtr->iCryptInContext = CRYPT_ERROR;
300  }
301  if( sessionInfoPtr->iCryptOutContext != CRYPT_ERROR )
302  {
303  krnlSendNotifier( sessionInfoPtr->iCryptOutContext,
305  sessionInfoPtr->iCryptOutContext = CRYPT_ERROR;
306  }
307  }
308 
309 /* Clone a hash context so that we can continue using the original to hash
310  further messages */
311 
313 int cloneHashContext( IN_HANDLE const CRYPT_CONTEXT hashContext,
315  {
316  MESSAGE_CREATEOBJECT_INFO createInfo;
317  int hashAlgo, status; /* int vs.enum */
318 
319  assert( isWritePtr( clonedHashContext, sizeof( CRYPT_CONTEXT * ) ) );
320 
321  REQUIRES( isHandleRangeValid( hashContext ) );
322 
323  /* Clear return value */
324  *clonedHashContext = CRYPT_ERROR;
325 
326  /* Determine the type of context that we have to clone */
327  status = krnlSendMessage( hashContext, IMESSAGE_GETATTRIBUTE,
328  &hashAlgo, CRYPT_CTXINFO_ALGO );
329  if( cryptStatusError( status ) )
330  return( status );
331 
332  /* Create a new hash context and clone the existing one's state into
333  it */
334  setMessageCreateObjectInfo( &createInfo, hashAlgo );
336  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
338  if( cryptStatusError( status ) )
339  return( status );
340  status = krnlSendMessage( hashContext, IMESSAGE_CLONE, NULL,
341  createInfo.cryptHandle );
342  if( cryptStatusError( status ) )
343  {
345  return( status );
346  }
347  *clonedHashContext = createInfo.cryptHandle;
348 
349  return( CRYPT_OK );
350  }
351 
352 /****************************************************************************
353 * *
354 * Keyex Functions *
355 * *
356 ****************************************************************************/
357 
358 /* Load a DH key into a context, with the fixed value below being used for
359  the SSL server. The prime is the value 2^1024 - 2^960 - 1 +
360  2^64 * { [2^894 pi] + 129093 }, from the Oakley spec (RFC 2412) */
361 
362 static const BYTE FAR_BSS dh1024SSL[] = {
363  0x00, 0x80, /* p */
364  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
365  0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
366  0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
367  0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
368  0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
369  0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
370  0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
371  0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
372  0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
373  0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
374  0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
375  0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
376  0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
377  0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
378  0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
379  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
380  0x00, 0x01, /* g */
381  0x02
382  };
383 
384 static const BYTE FAR_BSS dh2048SSL[] = {
385  0x01, 0x01, /* p */
386  0x00,
387  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
388  0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
389  0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
390  0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
391  0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
392  0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
393  0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
394  0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
395  0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
396  0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
397  0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
398  0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
399  0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
400  0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
401  0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
402  0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
403  0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
404  0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
405  0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
406  0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
407  0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
408  0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
409  0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
410  0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
411  0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
412  0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
413  0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
414  0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
415  0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
416  0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
417  0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
418  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
419  0x00, 0x01, /* g */
420  0x02
421  };
422 
423 typedef struct {
424  const CRYPT_ECCCURVE_TYPE curveType;
425  const BYTE FAR_BSS *curveData;
426  } ECCCURVE_SSL_INFO;
427 
428 static const BYTE FAR_BSS ecdh192SSL[] = {
429  0x03, /* NamedCurve */
430  0x00, 0x13 /* P192 */
431  };
432 static const BYTE FAR_BSS ecdh224SSL[] = {
433  0x03, /* NamedCurve */
434  0x00, 0x15 /* P224 */
435  };
436 static const BYTE FAR_BSS ecdh256SSL[] = {
437  0x03, /* NamedCurve */
438  0x00, 0x17 /* P256 */
439  };
440 static const BYTE FAR_BSS ecdh384SSL[] = {
441  0x03, /* NamedCurve */
442  0x00, 0x18 /* P384 */
443  };
444 static const BYTE FAR_BSS ecdh521SSL[] = {
445  0x03, /* NamedCurve */
446  0x00, 0x19 /* P521 */
447  };
448 static const ECCCURVE_SSL_INFO eccCurveMapTbl[] = {
449  { CRYPT_ECCCURVE_P192, ecdh192SSL },
450  { CRYPT_ECCCURVE_P224, ecdh224SSL },
451  { CRYPT_ECCCURVE_P256, ecdh256SSL },
452  { CRYPT_ECCCURVE_P384, ecdh384SSL },
453  { CRYPT_ECCCURVE_P521, ecdh521SSL },
454  { CRYPT_ECCCURVE_NONE, NULL },
455  { CRYPT_ECCCURVE_NONE, NULL }
456  };
457 
459 int initDHcontextSSL( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
460  IN_BUFFER_OPT( keyDataLength ) const void *keyData,
463  IN_ENUM_OPT( CRYPT_ECCCURVE ) \
464  const CRYPT_ECCCURVE_TYPE eccParams )
465  {
466  MESSAGE_CREATEOBJECT_INFO createInfo;
468  int keySize = bitsToBytes( 1024 ), status;
469 
470  assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
471  assert( ( keyData == NULL && keyDataLength == 0 ) || \
472  isReadPtr( keyData, keyDataLength ) );
473 
474  REQUIRES( ( keyData == NULL && keyDataLength == 0 ) || \
475  ( keyData != NULL && \
476  keyDataLength > 0 && keyDataLength < MAX_INTLENGTH_SHORT ) );
477  REQUIRES( iServerKeyTemplate == CRYPT_UNUSED || \
478  isHandleRangeValid( iServerKeyTemplate ) );
479  REQUIRES( eccParams >= CRYPT_ECCCURVE_NONE && \
480  eccParams < CRYPT_ECCCURVE_LAST );
481 
482  /* Clear return value */
483  *iCryptContext = CRYPT_ERROR;
484 
485  /* If we're loading a built-in DH key, match the key size to the server
486  authentication key size. If there's no server key present, we
487  default to the 1024-bit key because we don't know how much processing
488  power the client has, and if we're using anon-DH anyway (implied by
489  the lack of server authentication key) then 1024 vs. 2048 bits isn't
490  a big loss */
491  if( keyData == NULL && iServerKeyTemplate != CRYPT_UNUSED && \
492  eccParams == CRYPT_ECCCURVE_NONE )
493  {
494  status = krnlSendMessage( iServerKeyTemplate, IMESSAGE_GETATTRIBUTE,
495  &keySize, CRYPT_CTXINFO_KEYSIZE );
496  if( cryptStatusError( status ) )
497  return( status );
498  }
499 
500  /* Create the DH/ECDH context */
501  setMessageCreateObjectInfo( &createInfo, \
502  ( eccParams != CRYPT_ECCCURVE_NONE ) ? \
505  &createInfo, OBJECT_TYPE_CONTEXT );
506  if( cryptStatusError( status ) )
507  return( status );
508  setMessageData( &msgData, "TLS key agreement key", 21 );
510  &msgData, CRYPT_CTXINFO_LABEL );
511  if( cryptStatusError( status ) )
512  {
514  return( status );
515  }
516 
517  /* Load the key into the context. If we're being given externally-
518  supplied DH/ECDH key components, load them, otherwise use the built-
519  in key */
520  if( keyData != NULL )
521  {
522  /* If we're the client we'll have been sent DH/ECDH key components
523  by the server */
524  setMessageData( &msgData, ( MESSAGE_CAST ) keyData, keyDataLength );
525  }
526  else
527  {
528  /* If we've been given ECC parameter information then we're using
529  ECDH */
530  if( eccParams != CRYPT_ECCCURVE_NONE )
531  {
532  const ECCCURVE_SSL_INFO *eccCurveInfoPtr = NULL;
533  int i;
534 
535  for( i = 0;
536  eccCurveMapTbl[ i ].curveType != CRYPT_ECCCURVE_NONE && \
537  i < FAILSAFE_ARRAYSIZE( eccCurveMapTbl, ECCCURVE_SSL_INFO );
538  i++ )
539  {
540  if( eccCurveMapTbl[ i ].curveType == eccParams )
541  {
542  eccCurveInfoPtr = &eccCurveMapTbl[ i ];
543  break;
544  }
545  }
546  ENSURES( i < FAILSAFE_ARRAYSIZE( eccCurveMapTbl, \
547  ECCCURVE_SSL_INFO ) );
548  ENSURES( eccCurveInfoPtr != NULL );
549  setMessageData( &msgData,
550  ( MESSAGE_CAST ) eccCurveInfoPtr->curveData, 3 );
551  }
552  else
553  {
554  /* We're using straight DH, use a key that corresponds
555  approximately in size to the server authentication key. We
556  allow for a bit of slop to avoid having a 1025-bit server
557  authentication key lead to the use of a 2048-bit DH key */
558  if( keySize > bitsToBytes( 1024 ) + 16 )
559  { setMessageData( &msgData, ( MESSAGE_CAST ) dh2048SSL,
560  sizeof( dh2048SSL ) ); }
561  else
562  { setMessageData( &msgData, ( MESSAGE_CAST ) dh1024SSL,
563  sizeof( dh1024SSL ) ); }
564  }
565  }
566  status = krnlSendMessage( createInfo.cryptHandle,
567  IMESSAGE_SETATTRIBUTE_S, &msgData,
568  CRYPT_IATTRIBUTE_KEY_SSL );
569  if( cryptStatusError( status ) )
570  {
572  if( keyData == NULL )
573  {
574  /* If we got an error loading a known-good, fixed-format key
575  then we report the problem as an internal error rather than
576  (say) a bad-data error */
577  retIntError();
578  }
579  return( status );
580  }
581  *iCryptContext = createInfo.cryptHandle;
582  return( CRYPT_OK );
583  }
584 
585 /* Create the master secret from a shared secret value, typically a
586  password */
587 
588 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
589 int createSharedPremasterSecret( OUT_BUFFER( premasterSecretMaxLength, \
591  void *premasterSecret,
593  const int premasterSecretMaxLength,
596  const void *sharedSecret,
598  const BOOLEAN isEncodedValue )
599  {
600  STREAM stream;
601  BYTE zeroes[ CRYPT_MAX_TEXTSIZE + 8 ];
602  int status;
603 
604  assert( isWritePtr( premasterSecret, premasterSecretMaxLength ) );
605  assert( isWritePtr( premasterSecretLength, sizeof( int ) ) );
606  assert( isReadPtr( sharedSecret, sharedSecretLength ) );
607 
608  REQUIRES( premasterSecretMaxLength > 0 && \
609  premasterSecretMaxLength < MAX_INTLENGTH_SHORT );
610  REQUIRES( sharedSecretLength > 0 && \
611  sharedSecretLength < MAX_INTLENGTH_SHORT );
612 
613  /* Clear return value */
614  *premasterSecretLength = 0;
615 
616  /* Write the PSK-derived premaster secret value:
617 
618  uint16 otherSecretLen
619  byte[] otherSecret
620  uint16 pskLen
621  byte[] psk
622 
623  Because the TLS PRF splits the input into two halves of which one half
624  is processed by HMAC-MD5 and the other by HMAC-SHA1, it's necessary
625  to extend the PSK in some way to provide input to both halves of the
626  PRF. In a rather dubious decision, the spec requires that the MD5
627  half be set to all zeroes, with only the SHA1 half being used. This
628  is done by writing otherSecret as a number of zero bytes equal in
629  length to the password (when used with RSA or DH/ECDH otherSecret
630  contains the RSA/DH/ECDH value, for pure PSK it contains zeroes) */
631  memset( zeroes, 0, CRYPT_MAX_TEXTSIZE );
632  sMemOpen( &stream, premasterSecret, premasterSecretMaxLength );
633  if( isEncodedValue )
634  {
635  BYTE decodedValue[ 64 + 8 ];
636  int decodedValueLength;
637 
638  /* It's a cryptlib-style encoded password, decode it into its binary
639  value */
640  status = decodePKIUserValue( decodedValue, 64, &decodedValueLength,
641  sharedSecret, sharedSecretLength );
642  if( cryptStatusError( status ) )
643  {
644  DEBUG_DIAG(( "Couldn't decode supposedly valid PKI user "
645  "value" ));
646  assert( DEBUG_WARN );
647  return( status );
648  }
649  writeUint16( &stream, decodedValueLength );
650  swrite( &stream, zeroes, decodedValueLength );
651  writeUint16( &stream, decodedValueLength );
652  status = swrite( &stream, decodedValue, decodedValueLength );
653  zeroise( decodedValue, decodedValueLength );
654  }
655  else
656  {
657  writeUint16( &stream, sharedSecretLength );
658  swrite( &stream, zeroes, sharedSecretLength );
659  writeUint16( &stream, sharedSecretLength );
660  status = swrite( &stream, sharedSecret, sharedSecretLength );
661  }
662  if( cryptStatusError( status ) )
663  return( status );
664  *premasterSecretLength = stell( &stream );
665  sMemDisconnect( &stream );
666 
667  return( CRYPT_OK );
668  }
669 
670 /* Wrap/unwrap the pre-master secret */
671 
672 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
673 int wrapPremasterSecret( INOUT SESSION_INFO *sessionInfoPtr,
674  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
676  IN_LENGTH_SHORT const int dataMaxLength,
678  {
681  int status;
682 
683  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
684  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
685  assert( isWritePtr( data, dataMaxLength ) );
686  assert( isWritePtr( dataLength, sizeof( int ) ) );
687 
688  REQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_INTLENGTH_SHORT );
689 
690  /* Clear return values */
691  memset( data, 0, min( 16, dataMaxLength ) );
692  *dataLength = 0;
693 
694  /* Create the premaster secret and wrap it using the server's public
695  key. Note that the version that we advertise at this point is the
696  version originally offered by the client in its hello message, not
697  the version eventually negotiated for the connection. This is
698  designed to prevent rollback attacks (but see also the comment in
699  unwrapPremasterSecret() below) */
700  handshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;
701  handshakeInfo->premasterSecret[ 0 ] = SSL_MAJOR_VERSION;
702  handshakeInfo->premasterSecret[ 1 ] = \
703  intToByte( handshakeInfo->clientOfferedVersion );
704  setMessageData( &msgData,
705  handshakeInfo->premasterSecret + VERSIONINFO_SIZE,
706  handshakeInfo->premasterSecretSize - VERSIONINFO_SIZE );
708  IMESSAGE_GETATTRIBUTE_S, &msgData,
709  CRYPT_IATTRIBUTE_RANDOM );
710  if( cryptStatusError( status ) )
711  return( status );
712  setMechanismWrapInfo( &mechanismInfo, data, dataMaxLength,
713  handshakeInfo->premasterSecret,
714  handshakeInfo->premasterSecretSize, CRYPT_UNUSED,
715  sessionInfoPtr->iKeyexCryptContext );
717  &mechanismInfo, MECHANISM_ENC_PKCS1_RAW );
718  if( cryptStatusOK( status ) )
719  *dataLength = mechanismInfo.wrappedDataLength;
720  clearMechanismInfo( &mechanismInfo );
721 
722  return( status );
723  }
724 
725 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
726 int unwrapPremasterSecret( INOUT SESSION_INFO *sessionInfoPtr,
727  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
728  IN_BUFFER( dataLength ) const void *data,
729  IN_LENGTH_SHORT const int dataLength )
730  {
732  int status;
733 
734  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
735  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
736  assert( isReadPtr( data, dataLength ) );
737 
738  REQUIRES( dataLength > 0 && dataLength < MAX_INTLENGTH_SHORT );
739 
740  /* Decrypt the encrypted premaster secret. In theory we could
741  explicitly defend against Bleichenbacher-type attacks at this point
742  by setting the premaster secret to a pseudorandom value if we get a
743  bad data or (later) an incorrect version error and continuing as
744  normal, however the attack depends on the server returning
745  information required to pinpoint the cause of the failure and
746  cryptlib just returns a generic "failed" response for any handshake
747  failure, so this explicit defence isn't really necessary, and not
748  doing this avoids a trivial DoS attack in which a client sends us
749  junk and forces us to continue with the handshake even tbough we've
750  detected that it's junk.
751 
752  There's a second, lower-grade level of oracle that an attacker can
753  use in the version check if they can distinguish between a decrypt
754  failure due to bad PKCS #1 padding and a failure due to a bad version
755  number (see "Attacking RSA-based Sessions in SSL/TLS", Vlastimil
756  Klima, Ondrej Pokorny, and Tomas Rosa, CHES'03). If we use the
757  Bleichenbacher defence and continue the handshake on bad padding but
758  bail out on a bad version then the two cases can be distinguished,
759  however since cryptlib bails out immediately in either case the two
760  shouldn't be distinguishable */
761  handshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;
762  setMechanismWrapInfo( &mechanismInfo, ( MESSAGE_CAST ) data, dataLength,
763  handshakeInfo->premasterSecret,
764  handshakeInfo->premasterSecretSize, CRYPT_UNUSED,
765  sessionInfoPtr->privateKey );
767  &mechanismInfo, MECHANISM_ENC_PKCS1_RAW );
768  if( cryptStatusOK( status ) && \
769  mechanismInfo.keyDataLength != handshakeInfo->premasterSecretSize )
770  status = CRYPT_ERROR_BADDATA;
771  clearMechanismInfo( &mechanismInfo );
772  if( cryptStatusError( status ) )
773  return( status );
774 
775  /* Make sure that it looks OK. Note that the version that we check for
776  at this point is the version originally offered by the client in its
777  hello message, not the version eventually negotiated for the
778  connection. This is designed to prevent rollback attacks */
779  if( handshakeInfo->premasterSecret[ 0 ] != SSL_MAJOR_VERSION || \
780  handshakeInfo->premasterSecret[ 1 ] != handshakeInfo->clientOfferedVersion )
781  {
782  /* Microsoft braindamage, older versions of MSIE send the wrong
783  version number for the premaster secret (making it look like a
784  rollback attack) so if we're expecting 3.1 from the client and
785  get 3.0 in the premaster secret then it's MSIE screwing up. Note
786  that this bug-check is only applied for SSL and TLS 1.0, for TLS
787  1.1 and later the check of the version is mandatory */
788  if( handshakeInfo->originalVersion <= SSL_MINOR_VERSION_TLS && \
789  handshakeInfo->clientOfferedVersion == SSL_MINOR_VERSION_TLS && \
790  handshakeInfo->premasterSecret[ 0 ] == SSL_MAJOR_VERSION && \
791  handshakeInfo->premasterSecret[ 1 ] == SSL_MINOR_VERSION_SSL )
792  {
793  setErrorString( ( ERROR_INFO * ) &sessionInfoPtr->errorInfo,
794  "Warning: Accepting invalid premaster secret "
795  "version 3.0 (MSIE bug)", 66 );
796  }
797  else
798  {
801  "Invalid premaster secret version data 0x%02X 0x%02X, "
802  "expected 0x03 0x%02X",
803  handshakeInfo->premasterSecret[ 0 ],
804  handshakeInfo->premasterSecret[ 1 ],
805  handshakeInfo->clientOfferedVersion ) );
806  }
807  }
808 
809  return( CRYPT_OK );
810  }
811 
812 /****************************************************************************
813 * *
814 * Premaster -> Master -> Key Material Functions *
815 * *
816 ****************************************************************************/
817 
818 /* Convert a pre-master secret to a master secret, and a master secret to
819  keying material */
820 
821 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
822 static int premasterToMaster( const SESSION_INFO *sessionInfoPtr,
823  const SSL_HANDSHAKE_INFO *handshakeInfo,
824  OUT_BUFFER_FIXED( masterSecretLength ) \
825  void *masterSecret,
826  IN_LENGTH_SHORT const int masterSecretLength )
827  {
829  BYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];
830 
831  assert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
832  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
833  assert( isReadPtr( masterSecret, masterSecretLength ) );
834 
835  REQUIRES( masterSecretLength > 0 && \
836  masterSecretLength < MAX_INTLENGTH_SHORT );
837 
838  DEBUG_PRINT(( "Premaster secret:\n" ));
839  DEBUG_DUMP_DATA( handshakeInfo->premasterSecret,
840  handshakeInfo->premasterSecretSize );
841  if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
842  {
843  memcpy( nonceBuffer, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
844  memcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
845  SSL_NONCE_SIZE );
846  setMechanismDeriveInfo( &mechanismInfo, masterSecret,
847  masterSecretLength,
848  handshakeInfo->premasterSecret,
849  handshakeInfo->premasterSecretSize,
850  CRYPT_USE_DEFAULT, nonceBuffer,
853  &mechanismInfo, MECHANISM_DERIVE_SSL ) );
854  }
855 
856  memcpy( nonceBuffer, "master secret", 13 );
857  memcpy( nonceBuffer + 13, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
858  memcpy( nonceBuffer + 13 + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
859  SSL_NONCE_SIZE );
860  if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
861  {
862  setMechanismDeriveInfo( &mechanismInfo, masterSecret,
863  masterSecretLength,
864  handshakeInfo->premasterSecret,
865  handshakeInfo->premasterSecretSize,
866  CRYPT_ALGO_SHA2, nonceBuffer,
867  13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
868  if( handshakeInfo->integrityAlgoParam != 0 )
869  mechanismInfo.hashParam = handshakeInfo->integrityAlgoParam;
871  &mechanismInfo, MECHANISM_DERIVE_TLS12 ) );
872  }
873  setMechanismDeriveInfo( &mechanismInfo, masterSecret, masterSecretLength,
874  handshakeInfo->premasterSecret,
875  handshakeInfo->premasterSecretSize,
876  CRYPT_USE_DEFAULT, nonceBuffer,
877  13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
879  &mechanismInfo, MECHANISM_DERIVE_TLS ) );
880  }
881 
882 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
883 static int masterToKeys( const SESSION_INFO *sessionInfoPtr,
884  const SSL_HANDSHAKE_INFO *handshakeInfo,
885  IN_BUFFER( masterSecretLength ) \
886  const void *masterSecret,
887  IN_LENGTH_SHORT const int masterSecretLength,
888  OUT_BUFFER_FIXED( keyBlockLength ) void *keyBlock,
889  IN_LENGTH_SHORT const int keyBlockLength )
890  {
892  BYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];
893 
894  assert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
895  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
896  assert( isReadPtr( masterSecret, masterSecretLength ) );
897  assert( isWritePtr( keyBlock, keyBlockLength ) );
898 
899  REQUIRES( masterSecretLength > 0 && \
900  masterSecretLength < MAX_INTLENGTH_SHORT );
901  REQUIRES( keyBlockLength > 0 && \
902  keyBlockLength < MAX_INTLENGTH_SHORT );
903 
904  DEBUG_PRINT(( "Master secret:\n" ));
905  DEBUG_DUMP_DATA( masterSecret, masterSecretLength );
906  if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
907  {
908  memcpy( nonceBuffer, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
909  memcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->clientNonce,
910  SSL_NONCE_SIZE );
911  setMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,
912  masterSecret, masterSecretLength,
913  CRYPT_USE_DEFAULT, nonceBuffer,
916  &mechanismInfo, MECHANISM_DERIVE_SSL ) );
917  }
918 
919  memcpy( nonceBuffer, "key expansion", 13 );
920  memcpy( nonceBuffer + 13, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
921  memcpy( nonceBuffer + 13 + SSL_NONCE_SIZE, handshakeInfo->clientNonce,
922  SSL_NONCE_SIZE );
923  if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
924  {
925  setMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,
926  masterSecret, masterSecretLength,
927  CRYPT_ALGO_SHA2, nonceBuffer,
928  13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
929  if( handshakeInfo->integrityAlgoParam != 0 )
930  mechanismInfo.hashParam = handshakeInfo->integrityAlgoParam;
932  &mechanismInfo, MECHANISM_DERIVE_TLS12 ) );
933  }
934  setMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,
935  masterSecret, masterSecretLength,
936  CRYPT_USE_DEFAULT, nonceBuffer,
937  13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
939  &mechanismInfo, MECHANISM_DERIVE_TLS ) );
940  }
941 
942 /****************************************************************************
943 * *
944 * Key-load Functions *
945 * *
946 ****************************************************************************/
947 
948 /* Update the session cache with information on the current session */
949 
950 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
951 static int updateSessionCache( INOUT SESSION_INFO *sessionInfoPtr,
952  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
953  IN_BUFFER( masterSecretSize ) void *masterSecret,
954  IN_LENGTH_SHORT const int masterSecretSize,
955  const BOOLEAN isClient )
956  {
957  SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
958  int cachedID, status;
959 
960  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
961  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
962  assert( isWritePtr( masterSecret, masterSecretSize ) );
963 
964  REQUIRES( masterSecretSize > 0 && \
965  masterSecretSize < MAX_INTLENGTH_SHORT );
966 
967  /* If we're the client then we have to add additional information to the
968  cache, in this case the server's name/address so that we can look up
969  the information if we try to reconnect later */
970  if( isClient )
971  {
973 
974  attributeListPtr = findSessionInfo( sessionInfoPtr->attributeList,
976  ENSURES( attributeListPtr != NULL );
977  status = cachedID = \
978  addScoreboardEntryEx( sslInfo->scoreboardInfoPtr,
979  handshakeInfo->sessionID,
980  handshakeInfo->sessionIDlength,
981  attributeListPtr->value,
982  attributeListPtr->valueLength,
983  masterSecret, masterSecretSize );
984  if( !cryptStatusError( status ) )
985  sslInfo->sessionCacheID = cachedID;
986  return( status );
987  }
988 
989  /* We're the server, add the client's state information indexed by the
990  sessionID */
991  status = cachedID = \
992  addScoreboardEntry( sslInfo->scoreboardInfoPtr,
993  handshakeInfo->sessionID,
994  handshakeInfo->sessionIDlength,
995  masterSecret, masterSecretSize );
996  if( !cryptStatusError( status ) )
997  sslInfo->sessionCacheID = cachedID;
998  return( status );
999  }
1000 
1001 /* Load the SSL/TLS cryptovariables */
1002 
1003 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
1004 static int loadKeys( INOUT SESSION_INFO *sessionInfoPtr,
1005  const SSL_HANDSHAKE_INFO *handshakeInfo,
1006  IN_BUFFER( keyBlockLength ) const void *keyBlock,
1007  IN_LENGTH_SHORT_MIN( 16 ) const int keyBlockLength,
1008  const BOOLEAN isClient )
1009  {
1010  SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
1012  BYTE *keyBlockPtr = ( BYTE * ) keyBlock;
1013  int status;
1014 
1015  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1016  assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1017  assert( isReadPtr( keyBlock, keyBlockLength ) );
1018 
1019  REQUIRES( keyBlockLength >= ( sessionInfoPtr->authBlocksize * 2 ) + \
1020  ( handshakeInfo->cryptKeysize * 2 ) + \
1021  ( sessionInfoPtr->cryptBlocksize * 2 ) && \
1022  keyBlockLength < MAX_INTLENGTH_SHORT );
1023 
1024  /* Load the keys and secrets:
1025 
1026  ( client_write_mac || server_write_mac || \
1027  client_write_key || server_write_key || \
1028  client_write_iv || server_write_iv )
1029 
1030  First we load the MAC keys. For TLS these are proper MAC keys, for
1031  SSL we have to build the proto-HMAC ourselves from a straight hash
1032  context so we store the raw cryptovariables rather than loading them
1033  into a context, and if we're using GCM we skip them since the
1034  encryption key also functions as the authentication key */
1035  if( !( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM ) )
1036  {
1037  if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
1038  {
1039  ENSURES( rangeCheckZ( 0, sessionInfoPtr->authBlocksize,
1040  CRYPT_MAX_HASHSIZE ) );
1041  memcpy( isClient ? sslInfo->macWriteSecret : sslInfo->macReadSecret,
1042  keyBlockPtr, sessionInfoPtr->authBlocksize );
1043  memcpy( isClient ? sslInfo->macReadSecret : sslInfo->macWriteSecret,
1044  keyBlockPtr + sessionInfoPtr->authBlocksize,
1045  sessionInfoPtr->authBlocksize );
1046  }
1047  else
1048  {
1049  setMessageData( &msgData, keyBlockPtr,
1050  sessionInfoPtr->authBlocksize );
1051  status = krnlSendMessage( isClient ? \
1052  sessionInfoPtr->iAuthOutContext : \
1053  sessionInfoPtr->iAuthInContext,
1054  IMESSAGE_SETATTRIBUTE_S, &msgData,
1056  if( cryptStatusError( status ) )
1057  return( status );
1058  setMessageData( &msgData,
1059  keyBlockPtr + sessionInfoPtr->authBlocksize,
1060  sessionInfoPtr->authBlocksize );
1061  status = krnlSendMessage( isClient ? \
1062  sessionInfoPtr->iAuthInContext: \
1063  sessionInfoPtr->iAuthOutContext,
1064  IMESSAGE_SETATTRIBUTE_S, &msgData,
1066  if( cryptStatusError( status ) )
1067  return( status );
1068  }
1069  keyBlockPtr += sessionInfoPtr->authBlocksize * 2;
1070  }
1071 
1072  /* Then we load the encryption keys */
1073  setMessageData( &msgData, keyBlockPtr, handshakeInfo->cryptKeysize );
1074  status = krnlSendMessage( isClient ? \
1075  sessionInfoPtr->iCryptOutContext : \
1076  sessionInfoPtr->iCryptInContext,
1077  IMESSAGE_SETATTRIBUTE_S, &msgData,
1079  keyBlockPtr += handshakeInfo->cryptKeysize;
1080  if( cryptStatusError( status ) )
1081  return( status );
1082  setMessageData( &msgData, keyBlockPtr, handshakeInfo->cryptKeysize );
1083  status = krnlSendMessage( isClient ? \
1084  sessionInfoPtr->iCryptInContext : \
1085  sessionInfoPtr->iCryptOutContext,
1086  IMESSAGE_SETATTRIBUTE_S, &msgData,
1088  keyBlockPtr += handshakeInfo->cryptKeysize;
1089  if( cryptStatusError( status ) )
1090  return( status );
1091 
1092  /* If we're using a stream cipher, there are no IVs */
1093  if( isStreamCipher( sessionInfoPtr->cryptAlgo ) )
1094  return( CRYPT_OK ); /* No IV, we're done */
1095 
1096  /* If we're using GCM then the IV is composed of two parts, an explicit
1097  portion that's sent with every packet and an implicit portion that's
1098  derived from the master secret */
1099  if( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM )
1100  {
1101  memcpy( isClient ? sessionInfoPtr->sessionSSL->gcmWriteSalt : \
1102  sessionInfoPtr->sessionSSL->gcmReadSalt,
1103  keyBlockPtr, GCM_SALT_SIZE );
1104  memcpy( isClient ? sessionInfoPtr->sessionSSL->gcmReadSalt : \
1105  sessionInfoPtr->sessionSSL->gcmWriteSalt,
1106  keyBlockPtr + GCM_SALT_SIZE, GCM_SALT_SIZE );
1107  sessionInfoPtr->sessionSSL->gcmSaltSize = GCM_SALT_SIZE;
1108 
1109  return( CRYPT_OK );
1110  }
1111 
1112  /* It's a standard block cipher, load the IVs. This load is actually
1113  redundant for TLS 1.1+ since it uses explicit IVs, but it's easier to
1114  just do it anyway */
1115  setMessageData( &msgData, keyBlockPtr,
1116  sessionInfoPtr->cryptBlocksize );
1117  krnlSendMessage( isClient ? sessionInfoPtr->iCryptOutContext : \
1118  sessionInfoPtr->iCryptInContext,
1119  IMESSAGE_SETATTRIBUTE_S, &msgData,
1120  CRYPT_CTXINFO_IV );
1121  keyBlockPtr += sessionInfoPtr->cryptBlocksize;
1122  setMessageData( &msgData, keyBlockPtr,
1123  sessionInfoPtr->cryptBlocksize );
1124  return( krnlSendMessage( isClient ? sessionInfoPtr->iCryptInContext : \
1125  sessionInfoPtr->iCryptOutContext,
1126  IMESSAGE_SETATTRIBUTE_S, &msgData,
1127  CRYPT_CTXINFO_IV ) );
1128  }
1129 
1130 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
1131 int initCryptoSSL( INOUT SESSION_INFO *sessionInfoPtr,
1132  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
1133  OUT_BUFFER_FIXED( masterSecretSize ) void *masterSecret,
1134  IN_LENGTH_SHORT const int masterSecretSize,
1135  const BOOLEAN isClient,
1136  const BOOLEAN isResumedSession )
1137  {
1138  BYTE keyBlock[ MAX_KEYBLOCK_SIZE + 8 ];
1139  int status;
1140 
1141  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1142  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1143  assert( isWritePtr( masterSecret, masterSecretSize ) );
1144 
1145  REQUIRES( masterSecretSize > 0 && \
1146  masterSecretSize < MAX_INTLENGTH_SHORT );
1147 
1148  /* Create the security contexts required for the session */
1149  status = initSecurityContextsSSL( sessionInfoPtr, handshakeInfo );
1150  if( cryptStatusError( status ) )
1151  return( status );
1152 
1153  /* If it's a fresh (i.e. non-cached) session, convert the premaster
1154  secret into the master secret */
1155  if( !isResumedSession )
1156  {
1157  status = premasterToMaster( sessionInfoPtr, handshakeInfo,
1158  masterSecret, masterSecretSize );
1159  if( cryptStatusError( status ) )
1160  return( status );
1161 
1162  /* Everything is OK so far, add the master secret to the session
1163  cache */
1164  if( handshakeInfo->sessionIDlength > 0 )
1165  {
1166  status = updateSessionCache( sessionInfoPtr, handshakeInfo,
1167  masterSecret, masterSecretSize,
1168  isClient );
1169  if( cryptStatusError( status ) )
1170  {
1171  zeroise( masterSecret, masterSecretSize );
1172  return( status );
1173  }
1174  }
1175  }
1176  else
1177  {
1178  /* We've already got the master secret present from the session that
1179  we're resuming from, reuse that */
1180  ENSURES( rangeCheckZ( 0, handshakeInfo->premasterSecretSize,
1181  masterSecretSize ) );
1182  memcpy( masterSecret, handshakeInfo->premasterSecret,
1183  handshakeInfo->premasterSecretSize );
1184  }
1185 
1186  /* Convert the master secret into keying material. Unfortunately we
1187  can't delete the master secret at this point because it's still
1188  needed to calculate the MAC for the handshake messages */
1189  status = masterToKeys( sessionInfoPtr, handshakeInfo, masterSecret,
1190  masterSecretSize, keyBlock, MAX_KEYBLOCK_SIZE );
1191  if( cryptStatusError( status ) )
1192  {
1193  zeroise( masterSecret, masterSecretSize );
1194  return( status );
1195  }
1196 
1197  /* Load the keys and secrets */
1198  status = loadKeys( sessionInfoPtr, handshakeInfo, keyBlock,
1199  MAX_KEYBLOCK_SIZE, isClient );
1200  zeroise( keyBlock, MAX_KEYBLOCK_SIZE );
1201  if( cryptStatusError( status ) )
1202  {
1203  zeroise( masterSecret, masterSecretSize );
1204  return( status );
1205  }
1206 
1207  return( CRYPT_OK );
1208  }
1209 
1210 /* TLS versions greater than 1.0 prepend an explicit IV to the data, the
1211  following function loads this from the packet data stream */
1212 
1213 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
1214 int loadExplicitIV( INOUT SESSION_INFO *sessionInfoPtr,
1215  INOUT STREAM *stream,
1216  OUT_INT_SHORT_Z int *ivLength )
1217  {
1218  SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
1220  BYTE iv[ CRYPT_MAX_IVSIZE + 8 ];
1221  int ivSize = sslInfo->ivSize, status;
1222 
1223  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1224  assert( isWritePtr( stream, sizeof( STREAM ) ) );
1225  assert( isWritePtr( ivLength, sizeof( int ) ) );
1226 
1227  /* Clear return value */
1228  *ivLength = 0;
1229 
1230  /* Read and load the IV */
1231  status = sread( stream, iv, sslInfo->ivSize );
1232  if( cryptStatusOK( status ) && \
1233  ( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM ) )
1234  {
1235  /* If we're using GCM then the IV has to be assembled from the
1236  implicit and explicit portions */
1237  ENSURES( rangeCheck( sslInfo->gcmSaltSize, sslInfo->ivSize,
1238  CRYPT_MAX_IVSIZE ) );
1239  memmove( iv + sslInfo->gcmSaltSize, iv, sslInfo->ivSize );
1240  memcpy( iv, sslInfo->gcmReadSalt, sslInfo->gcmSaltSize );
1241  ivSize += sslInfo->gcmSaltSize;
1242  }
1243  if( cryptStatusOK( status ) )
1244  {
1245  setMessageData( &msgData, iv, ivSize );
1246  status = krnlSendMessage( sessionInfoPtr->iCryptInContext,
1247  IMESSAGE_SETATTRIBUTE_S, &msgData,
1248  CRYPT_CTXINFO_IV );
1249  }
1250  if( cryptStatusError( status ) )
1251  {
1252  retExt( status,
1253  ( status, SESSION_ERRINFO,
1254  "Packet IV read/load failed" ) );
1255  }
1256 
1257  /* Tell the caller how much data we've consumed */
1258  *ivLength = sslInfo->ivSize;
1259 
1260  return( CRYPT_OK );
1261  }
1262 #endif /* USE_SSL */