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 #include "sslRecord.h"
21 #include "sslMemory.h"
22 #include "sslContext.h"
23 #include "sslAlertMessage.h"
24 #include "sslHandshake.h"
25 #include "sslSession.h"
27 #include "cipherSpecs.h"
28 #include "appleCdsa.h"
35 SSL2ProcessClientHello(SSLBuffer msg
, SSLContext
*ctx
)
37 UInt8
*charPtr
, *cipherList
;
38 unsigned i
, j
, cipherKindCount
, sessionIDLen
, challengeLen
;
39 SSL2CipherKind cipherKind
;
40 SSLCipherSuite matchingCipher
, selectedCipher
;
41 SSLProtocolVersion negVersion
;
43 if (msg
.length
< 27) {
44 sslErrorLog("SSL2ProcessClientHello: msg len error 1\n");
45 return errSSLProtocol
;
50 ctx
->clientReqProtocol
= (SSLProtocolVersion
)SSLDecodeInt(charPtr
, 2);
51 err
= sslVerifyProtVersion(ctx
, ctx
->clientReqProtocol
, &negVersion
);
57 * Note we can be here, processing a v2 client hello, even if
58 * we don't support SSL2. That can happen if the client is
59 * sending a v2 hello with an attempt to upgrade.
61 if (ctx
->negProtocolVersion
== SSL_Version_Undetermined
) {
63 sslLogNegotiateDebug("===SSL2 server: negVersion was undetermined; "
64 "is %s", protocolVersStr(negVersion
));
66 ctx
->negProtocolVersion
= negVersion
;
67 if(negVersion
>= TLS_Version_1_0
) {
68 ctx
->sslTslCalls
= &Tls1Callouts
;
71 /* default from context init */
72 assert(ctx
->sslTslCalls
== &Ssl3Callouts
);
77 cipherKindCount
= SSLDecodeInt(charPtr
, 2);
79 if (cipherKindCount
% 3 != 0) {
80 sslErrorLog("SSL2ProcessClientHello: cipherKindCount error\n");
81 return errSSLProtocol
;
84 sessionIDLen
= SSLDecodeInt(charPtr
, 2);
86 challengeLen
= SSLDecodeInt(charPtr
, 2);
89 if (msg
.length
!= 8 + 3*cipherKindCount
+ sessionIDLen
+ challengeLen
||
90 (sessionIDLen
!= 0 && sessionIDLen
!= 16) ||
91 challengeLen
< 16 || challengeLen
> 32 ) {
92 sslErrorLog("SSL2ProcessClientHello: msg len error 2\n");
93 return errSSLProtocol
;
96 selectedCipher
= SSL_NO_SUCH_CIPHERSUITE
;
98 assert(ctx
->negProtocolVersion
>= SSL_Version_2_0
); // i.e., not undetermined
99 if (ctx
->negProtocolVersion
>= SSL_Version_3_0
) {
100 /* If we're negotiating an SSL 3.0 session, use SSL 3.0 suites first */
101 for (i
= 0; i
< cipherKindCount
; i
++) {
102 cipherKind
= (SSL2CipherKind
)SSLDecodeInt(charPtr
, 3);
104 if (selectedCipher
!= SSL_NO_SUCH_CIPHERSUITE
)
106 if ((((UInt32
)cipherKind
) & 0xFF0000) != 0)
107 continue; /* Skip SSL 2 suites */
108 matchingCipher
= (SSLCipherSuite
)((UInt32
)cipherKind
& 0x00FFFF);
109 for (j
= 0; j
<ctx
->numValidCipherSpecs
; j
++) {
110 if (ctx
->validCipherSpecs
[j
].cipherSpec
== matchingCipher
) {
111 selectedCipher
= matchingCipher
;
114 } /* searching thru all our valid ciphers */
115 } /* for each client cipher */
116 } /* v3 or greater */
118 if(selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
) {
119 /* try again using SSL2 ciphers only */
120 charPtr
= cipherList
;
121 for (i
= 0; i
< cipherKindCount
; i
++) {
122 cipherKind
= (SSL2CipherKind
)SSLDecodeInt(charPtr
, 3);
124 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
) {
125 /* After we find one, just keep advancing ptr past
127 if ((((UInt32
)cipherKind
) & 0xFF0000) != 0) {
128 /* If it's a real SSL2 spec, look for it in the list */
129 matchingCipher
= SSL_NO_SUCH_CIPHERSUITE
;
130 for (j
= 0; j
< SSL2CipherMapCount
; j
++) {
131 if (cipherKind
== SSL2CipherMap
[j
].cipherKind
) {
132 matchingCipher
= SSL2CipherMap
[j
].cipherSuite
;
136 } /* real 3-byte SSL2 suite */
138 /* if the first byte is zero, it's an encoded SSL 3 CipherSuite */
139 matchingCipher
= (SSLCipherSuite
)((UInt32
)cipherKind
& 0x00FFFF);
141 * One more restriction - if we've negotiated a v2 session,
142 * ignore this matching cipher if it's not in the SSL2 map.
144 if(ctx
->negProtocolVersion
< SSL_Version_3_0
) {
146 for (j
= 0; j
< SSL2CipherMapCount
; j
++) {
147 if (matchingCipher
== SSL2CipherMap
[j
].cipherSuite
) {
153 /* Sorry, no can do */
154 matchingCipher
= SSL_NO_SUCH_CIPHERSUITE
;
157 } /* two-byte suite */
159 /* now see if we are enabled for this cipher */
160 if (matchingCipher
!= SSL_NO_SUCH_CIPHERSUITE
) {
161 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++) {
162 if (ctx
->validCipherSpecs
[j
].cipherSpec
== matchingCipher
) {
163 selectedCipher
= matchingCipher
;
168 } /* not ignoring this suite */
169 } /* for each suite in the hello msg */
170 } /* not found in SSL3 ciphersuites */
172 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
)
173 return errSSLNegotiation
;
175 ctx
->selectedCipher
= selectedCipher
;
176 err
= FindCipherSpec(ctx
);
180 if (sessionIDLen
> 0 && ctx
->peerID
.data
!= 0)
181 { /* Don't die on error; just treat it as an uncacheable session */
182 err
= SSLAllocBuffer(ctx
->sessionID
, sessionIDLen
, ctx
);
184 memcpy(ctx
->sessionID
.data
, charPtr
, sessionIDLen
);
186 charPtr
+= sessionIDLen
;
188 ctx
->ssl2ChallengeLength
= challengeLen
;
189 memset(ctx
->clientRandom
, 0, SSL_CLIENT_SRVR_RAND_SIZE
);
190 memcpy(ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
- challengeLen
,
191 charPtr
, challengeLen
);
192 charPtr
+= challengeLen
;
193 assert(charPtr
== msg
.data
+ msg
.length
);
199 * The SSL v2 spec says that the challenge string sent by the client can be
200 * between 16 and 32 bytes. However all Netscape enterprise servers actually
201 * require a 16 byte challenge. Q.v. cdnow.com, store.apple.com.
202 * Unfortunately this means that when we're trying to do an
203 * SSL2 hello with possible upgrade, we have to limit ourself to a
204 * 16-byte clientRandom, which we have to concatenate to 16 bytes of zeroes
205 * if we end up with a 3.0 or 3.1 connection. Thus we lose 16 bytes of entropy.
207 #define SSL2_CHALLENGE_LEN 16
210 SSL2EncodeClientHello(SSLBuffer
&msg
, SSLContext
*ctx
)
214 int useSSL3Ciphers
= 0;
215 int totalCipherCount
;
218 SSLBuffer sessionIdentifier
, randomData
;
219 SSLProtocolVersion maxVersion
;
221 assert(ctx
->versionSsl2Enable
);
222 err
= sslGetMaxProtVersion(ctx
, &maxVersion
);
224 /* we don't have a protocol enabled */
227 version
= maxVersion
;
228 if(version
> SSL_Version_2_0
) {
229 /* see if server can handle upgrading */
234 sslLogNegotiateDebug("===SSL client: proclaiming %s capable",
235 protocolVersStr((SSLProtocolVersion
)version
));
238 if (useSSL3Ciphers
!= 0)
239 totalCipherCount
= ctx
->numValidCipherSpecs
;
241 totalCipherCount
= 0;
243 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
244 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++)
245 if (ctx
->validCipherSpecs
[j
].cipherSpec
== SSL2CipherMap
[i
].cipherSuite
)
246 { totalCipherCount
++;
250 if(totalCipherCount
== 0) {
251 sslErrorLog("SSL2EncodeClientHello: no valid ciphers for SSL2");
252 return errSSLBadConfiguration
;
255 sessionIdentifier
.data
= 0;
256 if (ctx
->resumableSession
.data
!= 0)
257 { if ((err
= SSLRetrieveSessionID(ctx
->resumableSession
, &sessionIdentifier
, ctx
)) != 0)
259 sessionIDLen
= sessionIdentifier
.length
;
262 /* msg length = 9 + 3 * totalCipherCount + sessionIDLen + 16 bytes of challenge
263 * Use exactly 16 bytes of challenge because Netscape products have a bug
264 * that requires this length
266 if ((err
= SSLAllocBuffer(msg
, 9 + (3*totalCipherCount
) + sessionIDLen
+
267 SSL2_CHALLENGE_LEN
, ctx
)) != 0)
268 { SSLFreeBuffer(sessionIdentifier
, ctx
);
273 *charPtr
++ = SSL2_MsgClientHello
;
274 charPtr
= SSLEncodeInt(charPtr
, version
, 2);
275 charPtr
= SSLEncodeInt(charPtr
, 3*totalCipherCount
, 2);
276 charPtr
= SSLEncodeInt(charPtr
, sessionIDLen
, 2);
277 charPtr
= SSLEncodeInt(charPtr
, SSL2_CHALLENGE_LEN
, 2);
279 /* If we can send SSL3 ciphers, encode the two-byte cipher specs into three-byte
280 * CipherKinds which have a leading 0.
282 if (useSSL3Ciphers
!= 0)
283 for (i
= 0; i
< ctx
->numValidCipherSpecs
; i
++)
284 charPtr
= SSLEncodeInt(charPtr
, ctx
->validCipherSpecs
[i
].cipherSpec
, 3);
286 /* Now send those SSL2 specs for which we have implementations */
287 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
288 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++)
289 if (ctx
->validCipherSpecs
[j
].cipherSpec
== SSL2CipherMap
[i
].cipherSuite
)
290 { charPtr
= SSLEncodeInt(charPtr
, SSL2CipherMap
[i
].cipherKind
, 3);
294 if (sessionIDLen
> 0)
295 { memcpy(charPtr
, sessionIdentifier
.data
, sessionIDLen
);
296 charPtr
+= sessionIDLen
;
297 SSLFreeBuffer(sessionIdentifier
, ctx
);
300 randomData
.data
= charPtr
;
301 randomData
.length
= SSL2_CHALLENGE_LEN
;
302 if ((err
= sslRand(ctx
, &randomData
)) != 0)
303 { SSLFreeBuffer(msg
, ctx
);
306 charPtr
+= SSL2_CHALLENGE_LEN
;
308 /* Zero out the first 16 bytes of clientRandom, and store
309 * the challenge in the second 16 bytes */
310 #if (SSL2_CHALLENGE_LEN == SSL_CLIENT_SRVR_RAND_SIZE)
311 /* this path verified to fail with Netscape Enterprise servers 1/16/02 */
312 memcpy(ctx
->clientRandom
, randomData
.data
, SSL2_CHALLENGE_LEN
);
314 memset(ctx
->clientRandom
, 0, SSL_CLIENT_SRVR_RAND_SIZE
- SSL2_CHALLENGE_LEN
);
315 memcpy(ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
- SSL2_CHALLENGE_LEN
,
316 randomData
.data
, SSL2_CHALLENGE_LEN
);
318 ctx
->ssl2ChallengeLength
= SSL2_CHALLENGE_LEN
;
320 assert(charPtr
== msg
.data
+ msg
.length
);
326 SSL2ProcessClientMasterKey(SSLBuffer msg
, SSLContext
*ctx
)
328 SSL2CipherKind cipherKind
;
329 SSLBuffer secretData
;
330 unsigned clearLength
, encryptedLength
, keyArgLength
;
331 UInt32 secretLength
, localKeyModulusLen
;
333 const CSSM_KEY
*decryptKey
;
334 CSSM_CSP_HANDLE decryptCspHand
;
336 if (msg
.length
< 9) {
337 sslErrorLog("SSL2ProcessClientMasterKey: msg.length error 1\n");
338 return errSSLProtocol
;
340 assert(ctx
->protocolSide
== SSL_ServerSide
);
343 cipherKind
= (SSL2CipherKind
)SSLDecodeInt(charPtr
, 3);
345 clearLength
= SSLDecodeInt(charPtr
, 2);
347 encryptedLength
= SSLDecodeInt(charPtr
, 2);
349 keyArgLength
= SSLDecodeInt(charPtr
, 2);
352 if (msg
.length
!= 9 + clearLength
+ encryptedLength
+ keyArgLength
) {
353 sslErrorLog("SSL2ProcessClientMasterKey: msg.length error 2\n");
354 return errSSLProtocol
;
357 /* Master key == CLEAR_DATA || SECRET_DATA */
358 memcpy(ctx
->masterSecret
, charPtr
, clearLength
);
359 charPtr
+= clearLength
;
362 * Just as in SSL2EncodeServerHello, which key we use depends on the
365 if(ctx
->encryptPrivKey
) {
366 decryptKey
= ctx
->encryptPrivKey
;
367 assert(ctx
->encryptKeyCsp
!= 0);
368 decryptCspHand
= ctx
->encryptKeyCsp
;
370 else if(ctx
->signingPrivKey
) {
371 decryptKey
= ctx
->signingPrivKey
;
372 assert(ctx
->signingKeyCsp
!= 0);
373 decryptCspHand
= ctx
->signingKeyCsp
;
376 /* app configuration error */
377 sslErrorLog("SSL2ProcessClientMasterKey: No server key!\n");
378 return errSSLBadConfiguration
;
380 localKeyModulusLen
= sslKeyLengthInBytes(decryptKey
);
382 if (encryptedLength
!= localKeyModulusLen
) {
383 sslErrorLog("SSL2ProcessClientMasterKey: encryptedLength error 1\n");
384 return errSSLProtocol
;
387 /* Allocate enough room to hold any decrypted value */
388 if ((err
= SSLAllocBuffer(secretData
, encryptedLength
, ctx
)) != 0)
391 err
= sslRsaDecrypt(ctx
,
397 encryptedLength
, // same length for both...?
400 SSLFreeBuffer(secretData
, ctx
);
404 charPtr
+= encryptedLength
;
406 if (clearLength
+ secretLength
!= ctx
->selectedCipherSpec
->cipher
->keySize
) {
407 sslErrorLog("SSL2ProcessClientMasterKey: length error 3\n");
408 return errSSLProtocol
;
410 memcpy(ctx
->masterSecret
+ clearLength
, secretData
.data
, secretLength
);
411 if ((err
= SSLFreeBuffer(secretData
, ctx
)) != 0)
414 if (keyArgLength
!= ctx
->selectedCipherSpec
->cipher
->ivSize
) {
415 sslErrorLog("SSL2ProcessClientMasterKey: length error 4\n");
416 return errSSLProtocol
;
419 /* Stash the IV after the master key in master secret storage */
420 memcpy(ctx
->masterSecret
+ ctx
->selectedCipherSpec
->cipher
->keySize
, charPtr
, keyArgLength
);
421 charPtr
+= keyArgLength
;
422 assert(charPtr
= msg
.data
+ msg
.length
);
428 SSL2EncodeClientMasterKey(SSLBuffer
&msg
, SSLContext
*ctx
)
430 unsigned length
, i
, clearLen
;
431 UInt32 outputLen
, peerKeyModulusLen
;
435 peerKeyModulusLen
= sslKeyLengthInBytes(ctx
->peerPubKey
);
437 /* Length is 10 + clear key size + encrypted output size + iv size */
439 clearLen
= ctx
->selectedCipherSpec
->cipher
->keySize
- ctx
->selectedCipherSpec
->cipher
->secretKeySize
;
441 length
+= peerKeyModulusLen
;
442 length
+= ctx
->selectedCipherSpec
->cipher
->ivSize
;
444 if ((err
= SSLAllocBuffer(msg
, length
, ctx
)) != 0)
447 *charPtr
++ = SSL2_MsgClientMasterKey
;
448 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
449 if (ctx
->selectedCipher
== SSL2CipherMap
[i
].cipherSuite
)
451 assert(i
< SSL2CipherMapCount
);
452 sslLogNegotiateDebug("===SSL2EncodeClientMasterKey: sending cipherKind 0x%x",
453 SSL2CipherMap
[i
].cipherKind
);
454 charPtr
= SSLEncodeInt(charPtr
, SSL2CipherMap
[i
].cipherKind
, 3);
455 charPtr
= SSLEncodeInt(charPtr
, clearLen
, 2);
456 charPtr
= SSLEncodeInt(charPtr
, peerKeyModulusLen
, 2);
457 charPtr
= SSLEncodeInt(charPtr
, ctx
->selectedCipherSpec
->cipher
->ivSize
, 2);
459 /* Generate the keying material; we need enough data for the key and IV */
460 keyData
.data
= ctx
->masterSecret
;
461 keyData
.length
= ctx
->selectedCipherSpec
->cipher
->keySize
+ ctx
->selectedCipherSpec
->cipher
->ivSize
;
462 assert(keyData
.length
<= 48); /* Must be able to store it in the masterSecret array */
463 if ((err
= sslRand(ctx
, &keyData
)) != 0)
466 memcpy(charPtr
, ctx
->masterSecret
, clearLen
);
469 /* Replace this with code to do encryption at lower level & set PKCS1 padding
470 for rollback attack */
473 * encrypt only the secret key portion of masterSecret, starting at
476 err
= sslRsaEncrypt(ctx
,
478 ctx
->peerPubKeyCsp
, // XX - maybe cspHand
479 ctx
->masterSecret
+ clearLen
,
480 ctx
->selectedCipherSpec
->cipher
->keySize
- clearLen
,
488 charPtr
+= outputLen
;
490 /* copy clear IV to msg buf */
491 memcpy(charPtr
, ctx
->masterSecret
+ ctx
->selectedCipherSpec
->cipher
->keySize
,
492 ctx
->selectedCipherSpec
->cipher
->ivSize
);
493 charPtr
+= ctx
->selectedCipherSpec
->cipher
->ivSize
;
495 assert(charPtr
== msg
.data
+ msg
.length
);
501 SSL2ProcessClientFinished(SSLBuffer msg
, SSLContext
*ctx
)
502 { if (msg
.length
!= ctx
->sessionID
.length
) {
503 sslErrorLog("SSL2ProcessClientFinished: length error\n");
504 return errSSLProtocol
;
506 if (memcmp(msg
.data
, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
) != 0) {
507 sslErrorLog("SSL2ProcessClientFinished: data compare error\n");
508 return errSSLProtocol
;
514 SSL2EncodeClientFinished(SSLBuffer
&msg
, SSLContext
*ctx
)
517 if ((err
= SSLAllocBuffer(msg
, ctx
->ssl2ConnectionIDLength
+1, ctx
)) != 0)
519 msg
.data
[0] = SSL2_MsgClientFinished
;
520 memcpy(msg
.data
+1, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
);
525 SSL2ProcessServerHello(SSLBuffer msg
, SSLContext
*ctx
)
527 SSL2CertTypeCode certType
;
528 unsigned sessionIDMatch
, certLen
, cipherSpecsLen
, connectionIDLen
;
530 SSL2CipherKind cipherKind
;
531 SSLCertificate
*cert
;
532 SSLCipherSuite matchingCipher
= 0; // avoid compiler warning
533 SSLCipherSuite selectedCipher
;
535 SSLProtocolVersion version
;
537 if (msg
.length
< 10) {
538 sslErrorLog("SSL2ProcessServerHello: length error\n");
539 return errSSLProtocol
;
543 sessionIDMatch
= *charPtr
++;
544 certType
= (SSL2CertTypeCode
)*charPtr
++;
545 version
= (SSLProtocolVersion
)SSLDecodeInt(charPtr
, 2);
547 if (version
!= SSL_Version_2_0
) {
548 sslErrorLog("SSL2ProcessServerHello: version error\n");
549 return errSSLProtocol
;
551 ctx
->negProtocolVersion
= version
;
552 sslLogNegotiateDebug("===SSL2 client: negVersion is 2_0");
553 certLen
= SSLDecodeInt(charPtr
, 2);
555 cipherSpecsLen
= SSLDecodeInt(charPtr
, 2);
557 connectionIDLen
= SSLDecodeInt(charPtr
, 2);
560 if (connectionIDLen
< 16 || connectionIDLen
> 32 || cipherSpecsLen
% 3 != 0 ||
561 (msg
.length
!= 10 + certLen
+ cipherSpecsLen
+ connectionIDLen
) )
562 return errSSLProtocol
;
563 if (sessionIDMatch
!= 0)
564 { if (certLen
!= 0 || cipherSpecsLen
!= 0 /* || certType != 0 */ )
565 return errSSLProtocol
;
566 ctx
->sessionMatch
= 1;
568 ctx
->ssl2ConnectionIDLength
= connectionIDLen
;
569 memcpy(ctx
->serverRandom
, charPtr
, connectionIDLen
);
570 charPtr
+= connectionIDLen
;
573 { if (certType
!= SSL2_CertTypeX509
)
574 return errSSLNegotiation
;
577 cert
= (SSLCertificate
*)sslMalloc(sizeof(SSLCertificate
));
582 if ((err
= SSLAllocBuffer(cert
->derCert
, certLen
, ctx
)) != 0)
587 memcpy(cert
->derCert
.data
, charPtr
, certLen
);
589 ctx
->peerCert
= cert
;
590 if((err
= sslVerifyCertChain(ctx
, *ctx
->peerCert
)) != 0) {
593 if((err
= sslPubKeyFromCert(ctx
,
596 &ctx
->peerPubKeyCsp
)) != 0)
599 selectedCipher
= SSL_NO_SUCH_CIPHERSUITE
;
600 for (i
= 0; i
< cipherSpecsLen
; i
++)
601 { cipherKind
= (SSL2CipherKind
)SSLDecodeInt(charPtr
, 3);
603 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
) /* After we find one, just keep advancing charPtr past the unused ones */
604 { for (j
= 0; j
< SSL2CipherMapCount
; j
++)
605 if (cipherKind
== SSL2CipherMap
[j
].cipherKind
)
606 { matchingCipher
= SSL2CipherMap
[j
].cipherSuite
;
609 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++)
610 if (ctx
->validCipherSpecs
[j
].cipherSpec
== matchingCipher
)
611 { selectedCipher
= matchingCipher
;
616 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
)
617 return errSSLNegotiation
;
618 sslLogNegotiateDebug("===SSL2 client: selectedCipher 0x%x",
619 (unsigned)selectedCipher
);
621 ctx
->selectedCipher
= selectedCipher
;
622 if ((err
= FindCipherSpec(ctx
)) != 0) {
625 ctx
->ssl2ConnectionIDLength
= connectionIDLen
;
626 memcpy(ctx
->serverRandom
, charPtr
, connectionIDLen
);
627 charPtr
+= connectionIDLen
;
630 assert(charPtr
== msg
.data
+ msg
.length
);
636 SSL2EncodeServerHello(SSLBuffer
&msg
, SSLContext
*ctx
)
638 SSLCertificate
*cert
;
639 SSLBuffer randomData
;
643 /* Create the connection ID */
644 ctx
->ssl2ConnectionIDLength
= SSL2_CONNECTION_ID_LENGTH
;
645 randomData
.data
= ctx
->serverRandom
;
646 randomData
.length
= ctx
->ssl2ConnectionIDLength
;
647 if ((err
= sslRand(ctx
, &randomData
)) != 0)
650 if (ctx
->sessionMatch
!= 0)
651 { if ((err
= SSLAllocBuffer(msg
, 11 + ctx
->sessionID
.length
, ctx
)) != 0)
654 *charPtr
++ = SSL2_MsgServerHello
;
655 *charPtr
++ = ctx
->sessionMatch
;
656 *charPtr
++ = 0; /* cert type */
657 charPtr
= SSLEncodeInt(charPtr
, ctx
->negProtocolVersion
, 2);
658 charPtr
= SSLEncodeInt(charPtr
, 0, 2); /* cert len */
659 charPtr
= SSLEncodeInt(charPtr
, 0, 2); /* cipherspecs len */
660 charPtr
= SSLEncodeInt(charPtr
, ctx
->ssl2ConnectionIDLength
, 2);
661 memcpy(charPtr
, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
);
662 charPtr
+= ctx
->ssl2ConnectionIDLength
;
665 { /* First, find the last cert in the chain; it's the one we'll send */
668 * Use encryptCert if we have it, but allow for the case of app
669 * specifying one cert which can encrypt and sign.
671 if(ctx
->encryptCert
!= NULL
) {
672 cert
= ctx
->encryptCert
;
674 else if(ctx
->localCert
!= NULL
) {
675 cert
= ctx
->localCert
;
678 /* really should not happen... */
679 sslErrorLog("SSL2EncodeServerHello: No server cert!\n");
683 while (cert
->next
!= 0)
686 if ((err
= SSLAllocBuffer(msg
, 11 + cert
->derCert
.length
+ 3 + ctx
->sessionID
.length
, ctx
)) != 0)
689 *charPtr
++ = SSL2_MsgServerHello
;
690 *charPtr
++ = ctx
->sessionMatch
;
691 *charPtr
++ = SSL2_CertTypeX509
; /* cert type */
694 sslLogNegotiateDebug("===SSL2 server: sending vers info %s",
695 protocolVersStr((SSLProtocolVersion
)ctx
->negProtocolVersion
));
698 charPtr
= SSLEncodeInt(charPtr
, ctx
->negProtocolVersion
, 2);
699 charPtr
= SSLEncodeInt(charPtr
, cert
->derCert
.length
, 2);
700 charPtr
= SSLEncodeInt(charPtr
, 3, 2); /* cipherspecs len */
701 charPtr
= SSLEncodeInt(charPtr
, ctx
->ssl2ConnectionIDLength
, 2);
702 memcpy(charPtr
, cert
->derCert
.data
, cert
->derCert
.length
);
703 charPtr
+= cert
->derCert
.length
;
704 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
705 if (ctx
->selectedCipher
== SSL2CipherMap
[i
].cipherSuite
)
707 assert(i
< SSL2CipherMapCount
);
708 charPtr
= SSLEncodeInt(charPtr
, SSL2CipherMap
[i
].cipherKind
, 3);
709 sslLogNegotiateDebug("ssl2: server specifying cipherKind 0x%lx",
710 (UInt32
)SSL2CipherMap
[i
].cipherKind
);
711 memcpy(charPtr
, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
);
712 charPtr
+= ctx
->ssl2ConnectionIDLength
;
715 assert(charPtr
== msg
.data
+ msg
.length
);
720 SSL2ProcessServerVerify(SSLBuffer msg
, SSLContext
*ctx
)
721 { if (msg
.length
!= ctx
->ssl2ChallengeLength
)
722 return errSSLProtocol
;
724 if (memcmp(msg
.data
, ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
-
725 ctx
->ssl2ChallengeLength
, ctx
->ssl2ChallengeLength
) != 0)
726 return errSSLProtocol
;
732 SSL2EncodeServerVerify(SSLBuffer
&msg
, SSLContext
*ctx
)
735 if ((err
= SSLAllocBuffer(msg
, 1 + ctx
->ssl2ChallengeLength
, ctx
)) != 0)
738 msg
.data
[0] = SSL2_MsgServerVerify
;
739 memcpy(msg
.data
+1, ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
-
740 ctx
->ssl2ChallengeLength
, ctx
->ssl2ChallengeLength
);
746 SSL2ProcessServerFinished(SSLBuffer msg
, SSLContext
*ctx
)
749 if ((err
= SSLAllocBuffer(ctx
->sessionID
, msg
.length
, ctx
)) != 0)
751 memcpy(ctx
->sessionID
.data
, msg
.data
, msg
.length
);
756 SSL2EncodeServerFinished(SSLBuffer
&msg
, SSLContext
*ctx
)
759 if ((err
= SSLAllocBuffer(msg
, 1 + ctx
->sessionID
.length
, ctx
)) != 0)
762 msg
.data
[0] = SSL2_MsgServerFinished
;
763 memcpy(msg
.data
+1, ctx
->sessionID
.data
, ctx
->sessionID
.length
);