1 /****************************************************************************
2 * *
3 * cryptlib SSL v3/TLS Client Management *
4 * Copyright Peter Gutmann 1998-2012 *
5 * *
6 ****************************************************************************/
7
8 #if defined( INC_ALL )
9 #include "crypt.h"
10 #include "misc_rw.h"
11 #include "session.h"
12 #include "ssl.h"
13 #else
14 #include "crypt.h"
15 #include "enc_dec/misc_rw.h"
16 #include "session/session.h"
17 #include "session/ssl.h"
18 #endif /* Compiler-specific includes */
19
20 /* Testing the SSL/TLS code gets a bit complicated because in the presence
21 of the session cache every session after the first one will be a resumed
22 session. To deal with this we disable the client-side session cache in
23 the VC++ 6 debug build.
24
25 Note that changing the follow requires an equivalent change in
26 test/ssl.c */
27
28 #if defined( __WINDOWS__ ) && defined( _MSC_VER ) && ( _MSC_VER == 1200 ) && \
29 !defined( NDEBUG ) && 1
30 #define NO_SESSION_CACHE
31 #endif /* VC++ 6.0 debug build */
32
33 #ifdef USE_SSL
34
35 /****************************************************************************
36 * *
37 * Utility Functions *
38 * *
39 ****************************************************************************/
40
41 #ifdef CONFIG_SUITEB
42
43 /* For Suite B the first suite must be ECDHE/AES128-GCM/SHA256 or
44 ECDHE/AES256-GCM/SHA384 depending on the security level and the second
45 suite, at the 128-bit security level, must be ECDHE/AES256-GCM/SHA384 */
46
47 CHECK_RETVAL_BOOL \
48 static int checkSuiteBSelection( IN_RANGE( SSL_FIRST_VALID_SUITE, \
49 SSL_LAST_SUITE - 1 ) \
50 const int cipherSuite,
51 const int flags,
52 const BOOLEAN isFirstSuite )
53 {
54 REQUIRES( cipherSuite >= SSL_FIRST_VALID_SUITE && \
55 cipherSuite < SSL_LAST_SUITE );
56 REQUIRES( ( flags & ~( SSL_PFLAG_SUITEB ) ) == 0 );
57
58 if( isFirstSuite )
59 {
60 switch( flags )
61 {
62 case SSL_PFLAG_SUITEB_128:
63 if( cipherSuite == TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 )
64 return( TRUE );
65 break;
66
67 case SSL_PFLAG_SUITEB_256:
68 if( cipherSuite == TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 )
69 return( TRUE );
70 break;
71
72 default:
73 retIntError();
74 }
75 }
76 else
77 {
78 switch( flags )
79 {
80 case SSL_PFLAG_SUITEB_128:
81 if( cipherSuite == TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 )
82 return( TRUE );
83 break;
84
85 case SSL_PFLAG_SUITEB_256:
86 /* For the 256-bit level there are no further requirements */
87 return( TRUE );
88
89 default:
90 retIntError();
91 }
92 }
93
94 return( FALSE );
95 }
96 #endif /* CONFIG_SUITEB */
97
98 /* Encode a list of available algorithms */
99
100 #define MAX_NO_SUITES 32
101
102 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
writeCipherSuiteList(INOUT STREAM * stream,IN_RANGE (SSL_MINOR_VERSION_SSL,SSL_MINOR_VERSION_TLS12)const int sslVersion,const BOOLEAN usePSK,IN_FLAGS_Z (SSL)const int suiteBinfo)103 static int writeCipherSuiteList( INOUT STREAM *stream,
104 IN_RANGE( SSL_MINOR_VERSION_SSL, \
105 SSL_MINOR_VERSION_TLS12 ) \
106 const int sslVersion,
107 const BOOLEAN usePSK,
108 IN_FLAGS_Z( SSL ) const int suiteBinfo )
109 {
110 const CIPHERSUITE_INFO **cipherSuiteInfo;
111 int availableSuites[ MAX_NO_SUITES + 8 ], cipherSuiteCount = 0;
112 int suiteIndex, cipherSuiteInfoSize, status;
113 #ifdef CONFIG_SUITEB
114 int suiteNo = 0;
115 #endif /* CONFIG_SUITEB */
116
117 assert( isWritePtr( stream, sizeof( STREAM ) ) );
118
119 REQUIRES( sslVersion >= SSL_MINOR_VERSION_SSL && \
120 sslVersion <= SSL_MINOR_VERSION_TLS12 );
121 #ifdef CONFIG_SUITEB
122 REQUIRES( suiteBinfo >= SSL_PFLAG_NONE && suiteBinfo < SSL_PFLAG_MAX );
123 #endif /* CONFIG_SUITEB */
124
125 /* Get the information for the supported cipher suites */
126 status = getCipherSuiteInfo( &cipherSuiteInfo, &cipherSuiteInfoSize );
127 if( cryptStatusError( status ) )
128 return( status );
129
130 /* Walk down the list of algorithms (and the corresponding cipher
131 suites) remembering each one that's available for use */
132 for( suiteIndex = 0;
133 suiteIndex < cipherSuiteInfoSize && \
134 cipherSuiteInfo[ suiteIndex ]->cipherSuite != SSL_NULL_WITH_NULL && \
135 cipherSuiteCount < MAX_NO_SUITES;
136 /* No action */ )
137 {
138 const CIPHERSUITE_INFO *cipherSuiteInfoPtr = cipherSuiteInfo[ suiteIndex ];
139 const CRYPT_ALGO_TYPE keyexAlgo = cipherSuiteInfoPtr->keyexAlgo;
140 const CRYPT_ALGO_TYPE cryptAlgo = cipherSuiteInfoPtr->cryptAlgo;
141 const CRYPT_ALGO_TYPE authAlgo = cipherSuiteInfoPtr->authAlgo;
142 const CRYPT_ALGO_TYPE macAlgo = cipherSuiteInfoPtr->macAlgo;
143 const int suiteFlags = cipherSuiteInfoPtr->flags;
144
145 /* Make sure that the cipher suite is appropriate for SuiteB use if
146 necessary */
147 #ifdef CONFIG_SUITEB
148 if( suiteNo == 0 || suiteNo == 1 )
149 {
150 if( !checkSuiteBSelection( cipherSuiteInfoPtr->cipherSuite,
151 ( suiteBinfo == 0 ) ? \
152 SSL_PFLAG_SUITEB_128 : suiteBinfo,
153 ( suiteNo == 0 ) ? TRUE : FALSE ) )
154 {
155 suiteIndex++;
156 continue;
157 }
158 suiteNo++;
159 }
160 #endif /* CONFIG_SUITEB */
161
162 /* Make sure that the suite is appropriate for the SSL/TLS version
163 that we're using. Normally we can use TLS suites in SSL (e.g.
164 the AES suites), but we can't use ECC both because this requires
165 extensions and because the SSLv3 PRF mechanisms can't handle
166 ECC's premaster secrets */
167 if( ( ( suiteFlags & CIPHERSUITE_FLAG_ECC ) && \
168 sslVersion <= SSL_MINOR_VERSION_SSL ) || \
169 ( ( suiteFlags & CIPHERSUITE_FLAG_TLS12 ) && \
170 sslVersion <= SSL_MINOR_VERSION_TLS11 ) )
171 {
172 suiteIndex++;
173 continue;
174 }
175
176 /* If it's a PSK suite but we're not using PSK, skip it */
177 if( ( suiteFlags & CIPHERSUITE_FLAG_PSK ) && !usePSK )
178 {
179 suiteIndex++;
180 continue;
181 }
182
183 /* If the keyex algorithm for this suite isn't enabled for this
184 build of cryptlib, skip all suites that use it. We have to
185 explicitly exclude the special case where there's no keyex
186 algorithm in order to accomodate the bare TLS-PSK suites (used
187 without DH/ECDH or RSA), whose keyex mechanism is pure PSK */
188 if( keyexAlgo != CRYPT_ALGO_NONE && !algoAvailable( keyexAlgo ) )
189 {
190 while( cipherSuiteInfo[ suiteIndex ]->keyexAlgo == keyexAlgo && \
191 suiteIndex < cipherSuiteInfoSize )
192 suiteIndex++;
193 ENSURES( suiteIndex < cipherSuiteInfoSize );
194 continue;
195 }
196
197 /* If the bulk encryption algorithm or MAC algorithm for this suite
198 isn't enabled for this build of cryptlib, skip all suites that
199 use it */
200 if( !algoAvailable( cryptAlgo ) )
201 {
202 while( cipherSuiteInfo[ suiteIndex ]->cryptAlgo == cryptAlgo && \
203 suiteIndex < cipherSuiteInfoSize )
204 suiteIndex++;
205 ENSURES( suiteIndex < cipherSuiteInfoSize );
206 continue;
207 }
208 if( !algoAvailable( macAlgo ) )
209 {
210 while( cipherSuiteInfo[ suiteIndex ]->macAlgo == macAlgo && \
211 suiteIndex < cipherSuiteInfoSize )
212 suiteIndex++;
213 ENSURES( suiteIndex < cipherSuiteInfoSize );
214 continue;
215 }
216
217 /* The suite is supported, remember it. In theory there's only a
218 single combination of the various algorithms present, but these
219 can be subsetted into different key sizes (because they're there,
220 that's why) so we have to iterate the recording of available
221 suites instead of just assigning a single value on match */
222 while( cipherSuiteInfo[ suiteIndex ]->keyexAlgo == keyexAlgo && \
223 cipherSuiteInfo[ suiteIndex ]->authAlgo == authAlgo && \
224 cipherSuiteInfo[ suiteIndex ]->cryptAlgo == cryptAlgo && \
225 cipherSuiteInfo[ suiteIndex ]->macAlgo == macAlgo && \
226 cipherSuiteCount < MAX_NO_SUITES && \
227 suiteIndex < cipherSuiteInfoSize )
228 {
229 availableSuites[ cipherSuiteCount++ ] = \
230 cipherSuiteInfo[ suiteIndex++ ]->cipherSuite;
231 #ifdef CONFIG_SUITEB
232 if( suiteNo == 0 || suiteNo == 1 )
233 break; /* Suite B has special requirements for initial suites */
234 #endif /* CONFIG_SUITEB */
235 }
236 ENSURES( suiteIndex < cipherSuiteInfoSize );
237 ENSURES( cipherSuiteCount < MAX_NO_SUITES );
238 }
239 ENSURES( suiteIndex < cipherSuiteInfoSize );
240 ENSURES( cipherSuiteCount > 0 && cipherSuiteCount < MAX_NO_SUITES );
241
242 /* Encode the list of available cipher suites */
243 status = writeUint16( stream, cipherSuiteCount * UINT16_SIZE );
244 for( suiteIndex = 0;
245 cryptStatusOK( status ) && suiteIndex < cipherSuiteCount;
246 suiteIndex++ )
247 status = writeUint16( stream, availableSuites[ suiteIndex ] );
248
249 return( status );
250 }
251
252 /****************************************************************************
253 * *
254 * Handle Client/Server Keyex *
255 * *
256 ****************************************************************************/
257
258 /* Process the identity hint sent with the server keyex. It's uncertain
259 what we're supposed to do with this so we just skip it */
260
261 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
readIdentityHint(INOUT STREAM * stream)262 static int readIdentityHint( INOUT STREAM *stream )
263 {
264 int length, status;
265
266 status = length = readUint16( stream );
267 if( !cryptStatusError( status ) && length > 0 )
268 status = sSkip( stream, length, MAX_INTLENGTH_SHORT );
269 return( status );
270 }
271
272 /* Read a server's DH/ECDH key agreement data:
273
274 DH:
275 uint16 dh_pLen
276 byte[] dh_p
277 uint16 dh_gLen
278 byte[] dh_g
279 uint16 dh_YsLen
280 byte[] dh_Ys
281 ECDH:
282 byte curveType
283 uint16 namedCurve
284 uint8 ecPointLen -- NB uint8 not uint16
285 byte[] ecPoint */
286
287 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
readServerKeyex(INOUT STREAM * stream,OUT KEYAGREE_PARAMS * keyAgreeParams,OUT_HANDLE_OPT CRYPT_CONTEXT * dhContextPtr,const BOOLEAN isECC)288 static int readServerKeyex( INOUT STREAM *stream,
289 OUT KEYAGREE_PARAMS *keyAgreeParams,
290 OUT_HANDLE_OPT CRYPT_CONTEXT *dhContextPtr,
291 const BOOLEAN isECC )
292 {
293 void *keyData;
294 const int keyDataOffset = stell( stream );
295 int keyDataLength, dummy, status;
296
297 assert( isWritePtr( stream, sizeof( STREAM ) ) );
298 assert( isWritePtr( keyAgreeParams, sizeof( KEYAGREE_PARAMS ) ) );
299 assert( isWritePtr( dhContextPtr, sizeof( CRYPT_CONTEXT ) ) );
300
301 /* Clear return values */
302 memset( keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
303 *dhContextPtr = CRYPT_ERROR;
304
305 /* Read the server DH/ECDH public key data */
306 if( isECC )
307 {
308 ( void ) sgetc( stream );
309 status = readUint16( stream );
310 }
311 else
312 {
313 status = readInteger16UChecked( stream, NULL, &dummy,
314 MIN_PKCSIZE_THRESHOLD,
315 CRYPT_MAX_PKCSIZE );
316 if( cryptStatusOK( status ) )
317 status = readInteger16U( stream, NULL, &dummy, 1,
318 CRYPT_MAX_PKCSIZE );
319 }
320 if( cryptStatusError( status ) )
321 return( status );
322
323 /* Create a DH/ECDH context from the public key data. If it's an ECC
324 algorithm we set a dummy curve type, the actual value is determined
325 by the parameters sent by the server */
326 keyDataLength = stell( stream ) - keyDataOffset;
327 status = sMemGetDataBlockAbs( stream, keyDataOffset, &keyData,
328 keyDataLength );
329 if( cryptStatusOK( status ) )
330 {
331 status = initDHcontextSSL( dhContextPtr, keyData, keyDataLength,
332 CRYPT_UNUSED, isECC ? \
333 CRYPT_ECCCURVE_P256 /* Dummy */ : \
334 CRYPT_ECCCURVE_NONE );
335 }
336 if( cryptStatusError( status ) )
337 return( status );
338
339 /* Read the DH/ECDH public value */
340 if( isECC )
341 {
342 return( readEcdhValue( stream, keyAgreeParams->publicValue,
343 CRYPT_MAX_PKCSIZE,
344 &keyAgreeParams->publicValueLen ) );
345 }
346 return( readInteger16UChecked( stream, keyAgreeParams->publicValue,
347 &keyAgreeParams->publicValueLen,
348 MIN_PKCSIZE_THRESHOLD,
349 CRYPT_MAX_PKCSIZE ) );
350 }
351
352 /* Process the optional server keyex:
353
354 byte ID = SSL_HAND_SERVER_KEYEXCHANGE
355 uint24 len
356 DH:
357 uint16 dh_pLen
358 byte[] dh_p
359 uint16 dh_gLen
360 byte[] dh_g
361 uint16 dh_YsLen
362 byte[] dh_Ys
363 [ byte hashAlgoID -- TLS 1.2 ]
364 [ byte sigAlgoID -- TLS 1.2 ]
365 uint16 signatureLen
366 byte[] signature
367 DH-PSK:
368 uint16 pskIdentityHintLen
369 byte pskIdentityHint
370 uint16 dh_pLen
371 byte[] dh_p
372 uint16 dh_gLen
373 byte[] dh_g
374 uint16 dh_YsLen
375 byte[] dh_Ys
376 ECDH:
377 byte curveType
378 uint16 namedCurve
379 uint8 ecPointLen -- NB uint8 not uint16
380 byte[] ecPoint
381 [ byte hashAlgoID -- TLS 1.2 ]
382 [ byte sigAlgoID -- TLS 1.2 ]
383 uint16 signatureLen
384 byte[] signature */
385
386 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3, 4, 6 ) ) \
processServerKeyex(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,INOUT STREAM * stream,OUT_BUFFER (keyexPublicValueMaxLen,* keyexPublicValueLen)void * keyexPublicValue,IN_LENGTH_SHORT const int keyexPublicValueMaxLen,OUT_DATALENGTH_Z int * keyexPublicValueLen)387 static int processServerKeyex( INOUT SESSION_INFO *sessionInfoPtr,
388 INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
389 INOUT STREAM *stream,
390 OUT_BUFFER( keyexPublicValueMaxLen, \
391 *keyexPublicValueLen ) \
392 void *keyexPublicValue,
393 IN_LENGTH_SHORT const int keyexPublicValueMaxLen,
394 OUT_DATALENGTH_Z int *keyexPublicValueLen )
395
396 {
397 KEYAGREE_PARAMS keyAgreeParams, tempKeyAgreeParams;
398 void *keyData DUMMY_INIT_PTR;
399 const BOOLEAN isECC = isEccAlgo( handshakeInfo->keyexAlgo );
400 const BOOLEAN isPSK = ( handshakeInfo->authAlgo == CRYPT_ALGO_NONE ) ? \
401 TRUE : FALSE;
402 int keyDataOffset, keyDataLength DUMMY_INIT;
403 int length, status;
404
405 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
406 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
407 assert( isWritePtr( stream, sizeof( STREAM ) ) );
408 assert( isWritePtr( keyexPublicValue, keyexPublicValueMaxLen ) );
409 assert( isWritePtr( keyexPublicValueLen, sizeof( int ) ) );
410
411 REQUIRES( keyexPublicValueMaxLen > 0 && \
412 keyexPublicValueMaxLen < MAX_INTLENGTH_SHORT );
413
414 /* Clear return values */
415 memset( keyexPublicValue, 0, min( 16, keyexPublicValueMaxLen ) );
416 *keyexPublicValueLen = 0;
417
418 /* Make sure that we've got an appropriate server keyex packet. We set
419 the minimum key size to MIN_PKCSIZE_THRESHOLD/MIN_PKCSIZE_ECC_THRESHOLD
420 instead of MIN_PKCSIZE/MIN_PKCSIZE_ECC in order to provide better
421 diagnostics if the server is using weak keys since otherwise the data
422 will be rejected in the packet read long before we get to the keysize
423 check */
424 status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
425 SSL_HAND_SERVER_KEYEXCHANGE,
426 isECC ? \
427 ( 1 + UINT16_SIZE + \
428 1 + MIN_PKCSIZE_ECCPOINT_THRESHOLD + \
429 UINT16_SIZE + MIN_PKCSIZE_ECCPOINT_THRESHOLD ) : \
430 ( UINT16_SIZE + MIN_PKCSIZE_THRESHOLD + \
431 UINT16_SIZE + 1 + \
432 UINT16_SIZE + MIN_PKCSIZE_THRESHOLD + \
433 UINT16_SIZE + MIN_PKCSIZE_THRESHOLD ) );
434 if( cryptStatusError( status ) )
435 return( status );
436
437 /* If we're using a PSK suite then the keyex information is preceded by
438 a PSK identity hint */
439 if( isPSK )
440 {
441 status = readIdentityHint( stream );
442 if( cryptStatusError( status ) )
443 {
444 retExt( CRYPT_ERROR_BADDATA,
445 ( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
446 "Invalid PSK identity hint" ) );
447 }
448 }
449
450 /* Read the server's keyex information and convert it into a DH/ECDH
451 context */
452 keyDataOffset = stell( stream );
453 status = readServerKeyex( stream, &keyAgreeParams,
454 &handshakeInfo->dhContext, isECC );
455 if( cryptStatusOK( status ) )
456 {
457 keyDataLength = stell( stream ) - keyDataOffset;
458 status = sMemGetDataBlockAbs( stream, keyDataOffset, &keyData,
459 keyDataLength );
460 }
461 if( cryptStatusError( status ) )
462 {
463 /* Some misconfigured servers may use very short keys, we perform a
464 special-case check for these and return a more specific message
465 than the generic bad-data error */
466 if( status == CRYPT_ERROR_NOSECURE )
467 {
468 retExt( CRYPT_ERROR_NOSECURE,
469 ( CRYPT_ERROR_NOSECURE, SESSION_ERRINFO,
470 "Insecure key used in key exchange" ) );
471 }
472
473 retExt( cryptArgError( status ) ? \
474 CRYPT_ERROR_BADDATA : status,
475 ( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status,
476 SESSION_ERRINFO,
477 "Invalid server key agreement parameters" ) );
478 }
479 ANALYSER_HINT( keyData != NULL );
480
481 /* Check the server's signature on the DH/ECDH parameters, unless it's a
482 PSK suite in which case the exchange is authenticated via the PSK */
483 #ifndef CONFIG_FUZZ
484 if( !isPSK )
485 {
486 status = checkKeyexSignature( sessionInfoPtr, handshakeInfo, stream,
487 keyData, keyDataLength, isECC );
488 if( cryptStatusError( status ) )
489 {
490 retExt( status,
491 ( status, SESSION_ERRINFO,
492 "Invalid server key agreement parameter signature" ) );
493 }
494 }
495 #else
496 /* Skip the server's signature, set up a dummy premaster secret, and
497 exit */
498 status = readUniversal16( stream );
499 if( cryptStatusError( status ) )
500 return( status );
501 memset( handshakeInfo->premasterSecret, '*', SSL_SECRET_SIZE );
502 handshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;
503 FUZZ_SKIP();
504 #endif /* CONFIG_FUZZ */
505
506 /* Perform phase 1 of the DH/ECDH key agreement process and save the
507 result so that we can send it to the server later on. The order of
508 the SSL messages is a bit unfortunate since we get the one for phase
509 2 before we need the phase 1 value, so we have to cache the phase 1
510 result for when we need it later on */
511 memset( &tempKeyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
512 status = krnlSendMessage( handshakeInfo->dhContext,
513 IMESSAGE_CTX_ENCRYPT, &tempKeyAgreeParams,
514 sizeof( KEYAGREE_PARAMS ) );
515 if( cryptStatusError( status ) )
516 {
517 zeroise( &tempKeyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
518 return( status );
519 }
520 ENSURES( rangeCheckZ( 0, tempKeyAgreeParams.publicValueLen,
521 keyexPublicValueMaxLen ) );
522 memcpy( keyexPublicValue, tempKeyAgreeParams.publicValue,
523 tempKeyAgreeParams.publicValueLen );
524 *keyexPublicValueLen = tempKeyAgreeParams.publicValueLen;
525 zeroise( &tempKeyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
526
527 /* Perform phase 2 of the DH/ECDH key agreement */
528 status = krnlSendMessage( handshakeInfo->dhContext, IMESSAGE_CTX_DECRYPT,
529 &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
530 if( cryptStatusError( status ) )
531 {
532 zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
533 return( status );
534 }
535 if( isECC )
536 {
537 const int xCoordLen = ( keyAgreeParams.wrappedKeyLen - 1 ) / 2;
538
539 /* The output of the ECDH operation is an ECC point, but for some
540 unknown reason TLS only uses the x coordinate and not the full
541 point. To work around this we have to rewrite the point as a
542 standalone x coordinate, which is relatively easy because we're
543 using an uncompressed point format:
544
545 +---+---------------+---------------+
546 |04 | qx | qy |
547 +---+---------------+---------------+
548 |<- fldSize --> |<- fldSize --> | */
549 REQUIRES( keyAgreeParams.wrappedKeyLen >= MIN_PKCSIZE_ECCPOINT && \
550 keyAgreeParams.wrappedKeyLen <= MAX_PKCSIZE_ECCPOINT && \
551 ( keyAgreeParams.wrappedKeyLen & 1 ) == 1 && \
552 keyAgreeParams.wrappedKey[ 0 ] == 0x04 );
553 memmove( keyAgreeParams.wrappedKey,
554 keyAgreeParams.wrappedKey + 1, xCoordLen );
555 keyAgreeParams.wrappedKeyLen = xCoordLen;
556 }
557 ENSURES( rangeCheckZ( 0, keyAgreeParams.wrappedKeyLen,
558 CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE ) );
559 memcpy( handshakeInfo->premasterSecret, keyAgreeParams.wrappedKey,
560 keyAgreeParams.wrappedKeyLen );
561 handshakeInfo->premasterSecretSize = keyAgreeParams.wrappedKeyLen;
562 zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
563
564 return( CRYPT_OK );
565 }
566
567 /* Build the client key exchange packet:
568
569 [ byte ID = SSL_HAND_CLIENT_KEYEXCHANGE ]
570 [ uint24 len -- Written by caller ]
571 DH:
572 uint16 yLen
573 byte[] y
574 DH-PSK:
575 uint16 userIDLen
576 byte[] userID
577 uint16 yLen
578 byte[] y
579 ECDH:
580 uint8 ecPointLen -- NB uint8 not uint16
581 byte[] ecPoint
582 PSK:
583 uint16 userIDLen
584 byte[] userID
585 RSA:
586 [ uint16 encKeyLen -- TLS only ]
587 byte[] rsaPKCS1( byte[2] { 0x03, 0x0n } || byte[46] random ) */
588
589 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
createClientKeyex(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo,INOUT STREAM * stream,IN_BUFFER_OPT (keyexPublicValueLen)const BYTE * keyexPublicValue,IN_LENGTH_PKC_Z const int keyexPublicValueLen,const BOOLEAN isPSK)590 static int createClientKeyex( INOUT SESSION_INFO *sessionInfoPtr,
591 INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
592 INOUT STREAM *stream,
593 IN_BUFFER_OPT( keyexPublicValueLen ) \
594 const BYTE *keyexPublicValue,
595 IN_LENGTH_PKC_Z const int keyexPublicValueLen,
596 const BOOLEAN isPSK )
597 {
598 const ATTRIBUTE_LIST *userNamePtr DUMMY_INIT_PTR;
599 const ATTRIBUTE_LIST *passwordPtr DUMMY_INIT_PTR;
600 BYTE wrappedKey[ CRYPT_MAX_PKCSIZE + 8 ];
601 int wrappedKeyLength, status;
602
603 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
604 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
605 assert( isWritePtr( stream, sizeof( STREAM ) ) );
606 assert( ( keyexPublicValue == NULL && keyexPublicValueLen == 0 ) || \
607 isReadPtr( keyexPublicValue, keyexPublicValueLen ) );
608
609 REQUIRES( ( keyexPublicValue == NULL && keyexPublicValueLen == 0 ) || \
610 ( keyexPublicValueLen > 0 && \
611 keyexPublicValueLen <= CRYPT_MAX_PKCSIZE ) );
612
613 /* If we're using a PSK mechanism, get the user name and password/PSK */
614 if( isPSK )
615 {
616 userNamePtr = findSessionInfo( sessionInfoPtr->attributeList,
617 CRYPT_SESSINFO_USERNAME );
618 passwordPtr = findSessionInfo( sessionInfoPtr->attributeList,
619 CRYPT_SESSINFO_PASSWORD );
620
621 REQUIRES( passwordPtr != NULL );
622 REQUIRES( userNamePtr != NULL );
623 }
624
625 /* If we're using DH/ECDH (with optional PSK additions), write the
626 necessary information */
627 if( keyexPublicValue != NULL )
628 {
629 /* If it's a PSK algorithm, convert the DH/ECDH premaster secret to
630 a DH/ECDH + PSK premaster secret and write the client identity
631 that's required by PSK */
632 if( isPSK )
633 {
634 BYTE premasterTempBuffer[ CRYPT_MAX_PKCSIZE + 8 ];
635 const int premasterTempSize = handshakeInfo->premasterSecretSize;
636
637 /* Since this operation rewrites the premaster secret, we have to
638 save the original contents into a temporary buffer first */
639 REQUIRES( rangeCheckZ( 0, handshakeInfo->premasterSecretSize,
640 CRYPT_MAX_PKCSIZE ) );
641 memcpy( premasterTempBuffer, handshakeInfo->premasterSecret,
642 handshakeInfo->premasterSecretSize );
643 status = createSharedPremasterSecret( \
644 handshakeInfo->premasterSecret,
645 CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE,
646 &handshakeInfo->premasterSecretSize,
647 passwordPtr->value,
648 passwordPtr->valueLength,
649 premasterTempBuffer, premasterTempSize,
650 ( passwordPtr->flags & ATTR_FLAG_ENCODEDVALUE ) ? \
651 TRUE : FALSE );
652 zeroise( premasterTempBuffer, premasterTempSize );
653 if( cryptStatusError( status ) )
654 {
655 retExt( status,
656 ( status, SESSION_ERRINFO,
657 "Couldn't create master secret from shared "
658 "secret/password value" ) );
659 }
660
661 /* Write the PSK client identity */
662 writeUint16( stream, userNamePtr->valueLength );
663 status = swrite( stream, userNamePtr->value,
664 userNamePtr->valueLength );
665 if( cryptStatusError( status ) )
666 return( status );
667 }
668
669 /* Write the DH/ECDH public value that we saved earlier when we
670 performed phase 1 of the key agreement process */
671 if( isEccAlgo( handshakeInfo->keyexAlgo ) )
672 {
673 sputc( stream, keyexPublicValueLen );
674 status = swrite( stream, keyexPublicValue,
675 keyexPublicValueLen );
676 }
677 else
678 {
679 status = writeInteger16U( stream, keyexPublicValue,
680 keyexPublicValueLen );
681 }
682
683 return( status );
684 }
685
686 /* If we're using straight PSK, write the client identity */
687 if( isPSK )
688 {
689 /* Create the shared premaster secret from the user password */
690 status = createSharedPremasterSecret( \
691 handshakeInfo->premasterSecret,
692 CRYPT_MAX_PKCSIZE + CRYPT_MAX_TEXTSIZE,
693 &handshakeInfo->premasterSecretSize,
694 passwordPtr->value,
695 passwordPtr->valueLength, NULL, 0,
696 ( passwordPtr->flags & ATTR_FLAG_ENCODEDVALUE ) ? \
697 TRUE : FALSE );
698 if( cryptStatusError( status ) )
699 {
700 retExt( status,
701 ( status, SESSION_ERRINFO,
702 "Couldn't create master secret from shared "
703 "secret/password value" ) );
704 }
705
706 /* Write the PSK client identity */
707 writeUint16( stream, userNamePtr->valueLength );
708 return( swrite( stream, userNamePtr->value,
709 userNamePtr->valueLength ) );
710 }
711
712 /* It's an RSA keyex, write the RSA-wrapped premaster secret */
713 status = wrapPremasterSecret( sessionInfoPtr, handshakeInfo, wrappedKey,
714 CRYPT_MAX_PKCSIZE, &wrappedKeyLength );
715 if( cryptStatusError( status ) )
716 return( status );
717 if( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL )
718 {
719 /* The original Netscape SSL implementation didn't provide a length
720 for the encrypted key and everyone copied that so it became the
721 de facto standard way to do it (sic faciunt omnes. The spec
722 itself is ambiguous on the topic). This was fixed in TLS
723 (although the spec is still ambiguous) so the encoding differs
724 slightly between SSL and TLS */
725 return( swrite( stream, wrappedKey, wrappedKeyLength ) );
726 }
727
728 return( writeInteger16U( stream, wrappedKey, wrappedKeyLength ) );
729 }
730
731 /****************************************************************************
732 * *
733 * Server Certificate Checking Functions *
734 * *
735 ****************************************************************************/
736
737 /* Matching names in certificates can get quite tricky due to the usual
738 erratic nature of what gets put in them. Firstly, supposed FQDNs can be
739 unqualified names and/or can be present as full URLs rather than just
740 domain names, so we use sNetParseURL() on them before doing anything else
741 with them. Secondly, PKIX tries to pretend that wildcard certificates
742 don't exist, and so there are no official guidelines for how they should
743 be laid out. To minimise the potential for mischief we only allow a
744 wildcard at the start of the domain, and don't allow wildcards for the
745 first- or second-level names.
746
747 Since this code is going to result in server names (and therefore
748 connections) being rejected, it's unusually loquacious about the reasons
749 for the rejection */
750
751 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3, 5 ) ) \
matchName(INOUT_BUFFER_FIXED (serverNameLength)BYTE * serverName,IN_LENGTH_DNS const int serverNameLength,INOUT_BUFFER_FIXED (originalCertNameLength)BYTE * certName,IN_LENGTH_DNS const int originalCertNameLength,OUT ERROR_INFO * errorInfo)752 static int matchName( INOUT_BUFFER_FIXED( serverNameLength ) \
753 BYTE *serverName,
754 IN_LENGTH_DNS const int serverNameLength,
755 INOUT_BUFFER_FIXED( originalCertNameLength ) \
756 BYTE *certName,
757 IN_LENGTH_DNS const int originalCertNameLength,
758 OUT ERROR_INFO *errorInfo )
759 {
760 URL_INFO urlInfo;
761 BOOLEAN hasWildcard = FALSE;
762 int certNameLength, dotCount = 0, i, status;
763
764 assert( isWritePtr( serverName, serverNameLength ) );
765 assert( isWritePtr( certName, originalCertNameLength ) );
766 assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );
767
768 REQUIRES( serverNameLength > 0 && serverNameLength <= MAX_DNS_SIZE );
769 REQUIRES( originalCertNameLength > 0 && \
770 originalCertNameLength <= MAX_DNS_SIZE );
771
772 /* Clear return value */
773 memset( errorInfo, 0, sizeof( ERROR_INFO ) );
774
775 /* Extract the FQDN portion from the certificate name */
776 status = sNetParseURL( &urlInfo, certName, originalCertNameLength,
777 URL_TYPE_NONE );
778 if( cryptStatusError( status ) )
779 {
780 retExt( CRYPT_ERROR_INVALID,
781 ( CRYPT_ERROR_INVALID, errorInfo,
782 "Invalid host name '%s' in server's certificate",
783 sanitiseString( certName, CRYPT_MAX_TEXTSIZE,
784 originalCertNameLength ) ) );
785 }
786 certName = ( BYTE * ) urlInfo.host;
787 certNameLength = urlInfo.hostLen;
788
789 /* If the name in the certificate is longer than the server name then it
790 can't be a match */
791 if( certNameLength > serverNameLength )
792 {
793 retExt( CRYPT_ERROR_INVALID,
794 ( CRYPT_ERROR_INVALID, errorInfo,
795 "Server name '%s' doesn't match host name '%s' in "
796 "server's certificate",
797 sanitiseString( serverName, CRYPT_MAX_TEXTSIZE,
798 serverNameLength ),
799 sanitiseString( certName, CRYPT_MAX_TEXTSIZE,
800 certNameLength ) ) );
801 }
802
803 /* Make sure that, if it's a wildcarded name, it follows the pattern
804 "'*' ... '.' ... '.' ..." */
805 for( i = 0; i < certNameLength; i++ )
806 {
807 const int ch = byteToInt( certName[ i ] );
808
809 if( ch == '*' )
810 {
811 if( i != 0 )
812 {
813 /* The wildcard character isn't the first one in the name,
814 it's invalid */
815 retExt( CRYPT_ERROR_INVALID,
816 ( CRYPT_ERROR_INVALID, errorInfo,
817 "Host name '%s' in server's certificate contains "
818 "wildcard at invalid location",
819 sanitiseString( certName, CRYPT_MAX_TEXTSIZE,
820 certNameLength ) ) );
821 }
822 hasWildcard = TRUE;
823 }
824 if( ch == '.' )
825 dotCount++;
826 }
827 if( hasWildcard && dotCount < 2 )
828 {
829 /* The wildcard applies to the first- or second-level domain, it's
830 invalid */
831 retExt( CRYPT_ERROR_INVALID,
832 ( CRYPT_ERROR_INVALID, errorInfo,
833 "Host name '%s' in server's certificate contains "
834 "wildcard at invalid domain level",
835 sanitiseString( certName, CRYPT_MAX_TEXTSIZE,
836 certNameLength ) ) );
837 }
838
839 /* Match the certificate name and the server name, taking into account
840 wildcarding */
841 if( hasWildcard )
842 {
843 const int delta = serverNameLength - ( certNameLength - 1 );
844
845 ENSURES_B( delta > 0 && delta < serverNameLength );
846
847 /* Match the suffix past the wildcard */
848 if( !memcmp( certName + 1, serverName + delta, certNameLength - 1 ) )
849 return( CRYPT_OK );
850 }
851 else
852 {
853 /* It's a straight match */
854 if( certNameLength == serverNameLength && \
855 !memcmp( certName, serverName, certNameLength ) )
856 return( CRYPT_OK );
857 }
858
859 /* The name doesn't match */
860 retExt( CRYPT_ERROR_INVALID,
861 ( CRYPT_ERROR_INVALID, errorInfo,
862 "Server name '%s' doesn't match host name '%s' in server's "
863 "certificate",
864 sanitiseString( serverName, CRYPT_MAX_TEXTSIZE,
865 serverNameLength ),
866 sanitiseString( certName, CRYPT_MAX_TEXTSIZE,
867 certNameLength ) ) );
868 }
869
870 /* Check the remote host name against one or more server names in the
871 certificate */
872
873 CHECK_RETVAL STDC_NONNULL_ARG( ( 2, 5 ) ) \
checkHostName(const CRYPT_CERTIFICATE iCryptCert,INOUT_BUFFER_FIXED (serverNameLength)void * serverName,IN_LENGTH_DNS const int serverNameLength,const BOOLEAN multipleNamesPresent,OUT ERROR_INFO * errorInfo)874 static int checkHostName( const CRYPT_CERTIFICATE iCryptCert,
875 INOUT_BUFFER_FIXED( serverNameLength ) void *serverName,
876 IN_LENGTH_DNS const int serverNameLength,
877 const BOOLEAN multipleNamesPresent,
878 OUT ERROR_INFO *errorInfo )
879 {
880 MESSAGE_DATA msgData;
881 static const int nameValue = CRYPT_CERTINFO_SUBJECTNAME;
882 static const int altNameValue = CRYPT_CERTINFO_SUBJECTALTNAME;
883 static const int dnsNameValue = CRYPT_CERTINFO_DNSNAME;
884 char certName[ MAX_DNS_SIZE + 8 ];
885 int certNameLength = CRYPT_ERROR, status;
886
887 assert( isWritePtr( serverName, serverNameLength ) );
888 assert( isWritePtr( errorInfo, sizeof( ERROR_INFO ) ) );
889
890 REQUIRES( isHandleRangeValid( iCryptCert ) );
891 REQUIRES( serverNameLength > 0 && serverNameLength <= MAX_DNS_SIZE );
892
893 /* Clear return value */
894 memset( errorInfo, 0, sizeof( ERROR_INFO ) );
895
896 /* Get the CN and check it against the host name */
897 setMessageData( &msgData, certName, MAX_DNS_SIZE );
898 status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
899 &msgData, CRYPT_CERTINFO_COMMONNAME );
900 if( cryptStatusOK( status ) )
901 {
902 certNameLength = msgData.length;
903 status = matchName( serverName, serverNameLength, certName,
904 certNameLength, errorInfo );
905 if( cryptStatusOK( status ) )
906 return( status );
907
908 /* If this was the only name that's present then we can't go any
909 further (the extended error information will have been provided
910 by matchName()) */
911 if( !multipleNamesPresent )
912 return( CRYPT_ERROR_INVALID );
913 }
914
915 /* The CN didn't match, check the altName */
916 status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
917 ( MESSAGE_CAST ) &altNameValue,
918 CRYPT_ATTRIBUTE_CURRENT );
919 if( cryptStatusOK( status ) )
920 {
921 status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
922 ( MESSAGE_CAST ) &dnsNameValue,
923 CRYPT_ATTRIBUTE_CURRENT_INSTANCE );
924 }
925 if( cryptStatusError( status ) )
926 {
927 /* We couldn't find a DNS name in the altName, which means that the
928 server name doesn't match the name (from the previously-used CN)
929 in the certificate.
930
931 If there's no CN present then there's no certificate host name to
932 use in the error message and we have to construct our own one,
933 otherwise it'll have been provided by the previous call to
934 matchName() */
935 krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
936 ( MESSAGE_CAST ) &nameValue,
937 CRYPT_ATTRIBUTE_CURRENT ); /* Re-select subject DN */
938 if( certNameLength == CRYPT_ERROR )
939 {
940 retExt( CRYPT_ERROR_INVALID,
941 ( CRYPT_ERROR_INVALID, errorInfo,
942 "Server name '%s' doesn't match host name in "
943 "server's certificate",
944 sanitiseString( serverName, CRYPT_MAX_TEXTSIZE,
945 serverNameLength ) ) );
946 }
947 return( CRYPT_ERROR_INVALID ); /* See comment above */
948 }
949 do
950 {
951 setMessageData( &msgData, certName, MAX_DNS_SIZE );
952 status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
953 &msgData, CRYPT_CERTINFO_DNSNAME );
954 if( cryptStatusOK( status ) )
955 {
956 status = matchName( serverName, serverNameLength, certName,
957 msgData.length, errorInfo );
958 if( cryptStatusOK( status ) )
959 return( status );
960 }
961 }
962 while( krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
963 MESSAGE_VALUE_CURSORNEXT,
964 CRYPT_ATTRIBUTE_CURRENT_INSTANCE ) == CRYPT_OK );
965 krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
966 ( MESSAGE_CAST ) &nameValue, CRYPT_ATTRIBUTE_CURRENT );
967 /* Re-select subject DN */
968
969 /* We couldn't find any name that matches the server name */
970 retExt( CRYPT_ERROR_INVALID,
971 ( CRYPT_ERROR_INVALID, errorInfo,
972 "Server name '%s' doesn't match any of the host names in "
973 "server's certificate",
974 sanitiseString( serverName, CRYPT_MAX_TEXTSIZE,
975 serverNameLength ) ) );
976 }
977
978 /* Check that the certificate from the remote system is in order. This
979 involves checking that the name of the host that we've connected to
980 matches one of the names in the certificate, and that the certificate
981 itself is in order */
982
983 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
checkCertificateInfo(INOUT SESSION_INFO * sessionInfoPtr)984 static int checkCertificateInfo( INOUT SESSION_INFO *sessionInfoPtr )
985 {
986 const CRYPT_CERTIFICATE iCryptCert = sessionInfoPtr->iKeyexCryptContext;
987 MESSAGE_DATA msgData;
988 const ATTRIBUTE_LIST *serverNamePtr = \
989 findSessionInfo( sessionInfoPtr->attributeList,
990 CRYPT_SESSINFO_SERVER_NAME );
991 static const int nameValue = CRYPT_CERTINFO_SUBJECTNAME;
992 static const int altNameValue = CRYPT_CERTINFO_SUBJECTALTNAME;
993 const int verifyFlags = sessionInfoPtr->protocolFlags & \
994 ( SSL_PFLAG_DISABLE_NAMEVERIFY | SSL_PFLAG_DISABLE_CERTVERIFY );
995 BOOLEAN multipleNamesPresent = FALSE;
996 int status;
997
998 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
999
1000 /* If all verification has been disabled then there's nothing to do */
1001 if( verifyFlags == ( SSL_PFLAG_DISABLE_NAMEVERIFY | \
1002 SSL_PFLAG_DISABLE_CERTVERIFY ) )
1003 return( CRYPT_OK );
1004
1005 /* The server name is traditionally given as the certificate's CN,
1006 however it may also be present as an altName. First we check whether
1007 there's an altName present, this is used to control error handling
1008 since if there isn't one present we stop after a failed CN check and
1009 if there is one present we continue on to the altName(s) */
1010 status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
1011 ( MESSAGE_CAST ) &altNameValue,
1012 CRYPT_ATTRIBUTE_CURRENT );
1013 if( cryptStatusOK( status ) )
1014 {
1015 setMessageData( &msgData, NULL, 0 );
1016 status = krnlSendMessage( iCryptCert, IMESSAGE_GETATTRIBUTE_S,
1017 &msgData, CRYPT_CERTINFO_DNSNAME );
1018 if( cryptStatusOK( status ) )
1019 multipleNamesPresent = TRUE;
1020 }
1021 krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
1022 ( MESSAGE_CAST ) &nameValue, CRYPT_ATTRIBUTE_CURRENT );
1023 /* Re-select the subject DN */
1024
1025 /* If there's a server name present and name checking hasn't been
1026 disabled, make sure that it matches one of the names in the
1027 certificate */
1028 if( serverNamePtr != NULL && \
1029 !( verifyFlags & SSL_PFLAG_DISABLE_NAMEVERIFY ) )
1030 {
1031 status = checkHostName( iCryptCert, serverNamePtr->value,
1032 serverNamePtr->valueLength,
1033 multipleNamesPresent, SESSION_ERRINFO );
1034 if( cryptStatusError( status ) )
1035 return( status );
1036 }
1037
1038 /* If certificate verification hasn't been disabled, make sure that the
1039 server's certificate verifies */
1040 if( !( verifyFlags & SSL_PFLAG_DISABLE_CERTVERIFY ) )
1041 {
1042 /* This is something that can't be easily enabled by default since
1043 cryptlib isn't a web browser and therefore won't follow the
1044 "trust anything from a commercial CA" model. In particular
1045 cryptlib users tend to fall into two classes, commercial/
1046 government users, often in high-security environments, who run
1047 their own PKIs and definitely won't want anything from a
1048 commercial CA to be accepted, and noncommercial users who won't
1049 be buying certificates from a commercial CA. In neither of these
1050 cases is trusting certs from a commercial CA useful, in the
1051 former case it leads to a serious security breach (as some US
1052 government agencies have discovered), in the latter case it leads
1053 to all certificates being rejected since they weren't bought from
1054 a commercial CA. The recommended solutions to this problem are
1055 covered in the cryptlib manual */
1056 }
1057
1058 return( CRYPT_OK );
1059 }
1060
1061 /****************************************************************************
1062 * *
1063 * Client-side Connect Functions *
1064 * *
1065 ****************************************************************************/
1066
1067 /* Perform the initial part of the handshake with the server */
1068
1069 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
beginClientHandshake(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo)1070 static int beginClientHandshake( INOUT SESSION_INFO *sessionInfoPtr,
1071 INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
1072 {
1073 #ifndef NO_SESSION_CACHE
1074 const ATTRIBUTE_LIST *attributeListPtr;
1075 #endif /* NO_SESSION_CACHE */
1076 STREAM *stream = &handshakeInfo->stream;
1077 SCOREBOARD_INFO scoreboardInfo;
1078 MESSAGE_DATA msgData;
1079 BYTE sentSessionID[ MAX_SESSIONID_SIZE + 8 ];
1080 BOOLEAN sessionIDsent = FALSE;
1081 int packetOffset, length, sentSessionIDlength DUMMY_INIT, status;
1082
1083 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1084 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1085
1086 /* Check whether we have (potentially) cached data available for the
1087 server. If we've had the connection to the remote system provided
1088 by the user (for example as an already-connected socket) then there
1089 won't be any server name information present, so we can only
1090 perform a session resume if we've established the connection
1091 ourselves */
1092 #ifndef NO_SESSION_CACHE
1093 attributeListPtr = findSessionInfo( sessionInfoPtr->attributeList,
1094 CRYPT_SESSINFO_SERVER_NAME );
1095 if( attributeListPtr != NULL )
1096 {
1097 status = lookupScoreboardEntry( sessionInfoPtr->sessionSSL->scoreboardInfoPtr,
1098 SCOREBOARD_KEY_FQDN, attributeListPtr->value,
1099 attributeListPtr->valueLength, &scoreboardInfo );
1100 if( !cryptStatusError( status ) )
1101 {
1102 /* We've got cached data for the server available, remember the
1103 session ID so that we can send it to the server */
1104 status = attributeCopyParams( handshakeInfo->sessionID,
1105 MAX_SESSIONID_SIZE,
1106 &handshakeInfo->sessionIDlength,
1107 scoreboardInfo.key,
1108 scoreboardInfo.keySize );
1109 ENSURES( cryptStatusOK( status ) );
1110
1111 /* Make a copy of the session ID that we're sending so that we
1112 can check it against what the server sends back to us later.
1113 This isn't technically necessary, but if we request the reuse
1114 of a session with ID X and the server comes back to us with a
1115 response indicating we should reuse session Y then there's
1116 something funny going on */
1117 memcpy( sentSessionID, handshakeInfo->sessionID,
1118 handshakeInfo->sessionIDlength );
1119 sentSessionIDlength = handshakeInfo->sessionIDlength;
1120 }
1121 }
1122 #endif /* NO_SESSION_CACHE */
1123
1124 /* Get the nonce that's used to randomise all crypto ops */
1125 setMessageData( &msgData, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
1126 status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
1127 &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
1128 if( cryptStatusError( status ) )
1129 return( status );
1130
1131 /* Build the client hello packet:
1132
1133 byte ID = SSL_HAND_CLIENT_HELLO
1134 uint24 len
1135 byte[2] version = { 0x03, 0x0n }
1136 byte[32] nonce
1137 byte sessIDlen
1138 byte[] sessID
1139 uint16 suiteLen
1140 uint16[] suite
1141 byte coprLen = 1
1142 byte[] copr = { 0x00 }
1143 [ uint16 extListLen -- RFC 3546/RFC 4366
1144 byte extType
1145 uint16 extLen
1146 byte[] extData ]
1147
1148 Extensions present a bit of an interoperability problem on the client
1149 side, if we use them then we have to add them to the client hello
1150 before we know whether the server can handle them, and many servers
1151 can't (this is particularly bad in cryptlib's case where it's used
1152 with embedded systems, which have ancient and buggy SSL/TLS
1153 implementations that are rarely if ever updated). A reasonable
1154 compromise is to only enable the use of extensions when the user has
1155 asked for TLS 1.1+ support */
1156 status = openPacketStreamSSL( stream, sessionInfoPtr, CRYPT_USE_DEFAULT,
1157 SSL_MSG_HANDSHAKE );
1158 if( cryptStatusError( status ) )
1159 return( status );
1160 status = continueHSPacketStream( stream, SSL_HAND_CLIENT_HELLO,
1161 &packetOffset );
1162 if( cryptStatusError( status ) )
1163 {
1164 sMemDisconnect( stream );
1165 return( status );
1166 }
1167 sputc( stream, SSL_MAJOR_VERSION );
1168 sputc( stream, sessionInfoPtr->version );
1169 handshakeInfo->clientOfferedVersion = sessionInfoPtr->version;
1170 swrite( stream, handshakeInfo->clientNonce, SSL_NONCE_SIZE );
1171 sputc( stream, handshakeInfo->sessionIDlength );
1172 if( handshakeInfo->sessionIDlength > 0 )
1173 {
1174 swrite( stream, handshakeInfo->sessionID,
1175 handshakeInfo->sessionIDlength );
1176 sessionIDsent = TRUE;
1177 }
1178 status = writeCipherSuiteList( stream, sessionInfoPtr->version,
1179 findSessionInfo( sessionInfoPtr->attributeList,
1180 CRYPT_SESSINFO_USERNAME ) != NULL ? \
1181 TRUE : FALSE,
1182 ( sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB ) ? \
1183 TRUE : FALSE );
1184 if( cryptStatusOK( status ) )
1185 {
1186 sputc( stream, 1 ); /* No compression */
1187 status = sputc( stream, 0 );
1188 }
1189 if( cryptStatusOK( status ) && \
1190 sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS11 )
1191 {
1192 /* Extensions are only written when newer versions of TLS are
1193 enabled, see the comment earlier for details */
1194 status = writeClientExtensions( stream, sessionInfoPtr );
1195 }
1196 if( cryptStatusOK( status ) )
1197 status = completeHSPacketStream( stream, packetOffset );
1198 if( cryptStatusOK( status ) )
1199 status = sendPacketSSL( sessionInfoPtr, stream, FALSE );
1200 if( cryptStatusError( status ) )
1201 {
1202 sMemDisconnect( stream );
1203 return( status );
1204 }
1205
1206 /* Perform the assorted hashing of the client hello in between the
1207 network ops where it's effectively free */
1208 status = hashHSPacketWrite( handshakeInfo, stream, 0 );
1209 sMemDisconnect( stream );
1210 if( cryptStatusError( status ) )
1211 return( status );
1212
1213 /* Process the server hello. The server usually sends us a session ID
1214 to indicate a (potentially) resumable session, indicated by a return
1215 status of OK_SPECIAL, but we don't do anything further with it since
1216 we won't be resuming the session.
1217
1218 Note that this processing leads to a slight inefficiency in hashing
1219 when multiple hash algorithms need to be accomodated (as they do
1220 when TLS 1.2+ is enabled) because readHSPacketSSL() hashes the
1221 incoming packet data as it arrives, and if all possible server
1222 handshake packets are combined into a single SSL message packet then
1223 they'll arrive, and need to be hashed, before the server hello is
1224 processed and we can selectively disable the hash algorithms that
1225 won't be needed. Fixing this would require adding special-case
1226 processing to readHSPacketSSL() to detect the use of
1227 SSL_MSG_FIRST_HANDSHAKE for the client and skip the hashing, relying
1228 on the calling code to then pick out the portions that need to be
1229 hashed. This probably isn't worth the effort required, since it adds
1230 a lot of code complexity and custom processing just to save a small
1231 amount of hashing on the client, which will generally be the less
1232 resource-constrained of the two parties */
1233 status = readHSPacketSSL( sessionInfoPtr, handshakeInfo, &length,
1234 SSL_MSG_FIRST_HANDSHAKE );
1235 if( cryptStatusError( status ) )
1236 return( status );
1237 sMemConnect( stream, sessionInfoPtr->receiveBuffer, length );
1238 status = processHelloSSL( sessionInfoPtr, handshakeInfo, stream, FALSE );
1239 if( cryptStatusError( status ) )
1240 {
1241 int resumedSessionID;
1242
1243 if( status != OK_SPECIAL )
1244 {
1245 sMemDisconnect( stream );
1246 return( status );
1247 }
1248
1249 /* The server has sent us a sessionID in an attempt to resume a
1250 previous session, see if it's in the session cache. If it's
1251 present then the server hello is followed immediately by the
1252 change cipherspec, which is sent by the shared handshake
1253 completion code */
1254 resumedSessionID = \
1255 lookupScoreboardEntry( sessionInfoPtr->sessionSSL->scoreboardInfoPtr,
1256 SCOREBOARD_KEY_SESSIONID_CLI, handshakeInfo->sessionID,
1257 handshakeInfo->sessionIDlength, &scoreboardInfo );
1258 #ifdef CONFIG_SUITEB_TESTS
1259 resumedSessionID = CRYPT_ERROR; /* Disable for Suite B tests */
1260 #endif /* CONFIG_SUITEB_TESTS */
1261 if( !cryptStatusError( resumedSessionID ) )
1262 {
1263 sMemDisconnect( stream );
1264
1265 /* Make sure that the session that the server OK'd for resumption
1266 was the one that we actually asked for */
1267 if( !sessionIDsent || \
1268 ( handshakeInfo->sessionIDlength != sentSessionIDlength || \
1269 memcmp( handshakeInfo->sessionID, sentSessionID,
1270 sentSessionIDlength ) ) )
1271 {
1272 /* Something very odd is going on, the server has told us to
1273 resume a session that we didn't ask for or don't know
1274 about */
1275 retExt( CRYPT_ERROR_INVALID,
1276 ( CRYPT_ERROR_INVALID, SESSION_ERRINFO,
1277 "Server indicated that a non-valid session should "
1278 "be resumed" ) );
1279 }
1280
1281 /* We're resuming a previous session, if extended TLS facilities
1282 were in use then make sure that the resumed session uses the
1283 same facilities */
1284 if( ( sessionInfoPtr->protocolFlags & \
1285 SSL_RESUMEDSESSION_FLAGS ) != scoreboardInfo.metaData )
1286 {
1287 DEBUG_PRINT(( "Session with options %x was resumed with "
1288 "options %x.\n", scoreboardInfo.metaData,
1289 sessionInfoPtr->protocolFlags & \
1290 SSL_RESUMEDSESSION_FLAGS ));
1291 return( CRYPT_ERROR_INVALID );
1292 }
1293
1294 /* Remember the premaster secret for the resumed session */
1295 status = attributeCopyParams( handshakeInfo->premasterSecret,
1296 SSL_SECRET_SIZE,
1297 &handshakeInfo->premasterSecretSize,
1298 scoreboardInfo.data,
1299 scoreboardInfo.dataSize );
1300 ENSURES( cryptStatusOK( status ) );
1301
1302 /* Tell the caller that it's a resumed session */
1303 DEBUG_PRINT(( "Resuming session with server based on "
1304 "sessionID = \n" ));
1305 DEBUG_DUMP_DATA( handshakeInfo->sessionID,
1306 handshakeInfo->sessionIDlength );
1307 return( OK_SPECIAL );
1308 }
1309 }
1310
1311 return( CRYPT_OK );
1312 }
1313
1314 /* Exchange keys with the server */
1315
1316 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
exchangeClientKeys(INOUT SESSION_INFO * sessionInfoPtr,INOUT SSL_HANDSHAKE_INFO * handshakeInfo)1317 static int exchangeClientKeys( INOUT SESSION_INFO *sessionInfoPtr,
1318 INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
1319 {
1320 STREAM *stream = &handshakeInfo->stream;
1321 BYTE keyexPublicValue[ CRYPT_MAX_PKCSIZE + 8 ];
1322 BOOLEAN needClientCert = FALSE;
1323 int packetOffset, length, keyexPublicValueLen = 0, status;
1324
1325 assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
1326 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1327
1328 /* Process the optional server supplemental data:
1329
1330 byte ID = SSL_HAND_SUPPLEMENTAL_DATA
1331 uint24 len
1332 uint16 type
1333 uint16 len
1334 byte[] value
1335
1336 This is a kitchen-sink mechanism for exchanging arbitrary further
1337 data during the TLS handshake (see RFC 4680). The presence of the
1338 supplemental data has to be negotiated using TLS extensions, however
1339 the nature of this negotiation is unspecified so we can't just
1340 reject an unexpected supplemental data message as required by the RFC
1341 because it may have been quite legitimately negotiated by a TLS
1342 extension that we don't know about. Because of this we perform
1343 basic validity checks on any supplemental data messages that arrive
1344 but otherwise ignore them */
1345 status = refreshHSStream( sessionInfoPtr, handshakeInfo );
1346 if( cryptStatusError( status ) )
1347 return( status );
1348 if( sPeek( stream ) == SSL_HAND_SUPPLEMENTAL_DATA )
1349 {
1350 status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
1351 SSL_HAND_SUPPLEMENTAL_DATA,
1352 UINT16_SIZE + UINT16_SIZE + 1 );
1353 if( cryptStatusError( status ) )
1354 {
1355 sMemDisconnect( stream );
1356 return( status );
1357 }
1358 readUint16( stream ); /* Type */
1359 status = readUniversal16( stream ); /* Value */
1360 if( cryptStatusError( status ) )
1361 {
1362 sMemDisconnect( stream );
1363 retExt( CRYPT_ERROR_BADDATA,
1364 ( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
1365 "Invalid supplemental data" ) );
1366 }
1367 }
1368
1369 #ifndef CONFIG_FUZZ
1370 /* Process the optional server certificate chain:
1371
1372 byte ID = SSL_HAND_CERTIFICATE
1373 uint24 len
1374 uint24 certLen -- 1...n certificates ordered
1375 byte[] certificate -- leaf -> root */
1376 if( handshakeInfo->authAlgo != CRYPT_ALGO_NONE )
1377 {
1378 status = refreshHSStream( sessionInfoPtr, handshakeInfo );
1379 if( cryptStatusError( status ) )
1380 return( status );
1381 status = readSSLCertChain( sessionInfoPtr, handshakeInfo,
1382 stream, &sessionInfoPtr->iKeyexCryptContext,
1383 FALSE );
1384 if( cryptStatusError( status ) )
1385 {
1386 sMemDisconnect( stream );
1387 return( status );
1388 }
1389
1390 /* Check the details in the certificate chain */
1391 status = checkCertificateInfo( sessionInfoPtr );
1392 if( cryptStatusError( status ) )
1393 {
1394 sMemDisconnect( stream );
1395 return( status );
1396 }
1397 }
1398 #endif /* CONFIG_FUZZ */
1399
1400 /* Process the optional server keyex */
1401 if( isKeyxAlgo( handshakeInfo->keyexAlgo ) )
1402 {
1403 status = refreshHSStream( sessionInfoPtr, handshakeInfo );
1404 if( cryptStatusError( status ) )
1405 return( status );
1406
1407 status = processServerKeyex( sessionInfoPtr, handshakeInfo,
1408 stream, keyexPublicValue,
1409 CRYPT_MAX_PKCSIZE,
1410 &keyexPublicValueLen );
1411 if( cryptStatusError( status ) )
1412 {
1413 sMemDisconnect( stream );
1414 return( status );
1415 }
1416 }
1417 else
1418 {
1419 /* If it's a pure PSK mechanism then there may be a pointless server
1420 keyex containing an identity hint whose purpose is never
1421 explained (more specifically the RFC makes it a SHOULD NOT, and
1422 clients MUST ignore it), in which case we have to process the
1423 packet to get rid of the identity hint */
1424 if( handshakeInfo->authAlgo == CRYPT_ALGO_NONE )
1425 {
1426 status = refreshHSStream( sessionInfoPtr, handshakeInfo );
1427 if( cryptStatusError( status ) )
1428 return( status );
1429 if( sPeek( stream ) == SSL_HAND_SUPPLEMENTAL_DATA )
1430 {
1431 status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
1432 SSL_HAND_SERVER_KEYEXCHANGE,
1433 ( UINT16_SIZE + 1 ) );
1434 if( cryptStatusError( status ) )
1435 return( status );
1436 status = readIdentityHint( stream );
1437 if( cryptStatusError( status ) )
1438 {
1439 retExt( CRYPT_ERROR_BADDATA,
1440 ( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
1441 "Invalid PSK identity hint" ) );
1442 }
1443 }
1444 }
1445
1446 #ifdef CONFIG_FUZZ
1447 /* Set up a dummy premaster secret */
1448 memset( handshakeInfo->premasterSecret, '*', SSL_SECRET_SIZE );
1449 handshakeInfo->premasterSecretSize = SSL_SECRET_SIZE;
1450 #endif /* CONFIG_FUZZ */
1451
1452 /* Keep static analysers happy */
1453 memset( keyexPublicValue, 0, CRYPT_MAX_PKCSIZE );
1454 }
1455
1456 /* Process the optional server certificate request:
1457
1458 byte ID = SSL_HAND_SERVER_CERTREQUEST
1459 uint24 len
1460 byte certTypeLen
1461 byte[] certType
1462 [ uint16 sigHashListLen -- TLS 1.2 ]
1463 [ byte hashAlgoID -- TLS 1.2 ]
1464 [ byte sigAlgoID -- TLS 1.2 ]
1465 uint16 caNameListLen
1466 uint16 caNameLen
1467 byte[] caName
1468
1469 We don't really care what's in the certificate request packet since
1470 the contents are irrelevant, in a number of cases servers have been
1471 known to send out superfluous certificate requests without the admins
1472 even knowing that they're doing it, in other cases servers send out
1473 requests for every CA that they know of (150-160 CAs), which is
1474 pretty much meaningless since they can't possibly trust all of those
1475 CAs to authorise access to their site. Because of this, all that we
1476 do here is perform a basic sanity check and remember that we may need
1477 to submit a certificate later on.
1478
1479 See the long comment in the cert-request handling code in ssl_svr.c
1480 for the handling of the sigHashList.
1481
1482 Since we're about to peek ahead into the stream to see if we need to
1483 process a server certificate request, we have to refresh the stream
1484 at this point in case the certificate request wasn't bundled with the
1485 preceding packets */
1486 status = refreshHSStream( sessionInfoPtr, handshakeInfo );
1487 if( cryptStatusError( status ) )
1488 return( status );
1489 if( sPeek( stream ) == SSL_HAND_SERVER_CERTREQUEST )
1490 {
1491 /* Although the spec says that at least one CA name entry must be
1492 present, some implementations send a zero-length list so we allow
1493 this as well. The spec was changed in late TLS 1.1 drafts to
1494 reflect this practice */
1495 status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
1496 SSL_HAND_SERVER_CERTREQUEST,
1497 1 + 1 + \
1498 ( ( sessionInfoPtr->version >= \
1499 SSL_MINOR_VERSION_TLS12 ) ? \
1500 ( UINT16_SIZE + 1 + 1 ) : 0 ) + \
1501 UINT16_SIZE );
1502 if( cryptStatusError( status ) )
1503 {
1504 sMemDisconnect( stream );
1505 return( status );
1506 }
1507 status = length = sgetc( stream );
1508 if( !cryptStatusError( status ) )
1509 {
1510 if( length < 1 || length > 64 )
1511 status = CRYPT_ERROR_BADDATA;
1512 }
1513 if( !cryptStatusError( status ) )
1514 status = sSkip( stream, length, MAX_INTLENGTH_SHORT );
1515 if( cryptStatusError( status ) )
1516 {
1517 sMemDisconnect( stream );
1518 retExt( CRYPT_ERROR_BADDATA,
1519 ( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
1520 "Invalid certificate request certificate-type "
1521 "information" ) );
1522 }
1523 if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
1524 {
1525 status = length = readUint16( stream );
1526 if( !cryptStatusError( status ) )
1527 {
1528 if( length < UINT16_SIZE || length > 64 || \
1529 ( length % UINT16_SIZE ) != 0 )
1530 status = CRYPT_ERROR_BADDATA;
1531 }
1532 if( !cryptStatusError( status ) )
1533 status = sSkip( stream, length, MAX_INTLENGTH_SHORT );
1534 if( cryptStatusError( status ) )
1535 {
1536 sMemDisconnect( stream );
1537 retExt( CRYPT_ERROR_BADDATA,
1538 ( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
1539 "Invalid certificate request signature/hash "
1540 "algorithm information" ) );
1541 }
1542 }
1543 status = readUniversal16( stream );
1544 if( cryptStatusError( status ) )
1545 {
1546 sMemDisconnect( stream );
1547 retExt( CRYPT_ERROR_BADDATA,
1548 ( CRYPT_ERROR_BADDATA, SESSION_ERRINFO,
1549 "Invalid certificate request CA name list" ) );
1550 }
1551 needClientCert = TRUE;
1552 }
1553
1554 /* Process the server hello done:
1555
1556 byte ID = SSL_HAND_SERVER_HELLODONE
1557 uint24 len = 0 */
1558 status = refreshHSStream( sessionInfoPtr, handshakeInfo );
1559 if( cryptStatusError( status ) )
1560 return( status );
1561 status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
1562 SSL_HAND_SERVER_HELLODONE, 0 );
1563 if( cryptStatusError( status ) )
1564 {
1565 sMemDisconnect( stream );
1566 return( status );
1567 }
1568
1569 /* If we're fuzzing the input then we don't need to go through any of
1570 the following crypto calisthenics */
1571 FUZZ_SKIP();
1572
1573 /* If we need a client certificate, build the client certificate packet */
1574 status = openPacketStreamSSL( stream, sessionInfoPtr, CRYPT_USE_DEFAULT,
1575 SSL_MSG_HANDSHAKE );
1576 if( cryptStatusError( status ) )
1577 return( status );
1578 if( needClientCert )
1579 {
1580 BOOLEAN sentResponse = FALSE;
1581
1582 /* If we haven't got a certificate available, tell the server. SSL
1583 and TLS differ here, SSL sends a no-certificate alert while TLS
1584 sends an empty client certificate packet, which is handled
1585 further on */
1586 if( sessionInfoPtr->privateKey == CRYPT_ERROR )
1587 {
1588 setErrorInfo( sessionInfoPtr, CRYPT_SESSINFO_PRIVATEKEY,
1589 CRYPT_ERRTYPE_ATTR_ABSENT );
1590 #ifdef USE_SSL3
1591 if( sessionInfoPtr->version == SSL_MINOR_VERSION_SSL )
1592 {
1593 static const BYTE FAR_BSS noCertAlertSSLTemplate[] = {
1594 SSL_MSG_ALERT, /* ID */
1595 SSL_MAJOR_VERSION, SSL_MINOR_VERSION_SSL,/* Version */
1596 0, 2, /* Length */
1597 SSL_ALERTLEVEL_WARNING, SSL_ALERT_NO_CERTIFICATE
1598 };
1599
1600 /* This is an alert-protocol message rather than a handshake
1601 message so we don't add it to the handshake packet stream
1602 but write it directly to the network stream */
1603 swrite( &sessionInfoPtr->stream, noCertAlertSSLTemplate, 7 );
1604 sentResponse = TRUE;
1605 }
1606 #endif /* USE_SSL3 */
1607
1608 /* The reaction to the lack of a certificate is up to the server
1609 (some just request one anyway even though they can't do
1610 anything with it) so from here on we just continue as if
1611 nothing had happened */
1612 sessionInfoPtr->protocolFlags |= SSL_PFLAG_CLIAUTHSKIPPED;
1613 needClientCert = FALSE;
1614 }
1615
1616 /* If we haven't sent a response yet, send it now. If no private
1617 key is available this will send the zero-length chain that's
1618 required by TLS */
1619 if( !sentResponse )
1620 {
1621 status = writeSSLCertChain( sessionInfoPtr, stream );
1622 if( cryptStatusError( status ) )
1623 {
1624 sMemDisconnect( stream );
1625 return( status );
1626 }
1627 }
1628 }
1629
1630 /* Build the client key exchange packet */
1631 status = continueHSPacketStream( stream, SSL_HAND_CLIENT_KEYEXCHANGE,
1632 &packetOffset );
1633 if( cryptStatusOK( status ) )
1634 {
1635 status = createClientKeyex( sessionInfoPtr, handshakeInfo, stream,
1636 isKeyxAlgo( handshakeInfo->keyexAlgo ) ? \
1637 keyexPublicValue : NULL,
1638 keyexPublicValueLen,
1639 ( handshakeInfo->authAlgo == CRYPT_ALGO_NONE ) ? \
1640 TRUE : FALSE );
1641 }
1642 if( cryptStatusOK( status ) )
1643 status = completeHSPacketStream( stream, packetOffset );
1644 if( cryptStatusError( status ) )
1645 {
1646 sMemDisconnect( stream );
1647 return( status );
1648 }
1649
1650 /* Wrap up the packet and create the session hash if required */
1651 status = completePacketStreamSSL( stream, 0 );
1652 if( cryptStatusOK( status ) )
1653 status = hashHSPacketWrite( handshakeInfo, stream, 0 );
1654 if( cryptStatusOK( status ) && \
1655 ( ( sessionInfoPtr->protocolFlags & SSL_PFLAG_EMS ) || \
1656 needClientCert ) )
1657 {
1658 status = createSessionHash( sessionInfoPtr, handshakeInfo );
1659 }
1660 if( cryptStatusError( status ) )
1661 {
1662 sMemDisconnect( stream );
1663 return( status );
1664 }
1665
1666 /* If we need to supply a client certificate, send the signature
1667 generated with the certificate to prove possession of the private
1668 key */
1669 if( needClientCert )
1670 {
1671 int packetStreamOffset;
1672
1673 /* Write the packet header and drop in the signature data. Since
1674 we've interrupted the packet stream to perform the hashing we
1675 have to restart it at this point */
1676 status = continuePacketStreamSSL( stream, sessionInfoPtr,
1677 SSL_MSG_HANDSHAKE,
1678 &packetStreamOffset );
1679 if( cryptStatusError( status ) )
1680 return( status );
1681 status = continueHSPacketStream( stream, SSL_HAND_CLIENT_CERTVERIFY,
1682 &packetOffset );
1683 if( cryptStatusOK( status ) )
1684 status = createCertVerify( sessionInfoPtr, handshakeInfo,
1685 stream );
1686 if( cryptStatusOK( status ) )
1687 status = completeHSPacketStream( stream, packetOffset );
1688 if( cryptStatusError( status ) )
1689 {
1690 sMemDisconnect( stream );
1691 return( status );
1692 }
1693
1694 /* Wrap the packet and perform the assorted hashing for it */
1695 status = completePacketStreamSSL( stream, packetStreamOffset );
1696 if( cryptStatusOK( status ) )
1697 status = hashHSPacketWrite( handshakeInfo, stream,
1698 packetStreamOffset );
1699 return( status );
1700 }
1701
1702 return( CRYPT_OK );
1703 }
1704
1705 /****************************************************************************
1706 * *
1707 * Session Access Routines *
1708 * *
1709 ****************************************************************************/
1710
1711 STDC_NONNULL_ARG( ( 1 ) ) \
initSSLclientProcessing(INOUT SSL_HANDSHAKE_INFO * handshakeInfo)1712 void initSSLclientProcessing( INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
1713 {
1714 assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
1715
1716 FNPTR_SET( handshakeInfo->beginHandshake, beginClientHandshake );
1717 FNPTR_SET( handshakeInfo->exchangeKeys, exchangeClientKeys );
1718 }
1719 #endif /* USE_SSL */
1720