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