1 /****************************************************************************
2 *																			*
3 *					cryptlib SSL v3/TLS Server Management					*
4 *					   Copyright Peter Gutmann 1998-2013					*
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 /* Determine whether the server needs to request client certificates/client
23    authentication.  This is normally determined by whether an access-control
24    keyset is available, but for the Suite B tests in which any test
25    certificate is regarded as being acceptable it can be overridden with a
26    self-test flag */
27 
28 #ifdef CONFIG_SUITEB_TESTS
29 #define clientCertAuthRequired( sessionInfoPtr ) \
30 		( sessionInfoPtr->cryptKeyset != CRYPT_ERROR || suiteBTestClientCert )
31 #else
32 #define clientCertAuthRequired( sessionInfoPtr ) \
33 		( sessionInfoPtr->cryptKeyset != CRYPT_ERROR || \
34 		  ( sessionInfoPtr->protocolFlags & SSL_PFLAG_MANUAL_CERTCHECK ) )
35 #endif /* CONFIG_SUITEB_TESTS */
36 
37 /****************************************************************************
38 *																			*
39 *								Utility Functions							*
40 *																			*
41 ****************************************************************************/
42 
43 /* Read the client certificate chain and make sure that the certificate
44    being presented is valid for access */
45 
46 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readCheckClientCerts(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,INOUT STREAM * stream)47 static int readCheckClientCerts( INOUT SESSION_INFO *sessionInfoPtr,
48 								 INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
49 								 INOUT STREAM *stream )
50 	{
51 #ifdef CONFIG_SUITEB
52 	int length;
53 #endif /* CONFIG_SUITEB */
54 	int status;
55 
56 	/* Read the client certificate chain */
57 	status = readSSLCertChain( sessionInfoPtr, handshakeInfo, stream,
58 							   &sessionInfoPtr->iKeyexAuthContext, TRUE );
59 	if( cryptStatusError( status ) )
60 		return( status );
61 
62 	/* If we're doing keyset-based certificate verification, make sure that
63 	   the client certificate is present in our certificate store.  Since
64 	   we've already got a copy of the certificate, we only do a presence
65 	   check rather than actually fetching the certificate.
66 
67 	   Checking whether the certificate is known to us at this point opens
68 	   us up to a theoretical account-enumeration attack in which an
69 	   attacker who has obtained a copy of every certificate in the world
70 	   can throw them at us one after the other and then using timing
71 	   measurements to see which ones get past this point.  OTOH deferring
72 	   the "is this certificate known to us" check until after we process
73 	   the keyex opens us up to a DoS attack since the attacker can force
74 	   us to perform a DH keyex rather than rejecting the handshake at this
75 	   point.  We could further flip things around and first read the
76 	   certificate, then read and cache the keyex data, then try and verify
77 	   the keyex data using the client signature, and only then actually
78 	   use it, but this greatly complicates the code and given the practical
79 	   nonexistence of client certificates just adds a pile of needless
80 	   complexity for a mechanism that's virtually never used anyway.
81 
82 	   Because of this we do a quick-reject check here and don't even go
83 	   into a keyex unless we recognise the certificate */
84 #ifndef CONFIG_SUITEB_TESTS
85 	if( sessionInfoPtr->cryptKeyset != CRYPT_ERROR )
86 		{
87 		MESSAGE_KEYMGMT_INFO getkeyInfo;
88 		MESSAGE_DATA msgData;
89 		BYTE certID[ KEYID_SIZE + 8 ];
90 
91 		setMessageData( &msgData, certID, KEYID_SIZE );
92 		status = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext,
93 								  IMESSAGE_GETATTRIBUTE_S, &msgData,
94 								  CRYPT_CERTINFO_FINGERPRINT_SHA1 );
95 		if( cryptStatusOK( status ) )
96 			{
97 			setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID,
98 								   certID, KEYID_SIZE, NULL, 0,
99 								   KEYMGMT_FLAG_CHECK_ONLY );
100 			status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
101 									  IMESSAGE_KEY_GETKEY, &getkeyInfo,
102 									  KEYMGMT_ITEM_PUBLICKEY );
103 			}
104 		if( cryptStatusError( status ) )
105 			{
106 			retExt( CRYPT_ERROR_INVALID,
107 					( CRYPT_ERROR_INVALID, SESSION_ERRINFO,
108 					  "Client certificate is not trusted for "
109 					  "authentication purposes" ) );
110 			}
111 		}
112 #endif /* CONFIG_SUITEB_TESTS */
113 
114 	/* Make sure that the key is of the appropriate size for the Suite B
115 	   security level.  At the 128-bit level both P256 and P384 are allowed,
116 	   at the 256-bit level only P384 is allowed */
117 #ifdef CONFIG_SUITEB
118 	status = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext,
119 							  IMESSAGE_GETATTRIBUTE, &length,
120 							  CRYPT_CTXINFO_KEYSIZE );
121 	if( cryptStatusOK( status ) )
122 		{
123 		const int suiteBtype = \
124 						sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB;
125 
126 		if( suiteBtype == SSL_PFLAG_SUITEB_256 )
127 			{
128 			if( length != bitsToBytes( 384 ) )
129 				{
130 				retExt( CRYPT_ERROR_INVALID,
131 						( CRYPT_ERROR_INVALID, SESSION_ERRINFO,
132 						  "Client Suite B certificate uses %d-bit key at "
133 						  "256-bit security level, should use 384-bit key",
134 						  bytesToBits( length ) ) );
135 				}
136 			}
137 		else
138 			{
139 			if( length != bitsToBytes( 256 ) && \
140 				length != bitsToBytes( 384 ) )
141 				{
142 				retExt( CRYPT_ERROR_INVALID,
143 						( CRYPT_ERROR_INVALID, SESSION_ERRINFO,
144 						  "Client Suite B certificate uses %d-bit key at "
145 						  "128-bit security level, should use 256- or "
146 						  "384-bit key", bytesToBits( length ) ) );
147 				}
148 			}
149 		}
150 #endif /* CONFIG_SUITEB */
151 
152 	return( CRYPT_OK );
153 	}
154 
155 /* Write the certificate request:
156 
157 	  [	byte		ID = SSL_HAND_SERVER_CERTREQUEST ]
158 	  [	uint24		len				-- Written by caller ]
159 		byte		certTypeLen
160 		byte[]		certType = { RSA, DSA, ECDSA }
161 	  [	uint16	sigHashListLen		-- TLS 1.2 ]
162 	  [		byte	hashAlgoID		-- TLS 1.2 ]
163 	  [		byte	sigAlgoID		-- TLS 1.2 ]
164 		uint16		caNameListLen = 4
165 			uint16	caNameLen = 2
166 			byte[]	caName = { 0x30, 0x00 }
167 
168    This message is a real mess, it originally had a rather muddled
169    certificate-type indicator (which included things like "Ephemeral DH
170    signed with RSA") and an equally ambiguous CA list that many
171    implementations either left empty or filled with the name of every CA
172    that they'd ever heard of.  TLS 1.2 added a means of indicating which
173    signature and hash algorithms were acceptable, which is kind of essential
174    because the explosion of hash algorithms in 1.2 means that a server would
175    have to run parallel hashes of every handshake message for every possible
176    hash algorithm until the client sends their certificate-verify message
177    (!!).  In other words although it was planned as a means of indicating
178    the server's capabilities, it actually acts as a mechanism for keeping
179    the client-auth process manageable */
180 
181 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
writeCertRequest(INOUT SESSION_INFO * sessionInfoPtr,INOUT STREAM * stream)182 static int writeCertRequest( INOUT SESSION_INFO *sessionInfoPtr,
183 							 INOUT STREAM *stream )
184 	{
185 	const BOOLEAN rsaAvailable = algoAvailable( CRYPT_ALGO_RSA );
186 	const BOOLEAN dsaAvailable = algoAvailable( CRYPT_ALGO_DSA );
187 	const BOOLEAN ecdsaAvailable = algoAvailable( CRYPT_ALGO_ECDSA );
188 	int status DUMMY_INIT;
189 
190 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
191 #ifdef CONFIG_SUITEB
192 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
193 #endif /* CONFIG_SUITEB */
194 
195 	REQUIRES( rsaAvailable || ecdsaAvailable );
196 
197 	/* Write the certificate type */
198 	sputc( stream, ( rsaAvailable ? 1 : 0 ) + \
199 				   ( dsaAvailable ? 1 : 0 ) + \
200 				   ( ecdsaAvailable ? 1 : 0 ) );
201 	if( rsaAvailable )
202 		status = sputc( stream, TLS_CERTTYPE_RSA );
203 	if( dsaAvailable )
204 		status = sputc( stream, TLS_CERTTYPE_DSA );
205 	if( ecdsaAvailable )
206 		status = sputc( stream, TLS_CERTTYPE_ECDSA );
207 	if( cryptStatusError( status ) )
208 		return( status );
209 
210 	/* Write the list of accepted signature and hash algorithms if required.
211 	   In theory we could write the full list of algorithms, but thanks to
212 	   SSL/TLS' braindamaged way of handling certificate-based
213 	   authentication (see the comment above) this would make the
214 	   certificate-authentication process unmanageable.  To get around this
215 	   we only allow one single algorithm, the SHA-2 default for TLS 1.2+.
216 
217 	   For Suite B things get a bit more complicated because this allows
218 	   both SHA-256 and SHA-384, dropping us straight back into the mess
219 	   that we've just escaped from.  To get around this we specify the
220 	   use of the hash algorithm that we've negotiated for the handshake,
221 	   on the assumption that a client using SHA384 for the handshake isn't
222 	   going to then try and use SHA256 for the authentication */
223 	if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
224 		{
225 #ifdef CONFIG_SUITEB
226 		writeUint16( stream, 2 );
227 		if( handshakeInfo->keyexSigHashAlgoParam == bitsToBytes( 384 ) )
228 			sputc( stream, TLS_HASHALGO_SHA384 );
229 		else
230 			sputc( stream, TLS_HASHALGO_SHA2 );
231 		status = sputc( stream, TLS_SIGALGO_ECDSA );
232 #else
233 		writeUint16( stream, ( rsaAvailable ? 2 : 0 ) + \
234 							 ( dsaAvailable ? 2 : 0 ) + \
235 							 ( ecdsaAvailable ? 2 : 0 ) );
236 		if( rsaAvailable )
237 			{
238 			sputc( stream, TLS_HASHALGO_SHA2 );
239 			status = sputc( stream, TLS_SIGALGO_RSA );
240 			}
241 		if( dsaAvailable )
242 			{
243 			sputc( stream, TLS_HASHALGO_SHA2 );
244 			status = sputc( stream, TLS_SIGALGO_DSA );
245 			}
246 		if( ecdsaAvailable )
247 			{
248 			sputc( stream, TLS_HASHALGO_SHA2 );
249 			status = sputc( stream, TLS_SIGALGO_ECDSA );
250 			}
251 #endif /* CONFIG_SUITEB */
252 		}
253 	if( cryptStatusError( status ) )
254 		return( status );
255 
256 	/* Write the CA name list */
257 	writeUint16( stream, UINT16_SIZE + 2 );
258 	writeUint16( stream, 2 );
259 	return( swrite( stream, "\x30\x00", 2 ) );
260 	}
261 
262 /* Calculate an ID for use with the session scoreboard from the session ID
263    and the SNI.  This prevents an attacker from taking advantage of virtual
264    hosting with a shared session cache to redirect a connection from one
265    domain to another, which a purely session ID-based lookup would allow */
266 
267 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
convertSNISessionID(INOUT SSL_HANDSHAKE_INFO * handshakeInfo,OUT_BUFFER_FIXED (idBufferLength)BYTE * idBuffer,IN_LENGTH_FIXED (KEYID_SIZE)const int idBufferLength)268 int convertSNISessionID( INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
269 						 OUT_BUFFER_FIXED( idBufferLength ) BYTE *idBuffer,
270 						 IN_LENGTH_FIXED( KEYID_SIZE ) const int idBufferLength )
271 	{
272 	STREAM sniStream;
273 	BYTE sniInfo[ UINT16_SIZE + MAX_SESSIONID_SIZE + \
274 				  UINT16_SIZE + KEYID_SIZE + 8 ];
275 	int sniInfoLength, status;
276 
277 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
278 	assert( isWritePtr( idBuffer, idBufferLength ) );
279 
280 	REQUIRES( idBufferLength == KEYID_SIZE );
281 
282 	/* Clear return value */
283 	memset( idBuffer, 0, idBufferLength );
284 
285 	/* Write the session ID and hashed SNI to a buffer for hashing */
286 	sMemOpen( &sniStream, sniInfo, UINT16_SIZE + MAX_SESSIONID_SIZE + \
287 								   UINT16_SIZE + KEYID_SIZE );
288 	writeUint16( &sniStream, handshakeInfo->sessionIDlength );
289 	swrite( &sniStream, handshakeInfo->sessionID,
290 			handshakeInfo->sessionIDlength );
291 	writeUint16( &sniStream, KEYID_SIZE );
292 	status = swrite( &sniStream, handshakeInfo->hashedSNI, KEYID_SIZE );
293 	ENSURES( !cryptStatusError( status ) );
294 	sniInfoLength = stell( &sniStream );
295 
296 	/* Generate the final ID from the combined session ID and SNI */
297 	hashData( idBuffer, idBufferLength, sniInfo, sniInfoLength );
298 	sMemClose( &sniStream );
299 
300 	return( CRYPT_OK );
301 	}
302 
303 /****************************************************************************
304 *																			*
305 *							Handle Client/Server Keyex						*
306 *																			*
307 ****************************************************************************/
308 
309 /* Process the client key exchange packet:
310 
311 		byte		ID = SSL_HAND_CLIENT_KEYEXCHANGE
312 		uint24		len
313 	   DH:
314 		uint16		yLen
315 		byte[]		y
316 	   DH-PSK:
317 		uint16		userIDLen
318 		byte[]		userID
319 		uint16		yLen
320 		byte[]		y
321 	   ECDH:
322 		uint16		ecPointLen
323 		byte[]		ecPoint
324 	   PSK:
325 		uint16		userIDLen
326 		byte[]		userID
327 	   RSA:
328 	  [ uint16		encKeyLen		-- TLS 1.x ]
329 		byte[]		rsaPKCS1( byte[2] { 0x03, 0x0n } || byte[46] random ) */
330 
331 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
processDHKeyex(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,INOUT STREAM * stream,IN_OPT const ATTRIBUTE_LIST * passwordInfoPtr)332 static int processDHKeyex( INOUT SESSION_INFO *sessionInfoPtr,
333 						   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
334 						   INOUT STREAM *stream,
335 						   IN_OPT const ATTRIBUTE_LIST *passwordInfoPtr )
336 	{
337 	KEYAGREE_PARAMS keyAgreeParams;
338 	const BOOLEAN isECC = isEccAlgo( handshakeInfo->keyexAlgo );
339 	int status;
340 
341 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
342 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
343 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
344 	assert( passwordInfoPtr == NULL || \
345 			isReadPtr( passwordInfoPtr, sizeof( ATTRIBUTE_LIST ) ) );
346 
347 	/* Read the DH/ECDH key agreement parameters */
348 	memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
349 	if( isECC )
350 		{
351 		status = readEcdhValue( stream, keyAgreeParams.publicValue,
352 								CRYPT_MAX_PKCSIZE,
353 								&keyAgreeParams.publicValueLen );
354 		}
355 	else
356 		{
357 		status = readInteger16UChecked( stream,
358 										keyAgreeParams.publicValue,
359 										&keyAgreeParams.publicValueLen,
360 										MIN_PKCSIZE, CRYPT_MAX_PKCSIZE );
361 		}
362 	if( cryptStatusError( status ) )
363 		{
364 		/* Some misconfigured clients may use very short keys, we perform a
365 		   special-case check for these and return a more specific message
366 		   than the generic bad-data error */
367 		if( status == CRYPT_ERROR_NOSECURE )
368 			{
369 			retExt( CRYPT_ERROR_NOSECURE,
370 					( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO,
371 					  "Insecure key used in key exchange" ) );
372 			}
373 
374 		retExt( CRYPT_ERROR_BADDATA,
375 				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
376 				  "Invalid %sDH phase 2 key agreement data",
377 				  isECC ? "EC" : "" ) );
378 		}
379 
380 	/* If we're fuzzing the input then we don't need to go through any of
381 	   the following crypto calisthenics.  In addition we can exit now
382 	   because the remaining fuzzable code is common with the client and
383 	   has already been tested there */
384 	FUZZ_EXIT();
385 
386 	/* Perform phase 2 of the DH/ECDH key agreement */
387 	status = krnlSendMessage( handshakeInfo->dhContext, IMESSAGE_CTX_DECRYPT,
388 							  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
389 	if( cryptStatusError( status ) )
390 		{
391 		zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
392 		retExt( status,
393 				( status, SESSION_ERRINFO,
394 				  "Invalid %sDH phase 2 key agreement value",
395 				  isECC ? "EC" : "" ) );
396 		}
397 	if( isECC )
398 		{
399 		const int xCoordLen = ( keyAgreeParams.wrappedKeyLen - 1 ) / 2;
400 
401 		/* The output of the ECDH operation is an ECC point, but for some
402 		   unknown reason TLS only uses the x coordinate and not the full
403 		   point.  To work around this we have to rewrite the point as a
404 		   standalone x coordinate, which is relatively easy because we're
405 		   using the uncompressed point format:
406 
407 			+---+---------------+---------------+
408 			|04	|		qx		|		qy		|
409 			+---+---------------+---------------+
410 				|<- fldSize --> |<- fldSize --> | */
411 		REQUIRES( keyAgreeParams.wrappedKeyLen >= MIN_PKCSIZE_ECCPOINT && \
412 				  keyAgreeParams.wrappedKeyLen <= MAX_PKCSIZE_ECCPOINT && \
413 				  ( keyAgreeParams.wrappedKeyLen & 1 ) == 1 && \
414 				  keyAgreeParams.wrappedKey[ 0 ] == 0x04 );
415 		memmove( keyAgreeParams.wrappedKey,
416 				 keyAgreeParams.wrappedKey + 1, xCoordLen );
417 		keyAgreeParams.wrappedKeyLen = xCoordLen;
418 		}
419 	if( passwordInfoPtr != NULL )
420 		{
421 		status = createSharedPremasterSecret( \
422 							handshakeInfo->premasterSecret,
423 							CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE,
424 							&handshakeInfo->premasterSecretSize,
425 							passwordInfoPtr->value,
426 							passwordInfoPtr->valueLength,
427 							keyAgreeParams.wrappedKey,
428 							keyAgreeParams.wrappedKeyLen,
429 							( passwordInfoPtr->flags & ATTR_FLAG_ENCODEDVALUE ) ? \
430 								TRUE : FALSE );
431 		if( cryptStatusError( status ) )
432 			{
433 			zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
434 			retExt( status,
435 					( status, SESSION_ERRINFO,
436 					  "Couldn't create master secret from shared "
437 					  "secret/password value" ) );
438 			}
439 		}
440 	else
441 		{
442 		ENSURES( rangeCheckZ( 0, keyAgreeParams.wrappedKeyLen,
443 							  CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE ) );
444 		memcpy( handshakeInfo->premasterSecret, keyAgreeParams.wrappedKey,
445 				keyAgreeParams.wrappedKeyLen );
446 		handshakeInfo->premasterSecretSize = keyAgreeParams.wrappedKeyLen;
447 		}
448 	zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
449 
450 	return( CRYPT_OK );
451 	}
452 
453 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
processPSKKeyex(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,INOUT STREAM * stream,const BOOLEAN isKeyex)454 static int processPSKKeyex( INOUT SESSION_INFO *sessionInfoPtr,
455 							INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
456 							INOUT STREAM *stream, const BOOLEAN isKeyex )
457 	{
458 	const ATTRIBUTE_LIST *attributeListPtr, *attributeListCursor;
459 	BYTE userID[ CRYPT_MAX_TEXTSIZE + 8 ];
460 	int length, iterationCount, status;
461 
462 	/* Read the client user ID and make sure that it's a valid user.
463 	   Handling non-valid users is somewhat problematic, we can either bail
464 	   out immediately or invent a fake password for the (non-)user and
465 	   continue with that.  The problem with this is that it doesn't really
466 	   help hide whether the user is valid or not due to the fact that we're
467 	   still vulnerable to a timing attack because it takes considerably
468 	   longer to generate the random password than it does to read a fixed
469 	   password string from memory, so an attacker can tell from the timing
470 	   whether the username is valid or not.  In addition usability research
471 	   on real-world users indicates that this actually reduces security
472 	   while having little to no tangible benefit.  Because of this we don't
473 	   try and fake out the valid/invalid user name indication but just exit
474 	   immediately if an invalid name is found */
475 	length = readUint16( stream );
476 	if( length < 1 || length > CRYPT_MAX_TEXTSIZE || \
477 		cryptStatusError( sread( stream, userID, length ) ) )
478 		{
479 		retExt( CRYPT_ERROR_BADDATA,
480 				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
481 				  "Invalid client user ID" ) );
482 		}
483 	attributeListPtr = findSessionInfoEx( sessionInfoPtr->attributeList,
484 										  CRYPT_SESSINFO_USERNAME, userID,
485 										  length );
486 	if( attributeListPtr == NULL )
487 		{
488 		retExt( CRYPT_ERROR_WRONGKEY,
489 				( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO,
490 				  "Unknown user name '%s'",
491 				  sanitiseString( userID, CRYPT_MAX_TEXTSIZE,
492 								  length ) ) );
493 		}
494 
495 	/* Move on to the associated password */
496 	attributeListPtr = attributeListPtr->next;
497 	ENSURES( attributeListPtr != NULL && \
498 			 attributeListPtr->attributeID == CRYPT_SESSINFO_PASSWORD );
499 
500 	/* Delete any other username/password pairs that may be present so that
501 	   the caller knows which set was used to authenticate */
502 	for( attributeListCursor = findSessionInfo( sessionInfoPtr->attributeList,
503 												CRYPT_SESSINFO_USERNAME ),
504 			iterationCount = 0;
505 		 attributeListCursor != NULL && \
506 			iterationCount < FAILSAFE_ITERATIONS_LARGE;
507 		 attributeListCursor = findSessionInfo( attributeListCursor,
508 												CRYPT_SESSINFO_USERNAME ),
509 			iterationCount++ )
510 		{
511 		ATTRIBUTE_LIST *userNamePtr = ( ATTRIBUTE_LIST * ) attributeListCursor;
512 		ATTRIBUTE_LIST *passwordPtr = userNamePtr->next;
513 
514 		ENSURES( passwordPtr != NULL && \
515 				 passwordPtr->attributeID == CRYPT_SESSINFO_PASSWORD );
516 		attributeListCursor = passwordPtr->next;
517 
518 		/* If this is the username/password that was used to authenticate,
519 		   leave it */
520 		if( passwordPtr == attributeListPtr )
521 			continue;
522 
523 		/* Delete the non-matching username/password pair */
524 		deleteSessionInfo( &sessionInfoPtr->attributeList,
525 						   &sessionInfoPtr->attributeListCurrent,
526 						   userNamePtr );
527 		deleteSessionInfo( &sessionInfoPtr->attributeList,
528 						   &sessionInfoPtr->attributeListCurrent,
529 						   passwordPtr );
530 		}
531 	ENSURES( iterationCount < FAILSAFE_ITERATIONS_LARGE );
532 
533 	/* If it's PSK with DH/ECDH, perform the keyex with the PSK added */
534 	if( isKeyex )
535 		{
536 		return( processDHKeyex( sessionInfoPtr, handshakeInfo, stream,
537 								attributeListPtr ) );
538 		}
539 
540 	/* If we're fuzzing the input then we don't need to go through any of
541 	   the following crypto calisthenics.  In addition we can exit now
542 	   because the remaining fuzzable code is common with the client and
543 	   has already been tested there */
544 	FUZZ_EXIT();
545 
546 	/* We're using straight PSK, the premaster secret is derived from the
547 	   user password */
548 	status = createSharedPremasterSecret( \
549 						handshakeInfo->premasterSecret,
550 						CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE,
551 						&handshakeInfo->premasterSecretSize,
552 						attributeListPtr->value,
553 						attributeListPtr->valueLength, NULL, 0,
554 						( attributeListPtr->flags & ATTR_FLAG_ENCODEDVALUE ) ? \
555 							TRUE : FALSE );
556 	if( cryptStatusError( status ) )
557 		{
558 		retExt( status,
559 				( status, SESSION_ERRINFO,
560 				  "Couldn't create master secret from shared secret/password "
561 				  "value" ) );
562 		}
563 
564 	return( CRYPT_OK );
565 	}
566 
567 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
processClientKeyex(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,INOUT STREAM * stream,const BOOLEAN isKeyex,const BOOLEAN isPSK)568 static int processClientKeyex( INOUT SESSION_INFO *sessionInfoPtr,
569 							   INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
570 							   INOUT STREAM *stream,
571 							   const BOOLEAN isKeyex, const BOOLEAN isPSK )
572 
573 	{
574 	BYTE wrappedKey[ CRYPT_MAX_PKCSIZE + 8 ];
575 	int length, status;
576 
577 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
578 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
579 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
580 
581 	status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
582 								  SSL_HAND_CLIENT_KEYEXCHANGE,
583 								  UINT16_SIZE + 1 );
584 	if( cryptStatusError( status ) )
585 		return( status );
586 
587 	/* If we're using any form of PSK, the keyex is handled specially */
588 	if( isPSK )
589 		{
590 		return( processPSKKeyex( sessionInfoPtr, handshakeInfo, stream,
591 								 isKeyex ) );
592 		}
593 
594 	/* If we're using DH/ECDH, perform the necessary keyex operations */
595 	if( isKeyex )
596 		return( processDHKeyex( sessionInfoPtr, handshakeInfo, stream, NULL ) );
597 
598 	/* It's an RSA keyex, read and unwrap the RSA-wrapped premaster secret */
599 #ifdef USE_SSL3
600 	if( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL )
601 		{
602 		/* The original Netscape SSL implementation didn't provide a length
603 		   for the encrypted key and everyone copied that so it became the
604 		   de facto standard way to do it (sic faciunt omnes.  The spec
605 		   itself is ambiguous on the topic).  This was fixed in TLS
606 		   (although the spec is still ambigous) so the encoding differs
607 		   slightly between SSL and TLS.  To work around this we have to
608 		   duplicate a certain amount of the integer-read code here */
609 		if( isShortPKCKey( length ) )
610 			status = CRYPT_ERROR_NOSECURE;
611 		else
612 			{
613 			if( length < MIN_PKCSIZE || length > CRYPT_MAX_PKCSIZE || \
614 				cryptStatusError( sread( stream, wrappedKey, length ) ) )
615 				status = CRYPT_ERROR_BADDATA;
616 			}
617 		}
618 	else
619 #endif /* USE_SSL3 */
620 		{
621 		status = readInteger16UChecked( stream, wrappedKey, &length,
622 										MIN_PKCSIZE, CRYPT_MAX_PKCSIZE );
623 		}
624 	if( cryptStatusError( status ) )
625 		{
626 		/* Some misconfigured clients may use very short keys, we perform a
627 		   special-case check for these and return a more specific message
628 		   than the generic bad-data */
629 		if( status == CRYPT_ERROR_NOSECURE )
630 			{
631 			retExt( CRYPT_ERROR_NOSECURE,
632 					( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO,
633 					  "Insecure key used in key exchange" ) );
634 			}
635 
636 		retExt( CRYPT_ERROR_BADDATA,
637 				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
638 				  "Invalid RSA encrypted key data" ) );
639 		}
640 
641 	/* If we're fuzzing the input then we don't need to go through any of
642 	   the following crypto calisthenics.  In addition we can exit now
643 	   because the remaining fuzzable code is common with the client and
644 	   has already been tested there */
645 	FUZZ_EXIT();
646 
647 	/* Decrypt the pre-master secret */
648 	return( unwrapPremasterSecret( sessionInfoPtr, handshakeInfo,
649 								   wrappedKey, length ) );
650 	}
651 
652 /* Build the server key exchange packet:
653 
654 	  [	byte		ID = SSL_HAND_SERVER_KEYEXCHANGE ]
655 	  [	uint24		len				-- Written by caller ]
656 	   DH:
657 		uint16		dh_pLen
658 		byte[]		dh_p
659 		uint16		dh_gLen
660 		byte[]		dh_g
661 		uint16		dh_YsLen
662 		byte[]		dh_Ys
663 	  [	byte		hashAlgoID		-- TLS 1.2 ]
664 	  [	byte		sigAlgoID		-- TLS 1.2 ]
665 		uint16		signatureLen
666 		byte[]		signature
667 	   DH-PSK:
668 		uint16		pskIdentityHintLen = 0
669 		uint16		dh_pLen
670 		byte[]		dh_p
671 		uint16		dh_gLen
672 		byte[]		dh_g
673 		uint16		dh_YsLen
674 		byte[]		dh_Ys
675 	   ECDH:
676 		byte		curveType
677 		uint16		namedCurve
678 		uint8		ecPointLen		-- NB uint8 not uint16
679 		byte[]		ecPoint
680 	  [	byte		hashAlgoID		-- TLS 1.2 ]
681 	  [	byte		sigAlgoID		-- TLS 1.2 ]
682 		uint16		signatureLen
683 		byte[]		signature */
684 
685 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
createServerKeyex(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,INOUT STREAM * stream,const BOOLEAN isPSK)686 static int createServerKeyex( INOUT SESSION_INFO *sessionInfoPtr,
687 							  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
688 							  INOUT STREAM *stream, const BOOLEAN isPSK )
689 	{
690 	KEYAGREE_PARAMS keyAgreeParams;
691 	void *keyData;
692 	int keyDataOffset, keyDataLength, status;
693 
694 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
695 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
696 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
697 
698 	/* Perform phase 1 of the DH/ECDH key agreement process */
699 	memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
700 	status = krnlSendMessage( handshakeInfo->dhContext, IMESSAGE_CTX_ENCRYPT,
701 							  &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
702 	if( cryptStatusError( status ) )
703 		{
704 		zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
705 		return( status );
706 		}
707 
708 	/* Write an empty PSK identity hint (whatever that's supposed to be) if
709 	   it's a PSK suite.  Perhaps we should always write "nan-demo
710 	   kaimasen" */
711 	if( isPSK )
712 		{
713 		status = writeUint16( stream, 0 );
714 		if( cryptStatusError( status ) )
715 			{
716 			zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
717 			return( status );
718 			}
719 		}
720 
721 	/* Write the DH/ECDH key parameters and public value */
722 	keyDataOffset = stell( stream );
723 	status = exportAttributeToStream( stream, handshakeInfo->dhContext,
724 									  CRYPT_IATTRIBUTE_KEY_SSL );
725 	if( cryptStatusOK( status ) )
726 		{
727 		if( isEccAlgo( handshakeInfo->keyexAlgo ) )
728 			{
729 			sputc( stream, keyAgreeParams.publicValueLen );
730 			status = swrite( stream, keyAgreeParams.publicValue,
731 							 keyAgreeParams.publicValueLen );
732 			}
733 		else
734 			{
735 			status = writeInteger16U( stream, keyAgreeParams.publicValue,
736 									  keyAgreeParams.publicValueLen );
737 			}
738 		}
739 	if( cryptStatusError( status ) )
740 		{
741 		zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
742 		return( status );
743 		}
744 	keyDataLength = stell( stream ) - keyDataOffset;
745 
746 	/* If we're using a PSK suite then the exchange is authenticated via the
747 	   PSK and we're done */
748 	if( isPSK )
749 		{
750 		zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
751 		return( CRYPT_OK );
752 		}
753 
754 	/* Non-PSK suites authenticate the exchange by signing it */
755 	status = sMemGetDataBlockAbs( stream, keyDataOffset, &keyData,
756 								  keyDataLength );
757 	if( cryptStatusOK( status ) )
758 		{
759 		ANALYSER_HINT( keyData != NULL );
760 
761 		INJECT_FAULT( SESSION_BADSIG_DATA, SESSION_BADSIG_DATA_SSL_1 );
762 		status = createKeyexSignature( sessionInfoPtr, handshakeInfo, stream,
763 									   keyData, keyDataLength );
764 		INJECT_FAULT( SESSION_BADSIG_DATA, SESSION_BADSIG_DATA_SSL_2 );
765 		}
766 	zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
767 
768 	return( status );
769 	}
770 
771 /****************************************************************************
772 *																			*
773 *							Server-side Connect Functions					*
774 *																			*
775 ****************************************************************************/
776 
777 /* Perform the initial part of the handshake with the client */
778 
779 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
beginServerHandshake(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo)780 int beginServerHandshake( INOUT SESSION_INFO *sessionInfoPtr,
781 						  INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
782 	{
783 	STREAM *stream = &handshakeInfo->stream;
784 	SCOREBOARD_INFO scoreboardInfo DUMMY_INIT_STRUCT;
785 	MESSAGE_DATA msgData;
786 	int length, resumedSessionID = CRYPT_ERROR;
787 	int packetOffset, status;
788 
789 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
790 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
791 
792 	/* Read and process the client hello */
793 	status = readHSPacketSSL( sessionInfoPtr, handshakeInfo, &length,
794 							  SSL_MSG_FIRST_HANDSHAKE );
795 	if( cryptStatusError( status ) )
796 		return( status );
797 	sMemConnect( stream, sessionInfoPtr->receiveBuffer, length );
798 #ifdef ALLOW_SSLV2_HELLO		/* See warning in ssl.h */
799 	if( handshakeInfo->isSSLv2 )
800 		{
801 		int processHelloSSLv2( SESSION_INFO *sessionInfoPtr,
802 							   SSL_HANDSHAKE_INFO *handshakeInfo,
803 							   STREAM *stream );
804 
805 		status = processHelloSSLv2( sessionInfoPtr, handshakeInfo, stream );
806 		}
807 	else
808 #endif /* ALLOW_SSLV2_HELLO */
809 	status = processHelloSSL( sessionInfoPtr, handshakeInfo, stream, TRUE );
810 	sMemDisconnect( stream );
811 	if( cryptStatusError( status ) )
812 		{
813 		BYTE sessionIDbuffer[ KEYID_SIZE + 8 ];
814 		const BYTE *sessionIDptr = handshakeInfo->sessionID;
815 		int sessionIDlength = handshakeInfo->sessionIDlength;
816 
817 		if( status != OK_SPECIAL )
818 			return( status );
819 
820 		/* If there's an SNI present, update the session ID to include it */
821 		if( handshakeInfo->hashedSNIpresent )
822 			{
823 			status = convertSNISessionID( handshakeInfo, sessionIDbuffer,
824 										  KEYID_SIZE );
825 			if( cryptStatusError( status ) )
826 				return( status );
827 			sessionIDptr = sessionIDbuffer;
828 			sessionIDlength = KEYID_SIZE;
829 			}
830 
831 		/* The client has sent us a sessionID in an attempt to resume a
832 		   previous session, see if it's in the session cache */
833 		resumedSessionID = \
834 			lookupScoreboardEntry( sessionInfoPtr->sessionSSL->scoreboardInfoPtr,
835 					SCOREBOARD_KEY_SESSIONID_SVR, sessionIDptr, sessionIDlength,
836 					&scoreboardInfo );
837 #ifdef CONFIG_SUITEB_TESTS
838 		resumedSessionID = CRYPT_ERROR;	/* Disable for Suite B tests */
839 #endif /* CONFIG_SUITEB_TESTS */
840 		}
841 
842 	/* If we're fuzzing the input then we can skip all data writes to
843 	   minimise the overhead during fuzz testing */
844 	FUZZ_SKIP();
845 
846 	/* Handle session resumption.  If it's a new session or the session data
847 	   has expired from the cache, generate a new session ID */
848 	if( cryptStatusError( resumedSessionID ) )
849 		{
850 		setMessageData( &msgData, handshakeInfo->sessionID, SESSIONID_SIZE );
851 		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
852 								  IMESSAGE_GETATTRIBUTE_S, &msgData,
853 								  CRYPT_IATTRIBUTE_RANDOM_NONCE );
854 		if( cryptStatusError( status ) )
855 			return( status );
856 		handshakeInfo->sessionIDlength = SESSIONID_SIZE;
857 		}
858 	else
859 		{
860 		/* We're resuming a previous session, if extended TLS facilities were
861 		   in use then make sure that the resumed session uses the same
862 		   facilities */
863 		if( ( sessionInfoPtr->protocolFlags & \
864 			  SSL_RESUMEDSESSION_FLAGS ) != scoreboardInfo.metaData )
865 			{
866 			DEBUG_PRINT(( "Session with options %x was resumed with "
867 						  "options %x.\n", scoreboardInfo.metaData,
868 						  sessionInfoPtr->protocolFlags & \
869 							SSL_RESUMEDSESSION_FLAGS ));
870 			return( CRYPT_ERROR_INVALID );
871 			}
872 
873 		/* Remember the premaster secret for the resumed session */
874 		status = attributeCopyParams( handshakeInfo->premasterSecret,
875 									  SSL_SECRET_SIZE,
876 									  &handshakeInfo->premasterSecretSize,
877 									  scoreboardInfo.data,
878 									  scoreboardInfo.dataSize );
879 		ENSURES( cryptStatusOK( status ) );
880 		}
881 
882 	/* Get the nonce that's used to randomise all crypto operations and set
883 	   up the server DH/ECDH context if necessary */
884 	setMessageData( &msgData, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
885 	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
886 							  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
887 	if( cryptStatusOK( status ) && isKeyxAlgo( handshakeInfo->keyexAlgo ) )
888 		{
889 		status = initDHcontextSSL( &handshakeInfo->dhContext, NULL, 0,
890 							( handshakeInfo->authAlgo != CRYPT_ALGO_NONE ) ? \
891 								sessionInfoPtr->privateKey : CRYPT_UNUSED,
892 							isEccAlgo( handshakeInfo->keyexAlgo ) ? \
893 								handshakeInfo->eccCurveID : CRYPT_ECCCURVE_NONE );
894 		}
895 	if( cryptStatusError( status ) )
896 		return( status );
897 
898 	/* Build the server hello, certificate, optional certificate request,
899 	   and done packets:
900 
901 		byte		ID = SSL_HAND_SERVER_HELLO
902 		uint24		len
903 		byte[2]		version = { 0x03, 0x0n }
904 		byte[32]	nonce
905 		byte		sessIDlen
906 		byte[]		sessID
907 		uint16		suite
908 		byte		copr = 0
909 	  [	uint16	extListLen		-- RFC 3546/RFC 4366
910 			byte	extType
911 			uint16	extLen
912 			byte[]	extData ]
913 		...
914 
915 	   We have to be careful how we handle extensions because the RFC makes
916 	   the rather optimistic assumption that implementations can handle the
917 	   presence of unexpected data at the end of the hello packet, to avoid
918 	   problems with this we avoid sending extensions unless they're in
919 	   response to extensions already sent by the client */
920 	status = openPacketStreamSSL( stream, sessionInfoPtr, CRYPT_USE_DEFAULT,
921 								  SSL_MSG_HANDSHAKE );
922 	if( cryptStatusError( status ) )
923 		return( status );
924 	status = continueHSPacketStream( stream, SSL_HAND_SERVER_HELLO,
925 									 &packetOffset );
926 	if( cryptStatusError( status ) )
927 		{
928 		sMemDisconnect( stream );
929 		return( status );
930 		}
931 	sputc( stream, SSL_MAJOR_VERSION );
932 	sputc( stream, sessionInfoPtr->version );
933 	swrite( stream, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
934 	sputc( stream, handshakeInfo->sessionIDlength );
935 	swrite( stream, handshakeInfo->sessionID,
936 			handshakeInfo->sessionIDlength );
937 	INJECT_FAULT( SESSION_CORRUPT_HANDSHAKE, SESSION_CORRUPT_HANDSHAKE_SSL_1 );
938 	writeUint16( stream, handshakeInfo->cipherSuite );
939 	status = sputc( stream, 0 );	/* No compression */
940 	if( cryptStatusOK( status ) && handshakeInfo->hasExtensions )
941 		status = writeServerExtensions( stream, handshakeInfo );
942 	if( cryptStatusOK( status ) )
943 		status = completeHSPacketStream( stream, packetOffset );
944 	if( cryptStatusError( status ) )
945 		{
946 		sMemDisconnect( stream );
947 		return( status );
948 		}
949 
950 	/* If it's a resumed session then the server hello is followed
951 	   immediately by the change cipherspec, which is sent by the shared
952 	   handshake completion code */
953 	if( !cryptStatusError( resumedSessionID ) )
954 		{
955 		status = completePacketStreamSSL( stream, 0 );
956 		if( cryptStatusOK( status ) )
957 			status = hashHSPacketWrite( handshakeInfo, stream, 0 );
958 		if( cryptStatusError( status ) )
959 			{
960 			sMemDisconnect( stream );
961 			return( status );
962 			}
963 
964 		/* Tell the caller that it's a resumed session, leaving the stream
965 		   open in order to write the change cipherspec message that follows
966 		   the server hello in a resumed session */
967 		DEBUG_PRINT(( "Resuming session with client based on "
968 					  "sessionID = \n" ));
969 		DEBUG_DUMP_DATA( handshakeInfo->sessionID,
970 						 handshakeInfo->sessionIDlength );
971 		return( OK_SPECIAL );
972 		}
973 
974 	/*	...	(optional server supplemental data)
975 		byte		ID = SSL_HAND_SUPPLEMENTAL_DATA
976 		uint24		len
977 		uint16		type
978 		uint16		len
979 		byte[]		value
980 		... */
981 
982 	/*	...
983 		(optional server certificate chain)
984 		... */
985 	if( handshakeInfo->authAlgo != CRYPT_ALGO_NONE )
986 		{
987 		INJECT_FAULT( SESSION_WRONGCERT, SESSION_WRONGCERT_SSL_1 );
988 		status = writeSSLCertChain( sessionInfoPtr, stream );
989 		if( cryptStatusError( status ) )
990 			{
991 			sMemDisconnect( stream );
992 			return( status );
993 			}
994 		INJECT_FAULT( SESSION_WRONGCERT, SESSION_WRONGCERT_SSL_2 );
995 		}
996 
997 	/*	...			(optional server keyex) */
998 	if( isKeyxAlgo( handshakeInfo->keyexAlgo ) )
999 		{
1000 		status = continueHSPacketStream( stream, SSL_HAND_SERVER_KEYEXCHANGE,
1001 										 &packetOffset );
1002 		if( cryptStatusOK( status ) )
1003 			{
1004 			status = createServerKeyex( sessionInfoPtr, handshakeInfo, stream,
1005 							( handshakeInfo->authAlgo == CRYPT_ALGO_NONE ) ? \
1006 								TRUE : FALSE );
1007 			}
1008 		if( cryptStatusOK( status ) )
1009 			status = completeHSPacketStream( stream, packetOffset );
1010 		if( cryptStatusError( status ) )
1011 			{
1012 			sMemDisconnect( stream );
1013 			return( status );
1014 			}
1015 		}
1016 
1017 	/*	...			(optional request for client certificate authentication)
1018 		byte		ID = SSL_HAND_SERVER_CERTREQUEST
1019 		uint24		len
1020 		byte		certTypeLen
1021 		byte[]		certType = { RSA, DSA, ECDSA }
1022 	  [	uint16	sigHashListLen		-- TLS 1.2 ]
1023 	  [		byte	hashAlgoID		-- TLS 1.2 ]
1024 	  [		byte	sigAlgoID		-- TLS 1.2 ]
1025 		uint16		caNameListLen = 4
1026 			uint16	caNameLen = 2
1027 			byte[]	caName = { 0x30, 0x00 }
1028 		... */
1029 	if( clientCertAuthRequired( sessionInfoPtr ) )
1030 		{
1031 		status = continueHSPacketStream( stream, SSL_HAND_SERVER_CERTREQUEST,
1032 										 &packetOffset );
1033 		if( cryptStatusError( status ) )
1034 			{
1035 			sMemDisconnect( stream );
1036 			return( status );
1037 			}
1038 		status = writeCertRequest( sessionInfoPtr, stream );
1039 		if( cryptStatusOK( status ) )
1040 			status = completeHSPacketStream( stream, packetOffset );
1041 		if( cryptStatusError( status ) )
1042 			{
1043 			sMemDisconnect( stream );
1044 			return( status );
1045 			}
1046 		}
1047 
1048 	/*	...
1049 		byte		ID = SSL_HAND_SERVER_HELLODONE
1050 		uint24		len = 0 */
1051 	status = continueHSPacketStream( stream, SSL_HAND_SERVER_HELLODONE,
1052 									 &packetOffset );
1053 	if( cryptStatusOK( status ) )
1054 		status = completeHSPacketStream( stream, packetOffset );
1055 	if( cryptStatusError( status ) )
1056 		{
1057 		sMemDisconnect( stream );
1058 		return( status );
1059 		}
1060 
1061 	/* Send the combined server packets to the client.  We perform the
1062 	   assorted hashing of the packets in between the network ops where
1063 	   it's effectively free */
1064 	status = sendPacketSSL( sessionInfoPtr, stream, FALSE );
1065 	INJECT_FAULT( SESSION_CORRUPT_HANDSHAKE, SESSION_CORRUPT_HANDSHAKE_SSL_2 );
1066 	if( cryptStatusOK( status ) )
1067 		status = hashHSPacketWrite( handshakeInfo, stream, 0 );
1068 	sMemDisconnect( stream );
1069 	return( status );
1070 	}
1071 
1072 /* Exchange keys with the client */
1073 
1074 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
exchangeServerKeys(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo)1075 int exchangeServerKeys( INOUT SESSION_INFO *sessionInfoPtr,
1076 						INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
1077 	{
1078 	STREAM *stream = &handshakeInfo->stream;
1079 	int length, status;
1080 
1081 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1082 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1083 
1084 	/* Read the response from the client and, if we're expecting a client
1085 	   certificate, make sure that it's present */
1086 	status = readHSPacketSSL( sessionInfoPtr, handshakeInfo, &length,
1087 							  SSL_MSG_HANDSHAKE );
1088 	if( cryptStatusError( status ) )
1089 		return( status );
1090 	sMemConnect( stream, sessionInfoPtr->receiveBuffer, length );
1091 	if( clientCertAuthRequired( sessionInfoPtr ) )
1092 		{
1093 		/* Read the client certificate chain and make sure that the
1094 		   certificate being presented is valid for access */
1095 		status = readCheckClientCerts( sessionInfoPtr, handshakeInfo,
1096 									   stream );
1097 		if( cryptStatusError( status ) )
1098 			{
1099 			sMemDisconnect( stream );
1100 			return( status );
1101 			}
1102 
1103 		/* Read the next packet(s) if necessary */
1104 		status = refreshHSStream( sessionInfoPtr, handshakeInfo );
1105 		if( cryptStatusError( status ) )
1106 			return( status );
1107 		}
1108 
1109 	/* Process the client key exchange packet */
1110 	status = processClientKeyex( sessionInfoPtr, handshakeInfo, stream,
1111 								 isKeyxAlgo( handshakeInfo->keyexAlgo ) ? \
1112 									TRUE : FALSE,
1113 								 ( handshakeInfo->authAlgo == CRYPT_ALGO_NONE ) ? \
1114 									TRUE : FALSE );
1115 	if( cryptStatusError( status ) )
1116 		{
1117 		sMemDisconnect( stream );
1118 		return( status );
1119 		}
1120 
1121 	/* Create the session hash if required */
1122 	if( ( sessionInfoPtr->protocolFlags & SSL_PFLAG_EMS ) || \
1123 		clientCertAuthRequired( sessionInfoPtr ) )
1124 		{
1125 		status = createSessionHash( sessionInfoPtr, handshakeInfo );
1126 		if( cryptStatusError( status ) )
1127 			return( status );
1128 		}
1129 
1130 	/* If we're expecting a client certificate, process the client
1131 	   certificate verify */
1132 	if( clientCertAuthRequired( sessionInfoPtr ) )
1133 		{
1134 		const BOOLEAN isECC = isEccAlgo( handshakeInfo->keyexAlgo );
1135 
1136 		/* Read the next packet(s) if necessary */
1137 		status = refreshHSStream( sessionInfoPtr, handshakeInfo );
1138 		if( cryptStatusError( status ) )
1139 			return( status );
1140 
1141 		/* Process the client certificate verify packet:
1142 
1143 			byte		ID = SSL_HAND_CLIENT_CERTVERIFY
1144 			uint24		len
1145 			byte[]		signature */
1146 		status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
1147 									  SSL_HAND_CLIENT_CERTVERIFY,
1148 									  isECC ? MIN_PKCSIZE_ECCPOINT : \
1149 											  MIN_PKCSIZE );
1150 		if( cryptStatusOK( status ) )
1151 			status = checkCertVerify( sessionInfoPtr, handshakeInfo, stream,
1152 									  length );
1153 		if( cryptStatusError( status ) )
1154 			{
1155 			sMemDisconnect( stream );
1156 			return( status );
1157 			}
1158 		}
1159 	sMemDisconnect( stream );
1160 
1161 	return( CRYPT_OK );
1162 	}
1163 
1164 /****************************************************************************
1165 *																			*
1166 *							Session Access Routines							*
1167 *																			*
1168 ****************************************************************************/
1169 
1170 STDC_NONNULL_ARG( ( 1 ) ) \
initSSLserverProcessing(SSL_HANDSHAKE_INFO * handshakeInfo)1171 void initSSLserverProcessing( SSL_HANDSHAKE_INFO *handshakeInfo )
1172 	{
1173 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1174 
1175 	FNPTR_SET( handshakeInfo->beginHandshake, beginServerHandshake );
1176 	FNPTR_SET( handshakeInfo->exchangeKeys, exchangeServerKeys );
1177 	}
1178 #endif /* USE_SSL */
1179