1 /****************************************************************************
2 * *
3 * cryptlib SSL v3/TLS Key Management Routines *
4 * Copyright Peter Gutmann 1998-2012 *
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
31 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
initHandshakeCryptInfo(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo)32 int initHandshakeCryptInfo( INOUT SESSION_INFO *sessionInfoPtr,
33 INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
34 {
35 MESSAGE_CREATEOBJECT_INFO createInfo;
36 int status;
37
38 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
39 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
40
41 /* Clear the handshake information contexts */
42 handshakeInfo->md5context = \
43 handshakeInfo->sha1context = \
44 handshakeInfo->sha2context = CRYPT_ERROR;
45 #ifdef CONFIG_SUITEB
46 handshakeInfo->sha384context = CRYPT_ERROR;
47 #endif /* CONFIG_SUITEB */
48 handshakeInfo->dhContext = \
49 handshakeInfo->sessionHashContext = CRYPT_ERROR;
50
51 /* Create the MAC/dual-hash contexts for incoming and outgoing data.
52 SSL uses a pre-HMAC variant for which we can't use real HMAC but have
53 to construct it ourselves from MD5 and SHA-1, TLS uses a straight dual
54 hash and MACs that once a MAC key becomes available at the end of the
55 handshake */
56 setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_MD5 );
57 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
58 IMESSAGE_DEV_CREATEOBJECT, &createInfo,
59 OBJECT_TYPE_CONTEXT );
60 if( cryptStatusOK( status ) )
61 {
62 handshakeInfo->md5context = createInfo.cryptHandle;
63 setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA1 );
64 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
65 IMESSAGE_DEV_CREATEOBJECT, &createInfo,
66 OBJECT_TYPE_CONTEXT );
67 }
68 if( cryptStatusOK( status ) )
69 {
70 handshakeInfo->sha1context = createInfo.cryptHandle;
71 if( sessionInfoPtr->version < SSL_MINOR_VERSION_TLS12 )
72 return( CRYPT_OK );
73 }
74 #ifdef CONFIG_SUITEB
75 if( cryptStatusOK( status ) )
76 {
77 /* Create the additional SHA2-384 context that's needed for Suite
78 B use */
79 setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA2 );
80 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
81 IMESSAGE_DEV_CREATEOBJECT, &createInfo,
82 OBJECT_TYPE_CONTEXT );
83 if( cryptStatusOK( status ) )
84 {
85 static const int blockSize = bitsToBytes( 384 );
86
87 handshakeInfo->sha384context = createInfo.cryptHandle;
88 status = krnlSendMessage( handshakeInfo->sha384context,
89 IMESSAGE_SETATTRIBUTE,
90 ( MESSAGE_CAST ) &blockSize,
91 CRYPT_CTXINFO_BLOCKSIZE );
92 }
93 }
94 #endif /* CONFIG_SUITEB */
95 if( cryptStatusOK( status ) )
96 {
97 /* Create additional contexts that may be needed for TLS 1.2 */
98 setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_SHA2 );
99 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
100 IMESSAGE_DEV_CREATEOBJECT, &createInfo,
101 OBJECT_TYPE_CONTEXT );
102 }
103 if( cryptStatusOK( status ) )
104 {
105 handshakeInfo->sha2context = createInfo.cryptHandle;
106 return( CRYPT_OK );
107 }
108
109 /* One or more of the contexts couldn't be created, destroy all of the
110 contexts that have been created so far */
111 destroyHandshakeCryptInfo( handshakeInfo );
112 return( status );
113 }
114
115 STDC_NONNULL_ARG( ( 1 ) ) \
destroyHandshakeCryptInfo(INOUT SSL_HANDSHAKE_INFO * handshakeInfo)116 void destroyHandshakeCryptInfo( INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
117 {
118 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
119
120 /* Destroy any active contexts. We need to do this here (even though
121 it's also done in the general session code) to provide a clean exit in
122 case the session activation fails, so that a second activation attempt
123 doesn't overwrite still-active contexts */
124 if( handshakeInfo->md5context != CRYPT_ERROR )
125 {
126 krnlSendNotifier( handshakeInfo->md5context,
127 IMESSAGE_DECREFCOUNT );
128 handshakeInfo->md5context = CRYPT_ERROR;
129 }
130 if( handshakeInfo->sha1context != CRYPT_ERROR )
131 {
132 krnlSendNotifier( handshakeInfo->sha1context,
133 IMESSAGE_DECREFCOUNT );
134 handshakeInfo->sha1context = CRYPT_ERROR;
135 }
136 if( handshakeInfo->sha2context != CRYPT_ERROR )
137 {
138 krnlSendNotifier( handshakeInfo->sha2context,
139 IMESSAGE_DECREFCOUNT );
140 handshakeInfo->sha2context = CRYPT_ERROR;
141 }
142 #ifdef CONFIG_SUITEB
143 if( handshakeInfo->sha384context != CRYPT_ERROR )
144 {
145 krnlSendNotifier( handshakeInfo->sha384context,
146 IMESSAGE_DECREFCOUNT );
147 handshakeInfo->sha384context = CRYPT_ERROR;
148 }
149 #endif /* CONFIG_SUITEB */
150 if( handshakeInfo->dhContext != CRYPT_ERROR )
151 {
152 krnlSendNotifier( handshakeInfo->dhContext, IMESSAGE_DECREFCOUNT );
153 handshakeInfo->dhContext = CRYPT_ERROR;
154 }
155 if( handshakeInfo->sessionHashContext != CRYPT_ERROR )
156 {
157 krnlSendNotifier( handshakeInfo->sessionHashContext,
158 IMESSAGE_DECREFCOUNT );
159 handshakeInfo->sessionHashContext = CRYPT_ERROR;
160 }
161 }
162
163 /* Initialise and destroy the session security contexts */
164
165 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
initSecurityContextsSSL(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo)166 static int initSecurityContextsSSL( INOUT SESSION_INFO *sessionInfoPtr
167 #ifdef CONFIG_SUITEB
168 , INOUT SSL_HANDSHAKE_INFO *handshakeInfo
169 #endif /* CONFIG_SUITEB */
170 )
171 {
172 MESSAGE_CREATEOBJECT_INFO createInfo;
173 int status;
174
175 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
176 #ifdef CONFIG_SUITEB
177 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
178 #endif /* CONFIG_SUITEB */
179
180 /* Create the authentication contexts, unless we're using a combined
181 encryption+authentication mode */
182 if( !( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM ) )
183 {
184 const CRYPT_ALGO_TYPE integrityAlgo = sessionInfoPtr->integrityAlgo;
185
186 setMessageCreateObjectInfo( &createInfo, integrityAlgo );
187 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
188 IMESSAGE_DEV_CREATEOBJECT, &createInfo,
189 OBJECT_TYPE_CONTEXT );
190 if( cryptStatusOK( status ) )
191 {
192 sessionInfoPtr->iAuthInContext = createInfo.cryptHandle;
193 setMessageCreateObjectInfo( &createInfo, integrityAlgo );
194 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
195 IMESSAGE_DEV_CREATEOBJECT, &createInfo,
196 OBJECT_TYPE_CONTEXT );
197 }
198 if( cryptStatusError( status ) )
199 {
200 destroySecurityContextsSSL( sessionInfoPtr );
201 return( status );
202 }
203 sessionInfoPtr->iAuthOutContext = createInfo.cryptHandle;
204 #ifdef CONFIG_SUITEB
205 if( cryptStatusOK( status ) && \
206 handshakeInfo->integrityAlgoParam == bitsToBytes( 384 ) )
207 {
208 static const int blockSize = bitsToBytes( 384 );
209
210 status = krnlSendMessage( sessionInfoPtr->iAuthInContext,
211 IMESSAGE_SETATTRIBUTE,
212 ( MESSAGE_CAST ) &blockSize,
213 CRYPT_CTXINFO_BLOCKSIZE );
214 if( cryptStatusOK( status ) )
215 {
216 status = krnlSendMessage( sessionInfoPtr->iAuthOutContext,
217 IMESSAGE_SETATTRIBUTE,
218 ( MESSAGE_CAST ) &blockSize,
219 CRYPT_CTXINFO_BLOCKSIZE );
220 }
221 if( cryptStatusError( status ) )
222 {
223 destroySecurityContextsSSL( sessionInfoPtr );
224 return( status );
225 }
226 }
227 #endif /* CONFIG_SUITEB */
228 }
229
230 /* Create the encryption contexts */
231 setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );
232 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
233 IMESSAGE_DEV_CREATEOBJECT, &createInfo,
234 OBJECT_TYPE_CONTEXT );
235 if( cryptStatusOK( status ) )
236 {
237 sessionInfoPtr->iCryptInContext = createInfo.cryptHandle;
238 setMessageCreateObjectInfo( &createInfo, sessionInfoPtr->cryptAlgo );
239 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
240 IMESSAGE_DEV_CREATEOBJECT, &createInfo,
241 OBJECT_TYPE_CONTEXT );
242 }
243 if( cryptStatusError( status ) )
244 {
245 destroySecurityContextsSSL( sessionInfoPtr );
246 return( status );
247 }
248 sessionInfoPtr->iCryptOutContext = createInfo.cryptHandle;
249
250 /* If we're using GCM we also need to change the encryption mode from
251 the default CBC */
252 if( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM )
253 {
254 static const int mode = CRYPT_MODE_GCM; /* int vs.enum */
255
256 status = krnlSendMessage( sessionInfoPtr->iCryptInContext,
257 IMESSAGE_SETATTRIBUTE,
258 ( MESSAGE_CAST ) &mode,
259 CRYPT_CTXINFO_MODE );
260 if( cryptStatusOK( status ) )
261 {
262 status = krnlSendMessage( sessionInfoPtr->iCryptOutContext,
263 IMESSAGE_SETATTRIBUTE,
264 ( MESSAGE_CAST ) &mode,
265 CRYPT_CTXINFO_MODE );
266 }
267 if( cryptStatusError( status ) )
268 {
269 destroySecurityContextsSSL( sessionInfoPtr );
270 return( status );
271 }
272 }
273
274 return( CRYPT_OK );
275 }
276
277 STDC_NONNULL_ARG( ( 1 ) ) \
destroySecurityContextsSSL(INOUT SESSION_INFO * sessionInfoPtr)278 void destroySecurityContextsSSL( INOUT SESSION_INFO *sessionInfoPtr )
279 {
280 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
281
282 /* Destroy any active contexts */
283 if( sessionInfoPtr->iKeyexCryptContext != CRYPT_ERROR )
284 {
285 krnlSendNotifier( sessionInfoPtr->iKeyexCryptContext,
286 IMESSAGE_DECREFCOUNT );
287 sessionInfoPtr->iKeyexCryptContext = CRYPT_ERROR;
288 }
289 if( sessionInfoPtr->iAuthInContext != CRYPT_ERROR )
290 {
291 krnlSendNotifier( sessionInfoPtr->iAuthInContext,
292 IMESSAGE_DECREFCOUNT );
293 sessionInfoPtr->iAuthInContext = CRYPT_ERROR;
294 }
295 if( sessionInfoPtr->iAuthOutContext != CRYPT_ERROR )
296 {
297 krnlSendNotifier( sessionInfoPtr->iAuthOutContext,
298 IMESSAGE_DECREFCOUNT );
299 sessionInfoPtr->iAuthOutContext = CRYPT_ERROR;
300 }
301 if( sessionInfoPtr->iCryptInContext != CRYPT_ERROR )
302 {
303 krnlSendNotifier( sessionInfoPtr->iCryptInContext,
304 IMESSAGE_DECREFCOUNT );
305 sessionInfoPtr->iCryptInContext = CRYPT_ERROR;
306 }
307 if( sessionInfoPtr->iCryptOutContext != CRYPT_ERROR )
308 {
309 krnlSendNotifier( sessionInfoPtr->iCryptOutContext,
310 IMESSAGE_DECREFCOUNT );
311 sessionInfoPtr->iCryptOutContext = CRYPT_ERROR;
312 }
313 }
314
315 /* Clone a hash context so that we can continue using the original to hash
316 further messages */
317
318 CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
cloneHashContext(IN_HANDLE const CRYPT_CONTEXT hashContext,OUT_HANDLE_OPT CRYPT_CONTEXT * clonedHashContext)319 int cloneHashContext( IN_HANDLE const CRYPT_CONTEXT hashContext,
320 OUT_HANDLE_OPT CRYPT_CONTEXT *clonedHashContext )
321 {
322 MESSAGE_CREATEOBJECT_INFO createInfo;
323 int hashAlgo, status; /* int vs.enum */
324
325 assert( isWritePtr( clonedHashContext, sizeof( CRYPT_CONTEXT * ) ) );
326
327 REQUIRES( isHandleRangeValid( hashContext ) );
328
329 /* Clear return value */
330 *clonedHashContext = CRYPT_ERROR;
331
332 /* Determine the type of context that we have to clone */
333 status = krnlSendMessage( hashContext, IMESSAGE_GETATTRIBUTE,
334 &hashAlgo, CRYPT_CTXINFO_ALGO );
335 if( cryptStatusError( status ) )
336 return( status );
337
338 /* Create a new hash context and clone the existing one's state into
339 it */
340 setMessageCreateObjectInfo( &createInfo, hashAlgo );
341 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
342 IMESSAGE_DEV_CREATEOBJECT, &createInfo,
343 OBJECT_TYPE_CONTEXT );
344 if( cryptStatusError( status ) )
345 return( status );
346 status = krnlSendMessage( hashContext, IMESSAGE_CLONE, NULL,
347 createInfo.cryptHandle );
348 if( cryptStatusError( status ) )
349 {
350 krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
351 return( status );
352 }
353 *clonedHashContext = createInfo.cryptHandle;
354
355 return( CRYPT_OK );
356 }
357
358 /****************************************************************************
359 * *
360 * Keyex Functions *
361 * *
362 ****************************************************************************/
363
364 /* Load a DH/ECDH key into a context */
365
366 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
initDHcontextSSL(OUT_HANDLE_OPT CRYPT_CONTEXT * iCryptContext,IN_BUFFER_OPT (keyDataLength)const void * keyData,IN_LENGTH_SHORT_Z const int keyDataLength,IN_HANDLE_OPT const CRYPT_CONTEXT iServerKeyTemplate,IN_ENUM_OPT (CRYPT_ECCCURVE)const CRYPT_ECCCURVE_TYPE eccParams)367 int initDHcontextSSL( OUT_HANDLE_OPT CRYPT_CONTEXT *iCryptContext,
368 IN_BUFFER_OPT( keyDataLength ) const void *keyData,
369 IN_LENGTH_SHORT_Z const int keyDataLength,
370 IN_HANDLE_OPT const CRYPT_CONTEXT iServerKeyTemplate,
371 IN_ENUM_OPT( CRYPT_ECCCURVE ) \
372 const CRYPT_ECCCURVE_TYPE eccParams )
373 {
374 MESSAGE_CREATEOBJECT_INFO createInfo;
375 MESSAGE_DATA msgData;
376 int keySize = TLS_DH_KEYSIZE, status;
377
378 assert( isWritePtr( iCryptContext, sizeof( CRYPT_CONTEXT ) ) );
379 assert( ( keyData == NULL && keyDataLength == 0 ) || \
380 isReadPtr( keyData, keyDataLength ) );
381
382 REQUIRES( ( keyData == NULL && keyDataLength == 0 ) || \
383 ( keyData != NULL && \
384 keyDataLength > 0 && keyDataLength < MAX_INTLENGTH_SHORT ) );
385 REQUIRES( iServerKeyTemplate == CRYPT_UNUSED || \
386 isHandleRangeValid( iServerKeyTemplate ) );
387 REQUIRES( eccParams >= CRYPT_ECCCURVE_NONE && \
388 eccParams < CRYPT_ECCCURVE_LAST );
389
390 /* Clear return value */
391 *iCryptContext = CRYPT_ERROR;
392
393 /* If we're loading a built-in DH key, match the key size to the server
394 authentication key size. If there's no server key present, we
395 default to the TLS_DH_KEYSIZE-byte key because we don't know how much
396 processing power the client has */
397 if( keyData == NULL && iServerKeyTemplate != CRYPT_UNUSED && \
398 eccParams == CRYPT_ECCCURVE_NONE )
399 {
400 status = krnlSendMessage( iServerKeyTemplate, IMESSAGE_GETATTRIBUTE,
401 &keySize, CRYPT_CTXINFO_KEYSIZE );
402 if( cryptStatusError( status ) )
403 return( status );
404 }
405
406 /* Create the DH/ECDH context */
407 setMessageCreateObjectInfo( &createInfo, \
408 ( eccParams != CRYPT_ECCCURVE_NONE ) ? \
409 CRYPT_ALGO_ECDH : CRYPT_ALGO_DH );
410 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
411 &createInfo, OBJECT_TYPE_CONTEXT );
412 if( cryptStatusError( status ) )
413 return( status );
414 setMessageData( &msgData, "TLS key agreement key", 21 );
415 status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,
416 &msgData, CRYPT_CTXINFO_LABEL );
417 if( cryptStatusError( status ) )
418 {
419 krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
420 return( status );
421 }
422
423 /* Load the key into the context. If we're being given externally-
424 supplied DH/ECDH key components, load them, otherwise use the built-
425 in key */
426 if( keyData != NULL )
427 {
428 /* If we're the client we'll have been sent DH/ECDH key components
429 by the server */
430 setMessageData( &msgData, ( MESSAGE_CAST ) keyData, keyDataLength );
431 status = krnlSendMessage( createInfo.cryptHandle,
432 IMESSAGE_SETATTRIBUTE_S, &msgData,
433 CRYPT_IATTRIBUTE_KEY_SSL );
434 }
435 else
436 {
437 #ifdef USE_ECDH
438 /* If we've been given ECC parameter information then we're using
439 ECDH */
440 if( eccParams != CRYPT_ECCCURVE_NONE )
441 {
442 status = krnlSendMessage( createInfo.cryptHandle,
443 IMESSAGE_SETATTRIBUTE,
444 ( MESSAGE_CAST ) &eccParams,
445 CRYPT_IATTRIBUTE_KEY_DLPPARAM );
446 }
447 else
448 #endif /* USE_ECDH */
449 {
450 /* We're loading a standard DH key of the appropriate size */
451 status = krnlSendMessage( createInfo.cryptHandle,
452 IMESSAGE_SETATTRIBUTE,
453 ( MESSAGE_CAST ) &keySize,
454 CRYPT_IATTRIBUTE_KEY_DLPPARAM );
455 }
456 }
457 if( cryptStatusError( status ) )
458 {
459 krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
460 if( keyData == NULL )
461 {
462 /* If we got an error loading a known-good, fixed-format key
463 then we report the problem as an internal error rather than
464 (say) a bad-data error */
465 retIntError();
466 }
467 return( status );
468 }
469 *iCryptContext = createInfo.cryptHandle;
470 return( CRYPT_OK );
471 }
472
473 /* Create the master secret from a shared (PSK) secret value, typically a
474 password */
475
476 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 4 ) ) \
createSharedPremasterSecret(OUT_BUFFER (premasterSecretMaxLength,* premasterSecretLength)void * premasterSecret,IN_LENGTH_SHORT const int premasterSecretMaxLength,OUT_LENGTH_BOUNDED_Z (premasterSecretMaxLength)int * premasterSecretLength,IN_BUFFER (sharedSecretLength)const void * sharedSecret,IN_LENGTH_SHORT const int sharedSecretLength,IN_BUFFER_OPT (otherSecretLength)const void * otherSecret,IN_LENGTH_PKC_Z const int otherSecretLength,const BOOLEAN isEncodedValue)477 int createSharedPremasterSecret( OUT_BUFFER( premasterSecretMaxLength, \
478 *premasterSecretLength ) \
479 void *premasterSecret,
480 IN_LENGTH_SHORT \
481 const int premasterSecretMaxLength,
482 OUT_LENGTH_BOUNDED_Z( premasterSecretMaxLength ) \
483 int *premasterSecretLength,
484 IN_BUFFER( sharedSecretLength ) \
485 const void *sharedSecret,
486 IN_LENGTH_SHORT const int sharedSecretLength,
487 IN_BUFFER_OPT( otherSecretLength ) \
488 const void *otherSecret,
489 IN_LENGTH_PKC_Z const int otherSecretLength,
490 const BOOLEAN isEncodedValue )
491 {
492 STREAM stream;
493 BYTE decodedValue[ 64 + 8 ];
494 static const BYTE zeroes[ CRYPT_MAX_TEXTSIZE + 8 ] = { 0 };
495 int valueLength = sharedSecretLength;
496 int status;
497
498 assert( isWritePtr( premasterSecret, premasterSecretMaxLength ) );
499 assert( isWritePtr( premasterSecretLength, sizeof( int ) ) );
500 assert( isReadPtr( sharedSecret, sharedSecretLength ) );
501 assert( otherSecret == NULL || \
502 isReadPtr( otherSecret, otherSecretLength ) );
503
504 REQUIRES( premasterSecretMaxLength > 0 && \
505 premasterSecretMaxLength < MAX_INTLENGTH_SHORT );
506 REQUIRES( sharedSecretLength > 0 && \
507 sharedSecretLength < MAX_INTLENGTH_SHORT );
508 REQUIRES( ( otherSecret == NULL && otherSecretLength == 0 ) || \
509 ( otherSecret != NULL && \
510 otherSecretLength > 0 && \
511 otherSecretLength <= CRYPT_MAX_PKCSIZE ) );
512
513 /* Clear return values */
514 memset( premasterSecret, 0, min( 16, premasterSecretMaxLength ) );
515 *premasterSecretLength = 0;
516
517 /* Write the PSK-derived premaster secret value:
518
519 uint16 otherSecretLen
520 byte[] otherSecret -- DH value for DHE-PSK, zeroes for pure PSK
521 uint16 pskLen
522 byte[] psk
523
524 Because the TLS PRF splits the input into two halves of which one half
525 is processed by HMAC-MD5 and the other by HMAC-SHA1, it's necessary
526 to extend the PSK in some way to provide input to both halves of the
527 PRF. In a rather dubious decision, the spec requires that for pure
528 PSK (not DHE-PSK or RSA-PSK) the MD5 half be set to all zeroes, with
529 only the SHA1 half being used. This is done by writing otherSecret
530 as a number of zero bytes equal in length to the password */
531 sMemOpen( &stream, premasterSecret, premasterSecretMaxLength );
532 if( isEncodedValue )
533 {
534 /* It's a cryptlib-style encoded password, decode it into its binary
535 value */
536 status = decodePKIUserValue( decodedValue, 64, &valueLength,
537 sharedSecret, sharedSecretLength );
538 if( cryptStatusError( status ) )
539 {
540 DEBUG_DIAG(( "Couldn't decode supposedly valid PKI user "
541 "value" ));
542 assert( DEBUG_WARN );
543 return( status );
544 }
545 sharedSecret = decodedValue;
546 }
547 if( otherSecret != NULL )
548 {
549 writeUint16( &stream, otherSecretLength );
550 swrite( &stream, otherSecret, otherSecretLength );
551 }
552 else
553 {
554 /* It's pure PSK, otherSecret is a string of zeroes */
555 writeUint16( &stream, valueLength );
556 swrite( &stream, zeroes, valueLength );
557 }
558 writeUint16( &stream, valueLength );
559 status = swrite( &stream, sharedSecret, valueLength );
560 if( isEncodedValue )
561 zeroise( decodedValue, valueLength );
562 if( cryptStatusError( status ) )
563 return( status );
564 *premasterSecretLength = stell( &stream );
565 sMemDisconnect( &stream );
566
567 return( CRYPT_OK );
568 }
569
570 /* Wrap/unwrap the pre-master secret */
571
572 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
wrapPremasterSecret(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,OUT_BUFFER (dataMaxLength,* dataLength)void * data,IN_LENGTH_SHORT const int dataMaxLength,OUT_LENGTH_BOUNDED_Z (dataMaxLength)int * dataLength)573 int wrapPremasterSecret( INOUT SESSION_INFO *sessionInfoPtr,
574 INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
575 OUT_BUFFER( dataMaxLength, *dataLength ) void *data,
576 IN_LENGTH_SHORT const int dataMaxLength,
577 OUT_LENGTH_BOUNDED_Z( dataMaxLength ) \
578 int *dataLength )
579 {
580 MECHANISM_WRAP_INFO mechanismInfo;
581 MESSAGE_DATA msgData;
582 int status;
583
584 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
585 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
586 assert( isWritePtr( data, dataMaxLength ) );
587 assert( isWritePtr( dataLength, sizeof( int ) ) );
588
589 REQUIRES( dataMaxLength > 0 && dataMaxLength < MAX_INTLENGTH_SHORT );
590
591 /* Clear return values */
592 memset( data, 0, min( 16, dataMaxLength ) );
593 *dataLength = 0;
594
595 /* Create the premaster secret and wrap it using the server's public
596 key. Note that the version that we advertise at this point is the
597 version originally offered by the client in its hello message, not
598 the version eventually negotiated for the connection. This is
599 designed to prevent rollback attacks (but see also the comment in
600 unwrapPremasterSecret() below) */
601 handshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;
602 handshakeInfo->premasterSecret[ 0 ] = SSL_MAJOR_VERSION;
603 handshakeInfo->premasterSecret[ 1 ] = \
604 intToByte( handshakeInfo->clientOfferedVersion );
605 setMessageData( &msgData,
606 handshakeInfo->premasterSecret + VERSIONINFO_SIZE,
607 handshakeInfo->premasterSecretSize - VERSIONINFO_SIZE );
608 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
609 IMESSAGE_GETATTRIBUTE_S, &msgData,
610 CRYPT_IATTRIBUTE_RANDOM );
611 if( cryptStatusError( status ) )
612 return( status );
613 setMechanismWrapInfo( &mechanismInfo, data, dataMaxLength,
614 handshakeInfo->premasterSecret,
615 handshakeInfo->premasterSecretSize, CRYPT_UNUSED,
616 sessionInfoPtr->iKeyexCryptContext );
617 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_EXPORT,
618 &mechanismInfo, MECHANISM_ENC_PKCS1_RAW );
619 if( cryptStatusOK( status ) )
620 *dataLength = mechanismInfo.wrappedDataLength;
621 clearMechanismInfo( &mechanismInfo );
622
623 return( status );
624 }
625
626 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
unwrapPremasterSecret(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,IN_BUFFER (dataLength)const void * data,IN_LENGTH_SHORT const int dataLength)627 int unwrapPremasterSecret( INOUT SESSION_INFO *sessionInfoPtr,
628 INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
629 IN_BUFFER( dataLength ) const void *data,
630 IN_LENGTH_SHORT const int dataLength )
631 {
632 MECHANISM_WRAP_INFO mechanismInfo;
633 int status;
634
635 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
636 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
637 assert( isReadPtr( data, dataLength ) );
638
639 REQUIRES( dataLength > 0 && dataLength < MAX_INTLENGTH_SHORT );
640
641 /* Decrypt the encrypted premaster secret. In theory we could
642 explicitly defend against Bleichenbacher-type attacks at this point
643 by setting the premaster secret to a pseudorandom value if we get a
644 bad data or (later) an incorrect version error and continuing as
645 normal, however the attack depends on the server returning
646 information required to pinpoint the cause of the failure and
647 cryptlib just returns a generic "failed" response for any handshake
648 failure, so this explicit defence isn't really necessary, and not
649 doing this avoids a trivial DoS attack in which a client sends us
650 junk and forces us to continue with the handshake even though we've
651 detected that it's junk.
652
653 There's a second, lower-grade level of oracle that an attacker can
654 use in the version check if they can distinguish between a decrypt
655 failure due to bad PKCS #1 padding and a failure due to a bad version
656 number (see "Attacking RSA-based Sessions in SSL/TLS", Vlastimil
657 Klima, Ondrej Pokorny, and Tomas Rosa, CHES'03). If we use the
658 Bleichenbacher defence and continue the handshake on bad padding but
659 bail out on a bad version then the two cases can be distinguished,
660 however since cryptlib bails out immediately in either case the two
661 shouldn't be distinguishable */
662 handshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;
663 setMechanismWrapInfo( &mechanismInfo, ( MESSAGE_CAST ) data, dataLength,
664 handshakeInfo->premasterSecret,
665 handshakeInfo->premasterSecretSize, CRYPT_UNUSED,
666 sessionInfoPtr->privateKey );
667 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_IMPORT,
668 &mechanismInfo, MECHANISM_ENC_PKCS1_RAW );
669 if( cryptStatusOK( status ) && \
670 mechanismInfo.keyDataLength != handshakeInfo->premasterSecretSize )
671 status = CRYPT_ERROR_BADDATA;
672 clearMechanismInfo( &mechanismInfo );
673 if( cryptStatusError( status ) )
674 return( status );
675
676 /* Make sure that it looks OK. Note that the version that we check for
677 at this point is the version originally offered by the client in its
678 hello message, not the version eventually negotiated for the
679 connection. This is designed to prevent rollback attacks */
680 if( handshakeInfo->premasterSecret[ 0 ] != SSL_MAJOR_VERSION || \
681 handshakeInfo->premasterSecret[ 1 ] != handshakeInfo->clientOfferedVersion )
682 {
683 /* Microsoft braindamage, older versions of MSIE send the wrong
684 version number for the premaster secret (making it look like a
685 rollback attack) so if we're expecting 3.1 from the client and
686 get 3.0 in the premaster secret then it's MSIE screwing up. Note
687 that this bug-check is only applied for SSL and TLS 1.0, for TLS
688 1.1 and later the check of the version is mandatory */
689 if( handshakeInfo->originalVersion <= SSL_MINOR_VERSION_TLS && \
690 handshakeInfo->clientOfferedVersion == SSL_MINOR_VERSION_TLS && \
691 handshakeInfo->premasterSecret[ 0 ] == SSL_MAJOR_VERSION && \
692 handshakeInfo->premasterSecret[ 1 ] == SSL_MINOR_VERSION_SSL )
693 {
694 setErrorString( ( ERROR_INFO * ) &sessionInfoPtr->errorInfo,
695 "Warning: Accepting invalid premaster secret "
696 "version 3.0 (MSIE bug)", 66 );
697 }
698 else
699 {
700 retExt( CRYPT_ERROR_BADDATA,
701 ( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
702 "Invalid premaster secret version data 0x%02X 0x%02X, "
703 "expected 0x03 0x%02X",
704 handshakeInfo->premasterSecret[ 0 ],
705 handshakeInfo->premasterSecret[ 1 ],
706 handshakeInfo->clientOfferedVersion ) );
707 }
708 }
709
710 return( CRYPT_OK );
711 }
712
713 /****************************************************************************
714 * *
715 * Premaster -> Master -> Key Material Functions *
716 * *
717 ****************************************************************************/
718
719 /* Convert a pre-master secret to a master secret, and a master secret to
720 keying material */
721
722 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
premasterToMaster(const SESSION_INFO * sessionInfoPtr,const SSL_HANDSHAKE_INFO * handshakeInfo,OUT_BUFFER_FIXED (masterSecretLength)void * masterSecret,IN_LENGTH_SHORT const int masterSecretLength)723 static int premasterToMaster( const SESSION_INFO *sessionInfoPtr,
724 const SSL_HANDSHAKE_INFO *handshakeInfo,
725 OUT_BUFFER_FIXED( masterSecretLength ) \
726 void *masterSecret,
727 IN_LENGTH_SHORT const int masterSecretLength )
728 {
729 MECHANISM_DERIVE_INFO mechanismInfo;
730 BYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];
731 int nonceSize;
732
733 assert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
734 assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
735 assert( isReadPtr( masterSecret, masterSecretLength ) );
736
737 REQUIRES( masterSecretLength > 0 && \
738 masterSecretLength < MAX_INTLENGTH_SHORT );
739
740 DEBUG_PRINT(( "Premaster secret:\n" ));
741 DEBUG_DUMP_DATA( handshakeInfo->premasterSecret,
742 handshakeInfo->premasterSecretSize );
743 #ifdef USE_SSL3
744 if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
745 {
746 memcpy( nonceBuffer, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
747 memcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->serverNonce,
748 SSL_NONCE_SIZE );
749 setMechanismDeriveInfo( &mechanismInfo, masterSecret,
750 masterSecretLength,
751 handshakeInfo->premasterSecret,
752 handshakeInfo->premasterSecretSize,
753 ( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT,
754 nonceBuffer,
755 SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
756 return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
757 &mechanismInfo, MECHANISM_DERIVE_SSL ) );
758 }
759 #endif /* USE_SSL3 */
760
761 if( sessionInfoPtr->protocolFlags & SSL_PFLAG_EMS )
762 {
763 memcpy( nonceBuffer, "extended master secret", 22 );
764 memcpy( nonceBuffer + 22, handshakeInfo->sessionHash,
765 handshakeInfo->sessionHashSize );
766 nonceSize = 22 + handshakeInfo->sessionHashSize;
767 }
768 else
769 {
770 memcpy( nonceBuffer, "master secret", 13 );
771 memcpy( nonceBuffer + 13, handshakeInfo->clientNonce,
772 SSL_NONCE_SIZE );
773 memcpy( nonceBuffer + 13 + SSL_NONCE_SIZE,
774 handshakeInfo->serverNonce, SSL_NONCE_SIZE );
775 nonceSize = 13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE;
776 }
777 if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
778 {
779 setMechanismDeriveInfo( &mechanismInfo, masterSecret,
780 masterSecretLength,
781 handshakeInfo->premasterSecret,
782 handshakeInfo->premasterSecretSize,
783 CRYPT_ALGO_SHA2, nonceBuffer, nonceSize, 1 );
784 if( handshakeInfo->integrityAlgoParam != 0 )
785 mechanismInfo.hashParam = handshakeInfo->integrityAlgoParam;
786 return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
787 &mechanismInfo, MECHANISM_DERIVE_TLS12 ) );
788 }
789 setMechanismDeriveInfo( &mechanismInfo, masterSecret, masterSecretLength,
790 handshakeInfo->premasterSecret,
791 handshakeInfo->premasterSecretSize,
792 ( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT,
793 nonceBuffer, nonceSize, 1 );
794 return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
795 &mechanismInfo, MECHANISM_DERIVE_TLS ) );
796 }
797
798 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 5 ) ) \
masterToKeys(const SESSION_INFO * sessionInfoPtr,const SSL_HANDSHAKE_INFO * handshakeInfo,IN_BUFFER (masterSecretLength)const void * masterSecret,IN_LENGTH_SHORT const int masterSecretLength,OUT_BUFFER_FIXED (keyBlockLength)void * keyBlock,IN_LENGTH_SHORT const int keyBlockLength)799 static int masterToKeys( const SESSION_INFO *sessionInfoPtr,
800 const SSL_HANDSHAKE_INFO *handshakeInfo,
801 IN_BUFFER( masterSecretLength ) \
802 const void *masterSecret,
803 IN_LENGTH_SHORT const int masterSecretLength,
804 OUT_BUFFER_FIXED( keyBlockLength ) void *keyBlock,
805 IN_LENGTH_SHORT const int keyBlockLength )
806 {
807 MECHANISM_DERIVE_INFO mechanismInfo;
808 BYTE nonceBuffer[ 64 + SSL_NONCE_SIZE + SSL_NONCE_SIZE + 8 ];
809
810 assert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
811 assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
812 assert( isReadPtr( masterSecret, masterSecretLength ) );
813 assert( isWritePtr( keyBlock, keyBlockLength ) );
814
815 REQUIRES( masterSecretLength > 0 && \
816 masterSecretLength < MAX_INTLENGTH_SHORT );
817 REQUIRES( keyBlockLength > 0 && \
818 keyBlockLength < MAX_INTLENGTH_SHORT );
819
820 DEBUG_PRINT(( "Master secret:\n" ));
821 DEBUG_DUMP_DATA( masterSecret, masterSecretLength );
822 #ifdef USE_SSL3
823 if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
824 {
825 memcpy( nonceBuffer, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
826 memcpy( nonceBuffer + SSL_NONCE_SIZE, handshakeInfo->clientNonce,
827 SSL_NONCE_SIZE );
828 setMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,
829 masterSecret, masterSecretLength,
830 ( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT,
831 nonceBuffer,
832 SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
833 return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
834 &mechanismInfo, MECHANISM_DERIVE_SSL ) );
835 }
836 #endif /* USE_SSL3 */
837
838 memcpy( nonceBuffer, "key expansion", 13 );
839 memcpy( nonceBuffer + 13, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
840 memcpy( nonceBuffer + 13 + SSL_NONCE_SIZE, handshakeInfo->clientNonce,
841 SSL_NONCE_SIZE );
842 if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
843 {
844 setMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,
845 masterSecret, masterSecretLength,
846 CRYPT_ALGO_SHA2, nonceBuffer,
847 13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
848 if( handshakeInfo->integrityAlgoParam != 0 )
849 mechanismInfo.hashParam = handshakeInfo->integrityAlgoParam;
850 return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
851 &mechanismInfo, MECHANISM_DERIVE_TLS12 ) );
852 }
853 setMechanismDeriveInfo( &mechanismInfo, keyBlock, keyBlockLength,
854 masterSecret, masterSecretLength,
855 ( CRYPT_ALGO_TYPE ) CRYPT_USE_DEFAULT,
856 nonceBuffer,
857 13 + SSL_NONCE_SIZE + SSL_NONCE_SIZE, 1 );
858 return( krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_DERIVE,
859 &mechanismInfo, MECHANISM_DERIVE_TLS ) );
860 }
861
862 /****************************************************************************
863 * *
864 * Key-load Functions *
865 * *
866 ****************************************************************************/
867
868 /* Load the SSL/TLS cryptovariables */
869
870 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
871 static int loadKeys( INOUT SESSION_INFO *sessionInfoPtr,
872 const SSL_HANDSHAKE_INFO *handshakeInfo,
873 IN_BUFFER( keyBlockLength ) const void *keyBlock,
874 IN_LENGTH_SHORT_MIN( 16 ) const int keyBlockLength,
875 const BOOLEAN isClient )
876 {
877 SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
878 MESSAGE_DATA msgData;
879 BYTE *keyBlockPtr = ( BYTE * ) keyBlock;
880 int status;
881
882 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
883 assert( isReadPtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
884 assert( isReadPtr( keyBlock, keyBlockLength ) );
885
886 REQUIRES( keyBlockLength >= ( sessionInfoPtr->authBlocksize * 2 ) + \
887 ( handshakeInfo->cryptKeysize * 2 ) + \
888 ( sessionInfoPtr->cryptBlocksize * 2 ) && \
889 keyBlockLength < MAX_INTLENGTH_SHORT );
890
891 /* Load the keys and secrets:
892
893 ( client_write_mac || server_write_mac || \
894 client_write_key || server_write_key || \
895 client_write_iv || server_write_iv )
896
897 First we load the MAC keys. For TLS these are proper MAC keys, for
898 SSL we have to build the proto-HMAC ourselves from a straight hash
899 context so we store the raw cryptovariables rather than loading them
900 into a context, and if we're using GCM we skip them since the
901 encryption key also functions as the authentication key */
902 if( !( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM ) )
903 {
904 if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
905 {
906 ENSURES( rangeCheckZ( 0, sessionInfoPtr->authBlocksize,
907 CRYPT_MAX_HASHSIZE ) );
908 memcpy( isClient ? sslInfo->macWriteSecret : sslInfo->macReadSecret,
909 keyBlockPtr, sessionInfoPtr->authBlocksize );
910 memcpy( isClient ? sslInfo->macReadSecret : sslInfo->macWriteSecret,
911 keyBlockPtr + sessionInfoPtr->authBlocksize,
912 sessionInfoPtr->authBlocksize );
913 }
914 else
915 {
916 setMessageData( &msgData, keyBlockPtr,
917 sessionInfoPtr->authBlocksize );
918 status = krnlSendMessage( isClient ? \
919 sessionInfoPtr->iAuthOutContext : \
920 sessionInfoPtr->iAuthInContext,
921 IMESSAGE_SETATTRIBUTE_S, &msgData,
922 CRYPT_CTXINFO_KEY );
923 if( cryptStatusError( status ) )
924 return( status );
925 setMessageData( &msgData,
926 keyBlockPtr + sessionInfoPtr->authBlocksize,
927 sessionInfoPtr->authBlocksize );
928 status = krnlSendMessage( isClient ? \
929 sessionInfoPtr->iAuthInContext: \
930 sessionInfoPtr->iAuthOutContext,
931 IMESSAGE_SETATTRIBUTE_S, &msgData,
932 CRYPT_CTXINFO_KEY );
933 if( cryptStatusError( status ) )
934 return( status );
935 }
936 keyBlockPtr += sessionInfoPtr->authBlocksize * 2;
937 }
938
939 /* Then we load the encryption keys */
940 setMessageData( &msgData, keyBlockPtr, handshakeInfo->cryptKeysize );
941 status = krnlSendMessage( isClient ? \
942 sessionInfoPtr->iCryptOutContext : \
943 sessionInfoPtr->iCryptInContext,
944 IMESSAGE_SETATTRIBUTE_S, &msgData,
945 CRYPT_CTXINFO_KEY );
946 keyBlockPtr += handshakeInfo->cryptKeysize;
947 if( cryptStatusError( status ) )
948 return( status );
949 setMessageData( &msgData, keyBlockPtr, handshakeInfo->cryptKeysize );
950 status = krnlSendMessage( isClient ? \
951 sessionInfoPtr->iCryptInContext : \
952 sessionInfoPtr->iCryptOutContext,
953 IMESSAGE_SETATTRIBUTE_S, &msgData,
954 CRYPT_CTXINFO_KEY );
955 keyBlockPtr += handshakeInfo->cryptKeysize;
956 if( cryptStatusError( status ) )
957 return( status );
958
959 /* If we're using a stream cipher, there are no IVs */
960 if( isStreamCipher( sessionInfoPtr->cryptAlgo ) )
961 return( CRYPT_OK ); /* No IV, we're done */
962
963 /* If we're using GCM then the IV is composed of two parts, an explicit
964 portion that's sent with every packet and an implicit portion that's
965 derived from the master secret */
966 if( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM )
967 {
968 memcpy( isClient ? sessionInfoPtr->sessionSSL->gcmWriteSalt : \
969 sessionInfoPtr->sessionSSL->gcmReadSalt,
970 keyBlockPtr, GCM_SALT_SIZE );
971 memcpy( isClient ? sessionInfoPtr->sessionSSL->gcmReadSalt : \
972 sessionInfoPtr->sessionSSL->gcmWriteSalt,
973 keyBlockPtr + GCM_SALT_SIZE, GCM_SALT_SIZE );
974 sessionInfoPtr->sessionSSL->gcmSaltSize = GCM_SALT_SIZE;
975
976 return( CRYPT_OK );
977 }
978
979 /* It's a standard block cipher, load the IVs. This load is actually
980 redundant for TLS 1.1+ since it uses explicit IVs, but it's easier to
981 just do it anyway */
982 setMessageData( &msgData, keyBlockPtr,
983 sessionInfoPtr->cryptBlocksize );
984 krnlSendMessage( isClient ? sessionInfoPtr->iCryptOutContext : \
985 sessionInfoPtr->iCryptInContext,
986 IMESSAGE_SETATTRIBUTE_S, &msgData,
987 CRYPT_CTXINFO_IV );
988 keyBlockPtr += sessionInfoPtr->cryptBlocksize;
989 setMessageData( &msgData, keyBlockPtr,
990 sessionInfoPtr->cryptBlocksize );
991 return( krnlSendMessage( isClient ? sessionInfoPtr->iCryptInContext : \
992 sessionInfoPtr->iCryptOutContext,
993 IMESSAGE_SETATTRIBUTE_S, &msgData,
994 CRYPT_CTXINFO_IV ) );
995 }
996
997 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
initCryptoSSL(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,OUT_BUFFER_FIXED (masterSecretSize)void * masterSecret,IN_LENGTH_SHORT const int masterSecretSize,const BOOLEAN isClient,const BOOLEAN isResumedSession)998 int initCryptoSSL( INOUT SESSION_INFO *sessionInfoPtr,
999 INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
1000 OUT_BUFFER_FIXED( masterSecretSize ) void *masterSecret,
1001 IN_LENGTH_SHORT const int masterSecretSize,
1002 const BOOLEAN isClient,
1003 const BOOLEAN isResumedSession )
1004 {
1005 BYTE keyBlock[ MAX_KEYBLOCK_SIZE + 8 ];
1006 int status;
1007
1008 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1009 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1010 assert( isWritePtr( masterSecret, masterSecretSize ) );
1011
1012 REQUIRES( masterSecretSize > 0 && \
1013 masterSecretSize < MAX_INTLENGTH_SHORT );
1014
1015 /* Create the security contexts required for the session */
1016 status = initSecurityContextsSSL( sessionInfoPtr );
1017 if( cryptStatusError( status ) )
1018 return( status );
1019
1020 /* If it's a fresh (i.e. non-cached) session, convert the premaster
1021 secret into the master secret */
1022 if( !isResumedSession )
1023 {
1024 status = premasterToMaster( sessionInfoPtr, handshakeInfo,
1025 masterSecret, masterSecretSize );
1026 if( cryptStatusError( status ) )
1027 return( status );
1028 }
1029 else
1030 {
1031 /* We've already got the master secret present from the session that
1032 we're resuming from, reuse that */
1033 ENSURES( rangeCheckZ( 0, handshakeInfo->premasterSecretSize,
1034 masterSecretSize ) );
1035 memcpy( masterSecret, handshakeInfo->premasterSecret,
1036 handshakeInfo->premasterSecretSize );
1037 }
1038
1039 /* Convert the master secret into keying material. Unfortunately we
1040 can't delete the master secret at this point because it's still
1041 needed to calculate the MAC for the handshake messages and because
1042 we may still need it in order to add it to the session cache */
1043 status = masterToKeys( sessionInfoPtr, handshakeInfo, masterSecret,
1044 masterSecretSize, keyBlock, MAX_KEYBLOCK_SIZE );
1045 if( cryptStatusError( status ) )
1046 {
1047 zeroise( masterSecret, masterSecretSize );
1048 return( status );
1049 }
1050
1051 /* Load the keys and secrets */
1052 status = loadKeys( sessionInfoPtr, handshakeInfo, keyBlock,
1053 MAX_KEYBLOCK_SIZE, isClient );
1054 zeroise( keyBlock, MAX_KEYBLOCK_SIZE );
1055 if( cryptStatusError( status ) )
1056 {
1057 zeroise( masterSecret, masterSecretSize );
1058 return( status );
1059 }
1060
1061 return( CRYPT_OK );
1062 }
1063
1064 /* TLS versions greater than 1.0 prepend an explicit IV to the data, the
1065 following function loads this from the packet data stream */
1066
1067 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
loadExplicitIV(INOUT SESSION_INFO * sessionInfoPtr,INOUT STREAM * stream,OUT_INT_SHORT_Z int * ivLength)1068 int loadExplicitIV( INOUT SESSION_INFO *sessionInfoPtr,
1069 INOUT STREAM *stream,
1070 OUT_INT_SHORT_Z int *ivLength )
1071 {
1072 SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
1073 MESSAGE_DATA msgData;
1074 BYTE iv[ CRYPT_MAX_IVSIZE + 8 ];
1075 int ivSize = sslInfo->ivSize, status;
1076
1077 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1078 assert( isWritePtr( stream, sizeof( STREAM ) ) );
1079 assert( isWritePtr( ivLength, sizeof( int ) ) );
1080
1081 /* Clear return value */
1082 *ivLength = 0;
1083
1084 /* Read and load the IV */
1085 status = sread( stream, iv, sslInfo->ivSize );
1086 if( cryptStatusError( status ) )
1087 {
1088 retExt( status,
1089 ( status, SESSION_ERRINFO,
1090 "Packet IV read" ) );
1091 }
1092 if( sessionInfoPtr->protocolFlags & SSL_PFLAG_GCM )
1093 {
1094 /* If we're using GCM then the IV has to be assembled from the
1095 implicit and explicit portions */
1096 ENSURES( rangeCheck( sslInfo->gcmSaltSize, sslInfo->ivSize,
1097 CRYPT_MAX_IVSIZE ) );
1098 memmove( iv + sslInfo->gcmSaltSize, iv, sslInfo->ivSize );
1099 memcpy( iv, sslInfo->gcmReadSalt, sslInfo->gcmSaltSize );
1100 ivSize += sslInfo->gcmSaltSize;
1101 }
1102 if( sessionInfoPtr->protocolFlags & SSL_PFLAG_ENCTHENMAC )
1103 {
1104 /* If we're using encrypt-then-MAC then we have to save a copy of
1105 the IV for MAC'ing when the packet is processed */
1106 memcpy( sslInfo->iv, iv, sslInfo->ivSize );
1107 }
1108 if( cryptStatusOK( status ) )
1109 {
1110 setMessageData( &msgData, iv, ivSize );
1111 status = krnlSendMessage( sessionInfoPtr->iCryptInContext,
1112 IMESSAGE_SETATTRIBUTE_S, &msgData,
1113 CRYPT_CTXINFO_IV );
1114 }
1115 if( cryptStatusError( status ) )
1116 {
1117 retExt( status,
1118 ( status, SESSION_ERRINFO,
1119 "Packet IV load failed" ) );
1120 }
1121
1122 /* Tell the caller how much data we've consumed */
1123 *ivLength = sslInfo->ivSize;
1124
1125 return( CRYPT_OK );
1126 }
1127 #endif /* USE_SSL */
1128