cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ssl_svr.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib SSL v3/TLS Server Management *
4 * Copyright Peter Gutmann 1998-2011 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "misc_rw.h"
11  #include "session.h"
12  #include "ssl.h"
13 #else
14  #include "crypt.h"
15  #include "enc_dec/misc_rw.h"
16  #include "session/session.h"
17  #include "session/ssl.h"
18 #endif /* Compiler-specific includes */
19 
20 #ifdef USE_SSL
21 
22 /* Determine whether the server needs to request client certificates/client
23  authentication. This is normally determined by whether an access-control
24  keyset is available, but for the Suite B tests in which any test
25  certificate is regarded as being acceptable it can be overridden with a
26  self-test flag */
27 
28 #ifdef CONFIG_SUITEB_TESTS
29 #define clientCertAuthRequired( sessionInfoPtr ) \
30  ( sessionInfoPtr->cryptKeyset != CRYPT_ERROR || suiteBTestClientCert )
31 #else
32 #define clientCertAuthRequired( sessionInfoPtr ) \
33  ( sessionInfoPtr->cryptKeyset != CRYPT_ERROR )
34 #endif /* CONFIG_SUITEB_TESTS */
35 
36 /****************************************************************************
37 * *
38 * Utility Functions *
39 * *
40 ****************************************************************************/
41 
42 /* Read the client certificate chain and make sure that the certificate
43  being presented is valid for access */
44 
45 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
46 static int readCheckClientCerts( INOUT SESSION_INFO *sessionInfoPtr,
49  {
50 #ifndef CONFIG_SUITEB_TESTS
51  MESSAGE_KEYMGMT_INFO getkeyInfo;
53  BYTE certID[ KEYID_SIZE + 8 ];
54 #endif /* !CONFIG_SUITEB_TESTS */
55 #ifdef CONFIG_SUITEB
56  int length;
57 #endif /* CONFIG_SUITEB */
58  int status;
59 
60  /* Read the client certificate chain */
61  status = readSSLCertChain( sessionInfoPtr, handshakeInfo, stream,
62  &sessionInfoPtr->iKeyexAuthContext, TRUE );
63  if( cryptStatusError( status ) )
64  return( status );
65 
66  /* Make sure that the client certificate is present in our certificate
67  store. Since we've already got a copy of the certificate, we only do
68  a presence check rather than actually fetching the certificate */
69 #ifndef CONFIG_SUITEB_TESTS
70  setMessageData( &msgData, certID, KEYID_SIZE );
71  status = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext,
72  IMESSAGE_GETATTRIBUTE_S, &msgData,
74  if( cryptStatusOK( status ) )
75  {
76  setMessageKeymgmtInfo( &getkeyInfo, CRYPT_IKEYID_CERTID, certID,
78  status = krnlSendMessage( sessionInfoPtr->cryptKeyset,
79  IMESSAGE_KEY_GETKEY, &getkeyInfo,
81  }
82  if( cryptStatusError( status ) )
83  {
86  "Client certificate is not trusted for authentication "
87  "purposes" ) );
88  }
89 #endif /* CONFIG_SUITEB_TESTS */
90 
91  /* Make sure that the key is of the appropriate size for the Suite B
92  security level. At the 128-bit level both P256 and P384 are allowed,
93  at the 256-bit level only P384 is allowed */
94 #ifdef CONFIG_SUITEB
95  status = krnlSendMessage( sessionInfoPtr->iKeyexAuthContext,
96  IMESSAGE_GETATTRIBUTE, &length,
98  if( cryptStatusOK( status ) )
99  {
100  const int suiteBtype = \
101  sessionInfoPtr->protocolFlags & SSL_PFLAG_SUITEB;
102 
103  if( suiteBtype == SSL_PFLAG_SUITEB_256 )
104  {
105  if( length != bitsToBytes( 384 ) )
106  {
109  "Client Suite B certificate uses %d-bit key at "
110  "256-bit security level, should use 384-bit key",
111  bytesToBits( length ) ) );
112  }
113  }
114  else
115  {
116  if( length != bitsToBytes( 256 ) && \
117  length != bitsToBytes( 384 ) )
118  {
121  "Client Suite B certificate uses %d-bit key at "
122  "128-bit security level, should use 256- or "
123  "384-bit key", bytesToBits( length ) ) );
124  }
125  }
126  }
127 #endif /* CONFIG_SUITEB */
128 
129  return( CRYPT_OK );
130  }
131 
132 
133 /* Write the certificate request:
134 
135  [ byte ID = SSL_HAND_SERVER_CERTREQUEST ]
136  [ uint24 len -- Written by caller ]
137  byte certTypeLen
138  byte[] certType = { RSA, DSA, ECDSA }
139  [ uint16 sigHashListLen -- TLS 1.2 ]
140  [ byte hashAlgoID -- TLS 1.2 ]
141  [ byte sigAlgoID -- TLS 1.2 ]
142  uint16 caNameListLen = 4
143  uint16 caNameLen = 2
144  byte[] caName = { 0x30, 0x00 }
145 
146  This message is a real mess, it originally had a rather muddled
147  certificate-type indicator (which included things like "Ephemeral DH
148  signed with RSA") and an equally ambiguous CA list that many
149  implementations either left empty or filled with the name of every CA
150  that they'd ever heard of. TLS 1.2 added a means of indicating which
151  signature and hash algorithms were acceptable, which is kind of essential
152  because the explosion of hash algorithms in 1.2 means that a server would
153  have to run parallel hashes of every handshake message for every possible
154  hash algorithm until the client sends their certificate-verify message
155  (!!). In other words although it was planned as a means of indicating
156  the server's capabilities, it actually acts as a mechanism for keeping
157  the client-auth process manageable */
158 
159 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
160 static int writeCertRequest( INOUT SESSION_INFO *sessionInfoPtr,
161  INOUT SSL_HANDSHAKE_INFO *handshakeInfo,
162  INOUT STREAM *stream )
163  {
164  const BOOLEAN rsaAvailable = algoAvailable( CRYPT_ALGO_RSA );
165  const BOOLEAN dsaAvailable = algoAvailable( CRYPT_ALGO_DSA );
166  const BOOLEAN ecdsaAvailable = algoAvailable( CRYPT_ALGO_ECDSA );
167 
168  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
169  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
170 
171  REQUIRES( rsaAvailable || ecdsaAvailable );
172 
173  /* Write the certificate type */
174  sputc( stream, ( rsaAvailable ? 1 : 0 ) + \
175  ( dsaAvailable ? 1 : 0 ) + \
176  ( ecdsaAvailable ? 1 : 0 ) );
177  if( rsaAvailable )
178  sputc( stream, TLS_CERTTYPE_RSA );
179  if( dsaAvailable )
180  sputc( stream, TLS_CERTTYPE_DSA );
181  if( ecdsaAvailable )
182  sputc( stream, TLS_CERTTYPE_ECDSA );
183 
184  /* Write the list of accepted signature and hash algorithms if required.
185  In theory we could write the full list of algorithms, but thanks to
186  SSL/TLS' braindamaged way of handling certificate-based
187  authentication (see the comment above) this would make the
188  certificate-authentication process unmanageable. To get around this
189  we only allow one single algorithm, the SHA-2 default for TLS 1.2+.
190  In addition we can't allow DSA because it's only defined for use with
191  SHA-1 (unless we go for "DSA-2" / FIPS 186-3 key sizes like 2048
192  bits, which nothing seems to support).
193 
194  For Suite B things get a bit more complicated because this allows
195  both SHA-256 and SHA-384, dropping us straight back into the mess
196  that we've just escaped from. To get around this we specify the
197  use of the hash algorithm that we've negotiated for the handshake,
198  on the assumption that a client using SHA384 for the handshake isn't
199  going to then try and use SHA256 for the authentication */
200  if( sessionInfoPtr->version >= SSL_MINOR_VERSION_TLS12 )
201  {
202 #ifdef CONFIG_SUITEB
203  writeUint16( stream, 2 );
204  if( handshakeInfo->keyexSigHashAlgoParam == bitsToBytes( 384 ) )
205  sputc( stream, TLS_HASHALGO_SHA384 );
206  else
207  sputc( stream, TLS_HASHALGO_SHA2 );
208  sputc( stream, TLS_SIGALGO_ECDSA );
209 #else
210  writeUint16( stream, ( rsaAvailable ? 2 : 0 ) + \
211  ( ecdsaAvailable ? 2 : 0 ) );
212  if( rsaAvailable )
213  {
214  sputc( stream, TLS_HASHALGO_SHA2 );
215  sputc( stream, TLS_SIGALGO_RSA );
216  }
217  if( ecdsaAvailable )
218  {
219  sputc( stream, TLS_HASHALGO_SHA2 );
220  sputc( stream, TLS_SIGALGO_ECDSA );
221  }
222 #endif /* CONFIG_SUITEB */
223  }
224 
225  /* Write the CA name list */
226  writeUint16( stream, UINT16_SIZE + 2 );
227  writeUint16( stream, 2 );
228  return( swrite( stream, "\x30\x00", 2 ) );
229  }
230 
231 /****************************************************************************
232 * *
233 * Server-side Connect Functions *
234 * *
235 ****************************************************************************/
236 
237 /* Perform the initial part of the handshake with the client */
238 
239 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
240 int beginServerHandshake( INOUT SESSION_INFO *sessionInfoPtr,
241  INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
242  {
243  STREAM *stream = &handshakeInfo->stream;
246  int length, resumedSessionID = CRYPT_ERROR;
247  int packetOffset, status;
248 
249  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
250  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
251 
252  /* Read and process the client hello */
253  status = readHSPacketSSL( sessionInfoPtr, handshakeInfo, &length,
255  if( cryptStatusError( status ) )
256  return( status );
257  sMemConnect( stream, sessionInfoPtr->receiveBuffer, length );
258  status = processHelloSSL( sessionInfoPtr, handshakeInfo, stream, TRUE );
259  sMemDisconnect( stream );
260  if( cryptStatusError( status ) )
261  {
262  if( status != OK_SPECIAL )
263  return( status );
264 
265  /* The client has sent us a sessionID in an attempt to resume a
266  previous session, see if it's in the session cache */
267  resumedSessionID = \
268  lookupScoreboardEntry( sessionInfoPtr->sessionSSL->scoreboardInfoPtr,
269  SCOREBOARD_KEY_SESSIONID_SVR, handshakeInfo->sessionID,
270  handshakeInfo->sessionIDlength,
271  &lookupResult );
272 #ifdef CONFIG_SUITEB_TESTS
273  resumedSessionID = CRYPT_ERROR; /* Disable for Suite B tests */
274 #endif /* CONFIG_SUITEB_TESTS */
275  }
276 
277  /* Handle session resumption. If it's a new session or the session data
278  has expired from the cache, generate a new session ID */
279  if( cryptStatusError( resumedSessionID ) )
280  {
281  setMessageData( &msgData, handshakeInfo->sessionID, SESSIONID_SIZE );
283  IMESSAGE_GETATTRIBUTE_S, &msgData,
284  CRYPT_IATTRIBUTE_RANDOM_NONCE );
285  if( cryptStatusError( status ) )
286  return( status );
287  handshakeInfo->sessionIDlength = SESSIONID_SIZE;
288  }
289  else
290  {
291  /* We're resuming a previous session, remember the premaster secret */
292  status = attributeCopyParams( handshakeInfo->premasterSecret,
294  &handshakeInfo->premasterSecretSize,
295  lookupResult.data,
296  lookupResult.dataSize );
297  ENSURES( cryptStatusOK( status ) );
298  }
299 
300  /* Get the nonce that's used to randomise all crypto operations and set
301  up the server DH/ECDH context if necessary */
302  setMessageData( &msgData, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
304  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
305  if( cryptStatusOK( status ) && isKeyxAlgo( handshakeInfo->keyexAlgo ) )
306  {
307  status = initDHcontextSSL( &handshakeInfo->dhContext, NULL, 0,
308  ( handshakeInfo->authAlgo != CRYPT_ALGO_NONE ) ? \
309  sessionInfoPtr->privateKey : CRYPT_UNUSED,
310  isEccAlgo( handshakeInfo->keyexAlgo ) ? \
311  handshakeInfo->eccCurveID : CRYPT_ECCCURVE_NONE );
312  }
313  if( cryptStatusError( status ) )
314  return( status );
315 
316  /* Build the server hello, certificate, optional certificate request,
317  and done packets:
318 
319  byte ID = SSL_HAND_SERVER_HELLO
320  uint24 len
321  byte[2] version = { 0x03, 0x0n }
322  byte[32] nonce
323  byte sessIDlen
324  byte[] sessID
325  uint16 suite
326  byte copr = 0
327  [ uint16 extListLen -- RFC 3546/RFC 4366
328  byte extType
329  uint16 extLen
330  byte[] extData ]
331  ...
332 
333  We have to be careful how we handle extensions because the RFC makes
334  the rather optimistic assumption that implementations can handle the
335  presence of unexpected data at the end of the hello packet, to avoid
336  problems with this we avoid sending extensions unless they're in
337  response to extensions already sent by the client */
338  status = openPacketStreamSSL( stream, sessionInfoPtr, CRYPT_USE_DEFAULT,
340  if( cryptStatusError( status ) )
341  return( status );
342  status = continueHSPacketStream( stream, SSL_HAND_SERVER_HELLO,
343  &packetOffset );
344  if( cryptStatusError( status ) )
345  {
346  sMemDisconnect( stream );
347  return( status );
348  }
349  sputc( stream, SSL_MAJOR_VERSION );
350  sputc( stream, sessionInfoPtr->version );
351  swrite( stream, handshakeInfo->serverNonce, SSL_NONCE_SIZE );
352  sputc( stream, handshakeInfo->sessionIDlength );
353  swrite( stream, handshakeInfo->sessionID,
354  handshakeInfo->sessionIDlength );
355  writeUint16( stream, handshakeInfo->cipherSuite );
356  status = sputc( stream, 0 ); /* No compression */
357  if( handshakeInfo->hasExtensions )
358  status = writeServerExtensions( stream, handshakeInfo );
359  if( cryptStatusOK( status ) )
360  status = completeHSPacketStream( stream, packetOffset );
361  if( cryptStatusError( status ) )
362  {
363  sMemDisconnect( stream );
364  return( status );
365  }
366 
367  /* If it's a resumed session then the server hello is followed
368  immediately by the change cipherspec, which is sent by the shared
369  handshake completion code */
370  if( !cryptStatusError( resumedSessionID ) )
371  {
372  status = completePacketStreamSSL( stream, 0 );
373  if( cryptStatusOK( status ) )
374  status = hashHSPacketWrite( handshakeInfo, stream, 0 );
375  if( cryptStatusError( status ) )
376  {
377  sMemDisconnect( stream );
378  return( status );
379  }
380 
381  /* Tell the caller that it's a resumed session, leaving the stream
382  open in order to write the change cipherspec message that follows
383  the server hello in a resumed session */
384  DEBUG_PRINT(( "Resuming session with client based on "
385  "sessionID = \n" ));
386  DEBUG_DUMP_DATA( handshakeInfo->sessionID,
387  handshakeInfo->sessionIDlength );
388  return( OK_SPECIAL );
389  }
390 
391  /* ... (optional server supplemental data)
392  byte ID = SSL_HAND_SUPPLEMENTAL_DATA
393  uint24 len
394  uint16 type
395  uint16 len
396  byte[] value
397  ... */
398 
399  /* ...
400  (optional server certificate chain)
401  ... */
402  if( handshakeInfo->authAlgo != CRYPT_ALGO_NONE )
403  {
404  status = writeSSLCertChain( sessionInfoPtr, stream );
405  if( cryptStatusError( status ) )
406  {
407  sMemDisconnect( stream );
408  return( status );
409  }
410  }
411 
412  /* ... (optional server keyex)
413  byte ID = SSL_HAND_SERVER_KEYEXCHANGE
414  uint24 len
415  DH:
416  uint16 dh_pLen
417  byte[] dh_p
418  uint16 dh_gLen
419  byte[] dh_g
420  uint16 dh_YsLen
421  byte[] dh_Ys
422  [ byte hashAlgoID -- TLS 1.2 ]
423  [ byte sigAlgoID -- TLS 1.2 ]
424  uint16 signatureLen
425  byte[] signature
426  ECDH:
427  byte curveType
428  uint16 namedCurve
429  uint8 ecPointLen -- NB uint8 not uint16
430  byte[] ecPoint
431  [ byte hashAlgoID -- TLS 1.2 ]
432  [ byte sigAlgoID -- TLS 1.2 ]
433  uint16 signatureLen
434  byte[] signature */
435  if( isKeyxAlgo( handshakeInfo->keyexAlgo ) )
436  {
437  KEYAGREE_PARAMS keyAgreeParams;
438  void *keyData = DUMMY_INIT_PTR;
439  int keyDataOffset, keyDataLength = DUMMY_INIT;
440 
441  /* Perform phase 1 of the DH/ECDH key agreement process */
442  memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
443  status = krnlSendMessage( handshakeInfo->dhContext,
444  IMESSAGE_CTX_ENCRYPT, &keyAgreeParams,
445  sizeof( KEYAGREE_PARAMS ) );
446  if( cryptStatusError( status ) )
447  {
448  zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
449  sMemDisconnect( stream );
450  return( status );
451  }
452 
453  /* Write the DH/ECDH key parameters and public value and sign them */
454  status = continueHSPacketStream( stream, SSL_HAND_SERVER_KEYEXCHANGE,
455  &packetOffset );
456  if( cryptStatusError( status ) )
457  {
458  zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
459  sMemDisconnect( stream );
460  return( status );
461  }
462  keyDataOffset = stell( stream );
463  status = exportAttributeToStream( stream, handshakeInfo->dhContext,
464  CRYPT_IATTRIBUTE_KEY_SSL );
465  if( cryptStatusOK( status ) )
466  {
467  if( isEccAlgo( handshakeInfo->keyexAlgo ) )
468  {
469  sputc( stream, keyAgreeParams.publicValueLen );
470  swrite( stream, keyAgreeParams.publicValue,
471  keyAgreeParams.publicValueLen );
472  }
473  else
474  {
475  status = writeInteger16U( stream, keyAgreeParams.publicValue,
476  keyAgreeParams.publicValueLen );
477  }
478  }
479  if( cryptStatusOK( status ) )
480  {
481  keyDataLength = stell( stream ) - keyDataOffset;
482  status = sMemGetDataBlockAbs( stream, keyDataOffset, &keyData,
483  keyDataLength );
484  }
485  if( cryptStatusOK( status ) )
486  {
487  status = createKeyexSignature( sessionInfoPtr, handshakeInfo,
488  stream, keyData, keyDataLength );
489  }
490  zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
491  if( cryptStatusOK( status ) )
492  status = completeHSPacketStream( stream, packetOffset );
493  if( cryptStatusError( status ) )
494  {
495  sMemDisconnect( stream );
496  return( status );
497  }
498  }
499 
500  /* ... (optional request for client certificate authentication)
501  byte ID = SSL_HAND_SERVER_CERTREQUEST
502  uint24 len
503  byte certTypeLen
504  byte[] certType = { RSA, DSA, ECDSA }
505  [ uint16 sigHashListLen -- TLS 1.2 ]
506  [ byte hashAlgoID -- TLS 1.2 ]
507  [ byte sigAlgoID -- TLS 1.2 ]
508  uint16 caNameListLen = 4
509  uint16 caNameLen = 2
510  byte[] caName = { 0x30, 0x00 }
511  ... */
512  if( clientCertAuthRequired( sessionInfoPtr ) )
513  {
514  status = continueHSPacketStream( stream, SSL_HAND_SERVER_CERTREQUEST,
515  &packetOffset );
516  if( cryptStatusError( status ) )
517  {
518  sMemDisconnect( stream );
519  return( status );
520  }
521  status = writeCertRequest( sessionInfoPtr, handshakeInfo, stream );
522  if( cryptStatusOK( status ) )
523  status = completeHSPacketStream( stream, packetOffset );
524  if( cryptStatusError( status ) )
525  {
526  sMemDisconnect( stream );
527  return( status );
528  }
529  }
530 
531  /* ...
532  byte ID = SSL_HAND_SERVER_HELLODONE
533  uint24 len = 0 */
534  status = continueHSPacketStream( stream, SSL_HAND_SERVER_HELLODONE,
535  &packetOffset );
536  if( cryptStatusOK( status ) )
537  status = completeHSPacketStream( stream, packetOffset );
538  if( cryptStatusError( status ) )
539  {
540  sMemDisconnect( stream );
541  return( status );
542  }
543 
544  /* Send the combined server packets to the client. We perform the
545  assorted hashing of the packets in between the network ops where
546  it's effectively free */
547  status = sendPacketSSL( sessionInfoPtr, stream, FALSE );
548  if( cryptStatusOK( status ) )
549  status = hashHSPacketWrite( handshakeInfo, stream, 0 );
550  sMemDisconnect( stream );
551  return( status );
552  }
553 
554 /* Exchange keys with the client */
555 
556 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
557 int exchangeServerKeys( INOUT SESSION_INFO *sessionInfoPtr,
558  INOUT SSL_HANDSHAKE_INFO *handshakeInfo )
559  {
560  STREAM *stream = &handshakeInfo->stream;
561  int length, status;
562 
563  assert( isWritePtr( sessionInfoPtr, sizeof( SESSION_INFO ) ) );
564  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
565 
566  /* Read the response from the client and, if we're expecting a client
567  certificate, make sure that it's present */
568  status = readHSPacketSSL( sessionInfoPtr, handshakeInfo, &length,
570  if( cryptStatusError( status ) )
571  return( status );
572  sMemConnect( stream, sessionInfoPtr->receiveBuffer, length );
573  if( clientCertAuthRequired( sessionInfoPtr ) )
574  {
575  /* Read the client certificate chain and make sure that the
576  certificate being presented is valid for access */
577  status = readCheckClientCerts( sessionInfoPtr, handshakeInfo,
578  stream );
579  if( cryptStatusError( status ) )
580  {
581  sMemDisconnect( stream );
582  return( status );
583  }
584 
585  /* Read the next packet(s) if necessary */
586  status = refreshHSStream( sessionInfoPtr, handshakeInfo );
587  if( cryptStatusError( status ) )
588  return( status );
589  }
590 
591  /* Process the client key exchange packet:
592 
593  byte ID = SSL_HAND_CLIENT_KEYEXCHANGE
594  uint24 len
595  DH:
596  uint16 yLen
597  byte[] y
598  ECDH:
599  uint16 ecPointLen
600  byte[] ecPoint
601  PSK:
602  uint16 userIDLen
603  byte[] userID
604  RSA:
605  [ uint16 encKeyLen -- TLS 1.x ]
606  byte[] rsaPKCS1( byte[2] { 0x03, 0x0n } || byte[46] random ) */
607  status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
609  UINT16_SIZE + 1 );
610  if( cryptStatusError( status ) )
611  {
612  sMemDisconnect( stream );
613  return( status );
614  }
615  if( isKeyxAlgo( handshakeInfo->keyexAlgo ) )
616  {
617  KEYAGREE_PARAMS keyAgreeParams;
618  const BOOLEAN isECC = isEccAlgo( handshakeInfo->keyexAlgo );
619 
620  memset( &keyAgreeParams, 0, sizeof( KEYAGREE_PARAMS ) );
621  if( isECC )
622  {
623  status = readEcdhValue( stream, keyAgreeParams.publicValue,
625  &keyAgreeParams.publicValueLen );
626  }
627  else
628  {
629  status = readInteger16UChecked( stream,
630  keyAgreeParams.publicValue,
631  &keyAgreeParams.publicValueLen,
633  }
634  if( cryptStatusError( status ) )
635  {
636  sMemDisconnect( stream );
637 
638  /* Some misconfigured clients may use very short keys, we
639  perform a special-case check for these and return a more
640  specific message than the generic bad-data error */
641  if( status == CRYPT_ERROR_NOSECURE )
642  {
645  "Insecure key used in key exchange" ) );
646  }
647 
650  "Invalid DH/ECDH phase 2 key agreement data" ) );
651  }
652 
653  /* Perform phase 2 of the DH/ECDH key agreement */
654  status = krnlSendMessage( handshakeInfo->dhContext,
655  IMESSAGE_CTX_DECRYPT, &keyAgreeParams,
656  sizeof( KEYAGREE_PARAMS ) );
657  if( cryptStatusError( status ) )
658  {
659  zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
660  sMemDisconnect( stream );
661  retExt( status,
662  ( status, SESSION_ERRINFO,
663  "Invalid DH/ECDH phase 2 key agreement value" ) );
664  }
665  if( isECC )
666  {
667  const int xCoordLen = ( keyAgreeParams.wrappedKeyLen - 1 ) / 2;
668 
669  /* The output of the ECDH operation is an ECC point, but for
670  some unknown reason TLS only uses the x coordinate and not
671  the full point. To work around this we have to rewrite the
672  point as a standalone x coordinate, which is relatively
673  easy because we're using an "uncompressed" point format:
674 
675  +---+---------------+---------------+
676  |04 | qx | qy |
677  +---+---------------+---------------+
678  |<- fldSize --> |<- fldSize --> | */
679  REQUIRES( keyAgreeParams.wrappedKeyLen >= MIN_PKCSIZE_ECCPOINT && \
680  keyAgreeParams.wrappedKeyLen <= MAX_PKCSIZE_ECCPOINT && \
681  ( keyAgreeParams.wrappedKeyLen & 1 ) == 1 && \
682  keyAgreeParams.wrappedKey[ 0 ] == 0x04 );
683  memmove( keyAgreeParams.wrappedKey,
684  keyAgreeParams.wrappedKey + 1, xCoordLen );
685  keyAgreeParams.wrappedKeyLen = xCoordLen;
686  }
687  ENSURES( rangeCheckZ( 0, keyAgreeParams.wrappedKeyLen,
689  memcpy( handshakeInfo->premasterSecret, keyAgreeParams.wrappedKey,
690  keyAgreeParams.wrappedKeyLen );
691  handshakeInfo->premasterSecretSize = keyAgreeParams.wrappedKeyLen;
692  zeroise( &keyAgreeParams, sizeof( KEYAGREE_PARAMS ) );
693  }
694  else
695  {
696  if( handshakeInfo->authAlgo == CRYPT_ALGO_NONE )
697  {
699  BYTE userID[ CRYPT_MAX_TEXTSIZE + 8 ];
700 
701  /* Read the client user ID and make sure that it's a valid
702  user. Handling non-valid users is somewhat problematic,
703  we can either bail out immediately or invent a fake
704  password for the (non-)user and continue with that. The
705  problem with this is that it doesn't really help hide
706  whether the user is valid or not due to the fact that we're
707  still vulnerable to a timing attack because it takes
708  considerably longer to generate the random password than it
709  does to read a fixed password string from memory, so an
710  attacker can tell from the timing whether the username is
711  valid or not. In addition usability research on real-world
712  users indicates that this actually reduces security while
713  having little to no tangible benefit. Because of this we
714  don't try and fake out the valid/invalid user name indication
715  but just exit immediately if an invalid name is found */
716  length = readUint16( stream );
717  if( length < 1 || length > CRYPT_MAX_TEXTSIZE || \
718  cryptStatusError( sread( stream, userID, length ) ) )
719  {
720  sMemDisconnect( stream );
723  "Invalid client user ID" ) );
724  }
725  attributeListPtr = \
726  findSessionInfoEx( sessionInfoPtr->attributeList,
727  CRYPT_SESSINFO_USERNAME, userID, length );
728  if( attributeListPtr == NULL )
729  {
730  sMemDisconnect( stream );
733  "Unknown user name '%s'",
734  sanitiseString( userID, CRYPT_MAX_TEXTSIZE,
735  length ) ) );
736  }
737 
738  /* Select the attribute with the user ID and move on to the
739  associated password */
740  sessionInfoPtr->attributeListCurrent = \
741  ( ATTRIBUTE_LIST * ) attributeListPtr;
742  attributeListPtr = attributeListPtr->next;
743  ENSURES( attributeListPtr != NULL && \
744  attributeListPtr->attributeID == CRYPT_SESSINFO_PASSWORD );
745 
746  /* Create the shared premaster secret from the user password */
747  status = createSharedPremasterSecret( \
748  handshakeInfo->premasterSecret,
750  &handshakeInfo->premasterSecretSize,
751  attributeListPtr->value,
752  attributeListPtr->valueLength,
753  ( attributeListPtr->flags & ATTR_FLAG_ENCODEDVALUE ) ? \
754  TRUE : FALSE );
755  if( cryptStatusError( status ) )
756  {
757  sMemDisconnect( stream );
758  retExt( status,
759  ( status, SESSION_ERRINFO,
760  "Couldn't create master secret from shared "
761  "secret/password value" ) );
762  }
763  }
764  else
765  {
766  BYTE wrappedKey[ CRYPT_MAX_PKCSIZE + 8 ];
767 
768  if( sessionInfoPtr->version <= SSL_MINOR_VERSION_SSL )
769  {
770  /* The original Netscape SSL implementation didn't provide a
771  length for the encrypted key and everyone copied that so
772  it became the de facto standard way to do it (sic faciunt
773  omnes. The spec itself is ambiguous on the topic). This
774  was fixed in TLS (although the spec is still ambigous) so
775  the encoding differs slightly between SSL and TLS. To
776  work around this we have to duplicate a certain amount of
777  the integer-read code here */
778  if( isShortPKCKey( length ) )
779  status = CRYPT_ERROR_NOSECURE;
780  else
781  {
782  if( length < MIN_PKCSIZE || length > CRYPT_MAX_PKCSIZE || \
783  cryptStatusError( sread( stream, wrappedKey, length ) ) )
784  status = CRYPT_ERROR_BADDATA;
785  }
786  }
787  else
788  {
789  status = readInteger16UChecked( stream, wrappedKey, &length,
790  MIN_PKCSIZE,
792  }
793  if( cryptStatusError( status ) )
794  {
795  sMemDisconnect( stream );
796 
797  /* Some misconfigured clients may use very short keys, we
798  perform a special-case check for these and return a more
799  specific message than the generic bad-data */
800  if( status == CRYPT_ERROR_NOSECURE )
801  {
804  "Insecure key used in key exchange" ) );
805  }
806 
809  "Invalid RSA encrypted key data" ) );
810  }
811 
812  /* Decrypt the pre-master secret */
813  status = unwrapPremasterSecret( sessionInfoPtr, handshakeInfo,
814  wrappedKey, length );
815  if( cryptStatusError( status ) )
816  {
817  sMemDisconnect( stream );
818  return( status );
819  }
820  }
821  }
822 
823  /* If we're expecting a client certificate, process the client
824  certificate verify */
825  if( clientCertAuthRequired( sessionInfoPtr ) )
826  {
827  const BOOLEAN isECC = isEccAlgo( handshakeInfo->keyexAlgo );
828 
829  /* Since the client certificate-verify message requires the hash of
830  all handshake packets up to this point, we have to interrupt the
831  processing to calculate the hash before we continue */
832  status = createCertVerifyHash( sessionInfoPtr, handshakeInfo );
833  if( cryptStatusError( status ) )
834  return( status );
835 
836  /* Read the next packet(s) if necessary */
837  status = refreshHSStream( sessionInfoPtr, handshakeInfo );
838  if( cryptStatusError( status ) )
839  return( status );
840 
841  /* Process the client certificate verify packet:
842 
843  byte ID = SSL_HAND_CLIENT_CERTVERIFY
844  uint24 len
845  byte[] signature */
846  status = checkHSPacketHeader( sessionInfoPtr, stream, &length,
848  isECC ? MIN_PKCSIZE_ECCPOINT : \
849  MIN_PKCSIZE );
850  if( cryptStatusOK( status ) )
851  status = checkCertVerify( sessionInfoPtr, handshakeInfo, stream,
852  length );
853  if( cryptStatusError( status ) )
854  {
855  sMemDisconnect( stream );
856  return( status );
857  }
858  }
859  sMemDisconnect( stream );
860 
861  return( CRYPT_OK );
862  }
863 
864 /****************************************************************************
865 * *
866 * Session Access Routines *
867 * *
868 ****************************************************************************/
869 
870 STDC_NONNULL_ARG( ( 1 ) ) \
871 void initSSLserverProcessing( SSL_HANDSHAKE_INFO *handshakeInfo )
872  {
873  assert( isWritePtr( handshakeInfo, sizeof( SSL_HANDSHAKE_INFO ) ) );
874 
875  handshakeInfo->beginHandshake = beginServerHandshake;
876  handshakeInfo->exchangeKeys = exchangeServerKeys;
877  }
878 #endif /* USE_SSL */