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