2  * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. 
   4  * The contents of this file constitute Original Code as defined in and are 
   5  * subject to the Apple Public Source License Version 1.2 (the 'License'). 
   6  * You may not use this file except in compliance with the License. Please obtain 
   7  * a copy of the License at http://www.apple.com/publicsource and read it before 
  10  * This Original Code and all software distributed under the License are 
  11  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS 
  12  * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT 
  13  * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
  14  * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the 
  15  * specific language governing rights and limitations under the License. 
  20         File:           sslHandshakeHello.c 
  22         Contains:       Support for client hello and server hello messages.  
  24         Written by:     Doug Mitchell 
  26         Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved. 
  30 #include "sslContext.h" 
  31 #include "sslHandshake.h" 
  32 #include "sslMemory.h" 
  33 #include "sslSession.h" 
  36 #include "appleCdsa.h" 
  37 #include "sslDigests.h" 
  38 #include "cipherSpecs.h" 
  42 static OSStatus 
SSLEncodeRandom(unsigned char *p
, SSLContext 
*ctx
); 
  44 /* IE treats null session id as valid; two consecutive sessions with NULL ID 
  45  * are considered a match. Workaround: when resumable sessions are disabled,  
  46  * send a random session ID. */ 
  47 #define SSL_IE_NULL_RESUME_BUG          1 
  48 #if             SSL_IE_NULL_RESUME_BUG 
  49 #define SSL_NULL_ID_LEN                         32      /* length of bogus session ID */ 
  53 SSLEncodeServerHello(SSLRecord 
&serverHello
, SSLContext 
*ctx
) 
  59     if (ctx
->sessionID
.data 
!= 0) 
  60         sessionIDLen 
