1 /****************************************************************************
2 *																			*
3 *					cryptlib SSL v3/TLS Session Management					*
4 *					   Copyright Peter Gutmann 1998-2014					*
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 *								Utility Functions							*
25 *																			*
26 ****************************************************************************/
27 
28 #if defined( __WIN32__ ) && !defined( NDEBUG )
29 
30 /* Dump a message to disk for diagnostic purposes.  The SSL messages are
31    broken up into parts by the read/write code so that we can't use the
32    normal DEBUG_DUMP() macro but have to use a special-purpose function that
33    assembles the packet contents if required, as well as providing
34    appropriate naming */
35 
36 STDC_NONNULL_ARG( ( 1 ) ) \
debugDumpSSL(const SESSION_INFO * sessionInfoPtr,IN_BUFFER_OPT (buffer1size)const void * buffer1,IN_LENGTH_SHORT const int buffer1size,IN_BUFFER_OPT (buffer2size)const void * buffer2,IN_LENGTH_SHORT_Z const int buffer2size)37 void debugDumpSSL( const SESSION_INFO *sessionInfoPtr,
38 				   IN_BUFFER_OPT( buffer1size ) const void *buffer1,
39 				   IN_LENGTH_SHORT const int buffer1size,
40 				   IN_BUFFER_OPT( buffer2size ) const void *buffer2,
41 				   IN_LENGTH_SHORT_Z const int buffer2size )
42 	{
43 	FILE *filePtr;
44 	static int messageCount = 1;
45 	const BYTE *bufPtr = buffer1;
46 	const BOOLEAN isRead = ( buffer2 != NULL ) ? TRUE : FALSE;
47 	const BOOLEAN encryptionActive = \
48 		( isRead && ( sessionInfoPtr->flags & SESSION_ISSECURE_READ ) ) || \
49 		( !isRead && ( sessionInfoPtr->flags & SESSION_ISSECURE_WRITE ) );
50 	char fileName[ 1024 + 8 ];
51 
52 	assert( isReadPtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
53 	assert( isReadPtr( buffer1,  buffer1size ) );
54 	assert( ( buffer2 == NULL && buffer2size == 0 ) || \
55 			isReadPtr( buffer2, buffer2size ) );
56 
57 	if( messageCount > 20 )
58 		return;	/* Don't dump too many messages */
59 	strlcpy_s( fileName, 1024, "/tmp/" );
60 	sprintf_s( &fileName[ 5 ], 1024, "tls3%d_%02d%c_",
61 			   sessionInfoPtr->version, messageCount++,
62 			   isRead ? 'r' : 'w' );
63 	if( bufPtr[ 0 ] == SSL_MSG_HANDSHAKE && !encryptionActive )
64 		{
65 		if( isRead && buffer2size >= 1 )
66 			{
67 			strlcat_s( fileName, 1024,
68 					   getSSLHSPacketName( ( ( BYTE * ) buffer2 )[ 0 ] ) );
69 			}
70 		else
71 			{
72 			if( !isRead && buffer1size >= 6 )
73 				{
74 				strlcat_s( fileName, 1024,
75 						   getSSLHSPacketName( bufPtr[ 5 ] ) );
76 				}
77 			else
78 				strlcat_s( fileName, 1024, "truncated_packet" );
79 			}
80 		}
81 	else
82 		strlcat_s( fileName, 1024, getSSLPacketName( bufPtr[ 0 ] ) );
83 	strlcat_s( fileName, 1024, ".dat" );
84 
85 #ifdef __STDC_LIB_EXT1__
86 	if( fopen_s( &filePtr, fileName, "wb" ) != 0 )
87 		filePtr = NULL;
88 #else
89 	filePtr = fopen( fileName, "wb" );
90 #endif /* __STDC_LIB_EXT1__ */
91 	if( filePtr != NULL )
92 		{
93 		fwrite( buffer1, 1, buffer1size, filePtr );
94 		if( buffer2 != NULL )
95 			fwrite( buffer2, 1, buffer2size, filePtr );
96 		fclose( filePtr );
97 		}
98 	}
99 #endif /* Windows debug mode only */
100 
101 /* Initialise and destroy the handshake state information */
102 
103 STDC_NONNULL_ARG( ( 1 ) ) \
destroyHandshakeInfo(INOUT SSL_HANDSHAKE_INFO * handshakeInfo)104 static void destroyHandshakeInfo( INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
105 	{
106 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
107 
108 	/* Destroy any active contexts.  We need to do this here (even though
109 	   it's also done in the general session code) to provide a clean exit in
110 	   case the session activation fails, so that a second activation attempt
111 	   doesn't overwrite still-active contexts */
112 	destroyHandshakeCryptInfo( handshakeInfo );
113 
114 	zeroise( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) );
115 	}
116 
117 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
initHandshakeInfo(INOUT SESSION_INFO * sessionInfoPtr,OUT_ALWAYS SSL_HANDSHAKE_INFO * handshakeInfo,const BOOLEAN isServer)118 static int initHandshakeInfo( INOUT SESSION_INFO *sessionInfoPtr,
119 							  OUT_ALWAYS SSL_HANDSHAKE_INFO *handshakeInfo,
120 							  const BOOLEAN isServer )
121 	{
122 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
123 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
124 
125 	memset( handshakeInfo, 0, sizeof( SSL_HANDSHAKE_INFO ) );
126 	if( isServer )
127 		initSSLserverProcessing( handshakeInfo );
128 	else
129 		initSSLclientProcessing( handshakeInfo );
130 	handshakeInfo->originalVersion = sessionInfoPtr->version;
131 	return( initHandshakeCryptInfo( sessionInfoPtr, handshakeInfo ) );
132 	}
133 
134 /* Push and pop the handshake state */
135 
136 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
pushHandshakeInfo(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo)137 static int pushHandshakeInfo( INOUT SESSION_INFO *sessionInfoPtr,
138 							  INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
139 	{
140 	SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
141 	const int bufPos = sessionInfoPtr->sendBufSize - \
142 					   sizeof( SSL_HANDSHAKE_INFO );
143 
144 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
145 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
146 
147 	/* Save the handshake state so that we can resume the handshake later
148 	   on.  This is somewhat ugly in that we need to store
149 	   sizeof( SSL_HANDSHAKE_INFO ) bytes of data somewhere, one way to do
150 	   this would be to allocate memory, use it for storage, and free it
151 	   again, however we have the send buffer sitting there unused so we
152 	   save it at the end of the send buffer.
153 
154 	   This creates the slight problem that we're saving the premaster
155 	   secret in the send buffer and potentially exposing it to a bug in
156 	   the send code, however it would have to be a pretty unusual bug to
157 	   jump into the send function and then write a block of data all the
158 	   way at the end of the buffer, far past where a handshake packet would
159 	   be, to the peer */
160 	REQUIRES( bufPos > 1024 && bufPos < sessionInfoPtr->sendBufSize - 512 );
161 	sslInfo->savedHandshakeInfo = sessionInfoPtr->sendBuffer + bufPos;
162 	memcpy( sslInfo->savedHandshakeInfo, handshakeInfo,
163 			sizeof( SSL_HANDSHAKE_INFO ) );
164 
165 	/* Clear the original copy of the handshake info (without doing a full
166 	   cleanup of objects and so on), which leaves the copy intact */
167 	zeroise( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) );
168 
169 	return( CRYPT_OK );
170 	}
171 
172 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
popHandshakeInfo(INOUT SESSION_INFO * sessionInfoPtr,OUT SSL_HANDSHAKE_INFO * handshakeInfo)173 static int popHandshakeInfo( INOUT SESSION_INFO *sessionInfoPtr,
174 							 OUT SSL_HANDSHAKE_INFO *handshakeInfo )
175 	{
176 	SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
177 
178 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
179 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
180 
181 	/* Restore the saved handshake state so that we can continue a partially-
182 	   completed handshake */
183 	REQUIRES( sslInfo->savedHandshakeInfo != NULL );
184 	memcpy( handshakeInfo, sslInfo->savedHandshakeInfo,
185 			sizeof( SSL_HANDSHAKE_INFO ) );
186 	zeroise( sslInfo->savedHandshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) );
187 	sslInfo->savedHandshakeInfo = NULL;
188 
189 	return( CRYPT_OK );
190 	}
191 
192 /* SSL uses 24-bit lengths in some places even though the maximum packet
193    length is only 16 bits (actually it's limited even further by the spec
194    to 14 bits).  To handle this odd length we define our own read/
195    writeUint24() functions that always set the high byte to zero */
196 
197 CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \
readUint24(INOUT STREAM * stream)198 int readUint24( INOUT STREAM *stream )
199 	{
200 	int status;
201 
202 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
203 
204 	status = sgetc( stream );
205 	if( cryptStatusError( status ) )
206 		return( status );
207 	if( status != 0 )
208 		return( sSetError( stream, CRYPT_ERROR_BADDATA ) );
209 	return( readUint16( stream ) );
210 	}
211 
212 STDC_NONNULL_ARG( ( 1 ) ) \
writeUint24(INOUT STREAM * stream,IN_LENGTH_Z const int length)213 int writeUint24( INOUT STREAM *stream, IN_LENGTH_Z const int length )
214 	{
215 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
216 
217 	REQUIRES_S( length >= 0 && \
218 				length < MAX_PACKET_SIZE + EXTRA_PACKET_SIZE );
219 
220 	sputc( stream, 0 );
221 	return( writeUint16( stream, length ) );
222 	}
223 
224 /* The ECDH public value is a bit complex to process because it's the usual
225    X9.62 stuff-point-data-into-a-byte-string value, and to make things even
226    messier it's stored with an 8-bit length instead of a 16-bit one so we
227    can't even read it as an integer16U().  To work around this we have to
228    duplicate a certain amount of the integer-read code here */
229 
230 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
231 int readEcdhValue( INOUT STREAM *stream,
232 				   OUT_BUFFER( valueMaxLen, *valueLen ) void *value,
233 				   IN_LENGTH_SHORT_MIN( 64 ) const int valueMaxLen,
234 				   OUT_LENGTH_BOUNDED_Z( valueMaxLen ) int *valueLen )
235 	{
236 	int length, status;
237 
238 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
239 	assert( isWritePtr( value, valueMaxLen ) );
240 	assert( isWritePtr( valueLen, sizeof( int ) ) );
241 
242 	REQUIRES( valueMaxLen >= 64 && valueMaxLen < MAX_INTLENGTH_SHORT );
243 
244 	/* Clear return value */
245 	memset( value, 0, min( 16, valueMaxLen ) );
246 	*valueLen = 0;
247 
248 
249 	/* Get the length (as a byte) and make sure that it's valid */
250 	status = length = sgetc( stream );
251 	if( cryptStatusError( status ) )
252 		return( status );
253 	if( isShortECCKey( length / 2 ) )
254 		return( CRYPT_ERROR_NOSECURE );
255 	if( length < MIN_PKCSIZE_ECCPOINT || length > MAX_PKCSIZE_ECCPOINT )
256 		return( CRYPT_ERROR_BADDATA );
257 	*valueLen = length;
258 
259 	/* Read the X9.62 point value */
260 	return( sread( stream, value, length ) );
261 	}
262 
263 /* Abort a session startup */
264 
265 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
abortStartup(INOUT SESSION_INFO * sessionInfoPtr,INOUT_OPT SSL_HANDSHAKE_INFO * handshakeInfo,const BOOLEAN cleanupSecurityContexts,IN_ERROR const int status)266 static int abortStartup( INOUT SESSION_INFO *sessionInfoPtr,
267 						 INOUT_OPT SSL_HANDSHAKE_INFO *handshakeInfo,
268 						 const BOOLEAN cleanupSecurityContexts,
269 						 IN_ERROR const int status )
270 	{
271 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
272 	assert( handshakeInfo == NULL || \
273 			isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
274 
275 	REQUIRES( cryptStatusError( status ) );
276 
277 	sendHandshakeFailAlert( sessionInfoPtr,
278 							( handshakeInfo != NULL && \
279 							  handshakeInfo->failAlertType != 0 ) ? \
280 								handshakeInfo->failAlertType : \
281 								SSL_ALERT_HANDSHAKE_FAILURE );
282 	if( cleanupSecurityContexts )
283 		destroySecurityContextsSSL( sessionInfoPtr );
284 	if( handshakeInfo != NULL )
285 		destroyHandshakeInfo( handshakeInfo );
286 	sNetDisconnect( &sessionInfoPtr->stream );
287 	return( status );
288 	}
289 
290 #ifdef CONFIG_SUITEB
291 
292 /* Check that a private key is valid for Suite B use */
293 
294 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
checkSuiteBKey(INOUT SESSION_INFO * sessionInfoPtr,IN_HANDLE const CRYPT_CONTEXT cryptContext,IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo)295 static int checkSuiteBKey( INOUT SESSION_INFO *sessionInfoPtr,
296 						   IN_HANDLE const CRYPT_CONTEXT cryptContext,
297 						   IN_ALGO const CRYPT_ALGO_TYPE cryptAlgo )
298 	{
299 	int keySize, status;
300 
301 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
302 
303 	REQUIRES( isPkcAlgo( cryptAlgo ) );
304 
305 	/* Suite B only allows P256 and P384 keys so we need to make sure that
306 	   the server key is of the appropriate type and size */
307 	if( cryptAlgo != CRYPT_ALGO_ECDSA )
308 		{
309 		setErrorInfo( sessionInfoPtr, CRYPT_CTXINFO_ALGO,
310 					  CRYPT_ERRTYPE_ATTR_VALUE );
311 		return( CRYPT_ARGERROR_NUM1 );
312 		}
313 	status = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE, &keySize,
314 							  CRYPT_CTXINFO_KEYSIZE );
315 	if( cryptStatusError( status ) )
316 		return( status );
317 #ifdef CONFIG_SUITEB_TESTS
318 	if( suiteBTestValue == SUITEB_TEST_SVRINVALIDCURVE && \
319 		keySize == bitsToBytes( 521 ) )
320 		return( CRYPT_OK );
321 #endif /* CONFIG_SUITEB_TESTS */
322 	if( keySize != bitsToBytes( 256 ) && keySize != bitsToBytes( 384 ) )
323 		{
324 		setErrorInfo( sessionInfoPtr, CRYPT_CTXINFO_KEYSIZE,
325 					  CRYPT_ERRTYPE_ATTR_VALUE );
326 		return( CRYPT_ARGERROR_NUM1 );
327 		}
328 
329 	/* In addition if a specific crypto strength has been configured then
330 	   the key size has to correspond to that strength.  At 128 bits we can
331 	   use both P256 and P384, but at 256 bits we have to use P384 */
332 	if( ( ( sessionInfoPtr->protocolFlags & \
333 						SSL_PFLAG_SUITEB ) == SSL_PFLAG_SUITEB_256 ) && \
334 		keySize != bitsToBytes( 384 ) )
335 		{
336 		setErrorInfo( sessionInfoPtr, CRYPT_CTXINFO_KEYSIZE,
337 					  CRYPT_ERRTYPE_ATTR_VALUE );
338 		return( CRYPT_ARGERROR_NUM1 );
339 		}
340 
341 	return( CRYPT_OK );
342 	}
343 
344 #ifdef CONFIG_SUITEB_TESTS
345 
346 /* Special kludge function used to enable nonstandard behaviour for Suite
347    B tests.  The magic value is used in appropriate locations to enable
348    nonstandard behaviour for testing purposes.  The values are listed in
349    ssl.h */
350 
351 SUITEB_TEST_VALUE suiteBTestValue = SUITEB_TEST_NONE;
352 BOOLEAN suiteBTestClientCert = FALSE;
353 
sslSuiteBTestConfig(const int magicValue)354 int sslSuiteBTestConfig( const int magicValue )
355 	{
356 	REQUIRES( ( magicValue >= SUITEB_TEST_NONE && \
357 				magicValue < SUITEB_TEST_LAST ) || \
358 			  magicValue == 1000 );
359 
360 	/* If it's the client-cert test indicator, set the flag and exit */
361 	if( magicValue == 1000 )
362 		{
363 		suiteBTestClientCert = TRUE;
364 
365 		return( CRYPT_OK );
366 		}
367 
368 	suiteBTestValue = magicValue;
369 	if( magicValue == 0 )
370 		{
371 		/* If we're doing a reset, clear the client-cert test indicator as
372 		   well */
373 		suiteBTestClientCert = FALSE;
374 		}
375 
376 	return( CRYPT_OK );
377 	}
378 #endif /* CONFIG_SUITEB_TESTS  */
379 #endif /* CONFIG_SUITEB */
380 
381 /****************************************************************************
382 *																			*
383 *						Read/Write SSL/TLS Certificate Chains				*
384 *																			*
385 ****************************************************************************/
386 
387 /* Read/write an SSL/TLS certificate chain:
388 
389 	byte		ID = SSL_HAND_CERTIFICATE
390 	uint24		len
391 	uint24		certListLen
392 	uint24		certLen			| 1...n certificates ordered
393 	byte[]		certificate		|   leaf -> root */
394 
395 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4 ) ) \
readSSLCertChain(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,INOUT STREAM * stream,OUT_HANDLE_OPT CRYPT_CERTIFICATE * iCertChain,const BOOLEAN isServer)396 int readSSLCertChain( INOUT SESSION_INFO *sessionInfoPtr,
397 					  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
398 					  INOUT STREAM *stream,
399 					  OUT_HANDLE_OPT CRYPT_CERTIFICATE *iCertChain,
400 					  const BOOLEAN isServer )
401 	{
402 	CRYPT_CERTIFICATE iLocalCertChain;
403 	const ATTRIBUTE_LIST *fingerprintPtr = \
404 				findSessionInfo( sessionInfoPtr->attributeList,
405 								 CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1 );
406 	MESSAGE_DATA msgData;
407 	BYTE certFingerprint[ CRYPT_MAX_HASHSIZE + 8 ];
408 #ifdef USE_ERRMSGS
409 	const char *peerTypeName = isServer ? "Client" : "Server";
410 #endif /* USE_ERRMSGS */
411 #ifdef CONFIG_SUITEB
412 	const char *requiredLengthString = NULL;
413 #endif /* CONFIG_SUITEB */
414 	int certAlgo, certFingerprintLength, chainLength, length, status;
415 
416 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
417 	assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
418 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
419 	assert( isWritePtr( iCertChain, sizeof( CRYPT_CERTIFICATE ) ) );
420 
421 	/* Clear return value */
422 	*iCertChain = CRYPT_ERROR;
423 
424 	/* Make sure that the packet header is in order */
425 	status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
426 								  SSL_HAND_CERTIFICATE,
427 								  isServer ? 0 : LENGTH_SIZE + MIN_CERTSIZE );
428 	if( cryptStatusError( status ) )
429 		return( status );
430 	if( isServer && ( length == 0 || length == LENGTH_SIZE ) )
431 		{
432 		/* There is one special case in which a too-short certificate packet
433 		   is valid and that's where it constitutes the TLS equivalent of an
434 		   SSL no-certificates alert.  SSLv3 sent an
435 		   SSL_ALERT_NO_CERTIFICATE alert to indicate that the client
436 		   doesn't have a certificate, which is handled by the
437 		   readHSPacketSSL() call.  TLS changed this to send an empty
438 		   certificate packet instead, supposedly because it lead to
439 		   implementation problems (presumably it's necessary to create a
440 		   state machine-based implementation to reproduce these problems,
441 		   whatever they are).  The TLS 1.0 spec is ambiguous as to what
442 		   constitutes an empty packet, it could be either a packet with a
443 		   length of zero or a packet containing a zero-length certificate
444 		   list so we check for both.  TLS 1.1 fixed this to say that that
445 		   certListLen entry has a length of zero.  To report this condition
446 		   we fake the error indicators for consistency with the status
447 		   obtained from an SSLv3 no-certificate alert */
448 		retExt( CRYPT_ERROR_PERMISSION,
449 				( CRYPT_ERROR_PERMISSION, SESSION_ERRINFO,
450 				  "Received TLS alert message: No certificate" ) );
451 		}
452 	status = chainLength = readUint24( stream );
453 	if( cryptStatusError( status ) )
454 		{
455 		retExt( CRYPT_ERROR_BADDATA,
456 				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
457 				  "Invalid certificate chain length information" ) );
458 		}
459 	if( chainLength < MIN_CERTSIZE || chainLength >= MAX_INTLENGTH_SHORT || \
460 		chainLength != length - LENGTH_SIZE )
461 		{
462 		retExt( CRYPT_ERROR_BADDATA,
463 				( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
464 				  "Invalid certificate chain length %d, should be %d",
465 				  chainLength, length - LENGTH_SIZE ) );
466 		}
467 
468 	/* Import the certificate chain.  This isn't a true certificate chain (in
469 	   the sense of being degenerate PKCS #7 SignedData) but a special-case
470 	   SSL/TLS-encoded certificate chain */
471 	status = importCertFromStream( stream, &iLocalCertChain,
472 								   DEFAULTUSER_OBJECT_HANDLE,
473 								   CRYPT_ICERTTYPE_SSL_CERTCHAIN,
474 								   chainLength, KEYMGMT_FLAG_NONE );
475 	if( cryptStatusError( status ) )
476 		{
477 		/* There are sufficient numbers of broken certificates around that
478 		   if we run into a problem importing one we provide a custom error
479 		   message telling the user to try again with a reduced compliance
480 		   level */
481 		if( status == CRYPT_ERROR_BADDATA || status == CRYPT_ERROR_INVALID )
482 			{
483 			retExt( status,
484 					( status, SESSION_ERRINFO,
485 					  "%s provided a broken/invalid certificate, try again "
486 					  "with a reduced level of certificate compliance "
487 					  "checking", peerTypeName ) );
488 			}
489 		retExt( status,
490 				( status, SESSION_ERRINFO, "Invalid certificate chain data" ) );
491 		}
492 
493 	/* Get information on the chain */
494 	status = krnlSendMessage( iLocalCertChain, IMESSAGE_GETATTRIBUTE,
495 							  &certAlgo, CRYPT_CTXINFO_ALGO );
496 	if( cryptStatusError( status ) )
497 		{
498 		krnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );
499 		return( status );
500 		}
501 	setMessageData( &msgData, certFingerprint, CRYPT_MAX_HASHSIZE );
502 	if( fingerprintPtr != NULL )
503 		{
504 		const CRYPT_ATTRIBUTE_TYPE fingerprintAttribute = \
505 							( fingerprintPtr->valueLength == 32 ) ? \
506 								CRYPT_CERTINFO_FINGERPRINT_SHA2 : \
507 							CRYPT_CERTINFO_FINGERPRINT_SHA1;
508 
509 		/* Use the hint provided by the fingerprint size to select the
510 		   appropriate algorithm to generate the fingerprint that we want
511 		   to compare against */
512 		status = krnlSendMessage( iLocalCertChain, IMESSAGE_GETATTRIBUTE_S,
513 								  &msgData, fingerprintAttribute );
514 		}
515 	else
516 		{
517 		/* There's no algorithm hint available, use the default of SHA-1 */
518 		status = krnlSendMessage( iLocalCertChain, IMESSAGE_GETATTRIBUTE_S,
519 								  &msgData, CRYPT_CERTINFO_FINGERPRINT_SHA1 );
520 		}
521 	if( cryptStatusError( status ) )
522 		{
523 		krnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );
524 		return( status );
525 		}
526 	certFingerprintLength = msgData.length;
527 	if( !isServer && certAlgo != handshakeInfo->authAlgo )
528 		{
529 		krnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );
530 		retExt( CRYPT_ERROR_WRONGKEY,
531 				( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO,
532 				  "Server key algorithm %d doesn't match negotiated "
533 				  "algorithm %d", certAlgo, handshakeInfo->authAlgo ) );
534 		}
535 
536 	/* Either compare the certificate fingerprint to a supplied one or save
537 	   it for the caller to examine */
538 	if( fingerprintPtr != NULL )
539 		{
540 		/* The caller has supplied a certificate fingerprint, compare it to
541 		   the received certificate's fingerprint to make sure that we're
542 		   talking to the right system */
543 		if( fingerprintPtr->valueLength != certFingerprintLength || \
544 			memcmp( fingerprintPtr->value, certFingerprint,
545 					certFingerprintLength ) )
546 			{
547 			krnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );
548 			retExt( CRYPT_ERROR_WRONGKEY,
549 					( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO,
550 					  "%s key didn't match key fingerprint", peerTypeName ) );
551 			}
552 		}
553 	else
554 		{
555 		/* Remember the certificate fingerprint in case the caller wants to
556 		   check it.  We don't worry if the add fails, it's a minor thing
557 		   and not worth aborting the handshake for */
558 		( void ) addSessionInfoS( &sessionInfoPtr->attributeList,
559 								  CRYPT_SESSINFO_SERVER_FINGERPRINT_SHA1,
560 								  certFingerprint, certFingerprintLength );
561 		}
562 
563 	/* Make sure that we can perform the required operation using the key
564 	   that we've been given.  For a client key we need signing capability,
565 	   for a server key when using DH/ECDH key agreement we also need
566 	   signing capability to authenticate the DH/ECDH parameters, and for
567 	   an RSA key transport key we need encryption capability.  This
568 	   operation also performs a variety of additional checks alongside the
569 	   obvious one so it's a good general health check before we go any
570 	   further */
571 	status = krnlSendMessage( iLocalCertChain, IMESSAGE_CHECK, NULL,
572 							  isServer || \
573 								isKeyxAlgo( handshakeInfo->keyexAlgo ) ? \
574 								MESSAGE_CHECK_PKC_SIGCHECK : \
575 								MESSAGE_CHECK_PKC_ENCRYPT );
576 	if( cryptStatusError( status ) )
577 		{
578 		krnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );
579 		retExt( CRYPT_ERROR_WRONGKEY,
580 				( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO,
581 				  "%s provided a key incapable of being used for %s",
582 				  peerTypeName,
583 				  isServer ? "client authentication" : \
584 				  isKeyxAlgo( certAlgo ) ? "key exchange authentication" : \
585 										    "encryption" ) );
586 		}
587 
588 	/* For ECC with Suite B there are additional constraints on the key
589 	   size */
590 #ifdef CONFIG_SUITEB
591 	status = krnlSendMessage( iLocalCertChain, IMESSAGE_GETATTRIBUTE,
592 							  &length, CRYPT_CTXINFO_KEYSIZE );
593 	if( cryptStatusError( status ) )
594 		return( status );
595 	switch( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB )
596 		{
597 		case 0:
598 			/* If we're not configured for Suite B mode then there's
599 			   nothing to check */
600 			break;
601 
602 		case SSL_PFLAG_SUITEB_128:
603 			/* 128-bit level can be P256 or P384 */
604 			if( length != bitsToBytes( 256 ) && \
605 				length != bitsToBytes( 384 ) )
606 				requiredLengthString = "256- or 384";
607 			break;
608 
609 		case SSL_PFLAG_SUITEB_256:
610 			/* 256-bit level only allows P384 */
611 			if( length != bitsToBytes( 384 ) )
612 				requiredLengthString = "384";
613 			break;
614 
615 		default:
616 			retIntError();
617 		}
618 	if( requiredLengthString != NULL )
619 		{
620 		krnlSendNotifier( iLocalCertChain, IMESSAGE_DECREFCOUNT );
621 		retExt( CRYPT_ERROR_WRONGKEY,
622 				( CRYPT_ERROR_WRONGKEY, SESSION_ERRINFO,
623 				  "%s provided a %d-bit Suite B key, should have been a "
624 				  "%s-bit key", peerTypeName, bytesToBits( length ),
625 				  requiredLengthString ) );
626 		}
627 #endif /* CONFIG_SUITEB */
628 
629 	*iCertChain = iLocalCertChain;
630 
631 	return( CRYPT_OK );
632 	}
633 
634 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
writeSSLCertChain(INOUT SESSION_INFO * sessionInfoPtr,INOUT STREAM * stream)635 int writeSSLCertChain( INOUT SESSION_INFO *sessionInfoPtr,
636 					   INOUT STREAM *stream )
637 	{
638 	int packetOffset, certListOffset DUMMY_INIT, certListEndPos, status;
639 
640 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
641 	assert( isWritePtr( stream, sizeof( STREAM ) ) );
642 
643 	status = continueHSPacketStream( stream, SSL_HAND_CERTIFICATE,
644 									 &packetOffset );
645 	if( cryptStatusError( status ) )
646 		return( status );
647 	if( sessionInfoPtr->privateKey == CRYPT_ERROR )
648 		{
649 		/* If there's no private key available, write an empty certificate
650 		   chain */
651 		status = writeUint24( stream, 0 );
652 		if( cryptStatusError( status ) )
653 			return( status );
654 		return( completeHSPacketStream( stream, packetOffset ) );
655 		}
656 
657 	/* Write a dummy length and export the certificate list to the stream */
658 	status = writeUint24( stream, 0 );
659 	if( cryptStatusOK( status ) )
660 		{
661 		certListOffset = stell( stream );
662 		status = exportCertToStream( stream, sessionInfoPtr->privateKey,
663 									 CRYPT_ICERTFORMAT_SSL_CERTCHAIN );
664 		}
665 	if( cryptStatusError( status ) )
666 		return( status );
667 	certListEndPos = stell( stream );
668 
669 	/* Go back and insert the length, then wrap up the packet */
670 	sseek( stream, certListOffset - LENGTH_SIZE );
671 	status = writeUint24( stream, certListEndPos - certListOffset );
672 	sseek( stream, certListEndPos );
673 	if( cryptStatusError( status ) )
674 		return( status );
675 	return( completeHSPacketStream( stream, packetOffset ) );
676 	}
677 
678 /****************************************************************************
679 *																			*
680 *								Init/Shutdown Functions						*
681 *																			*
682 ****************************************************************************/
683 
684 /* Close a previously-opened SSL/TLS session */
685 
686 STDC_NONNULL_ARG( ( 1 ) ) \
shutdownFunction(INOUT SESSION_INFO * sessionInfoPtr)687 static void shutdownFunction( INOUT SESSION_INFO *sessionInfoPtr )
688 	{
689 	SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
690 
691 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
692 
693 	/* Clean up SSL/TLS-specific objects if required */
694 	if( sslInfo->savedHandshakeInfo != NULL )
695 		{
696 		SSL_HANDSHAKE_INFO handshakeInfo;
697 		int status;
698 
699 		/* We got halfway through the handshake but didn't complete it,
700 		   restore the handshake state and use it to shut down the
701 		   session.  We set a dummy status since this is handled by the
702 		   higher-level code that called us */
703 		status = popHandshakeInfo( sessionInfoPtr, &handshakeInfo );
704 		ENSURES_V( cryptStatusOK( status ) );
705 		( void ) abortStartup( sessionInfoPtr, &handshakeInfo, FALSE,
706 							   CRYPT_ERROR_FAILED );
707 		return;
708 		}
709 
710 	sendCloseAlert( sessionInfoPtr, FALSE );
711 	sNetDisconnect( &sessionInfoPtr->stream );
712 	}
713 
714 /* Connect to an SSL/TLS server/client */
715 
716 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
commonStartup(INOUT SESSION_INFO * sessionInfoPtr,const BOOLEAN isServer)717 static int commonStartup( INOUT SESSION_INFO *sessionInfoPtr,
718 						  const BOOLEAN isServer )
719 	{
720 	SSL_HANDSHAKE_INFO handshakeInfo;
721 	BOOLEAN resumedSession = FALSE;
722 	int status;
723 
724 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
725 
726 	/* TLS 1.2 switched from the MD5+SHA-1 dual hash/MACs to SHA-2 so if the
727 	   user has requesetd TLS 1.2 or newer we need to make sure that SHA-2
728 	   is available */
729 	if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 && \
730 		!algoAvailable( CRYPT_ALGO_SHA2 ) )
731 		{
732 		retExt( CRYPT_ERROR_NOTAVAIL,
733 				( CRYPT_ERROR_NOTAVAIL, SESSION_ERRINFO,
734 				  "TLS 1.2 and newer require the SHA-2 hash algorithms which "
735 				  "aren't available in this build of cryptlib" ) );
736 		}
737 
738 	/* Begin the handshake, unless we're continuing a partially-opened
739 	   session */
740 	if( !( sessionInfoPtr->flags & SESSION_PARTIALOPEN ) )
741 		{
742 		SSL_HANDSHAKE_FUNCTION handshakeFunction;
743 
744 		/* Initialise the handshake information */
745 		status = initHandshakeInfo( sessionInfoPtr, &handshakeInfo,
746 									isServer );
747 		if( cryptStatusError( status ) )
748 			{
749 			return( abortStartup( sessionInfoPtr, &handshakeInfo, FALSE,
750 								  status ) );
751 			}
752 
753 		/* Exchange client/server hellos and other pleasantries */
754 		handshakeFunction = FNPTR_GET( handshakeInfo.beginHandshake );
755 		ENSURES( handshakeFunction != NULL );
756 		status = handshakeFunction( sessionInfoPtr, &handshakeInfo );
757 		if( cryptStatusError( status ) )
758 			{
759 			if( status == OK_SPECIAL )
760 				resumedSession = TRUE;
761 			else
762 				{
763 				return( abortStartup( sessionInfoPtr, &handshakeInfo,
764 									  FALSE, status ) );
765 				}
766 			}
767 
768 		/* Exchange keys with the server */
769 		if( !resumedSession )
770 			{
771 			handshakeFunction = FNPTR_GET( handshakeInfo.exchangeKeys );
772 			ENSURES( handshakeFunction != NULL );
773 			status = handshakeFunction( sessionInfoPtr, &handshakeInfo );
774 			if( cryptStatusError( status ) )
775 				return( abortStartup( sessionInfoPtr, &handshakeInfo, TRUE,
776 									  status ) );
777 			}
778 
779 		/* If we're performing manual verification of the peer's
780 		   certificate, let the caller know that they have to check it,
781 		   unless they've specified that they want to allow any certificate
782 		   (which implies that they'll perform the check after the handshake
783 		   completes) */
784 		if( ( sessionInfoPtr->protocolFlags & SSL_PFLAG_MANUAL_CERTCHECK ) && \
785 			sessionInfoPtr->authResponse != AUTHRESPONSE_SUCCESS )
786 			{
787 			/* Save the handshake state so that we can resume the handshake
788 			   later on */
789 			status = pushHandshakeInfo( sessionInfoPtr, &handshakeInfo );
790 			ENSURES( cryptStatusOK( status ) );
791 
792 			return( CRYPT_ENVELOPE_RESOURCE );
793 			}
794 		}
795 	else
796 		{
797 		/* We're continuing a partially-completed handshake, restore the
798 		   handshake state */
799 		status = popHandshakeInfo( sessionInfoPtr, &handshakeInfo );
800 		ENSURES( cryptStatusOK( status ) );
801 
802 		/* Reset the partial-open state since we're about to complete the
803 		   open.  This is also done by the calling code once the handshake
804 		   completes successfully, but we want to do it preemptively
805 		   unconditionally */
806 		sessionInfoPtr->flags &= ~SESSION_PARTIALOPEN;
807 		}
808 
809 	/* Complete the handshake */
810 	status = completeHandshakeSSL( sessionInfoPtr, &handshakeInfo, !isServer,
811 								   resumedSession );
812 	destroyHandshakeInfo( &handshakeInfo );
813 	if( cryptStatusError( status ) )
814 		return( abortStartup( sessionInfoPtr, NULL, TRUE, status ) );
815 
816 	return( CRYPT_OK );
817 	}
818 
819 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
clientStartup(INOUT SESSION_INFO * sessionInfoPtr)820 static int clientStartup( INOUT SESSION_INFO *sessionInfoPtr )
821 	{
822 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
823 
824 	/* Complete the handshake using the common client/server code */
825 	return( commonStartup( sessionInfoPtr, FALSE ) );
826 	}
827 
828 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
serverStartup(INOUT SESSION_INFO * sessionInfoPtr)829 static int serverStartup( INOUT SESSION_INFO *sessionInfoPtr )
830 	{
831 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
832 
833 	/* Complete the handshake using the common client/server code */
834 	return( commonStartup( sessionInfoPtr, TRUE ) );
835 	}
836 
837 /****************************************************************************
838 *																			*
839 *						Control Information Management Functions			*
840 *																			*
841 ****************************************************************************/
842 
843 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
getAttributeFunction(INOUT SESSION_INFO * sessionInfoPtr,OUT void * data,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type)844 static int getAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,
845 								 OUT void *data,
846 								 IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )
847 	{
848 	CRYPT_CERTIFICATE *certPtr = ( CRYPT_CERTIFICATE * ) data;
849 	CRYPT_CERTIFICATE iCryptCert = isServer( sessionInfoPtr ) ? \
850 		sessionInfoPtr->iKeyexAuthContext : sessionInfoPtr->iKeyexCryptContext;
851 
852 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
853 
854 	REQUIRES( type == CRYPT_SESSINFO_RESPONSE || \
855 			  type == CRYPT_SESSINFO_SSL_OPTIONS );
856 
857 	/* If the caller is after the current SSL option settings, return them */
858 	if( type == CRYPT_SESSINFO_SSL_OPTIONS )
859 		{
860 		const SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
861 		int *valuePtr = ( int * ) data;
862 
863 		*valuePtr = sslInfo->minVersion & SSL_MINVER_MASK;
864 #ifdef CONFIG_SUITEB
865 		if( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB_128 )
866 			*valuePtr |= CRYPT_SSLOPTION_SUITEB_128;
867 		if( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB_256 )
868 			*valuePtr |= CRYPT_SSLOPTION_SUITEB_256;
869 #endif /* CONFIG_SUITEB */
870 		if( sessionInfoPtr->protocolFlags & SSL_PFLAG_MANUAL_CERTCHECK )
871 			*valuePtr |= CRYPT_SSLOPTION_MANUAL_CERTCHECK;
872 		if( sessionInfoPtr->protocolFlags & SSL_PFLAG_DISABLE_NAMEVERIFY )
873 			*valuePtr |= CRYPT_SSLOPTION_DISABLE_NAMEVERIFY;
874 		if( sessionInfoPtr->protocolFlags & SSL_PFLAG_DISABLE_CERTVERIFY )
875 			*valuePtr |= CRYPT_SSLOPTION_DISABLE_CERTVERIFY;
876 
877 		return( CRYPT_OK );
878 		}
879 
880 	/* If we didn't get a client/server certificate then there's nothing to
881 	   return */
882 	if( iCryptCert == CRYPT_ERROR )
883 		return( CRYPT_ERROR_NOTFOUND );
884 
885 	/* Return the information to the caller */
886 	krnlSendNotifier( iCryptCert, IMESSAGE_INCREFCOUNT );
887 	*certPtr = iCryptCert;
888 
889 	return( CRYPT_OK );
890 	}
891 
892 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
setAttributeFunction(INOUT SESSION_INFO * sessionInfoPtr,IN const void * data,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type)893 static int setAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,
894 								 IN const void *data,
895 								 IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )
896 	{
897 	SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
898 	const int value = *( ( int * ) data );
899 
900 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
901 
902 	REQUIRES( type == CRYPT_SESSINFO_SSL_OPTIONS );
903 
904 	/* Set SuiteB options if this is enabled */
905 #ifdef CONFIG_SUITEB
906 	if( value & ( CRYPT_SSLOPTION_SUITEB_128 | CRYPT_SSLOPTION_SUITEB_256 ) )
907 		{
908 		const int suiteBvalue = value & ( CRYPT_SSLOPTION_SUITEB_128 | \
909 										  CRYPT_SSLOPTION_SUITEB_256 );
910 
911 		if( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB )
912 			{
913 			/* If a Suite B configuration option is already set then we
914 			   can't set another one on top of it */
915 			setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_SSL_OPTIONS,
916 						  CRYPT_ERRTYPE_ATTR_PRESENT );
917 			return( CRYPT_ERROR_INITED );
918 			}
919 		if( suiteBvalue == ( CRYPT_SSLOPTION_SUITEB_128 | \
920 							 CRYPT_SSLOPTION_SUITEB_256 ) )
921 			{
922 			/* We can't set both the 128-bit and 256-bit security levels at
923 			   the same time */
924 			return( CRYPT_ARGERROR_NUM1 );
925 			}
926 		if( suiteBvalue == CRYPT_SSLOPTION_SUITEB_128 )
927 			sessionInfoPtr->protocolFlags |= SSL_PFLAG_SUITEB_128;
928 		else
929 			sessionInfoPtr->protocolFlags |= SSL_PFLAG_SUITEB_256;
930 		}
931 #endif /* CONFIG_SUITEB */
932 
933 	/* Set the minimum protocol version, a two-bit field that contains the
934 	   minimum version that we're prepared to accept */
935 	if( value & SSL_MINVER_MASK )
936 		sslInfo->minVersion = value & SSL_MINVER_MASK;
937 
938 	/* By default if a certificate is used we try and verify the server name
939 	   against the name(s) in the certificate, and the certificate itself,
940 	   but since certificate use is so erratic we allow the user to disable
941 	   this if required */
942 	if( value & CRYPT_SSLOPTION_DISABLE_NAMEVERIFY )
943 		sessionInfoPtr->protocolFlags |= SSL_PFLAG_DISABLE_NAMEVERIFY;
944 	if( value & CRYPT_SSLOPTION_DISABLE_CERTVERIFY )
945 		sessionInfoPtr->protocolFlags |= SSL_PFLAG_DISABLE_CERTVERIFY;
946 
947 	/* Enable manual checking of certificates if required */
948 	if( value & CRYPT_SSLOPTION_MANUAL_CERTCHECK )
949 		sessionInfoPtr->protocolFlags |= SSL_PFLAG_MANUAL_CERTCHECK;
950 
951 	return( CRYPT_OK );
952 	}
953 
954 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
checkAttributeFunction(INOUT SESSION_INFO * sessionInfoPtr,IN const void * data,IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type)955 static int checkAttributeFunction( INOUT SESSION_INFO *sessionInfoPtr,
956 								   IN const void *data,
957 								   IN_ATTRIBUTE const CRYPT_ATTRIBUTE_TYPE type )
958 	{
959 	const CRYPT_CONTEXT cryptContext = *( ( CRYPT_CONTEXT * ) data );
960 	int pkcAlgo, status;
961 
962 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
963 	assert( isReadPtr( data, sizeof( int ) ) );
964 
965 	REQUIRES( type > CRYPT_ATTRIBUTE_NONE && type < CRYPT_ATTRIBUTE_LAST );
966 
967 	if( type != CRYPT_SESSINFO_PRIVATEKEY || !isServer( sessionInfoPtr ) )
968 		return( CRYPT_OK );
969 
970 	/* Check that the server key that we've been passed is usable.  For an
971 	   RSA key we can have either encryption (for RSA keyex) or signing (for
972 	   DH keyex) or both, for a DSA or ECDSA key we need signing (for DH/ECDH
973 	   keyex) */
974 	status = krnlSendMessage( cryptContext, IMESSAGE_GETATTRIBUTE,
975 							  &pkcAlgo, CRYPT_CTXINFO_ALGO );
976 	if( cryptStatusError( status ) )
977 		return( status );
978 	switch( pkcAlgo )
979 		{
980 		case CRYPT_ALGO_RSA:
981 			status = krnlSendMessage( cryptContext, IMESSAGE_CHECK, NULL,
982 									  MESSAGE_CHECK_PKC_DECRYPT );
983 			if( cryptStatusError( status ) )
984 				status = krnlSendMessage( cryptContext, IMESSAGE_CHECK, NULL,
985 										  MESSAGE_CHECK_PKC_SIGN );
986 			if( cryptStatusError( status ) )
987 				{
988 				retExt( CRYPT_ARGERROR_NUM1,
989 						( CRYPT_ARGERROR_NUM1, SESSION_ERRINFO,
990 						  "Server key can't be used for encryption or "
991 						  "signing" ) );
992 				}
993 			return( CRYPT_OK );
994 
995 		case CRYPT_ALGO_DSA:
996 		case CRYPT_ALGO_ECDSA:
997 			status = krnlSendMessage( cryptContext, IMESSAGE_CHECK, NULL,
998 									  MESSAGE_CHECK_PKC_SIGN );
999 			if( cryptStatusError( status ) )
1000 				{
1001 				retExt( CRYPT_ARGERROR_NUM1,
1002 						( CRYPT_ARGERROR_NUM1, SESSION_ERRINFO,
1003 						  "Server key can't be used for signing" ) );
1004 				}
1005 #ifdef CONFIG_SUITEB
1006 			return( checkSuiteBKey( sessionInfoPtr, cryptContext, pkcAlgo ) );
1007 #else
1008 			return( CRYPT_OK );
1009 #endif /* CONFIG_SUITEB */
1010 
1011 		default:
1012 			retExt( CRYPT_ARGERROR_NUM1,
1013 					( CRYPT_ARGERROR_NUM1, SESSION_ERRINFO,
1014 					  "Server key uses algorithm that can't be used with "
1015 					  "SSL/TLS" ) );
1016 		}
1017 
1018 	retIntError();
1019 	}
1020 
1021 /****************************************************************************
1022 *																			*
1023 *								Get/Put Data Functions						*
1024 *																			*
1025 ****************************************************************************/
1026 
1027 /* Read/write data over the SSL/TLS link */
1028 
1029 CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \
readHeaderFunction(INOUT SESSION_INFO * sessionInfoPtr,OUT_ENUM_OPT (READINFO)READSTATE_INFO * readInfo)1030 static int readHeaderFunction( INOUT SESSION_INFO *sessionInfoPtr,
1031 							   OUT_ENUM_OPT( READINFO ) \
1032 									READSTATE_INFO *readInfo )
1033 	{
1034 	SSL_INFO *sslInfo = sessionInfoPtr->sessionSSL;
1035 	STREAM stream;
1036 	int packetLength, status;
1037 
1038 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1039 	assert( isWritePtr( readInfo, sizeof( READSTATE_INFO ) ) );
1040 
1041 	/* Clear return value */
1042 	*readInfo = READINFO_NONE;
1043 
1044 	/* Read the SSL/TLS packet header data */
1045 	status = readFixedHeader( sessionInfoPtr, sslInfo->headerBuffer,
1046 							  sessionInfoPtr->receiveBufStartOfs );
1047 	if( cryptStatusError( status ) )
1048 		{
1049 		/* OK_SPECIAL means that we got a soft timeout before the entire
1050 		   header was read, so we return zero bytes read to tell the
1051 		   calling code that there's nothing more to do */
1052 		return( ( status == OK_SPECIAL ) ? 0 : status );
1053 		}
1054 
1055 	/* Since data errors are always fatal, we make all errors fatal until
1056 	   we've finished handling the header */
1057 	*readInfo = READINFO_FATAL;
1058 
1059 	/* Check for an SSL/TLS alert message */
1060 	if( sslInfo->headerBuffer[ 0 ] == SSL_MSG_ALERT )
1061 		{
1062 		return( processAlert( sessionInfoPtr, sslInfo->headerBuffer,
1063 							  sessionInfoPtr->receiveBufStartOfs ) );
1064 		}
1065 
1066 	/* Process the header data */
1067 	sMemConnect( &stream, sslInfo->headerBuffer,
1068 				 sessionInfoPtr->receiveBufStartOfs );
1069 	status = checkPacketHeaderSSL( sessionInfoPtr, &stream, &packetLength );
1070 	sMemDisconnect( &stream );
1071 	if( cryptStatusError( status ) )
1072 		return( status );
1073 
1074 	/* Determine how much data we'll be expecting */
1075 	sessionInfoPtr->pendingPacketLength = \
1076 		sessionInfoPtr->pendingPacketRemaining = packetLength;
1077 
1078 	/* Indicate that we got the header */
1079 	*readInfo = READINFO_NOOP;
1080 	return( OK_SPECIAL );
1081 	}
1082 
1083 CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1, 2 ) ) \
processBodyFunction(INOUT SESSION_INFO * sessionInfoPtr,OUT_ENUM_OPT (READINFO)READSTATE_INFO * readInfo)1084 static int processBodyFunction( INOUT SESSION_INFO *sessionInfoPtr,
1085 								OUT_ENUM_OPT( READINFO ) \
1086 									READSTATE_INFO *readInfo )
1087 	{
1088 	int length, status;
1089 
1090 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1091 	assert( isWritePtr( readInfo, sizeof( READSTATE_INFO ) ) );
1092 
1093 	/* All errors processing the payload are fatal */
1094 	*readInfo = READINFO_FATAL;
1095 
1096 	/* If we're potentially performing a rehandshake, process the packet
1097 	   as a handshake message and treat it as a no-op.  What the server
1098 	   does in response to this is implementation-specific, the spec says
1099 	   that a client can ignore this (as we do) at which point the server
1100 	   can close the connection or hang waiting for a rehandshake that'll
1101 	   never come (as IIS does) */
1102 	if( sessionInfoPtr->protocolFlags & SSL_PFLAG_CHECKREHANDSHAKE )
1103 		{
1104 		sessionInfoPtr->protocolFlags &= ~SSL_PFLAG_CHECKREHANDSHAKE;
1105 		status = unwrapPacketSSL( sessionInfoPtr,
1106 								  sessionInfoPtr->receiveBuffer + \
1107 									sessionInfoPtr->receiveBufPos,
1108 								  sessionInfoPtr->pendingPacketLength,
1109 								  &length, SSL_MSG_HANDSHAKE );
1110 		if( cryptStatusError( status ) )
1111 			return( status );
1112 
1113 		/* Discard the read packet */
1114 		sessionInfoPtr->receiveBufEnd = sessionInfoPtr->receiveBufPos;
1115 		sessionInfoPtr->pendingPacketLength = 0;
1116 		*readInfo = READINFO_NOOP;
1117 		return( OK_SPECIAL );
1118 		}
1119 
1120 	/* Unwrap the payload */
1121 	status = unwrapPacketSSL( sessionInfoPtr,
1122 							  sessionInfoPtr->receiveBuffer + \
1123 								sessionInfoPtr->receiveBufPos,
1124 							  sessionInfoPtr->pendingPacketLength,
1125 							  &length, SSL_MSG_APPLICATION_DATA );
1126 	if( cryptStatusError( status ) )
1127 		return( status );
1128 
1129 	*readInfo = READINFO_NONE;
1130 	return( length );
1131 	}
1132 
1133 CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \
preparePacketFunction(INOUT SESSION_INFO * sessionInfoPtr)1134 static int preparePacketFunction( INOUT SESSION_INFO *sessionInfoPtr )
1135 	{
1136 	STREAM stream;
1137 	int status;
1138 
1139 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1140 
1141 	REQUIRES( !( sessionInfoPtr->flags & SESSION_SENDCLOSED ) );
1142 	REQUIRES( !( sessionInfoPtr->protocolFlags & SSL_PFLAG_ALERTSENT ) );
1143 
1144 	/* Wrap up the payload ready for sending.  Since this is wrapping in-
1145 	   place data we first open a write stream to add the header, then open
1146 	   a read stream covering the full buffer in preparation for wrapping
1147 	   the packet (the first operation looks a bit counter-intuitive because
1148 	   we're opening a packet stream and then immediately closing it again,
1149 	   but this is as intended since all that we're using it for is to write
1150 	   the packet header at the start).  Note that we connect the later read
1151 	   stream to the full send buffer (bufSize) even though we only advance
1152 	   the current stream position to the end of the stream contents
1153 	   (bufPos), since the packet-wrapping process adds further data to the
1154 	   stream that exceeds the current stream position */
1155 	status = openPacketStreamSSL( &stream, sessionInfoPtr, 0,
1156 								  SSL_MSG_APPLICATION_DATA );
1157 	if( cryptStatusError( status ) )
1158 		return( status );
1159 	sMemDisconnect( &stream );
1160 	sMemConnect( &stream, sessionInfoPtr->sendBuffer,
1161 				 sessionInfoPtr->sendBufSize );
1162 	status = sSkip( &stream, sessionInfoPtr->sendBufPos, SSKIP_MAX );
1163 	if( cryptStatusOK( status ) )
1164 		status = wrapPacketSSL( sessionInfoPtr, &stream, 0 );
1165 	if( cryptStatusOK( status ) )
1166 		status = stell( &stream );
1167 	INJECT_FAULT( SESSION_CORRUPT_DATA, SESSION_CORRUPT_DATA_SSL_1 );
1168 	sMemDisconnect( &stream );
1169 
1170 	return( status );
1171 	}
1172 
1173 /****************************************************************************
1174 *																			*
1175 *							Session Access Routines							*
1176 *																			*
1177 ****************************************************************************/
1178 
1179 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
setAccessMethodSSL(INOUT SESSION_INFO * sessionInfoPtr)1180 int setAccessMethodSSL( INOUT SESSION_INFO *sessionInfoPtr )
1181 	{
1182 	static const PROTOCOL_INFO protocolInfo = {
1183 		/* General session information */
1184 		FALSE,						/* Request-response protocol */
1185 		SESSION_NONE,				/* Flags */
1186 		SSL_PORT,					/* SSL/TLS port */
1187 		SESSION_NEEDS_PRIVKEYSIGN,	/* Client attributes */
1188 			/* The client private key is optional, but if present it has to
1189 			   be signature-capable */
1190 		SESSION_NEEDS_PRIVATEKEY |	/* Server attributes */
1191 			SESSION_NEEDS_PRIVKEYCERT | \
1192 			SESSION_NEEDS_KEYORPASSWORD,
1193 			/* The server key capabilities are complex enough that they
1194 			   need to be checked specially via checkAttributeFunction(),
1195 			   for an RSA key we can have either encryption (for RSA keyex)
1196 			   or signing (for DH keyex) or both, for a DSA or ECDSA key
1197 			   we need signing (for DH/ECDH keyex).
1198 
1199 			   In theory we need neither a private key nor a password
1200 			   because the caller can provide the password during the
1201 			   handshake in response to a CRYPT_ENVELOPE_RESOURCE
1202 			   notification, however this facility is likely to be
1203 			   barely-used in comparison to users forgetting to add server
1204 			   certificates and the like, so we require some sort of
1205 			   server-side key set in advance */
1206 		SSL_MINOR_VERSION_TLS11,	/* TLS 1.1 */
1207 #ifdef USE_SSL3
1208 			SSL_MINOR_VERSION_SSL, SSL_MINOR_VERSION_TLS12,
1209 #else
1210 			SSL_MINOR_VERSION_TLS, SSL_MINOR_VERSION_TLS12,
1211 #endif /* USE_SSL3 */
1212 			/* We default to TLS 1.1 rather than TLS 1.2 because support for
1213 			   the latter will be minimal a long time, particularly among
1214 			   things like embedded devices.  However even TLS 1.1 support
1215 			   is still unreliable, see
1216 			   https://www.trustworthyinternet.org/ssl-pulse, which puts
1217 			   it just as low as TLS 1.2.  We still go with 1.1 however
1218 			   because we need it in order to have support for TLS
1219 			   extensions and, conveniently, explicit IVs */
1220 
1221 		/* Protocol-specific information */
1222 		EXTRA_PACKET_SIZE + \
1223 			MAX_PACKET_SIZE,		/* Send/receive buffer size */
1224 		SSL_HEADER_SIZE,			/* Payload data start */
1225 			/* This may be adjusted during the handshake if we're talking
1226 			   TLS 1.1+, which prepends extra data in the form of an IV to
1227 			   the payload */
1228 		MAX_PACKET_SIZE				/* (Default) maximum packet size */
1229 		};
1230 
1231 	assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1232 
1233 	/* Make sure that the huge list of cipher suites is set up correctly */
1234 	assert( SSL_NULL_WITH_NULL == 0x00 );
1235 	assert( TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA == 0x0B );
1236 	assert( TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 == 0x17 );
1237 	assert( TLS_KRB5_WITH_DES_CBC_SHA == 0x1E );
1238 	assert( TLS_PSK_WITH_NULL_SHA == 0x2C );
1239 	assert( TLS_RSA_WITH_AES_128_CBC_SHA == 0x2F );
1240 	assert( TLS_RSA_WITH_NULL_SHA256 == 0x3B );
1241 	assert( TLS_DH_DSS_WITH_AES_128_CBC_SHA256 == 0x3E );
1242 	assert( TLS_RSA_WITH_CAMELLIA_128_CBC_SHA == 0x41 );
1243 	assert( TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 == 0x67 );
1244 	assert( TLS_RSA_WITH_CAMELLIA_256_CBC_SHA == 0x84 );
1245 	assert( TLS_PSK_WITH_RC4_128_SHA == 0x8A );
1246 	assert( TLS_RSA_WITH_SEED_CBC_SHA == 0x96 );
1247 	assert( TLS_RSA_WITH_AES_128_GCM_SHA256 == 0x9C );
1248 	assert( TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 == 0xBA );
1249 	assert( TLS_ECDH_ECDSA_WITH_NULL_SHA == 0xC001 );
1250 	assert( TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA == 0xC01A );
1251 	assert( TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 == 0xC023 );
1252 	assert( TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 == 0xC02B );
1253 	assert( TLS_ECDHE_PSK_WITH_RC4_128_SHA == 0xC033 );
1254 
1255 	/* Set the access method pointers */
1256 	sessionInfoPtr->protocolInfo = &protocolInfo;
1257 	FNPTR_SET( sessionInfoPtr->shutdownFunction, shutdownFunction );
1258 	if( isServer( sessionInfoPtr ) )
1259 		{
1260 		FNPTR_SET( sessionInfoPtr->transactFunction, serverStartup );
1261 		}
1262 	else
1263 		{
1264 		FNPTR_SET( sessionInfoPtr->transactFunction, clientStartup );
1265 		}
1266 	FNPTR_SET( sessionInfoPtr->getAttributeFunction, getAttributeFunction );
1267 	FNPTR_SET( sessionInfoPtr->setAttributeFunction, setAttributeFunction );
1268 	FNPTR_SET( sessionInfoPtr->checkAttributeFunction, checkAttributeFunction );
1269 	FNPTR_SET( sessionInfoPtr->readHeaderFunction, readHeaderFunction );
1270 	FNPTR_SET( sessionInfoPtr->processBodyFunction, processBodyFunction );
1271 	FNPTR_SET( sessionInfoPtr->preparePacketFunction, preparePacketFunction );
1272 
1273 	return( CRYPT_OK );
1274 	}
1275 #endif /* USE_SSL */
1276