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 version
;
43 if (msg
.length
< 27) {
44 sslErrorLog("SSL2ProcessClientHello: msg len error 1\n");
45 return errSSLProtocol
;
50 version
= (SSLProtocolVersion
)SSLDecodeInt(charPtr
, 2);
51 if (version
> ctx
->maxProtocolVersion
) {
52 version
= ctx
->maxProtocolVersion
;
54 /* FIXME - I think this needs work for a SSL_Version_2_0 server, to ensure that
55 * the client isn't establishing a v3 session. */
56 if (ctx
->negProtocolVersion
== SSL_Version_Undetermined
)
58 /* FIXME - this ifndef should not be necessary */
60 sslLogNegotiateDebug("===SSL2 server: negVersion was undetermined; "
61 "is %s", protocolVersStr(version
));
63 ctx
->negProtocolVersion
= version
;
64 if(version
>= TLS_Version_1_0
) {
65 ctx
->sslTslCalls
= &Tls1Callouts
;
68 /* default from context init */
69 assert(ctx
->sslTslCalls
== &Ssl3Callouts
);
72 else if (ctx
->negProtocolVersion
== SSL_Version_3_0_With_2_0_Hello
)
73 { if (version
< SSL_Version_3_0
) {
74 sslErrorLog("SSL2ProcessClientHello: version error\n");
75 return errSSLProtocol
;
77 /* FIXME - I don't think path is ever taken - we NEVER set any
78 * protocol var to SSL_Version_3_0_With_2_0_Hello... */
79 sslLogNegotiateDebug("===SSL2 server: negVersion was "
80 "3_0_With_2_0_Hello; is 3_0");
81 ctx
->negProtocolVersion
= version
;
85 cipherKindCount
= SSLDecodeInt(charPtr
, 2);
87 if (cipherKindCount
% 3 != 0) {
88 sslErrorLog("SSL2ProcessClientHello: cipherKindCount error\n");
89 return errSSLProtocol
;
92 sessionIDLen
= SSLDecodeInt(charPtr
, 2);
94 challengeLen
= SSLDecodeInt(charPtr
, 2);
97 if (msg
.length
!= 8 + 3*cipherKindCount
+ sessionIDLen
+ challengeLen
||
98 (sessionIDLen
!= 0 && sessionIDLen
!= 16) ||
99 challengeLen
< 16 || challengeLen
> 32 ) {
100 sslErrorLog("SSL2ProcessClientHello: msg len error 2\n");
101 return errSSLProtocol
;
103 cipherList
= charPtr
;
104 selectedCipher
= SSL_NO_SUCH_CIPHERSUITE
;
106 if (ctx
->negProtocolVersion
>= SSL_Version_3_0
) {
107 /* If we're negotiating an SSL 3.0 session, use SSL 3.0 suites first */
108 for (i
= 0; i
< cipherKindCount
; i
++) {
109 cipherKind
= (SSL2CipherKind
)SSLDecodeInt(charPtr
, 3);
111 if (selectedCipher
!= SSL_NO_SUCH_CIPHERSUITE
)
113 if ((((UInt32
)cipherKind
) & 0xFF0000) != 0)
114 continue; /* Skip SSL 2 suites */
115 matchingCipher
= (SSLCipherSuite
)((UInt32
)cipherKind
& 0x00FFFF);
116 for (j
= 0; j
<ctx
->numValidCipherSpecs
; j
++) {
117 if (ctx
->validCipherSpecs
[j
].cipherSpec
== matchingCipher
) {
118 selectedCipher
= matchingCipher
;
121 } /* searching thru all our valid ciphers */
122 } /* for each client cipher */
123 } /* v3 or greater */
125 if(selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
) {
126 /* try again using SSL2 ciphers only */
127 charPtr
= cipherList
;
128 for (i
= 0; i
< cipherKindCount
; i
++) {
129 cipherKind
= (SSL2CipherKind
)SSLDecodeInt(charPtr
, 3);
131 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
) {
132 /* After we find one, just keep advancing ptr past
134 if ((((UInt32
)cipherKind
) & 0xFF0000) != 0) {
135 /* If it's a real SSL2 spec, look for it in the list */
136 matchingCipher
= SSL_NO_SUCH_CIPHERSUITE
;
137 for (j
= 0; j
< SSL2CipherMapCount
; j
++) {
138 if (cipherKind
== SSL2CipherMap
[j
].cipherKind
) {
139 matchingCipher
= SSL2CipherMap
[j
].cipherSuite
;
143 } /* real 3-byte SSL2 suite */
145 /* if the first byte is zero, it's an encoded SSL 3 CipherSuite */
146 matchingCipher
= (SSLCipherSuite
)((UInt32
)cipherKind
& 0x00FFFF);
148 * One more restriction - if we've negotiated a v2 session,
149 * ignore this matching cipher if it's not in the SSL2 map.
151 if(ctx
->negProtocolVersion
< SSL_Version_3_0
) {
153 for (j
= 0; j
< SSL2CipherMapCount
; j
++) {
154 if (matchingCipher
== SSL2CipherMap
[j
].cipherSuite
) {
160 /* Sorry, no can do */
161 matchingCipher
= SSL_NO_SUCH_CIPHERSUITE
;
164 } /* two-byte suite */
166 /* now see if we are enabled for this cipher */
167 if (matchingCipher
!= SSL_NO_SUCH_CIPHERSUITE
) {
168 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++) {
169 if (ctx
->validCipherSpecs
[j
].cipherSpec
== matchingCipher
) {
170 selectedCipher
= matchingCipher
;
175 } /* not ignoring this suite */
176 } /* for each suite in the hello msg */
177 } /* not found in SSL3 ciphersuites */
179 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
)
180 return errSSLNegotiation
;
182 ctx
->selectedCipher
= selectedCipher
;
183 err
= FindCipherSpec(ctx
);
187 if (sessionIDLen
> 0 && ctx
->peerID
.data
!= 0)
188 { /* Don't die on error; just treat it as an uncacheable session */
189 err
= SSLAllocBuffer(ctx
->sessionID
, sessionIDLen
, ctx
);
191 memcpy(ctx
->sessionID
.data
, charPtr
, sessionIDLen
);
193 charPtr
+= sessionIDLen
;
195 ctx
->ssl2ChallengeLength
= challengeLen
;
196 memset(ctx
->clientRandom
, 0, SSL_CLIENT_SRVR_RAND_SIZE
);
197 memcpy(ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
- challengeLen
,
198 charPtr
, challengeLen
);
199 charPtr
+= challengeLen
;
200 assert(charPtr
== msg
.data
+ msg
.length
);
206 * The SSL v2 spec says that the challenge string sent by the client can be
207 * between 16 and 32 bytes. However all Netscape enterprise servers actually
208 * require a 16 byte challenge. Q.v. cdnow.com, store.apple.com.
209 * Unfortunately this means that when we're trying to do a
210 * SSL_Version_3_0_With_2_0_Hello negotiation, we have to limit ourself to
211 * a 16-byte clientRandom, which we have to concatenate to 16 bytes of
212 * zeroes if we end up with a 3.0 or 3.1 connection. Thus we lose 16 bytes
215 #define SSL2_CHALLENGE_LEN 16
218 SSL2EncodeClientHello(SSLBuffer
&msg
, SSLContext
*ctx
)
222 int useSSL3Ciphers
= 0;
223 int totalCipherCount
;
226 SSLBuffer sessionIdentifier
, randomData
;
228 switch (ctx
->negProtocolVersion
)
229 { case SSL_Version_Undetermined
:
230 case SSL_Version_3_0_With_2_0_Hello
:
231 /* go for it, see if server can handle upgrading */
233 /* could be SSLv3 or TLSv1 */
234 version
= ctx
->maxProtocolVersion
;
236 case SSL_Version_2_0
:
238 version
= SSL_Version_2_0
;
240 case SSL_Version_3_0_Only
:
241 case SSL_Version_3_0
:
242 case TLS_Version_1_0_Only
:
243 case TLS_Version_1_0
:
245 assert("Bad protocol version for sending SSL 2 Client Hello");
246 return errSSLInternal
;
248 /* FIXME - this ifndef should not be necessary */
250 sslLogNegotiateDebug("===SSL client: proclaiming %s capable",
251 protocolVersStr((SSLProtocolVersion
)version
));
254 if (useSSL3Ciphers
!= 0)
255 totalCipherCount
= ctx
->numValidCipherSpecs
;
257 totalCipherCount
= 0;
259 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
260 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++)
261 if (ctx
->validCipherSpecs
[j
].cipherSpec
== SSL2CipherMap
[i
].cipherSuite
)
262 { totalCipherCount
++;
267 sessionIdentifier
.data
= 0;
268 if (ctx
->resumableSession
.data
!= 0)
269 { if ((err
= SSLRetrieveSessionID(ctx
->resumableSession
, &sessionIdentifier
, ctx
)) != 0)
271 sessionIDLen
= sessionIdentifier
.length
;
274 /* msg length = 9 + 3 * totalCipherCount + sessionIDLen + 16 bytes of challenge
275 * Use exactly 16 bytes of challenge because Netscape products have a bug
276 * that requires this length
278 if ((err
= SSLAllocBuffer(msg
, 9 + (3*totalCipherCount
) + sessionIDLen
+
279 SSL2_CHALLENGE_LEN
, ctx
)) != 0)
280 { SSLFreeBuffer(sessionIdentifier
, ctx
);
285 *charPtr
++ = SSL2_MsgClientHello
;
286 charPtr
= SSLEncodeInt(charPtr
, version
, 2);
287 charPtr
= SSLEncodeInt(charPtr
, 3*totalCipherCount
, 2);
288 charPtr
= SSLEncodeInt(charPtr
, sessionIDLen
, 2);
289 charPtr
= SSLEncodeInt(charPtr
, SSL2_CHALLENGE_LEN
, 2);
291 /* If we can send SSL3 ciphers, encode the two-byte cipher specs into three-byte
292 * CipherKinds which have a leading 0.
294 if (useSSL3Ciphers
!= 0)
295 for (i
= 0; i
< ctx
->numValidCipherSpecs
; i
++)
296 charPtr
= SSLEncodeInt(charPtr
, ctx
->validCipherSpecs
[i
].cipherSpec
, 3);
298 /* Now send those SSL2 specs for which we have implementations */
299 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
300 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++)
301 if (ctx
->validCipherSpecs
[j
].cipherSpec
== SSL2CipherMap
[i
].cipherSuite
)
302 { charPtr
= SSLEncodeInt(charPtr
, SSL2CipherMap
[i
].cipherKind
, 3);
306 if (sessionIDLen
> 0)
307 { memcpy(charPtr
, sessionIdentifier
.data
, sessionIDLen
);
308 charPtr
+= sessionIDLen
;
309 SSLFreeBuffer(sessionIdentifier
, ctx
);
312 randomData
.data
= charPtr
;
313 randomData
.length
= SSL2_CHALLENGE_LEN
;
314 if ((err
= sslRand(ctx
, &randomData
)) != 0)
315 { SSLFreeBuffer(msg
, ctx
);
318 charPtr
+= SSL2_CHALLENGE_LEN
;
320 /* Zero out the first 16 bytes of clientRandom, and store
321 * the challenge in the second 16 bytes */
322 #if (SSL2_CHALLENGE_LEN == SSL_CLIENT_SRVR_RAND_SIZE)
323 /* this path verified to fail with Netscape Enterprise servers 1/16/02 */
324 memcpy(ctx
->clientRandom
, randomData
.data
, SSL2_CHALLENGE_LEN
);
326 memset(ctx
->clientRandom
, 0, SSL_CLIENT_SRVR_RAND_SIZE
- SSL2_CHALLENGE_LEN
);
327 memcpy(ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
- SSL2_CHALLENGE_LEN
,
328 randomData
.data
, SSL2_CHALLENGE_LEN
);
330 ctx
->ssl2ChallengeLength
= SSL2_CHALLENGE_LEN
;
332 assert(charPtr
== msg
.data
+ msg
.length
);
338 SSL2ProcessClientMasterKey(SSLBuffer msg
, SSLContext
*ctx
)
340 SSL2CipherKind cipherKind
;
341 SSLBuffer secretData
;
342 unsigned clearLength
, encryptedLength
, keyArgLength
;
343 UInt32 secretLength
, localKeyModulusLen
;
345 const CSSM_KEY
*decryptKey
;
346 CSSM_CSP_HANDLE decryptCspHand
;
348 if (msg
.length
< 9) {
349 sslErrorLog("SSL2ProcessClientMasterKey: msg.length error 1\n");
350 return errSSLProtocol
;
352 assert(ctx
->protocolSide
== SSL_ServerSide
);
355 cipherKind
= (SSL2CipherKind
)SSLDecodeInt(charPtr
, 3);
357 clearLength
= SSLDecodeInt(charPtr
, 2);
359 encryptedLength
= SSLDecodeInt(charPtr
, 2);
361 keyArgLength
= SSLDecodeInt(charPtr
, 2);
364 if (msg
.length
!= 9 + clearLength
+ encryptedLength
+ keyArgLength
) {
365 sslErrorLog("SSL2ProcessClientMasterKey: msg.length error 2\n");
366 return errSSLProtocol
;
369 /* Master key == CLEAR_DATA || SECRET_DATA */
370 memcpy(ctx
->masterSecret
, charPtr
, clearLength
);
371 charPtr
+= clearLength
;
374 * Just as in SSL2EncodeServerHello, which key we use depends on the
377 if(ctx
->encryptPrivKey
) {
378 decryptKey
= ctx
->encryptPrivKey
;
379 assert(ctx
->encryptKeyCsp
!= 0);
380 decryptCspHand
= ctx
->encryptKeyCsp
;
382 else if(ctx
->signingPrivKey
) {
383 decryptKey
= ctx
->signingPrivKey
;
384 assert(ctx
->signingKeyCsp
!= 0);
385 decryptCspHand
= ctx
->signingKeyCsp
;
388 /* really should not happen... */
389 sslErrorLog("SSL2ProcessClientMasterKey: No server key!\n");
392 localKeyModulusLen
= sslKeyLengthInBytes(decryptKey
);
394 if (encryptedLength
!= localKeyModulusLen
) {
395 sslErrorLog("SSL2ProcessClientMasterKey: encryptedLength error 1\n");
396 return errSSLProtocol
;
399 /* Allocate enough room to hold any decrypted value */
400 if ((err
= SSLAllocBuffer(secretData
, encryptedLength
, ctx
)) != 0)
403 err
= sslRsaDecrypt(ctx
,
409 encryptedLength
, // same length for both...?
412 SSLFreeBuffer(secretData
, ctx
);
416 charPtr
+= encryptedLength
;
418 if (clearLength
+ secretLength
!= ctx
->selectedCipherSpec
->cipher
->keySize
) {
419 sslErrorLog("SSL2ProcessClientMasterKey: length error 3\n");
420 return errSSLProtocol
;
422 memcpy(ctx
->masterSecret
+ clearLength
, secretData
.data
, secretLength
);
423 if ((err
= SSLFreeBuffer(secretData
, ctx
)) != 0)
426 if (keyArgLength
!= ctx
->selectedCipherSpec
->cipher
->ivSize
) {
427 sslErrorLog("SSL2ProcessClientMasterKey: length error 4\n");
428 return errSSLProtocol
;
431 /* Stash the IV after the master key in master secret storage */
432 memcpy(ctx
->masterSecret
+ ctx
->selectedCipherSpec
->cipher
->keySize
, charPtr
, keyArgLength
);
433 charPtr
+= keyArgLength
;
434 assert(charPtr
= msg
.data
+ msg
.length
);
440 SSL2EncodeClientMasterKey(SSLBuffer
&msg
, SSLContext
*ctx
)
442 unsigned length
, i
, clearLen
;
443 UInt32 outputLen
, peerKeyModulusLen
;
447 peerKeyModulusLen
= sslKeyLengthInBytes(ctx
->peerPubKey
);
449 /* Length is 10 + clear key size + encrypted output size + iv size */
451 clearLen
= ctx
->selectedCipherSpec
->cipher
->keySize
- ctx
->selectedCipherSpec
->cipher
->secretKeySize
;
453 length
+= peerKeyModulusLen
;
454 length
+= ctx
->selectedCipherSpec
->cipher
->ivSize
;
456 if ((err
= SSLAllocBuffer(msg
, length
, ctx
)) != 0)
459 *charPtr
++ = SSL2_MsgClientMasterKey
;
460 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
461 if (ctx
->selectedCipher
== SSL2CipherMap
[i
].cipherSuite
)
463 assert(i
< SSL2CipherMapCount
);
464 sslLogNegotiateDebug("===SSL2EncodeClientMasterKey: sending cipherKind 0x%x",
465 SSL2CipherMap
[i
].cipherKind
);
466 charPtr
= SSLEncodeInt(charPtr
, SSL2CipherMap
[i
].cipherKind
, 3);
467 charPtr
= SSLEncodeInt(charPtr
, clearLen
, 2);
468 charPtr
= SSLEncodeInt(charPtr
, peerKeyModulusLen
, 2);
469 charPtr
= SSLEncodeInt(charPtr
, ctx
->selectedCipherSpec
->cipher
->ivSize
, 2);
471 /* Generate the keying material; we need enough data for the key and IV */
472 keyData
.data
= ctx
->masterSecret
;
473 keyData
.length
= ctx
->selectedCipherSpec
->cipher
->keySize
+ ctx
->selectedCipherSpec
->cipher
->ivSize
;
474 assert(keyData
.length
<= 48); /* Must be able to store it in the masterSecret array */
475 if ((err
= sslRand(ctx
, &keyData
)) != 0)
478 memcpy(charPtr
, ctx
->masterSecret
, clearLen
);
481 /* Replace this with code to do encryption at lower level & set PKCS1 padding
482 for rollback attack */
485 * encrypt only the secret key portion of masterSecret, starting at
488 err
= sslRsaEncrypt(ctx
,
490 ctx
->peerPubKeyCsp
, // XX - maybe cspHand
491 ctx
->masterSecret
+ clearLen
,
492 ctx
->selectedCipherSpec
->cipher
->keySize
- clearLen
,
500 charPtr
+= outputLen
;
502 /* copy clear IV to msg buf */
503 memcpy(charPtr
, ctx
->masterSecret
+ ctx
->selectedCipherSpec
->cipher
->keySize
,
504 ctx
->selectedCipherSpec
->cipher
->ivSize
);
505 charPtr
+= ctx
->selectedCipherSpec
->cipher
->ivSize
;
507 assert(charPtr
== msg
.data
+ msg
.length
);
513 SSL2ProcessClientFinished(SSLBuffer msg
, SSLContext
*ctx
)
514 { if (msg
.length
!= ctx
->sessionID
.length
) {
515 sslErrorLog("SSL2ProcessClientFinished: length error\n");
516 return errSSLProtocol
;
518 if (memcmp(msg
.data
, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
) != 0) {
519 sslErrorLog("SSL2ProcessClientFinished: data compare error\n");
520 return errSSLProtocol
;
526 SSL2EncodeClientFinished(SSLBuffer
&msg
, SSLContext
*ctx
)
529 if ((err
= SSLAllocBuffer(msg
, ctx
->ssl2ConnectionIDLength
+1, ctx
)) != 0)
531 msg
.data
[0] = SSL2_MsgClientFinished
;
532 memcpy(msg
.data
+1, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
);
537 SSL2ProcessServerHello(SSLBuffer msg
, SSLContext
*ctx
)
539 SSL2CertTypeCode certType
;
540 unsigned sessionIDMatch
, certLen
, cipherSpecsLen
, connectionIDLen
;
542 SSL2CipherKind cipherKind
;
543 SSLCertificate
*cert
;
544 SSLCipherSuite matchingCipher
= 0; // avoid compiler warning
545 SSLCipherSuite selectedCipher
;
547 SSLProtocolVersion version
;
549 if (msg
.length
< 10) {
550 sslErrorLog("SSL2ProcessServerHello: length error\n");
551 return errSSLProtocol
;
555 sessionIDMatch
= *charPtr
++;
556 certType
= (SSL2CertTypeCode
)*charPtr
++;
557 version
= (SSLProtocolVersion
)SSLDecodeInt(charPtr
, 2);
559 if (version
!= SSL_Version_2_0
) {
560 sslErrorLog("SSL2ProcessServerHello: version error\n");
561 return errSSLProtocol
;
563 ctx
->negProtocolVersion
= version
;
564 sslLogNegotiateDebug("===SSL2 client: negVersion is 2_0");
565 certLen
= SSLDecodeInt(charPtr
, 2);
567 cipherSpecsLen
= SSLDecodeInt(charPtr
, 2);
569 connectionIDLen
= SSLDecodeInt(charPtr
, 2);
572 if (connectionIDLen
< 16 || connectionIDLen
> 32 || cipherSpecsLen
% 3 != 0 ||
573 (msg
.length
!= 10 + certLen
+ cipherSpecsLen
+ connectionIDLen
) )
574 return errSSLProtocol
;
575 if (sessionIDMatch
!= 0)
576 { if (certLen
!= 0 || cipherSpecsLen
!= 0 /* || certType != 0 */ )
577 return errSSLProtocol
;
578 ctx
->ssl2SessionMatch
= 1;
580 ctx
->ssl2ConnectionIDLength
= connectionIDLen
;
581 memcpy(ctx
->serverRandom
, charPtr
, connectionIDLen
);
582 charPtr
+= connectionIDLen
;
585 { if (certType
!= SSL2_CertTypeX509
)
586 return errSSLNegotiation
;
589 cert
= (SSLCertificate
*)sslMalloc(sizeof(SSLCertificate
));
594 if ((err
= SSLAllocBuffer(cert
->derCert
, certLen
, ctx
)) != 0)
599 memcpy(cert
->derCert
.data
, charPtr
, certLen
);
601 ctx
->peerCert
= cert
;
602 if((err
= sslVerifyCertChain(ctx
, *ctx
->peerCert
)) != 0) {
605 if((err
= sslPubKeyFromCert(ctx
,
608 &ctx
->peerPubKeyCsp
)) != 0)
611 selectedCipher
= SSL_NO_SUCH_CIPHERSUITE
;
612 for (i
= 0; i
< cipherSpecsLen
; i
++)
613 { cipherKind
= (SSL2CipherKind
)SSLDecodeInt(charPtr
, 3);
615 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
) /* After we find one, just keep advancing charPtr past the unused ones */
616 { for (j
= 0; j
< SSL2CipherMapCount
; j
++)
617 if (cipherKind
== SSL2CipherMap
[j
].cipherKind
)
618 { matchingCipher
= SSL2CipherMap
[j
].cipherSuite
;
621 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++)
622 if (ctx
->validCipherSpecs
[j
].cipherSpec
== matchingCipher
)
623 { selectedCipher
= matchingCipher
;
628 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
)
629 return errSSLNegotiation
;
630 sslLogNegotiateDebug("===SSL2 client: selectedCipher 0x%x",
631 (unsigned)selectedCipher
);
633 ctx
->selectedCipher
= selectedCipher
;
634 if ((err
= FindCipherSpec(ctx
)) != 0) {
637 ctx
->ssl2ConnectionIDLength
= connectionIDLen
;
638 memcpy(ctx
->serverRandom
, charPtr
, connectionIDLen
);
639 charPtr
+= connectionIDLen
;
642 assert(charPtr
== msg
.data
+ msg
.length
);
648 SSL2EncodeServerHello(SSLBuffer
&msg
, SSLContext
*ctx
)
650 SSLCertificate
*cert
;
651 SSLBuffer randomData
;
655 /* Create the connection ID */
656 ctx
->ssl2ConnectionIDLength
= SSL2_CONNECTION_ID_LENGTH
;
657 randomData
.data
= ctx
->serverRandom
;
658 randomData
.length
= ctx
->ssl2ConnectionIDLength
;
659 if ((err
= sslRand(ctx
, &randomData
)) != 0)
662 if (ctx
->ssl2SessionMatch
!= 0)
663 { if ((err
= SSLAllocBuffer(msg
, 11 + ctx
->sessionID
.length
, ctx
)) != 0)
666 *charPtr
++ = SSL2_MsgServerHello
;
667 *charPtr
++ = ctx
->ssl2SessionMatch
;
668 *charPtr
++ = 0; /* cert type */
669 charPtr
= SSLEncodeInt(charPtr
, ctx
->negProtocolVersion
, 2);
670 charPtr
= SSLEncodeInt(charPtr
, 0, 2); /* cert len */
671 charPtr
= SSLEncodeInt(charPtr
, 0, 2); /* cipherspecs len */
672 charPtr
= SSLEncodeInt(charPtr
, ctx
->ssl2ConnectionIDLength
, 2);
673 memcpy(charPtr
, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
);
674 charPtr
+= ctx
->ssl2ConnectionIDLength
;
677 { /* First, find the last cert in the chain; it's the one we'll send */
680 * Use encryptCert if we have it, but allow for the case of app
681 * specifying one cert which can encrypt and sign.
683 if(ctx
->encryptCert
!= NULL
) {
684 cert
= ctx
->encryptCert
;
686 else if(ctx
->localCert
!= NULL
) {
687 cert
= ctx
->localCert
;
690 /* really should not happen... */
691 sslErrorLog("SSL2EncodeServerHello: No server cert!\n");
695 while (cert
->next
!= 0)
698 if ((err
= SSLAllocBuffer(msg
, 11 + cert
->derCert
.length
+ 3 + ctx
->sessionID
.length
, ctx
)) != 0)
701 *charPtr
++ = SSL2_MsgServerHello
;
702 *charPtr
++ = ctx
->ssl2SessionMatch
;
703 *charPtr
++ = SSL2_CertTypeX509
; /* cert type */
705 /* FIXME - this ifndef should not be necessary */
707 sslLogNegotiateDebug("===SSL2 server: sending vers info %s",
708 protocolVersStr((SSLProtocolVersion
)ctx
->negProtocolVersion
));
711 charPtr
= SSLEncodeInt(charPtr
, ctx
->negProtocolVersion
, 2);
712 charPtr
= SSLEncodeInt(charPtr
, cert
->derCert
.length
, 2);
713 charPtr
= SSLEncodeInt(charPtr
, 3, 2); /* cipherspecs len */
714 charPtr
= SSLEncodeInt(charPtr
, ctx
->ssl2ConnectionIDLength
, 2);
715 memcpy(charPtr
, cert
->derCert
.data
, cert
->derCert
.length
);
716 charPtr
+= cert
->derCert
.length
;
717 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
718 if (ctx
->selectedCipher
== SSL2CipherMap
[i
].cipherSuite
)
720 assert(i
< SSL2CipherMapCount
);
721 charPtr
= SSLEncodeInt(charPtr
, SSL2CipherMap
[i
].cipherKind
, 3);
722 sslLogNegotiateDebug("ssl2: server specifying cipherKind 0x%lx",
723 (UInt32
)SSL2CipherMap
[i
].cipherKind
);
724 memcpy(charPtr
, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
);
725 charPtr
+= ctx
->ssl2ConnectionIDLength
;
728 assert(charPtr
== msg
.data
+ msg
.length
);
733 SSL2ProcessServerVerify(SSLBuffer msg
, SSLContext
*ctx
)
734 { if (msg
.length
!= ctx
->ssl2ChallengeLength
)
735 return errSSLProtocol
;
737 if (memcmp(msg
.data
, ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
-
738 ctx
->ssl2ChallengeLength
, ctx
->ssl2ChallengeLength
) != 0)
739 return errSSLProtocol
;
745 SSL2EncodeServerVerify(SSLBuffer
&msg
, SSLContext
*ctx
)
748 if ((err
= SSLAllocBuffer(msg
, 1 + ctx
->ssl2ChallengeLength
, ctx
)) != 0)
751 msg
.data
[0] = SSL2_MsgServerVerify
;
752 memcpy(msg
.data
+1, ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
-
753 ctx
->ssl2ChallengeLength
, ctx
->ssl2ChallengeLength
);
759 SSL2ProcessServerFinished(SSLBuffer msg
, SSLContext
*ctx
)
762 if ((err
= SSLAllocBuffer(ctx
->sessionID
, msg
.length
, ctx
)) != 0)
764 memcpy(ctx
->sessionID
.data
, msg
.data
, msg
.length
);
769 SSL2EncodeServerFinished(SSLBuffer
&msg
, SSLContext
*ctx
)
772 if ((err
= SSLAllocBuffer(msg
, 1 + ctx
->sessionID
.length
, ctx
)) != 0)
775 msg
.data
[0] = SSL2_MsgServerFinished
;
776 memcpy(msg
.data
+1, ctx
->sessionID
.data
, ctx
->sessionID
.length
);