= (UInt8
)ctx
->sessionID
.length
; 
  61         #if     SSL_IE_NULL_RESUME_BUG 
  62         if(sessionIDLen 
== 0) { 
  63                 sessionIDLen 
= SSL_NULL_ID_LEN
; 
  65         #endif  /* SSL_IE_NULL_RESUME_BUG */ 
  67         /* this was set to a known quantity in SSLProcessClientHello */ 
  68         assert(ctx
->negProtocolVersion 
!= SSL_Version_Undetermined
); 
  69         /* should not be here in this case */ 
  70         assert(ctx
->negProtocolVersion 
!= SSL_Version_2_0
); 
  71         sslLogNegotiateDebug("===SSL3 server: sending version %d_%d", 
  72                 ctx
->negProtocolVersion 
>> 8, ctx
->negProtocolVersion 
& 0xff); 
  73         sslLogNegotiateDebug("...sessionIDLen = %d", sessionIDLen
); 
  74     serverHello
.protocolVersion 
= ctx
->negProtocolVersion
; 
  75     serverHello
.contentType 
= SSL_RecordTypeHandshake
; 
  76     if ((err 
= SSLAllocBuffer(serverHello
.contents
, 42 + sessionIDLen
, ctx
)) != 0) 
  79     charPtr 
= serverHello
.contents
.data
; 
  80     *charPtr
++ = SSL_HdskServerHello
; 
  81     charPtr 
= SSLEncodeInt(charPtr
, 38 + sessionIDLen
, 3); 
  82     charPtr 
= SSLEncodeInt(charPtr
, serverHello
.protocolVersion
, 2); 
  83     if ((err 
= SSLEncodeRandom(charPtr
, ctx
)) != 0) 
  85     memcpy(ctx
->serverRandom
, charPtr
, SSL_CLIENT_SRVR_RAND_SIZE
); 
  86     charPtr 
+= SSL_CLIENT_SRVR_RAND_SIZE
; 
  87         *(charPtr
++) = (UInt8
)sessionIDLen
; 
  88         #if     SSL_IE_NULL_RESUME_BUG 
  89         if(ctx
->sessionID
.data 
!= NULL
) { 
  90                 /* normal path for enabled resumable session */ 
  91                 memcpy(charPtr
, ctx
->sessionID
.data
, sessionIDLen
); 
  97                 rb
.length 
= SSL_NULL_ID_LEN
; 
 101     if (sessionIDLen 
> 0) 
 102         memcpy(charPtr
, ctx
->sessionID
.data
, sessionIDLen
); 
 103         #endif  /* SSL_IE_NULL_RESUME_BUG */ 
 104         charPtr 
+= sessionIDLen
; 
 105     charPtr 
= SSLEncodeInt(charPtr
, ctx
->selectedCipher
, 2); 
 106     *(charPtr
++) = 0;      /* Null compression */ 
 108     sslLogNegotiateDebug("ssl3: server specifying cipherSuite 0x%lx",  
 109                 (UInt32
)ctx
->selectedCipher
); 
 111     assert(charPtr 
== serverHello
.contents
.data 
+ serverHello
.contents
.length
); 
 117 SSLProcessServerHello(SSLBuffer message
, SSLContext 
*ctx
) 
 119     SSLProtocolVersion  protocolVersion
, negVersion
; 
 120     unsigned int        sessionIDLen
; 
 123     assert(ctx
->protocolSide 
== SSL_ClientSide
); 
 125     if (message
.length 
< 38 || message
.length 
> 70) { 
 126         sslErrorLog("SSLProcessServerHello: msg len error\n"); 
 127         return errSSLProtocol
; 
 131     protocolVersion 
= (SSLProtocolVersion
)SSLDecodeInt(p
, 2); 
 133         /* FIXME this should probably send appropriate alerts */ 
 134         err 
= sslVerifyProtVersion(ctx
, protocolVersion
, &negVersion
); 
 138     ctx
->negProtocolVersion 
= negVersion
; 
 140                 case SSL_Version_3_0
: 
 141                         ctx
->sslTslCalls 
= &Ssl3Callouts
; 
 143                 case TLS_Version_1_0
: 
 144                         ctx
->sslTslCalls 
= &Tls1Callouts
; 
 147                         return errSSLNegotiation
; 
 149     sslLogNegotiateDebug("===SSL3 client: negVersion is %d_%d", 
 150                 (negVersion 
>> 8) & 0xff, negVersion 
& 0xff); 
 152     memcpy(ctx
->serverRandom
, p
, 32); 
 156     if (message
.length 
!= 38 + sessionIDLen
) { 
 157         sslErrorLog("SSLProcessServerHello: msg len error 2\n"); 
 158         return errSSLProtocol
; 
 160     if (sessionIDLen 
> 0 && ctx
->peerID
.data 
!= 0) 
 161     {   /* Don't die on error; just treat it as an uncached session */ 
 162         err 
= SSLAllocBuffer(ctx
->sessionID
, sessionIDLen
, ctx
); 
 164             memcpy(ctx
->sessionID
.data
, p
, sessionIDLen
); 
 168     ctx
->selectedCipher 
= (UInt16
)SSLDecodeInt(p
,2); 
 169     sslLogNegotiateDebug("===ssl3: server requests cipherKind %d",  
 170         (unsigned)ctx
->selectedCipher
); 
 172     if ((err 
= FindCipherSpec(ctx
)) != 0) { 
 176     if (*p
++ != 0)      /* Compression */ 
 179     assert(p 
== message
.data 
+ message
.length
); 
 184 SSLEncodeClientHello(SSLRecord 
&clientHello
, SSLContext 
*ctx
) 
 189     SSLBuffer       sessionIdentifier
; 
 192     assert(ctx
->protocolSide 
== SSL_ClientSide
); 
 195     if (ctx
->resumableSession
.data 
!= 0) 
 196     {   if ((err 
= SSLRetrieveSessionID(ctx
->resumableSession
, 
 197                                 &sessionIdentifier
, ctx
)) != 0) 
 200         sessionIDLen 
= sessionIdentifier
.length
; 
 203     length 
= 39 + 2*(ctx
->numValidCipherSpecs
) + sessionIDLen
; 
 205         err 
= sslGetMaxProtVersion(ctx
, &clientHello
.protocolVersion
); 
 207                 /* we don't have a protocol enabled */ 
 210     clientHello
.contentType 
= SSL_RecordTypeHandshake
; 
 211     if ((err 
= SSLAllocBuffer(clientHello
.contents
, length 
+ 4, ctx
)) != 0) 
 214     p 
= clientHello
.contents
.data
; 
 215     *p
++ = SSL_HdskClientHello
; 
 216     p 
= SSLEncodeInt(p
, length
, 3); 
 217     p 
= SSLEncodeInt(p
, clientHello
.protocolVersion
, 2); 
 218         sslLogNegotiateDebug("===SSL3 client: proclaiming max protocol " 
 219                 "%d_%d capable ONLY", 
 220                 clientHello
.protocolVersion 
>> 8, clientHello
.protocolVersion 
& 0xff); 
 221    if ((err 
= SSLEncodeRandom(p
, ctx
)) != 0) 
 222     {   SSLFreeBuffer(clientHello
.contents
, ctx
); 
 225     memcpy(ctx
->clientRandom
, p
, SSL_CLIENT_SRVR_RAND_SIZE
); 
 227     *p
++ = sessionIDLen
;                                /* 1 byte vector length */ 
 228     if (sessionIDLen 
> 0) 
 229     {   memcpy(p
, sessionIdentifier
.data
, sessionIDLen
); 
 230         if ((err 
= SSLFreeBuffer(sessionIdentifier
, ctx
)) != 0) 
 234     p 
= SSLEncodeInt(p
, 2*(ctx
->numValidCipherSpecs
), 2);   
 235                                                                                         /* 2 byte long vector length */ 
 236     for (i 
= 0; i
<ctx
->numValidCipherSpecs
; ++i
) 
 237         p 
= SSLEncodeInt(p
, ctx
->validCipherSpecs
[i
].cipherSpec
, 2); 
 238     *p
++ = 1;                               /* 1 byte long vector */ 
 239     *p
++ = 0;                               /* null compression */ 
 241     assert(p 
== clientHello
.contents
.data 
+ clientHello
.contents
.length
); 
 243     if ((err 
= SSLInitMessageHashes(ctx
)) != 0) 
 250 SSLProcessClientHello(SSLBuffer message
, SSLContext 
*ctx
) 
 252     SSLProtocolVersion  negVersion
; 
 253     UInt16              cipherListLen
, cipherCount
, desiredSpec
, cipherSpec
; 
 254     UInt8               sessionIDLen
, compressionCount
; 
 258     if (message
.length 
< 41) { 
 259         sslErrorLog("SSLProcessClientHello: msg len error 1\n"); 
 260         return errSSLProtocol
; 
 262     charPtr 
= message
.data
; 
 263     ctx
->clientReqProtocol 
= (SSLProtocolVersion
)SSLDecodeInt(charPtr
, 2); 
 265         err 
= sslVerifyProtVersion(ctx
, ctx
->clientReqProtocol
, &negVersion
); 
 270                 case SSL_Version_3_0
: 
 271                         ctx
->sslTslCalls 
= &Ssl3Callouts
; 
 273                 case TLS_Version_1_0
: 
 274                         ctx
->sslTslCalls 
= &Tls1Callouts
; 
 277                         return errSSLNegotiation
; 
 279         ctx
->negProtocolVersion 
= negVersion
; 
 280     sslLogNegotiateDebug("===SSL3 server: negVersion is %d_%d", 
 281                 negVersion 
>> 8, negVersion 
& 0xff); 
 283     memcpy(ctx
->clientRandom
, charPtr
, SSL_CLIENT_SRVR_RAND_SIZE
); 
 285     sessionIDLen 
= *(charPtr
++); 
 286     if (message
.length 
< (unsigned)(41 + sessionIDLen
)) { 
 287         sslErrorLog("SSLProcessClientHello: msg len error 2\n"); 
 288         return errSSLProtocol
; 
 290         /* FIXME peerID is never set on server side.... */ 
 291     if (sessionIDLen 
> 0 && ctx
->peerID
.data 
!= 0)  
 292     {   /* Don't die on error; just treat it as an uncacheable session */ 
 293         err 
= SSLAllocBuffer(ctx
->sessionID
, sessionIDLen
, ctx
); 
 295             memcpy(ctx
->sessionID
.data
, charPtr
, sessionIDLen
); 
 297     charPtr 
+= sessionIDLen
; 
 299     cipherListLen 
= (UInt16
)SSLDecodeInt(charPtr
, 2);   
 300                                                                 /* Count of cipherSpecs, must be even & >= 2 */ 
 302     if ((cipherListLen 
& 1) ||  
 303             (cipherListLen 
< 2) ||  
 304                 (message
.length 
< (unsigned)(39 + sessionIDLen 
+ cipherListLen
))) { 
 305         sslErrorLog("SSLProcessClientHello: msg len error 3\n"); 
 306         return errSSLProtocol
; 
 308     cipherCount 
= cipherListLen
/2; 
 309     cipherSpec 
= 0xFFFF;        /* No match marker */ 
 310     while (cipherSpec 
== 0xFFFF && cipherCount
--) 
 311     {   desiredSpec 
= (UInt16
)SSLDecodeInt(charPtr
, 2); 
 313         for (i 
= 0; i 
<ctx
->numValidCipherSpecs
; i
++) 
 314         {   if (ctx
->validCipherSpecs
[i
].cipherSpec 
== desiredSpec
) 
 315             {   cipherSpec 
= desiredSpec
; 
 321     if (cipherSpec 
== 0xFFFF) 
 322         return errSSLNegotiation
; 
 323     charPtr 
+= 2 * cipherCount
;    /* Advance past unchecked cipherCounts */ 
 324     ctx
->selectedCipher 
= cipherSpec
; 
 325     if ((err 
= FindCipherSpec(ctx
)) != 0) { 
 328     sslLogNegotiateDebug("ssl3 server: selecting cipherKind 0x%x", (unsigned)ctx
->selectedCipher
); 
 330     compressionCount 
= *(charPtr
++); 
 331     if ((compressionCount 
< 1) ||  
 333                     (unsigned)(38 + sessionIDLen 
+ cipherListLen 
+ compressionCount
))) { 
 334         sslErrorLog("SSLProcessClientHello: msg len error 4\n"); 
 335         return errSSLProtocol
; 
 337     /* Ignore list; we're doing null */ 
 339     if ((err 
= SSLInitMessageHashes(ctx
)) != 0) 
 346 SSLEncodeRandom(unsigned char *p
, SSLContext 
*ctx
) 
 347 {   SSLBuffer   randomData
; 
 351     if ((err 
= sslTime(&time
)) != 0) 
 353     SSLEncodeInt(p
, time
, 4); 
 354     randomData
.data 
= p
+4; 
 355     randomData
.length 
= 28; 
 356         if((err 
= sslRand(ctx
, &randomData
)) != 0) 
 362 SSLInitMessageHashes(SSLContext 
*ctx
) 
 365     if ((err 
= CloseHash(SSLHashSHA1
, ctx
->shaState
, ctx
)) != 0) 
 367     if ((err 
= CloseHash(SSLHashMD5
,  ctx
->md5State
, ctx
)) != 0) 
 369     if ((err 
= ReadyHash(SSLHashSHA1
, ctx
->shaState
, ctx
)) != 0) 
 371     if ((err 
= ReadyHash(SSLHashMD5
,  ctx
->md5State
, ctx
)) != 0)