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.
19 /* *********************************************************************
22 SSLRef 3.0 Final -- 11/19/96
24 Copyright (c)1996 by Netscape Communications Corp.
26 By retrieving this software you are bound by the licensing terms
27 disclosed in the file "LICENSE.txt". Please read it, and if you don't
28 accept the terms, delete this software.
30 SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
31 View, California <http://home.netscape.com/> and Consensus Development
32 Corporation of Berkeley, California <http://www.consensus.com/>.
34 *********************************************************************
36 File: ssl2mesg.c Message encoding and decoding functions for SSL 2
38 The necessary message encoding and decoding for all SSL 2 handshake
41 ****************************************************************** */
79 #ifndef _CIPHER_SPECS_H_
80 #include "cipherSpecs.h"
83 #ifndef _APPLE_CDSA_H_
84 #include "appleCdsa.h"
95 SSL2ProcessClientHello(SSLBuffer msg
, SSLContext
*ctx
)
97 UInt8
*progress
, *cipherList
;
98 int i
, j
, cipherKindCount
, sessionIDLen
, challengeLen
;
99 SSL2CipherKind cipherKind
;
100 SSLCipherSuite matchingCipher
, selectedCipher
;
101 SSLProtocolVersion version
;
103 if (msg
.length
< 27) {
104 errorLog0("SSL2ProcessClientHello: msg len error 1\n");
105 return ERR(SSLProtocolErr
);
110 version
= (SSLProtocolVersion
)SSLDecodeInt(progress
, 2);
111 if (version
> ctx
->maxProtocolVersion
) {
112 version
= ctx
->maxProtocolVersion
;
114 /* FIXME - I think this needs work for a SSL_Version_2_0 server, to ensure that
115 * the client isn't establishing a v3 session. */
116 if (ctx
->negProtocolVersion
== SSL_Version_Undetermined
)
119 dprintf1("===SSL2 server: negVersion was undetermined; is %s\n",
120 protocolVersStr(version
));
122 ctx
->negProtocolVersion
= version
;
123 if(version
>= TLS_Version_1_0
) {
124 ctx
->sslTslCalls
= &Tls1Callouts
;
127 /* default from context init */
128 assert(ctx
->sslTslCalls
== &Ssl3Callouts
);
131 else if (ctx
->negProtocolVersion
== SSL_Version_3_0_With_2_0_Hello
)
132 { if (version
< SSL_Version_3_0
) {
133 errorLog0("SSL2ProcessClientHello: version error\n");
134 return ERR(SSLProtocolErr
);
136 /* FIXME - I don't think path is ever taken - we NEVER set any
137 * protocol var to SSL_Version_3_0_With_2_0_Hello... */
139 dprintf0("===SSL2 server: negVersion was 3_0_With_2_0_Hello; is 3_0\n");
141 ctx
->negProtocolVersion
= version
;
145 cipherKindCount
= SSLDecodeInt(progress
, 2);
147 if (cipherKindCount
% 3 != 0) {
148 errorLog0("SSL2ProcessClientHello: cipherKindCount error\n");
149 return ERR(SSLProtocolErr
);
151 cipherKindCount
/= 3;
152 sessionIDLen
= SSLDecodeInt(progress
, 2);
154 challengeLen
= SSLDecodeInt(progress
, 2);
157 if (msg
.length
!= 8 + 3*cipherKindCount
+ sessionIDLen
+ challengeLen
||
158 (sessionIDLen
!= 0 && sessionIDLen
!= 16) ||
159 challengeLen
< 16 || challengeLen
> 32 ) {
160 errorLog0("SSL2ProcessClientHello: msg len error 2\n");
161 return ERR(SSLProtocolErr
);
163 cipherList
= progress
;
164 selectedCipher
= SSL_NO_SUCH_CIPHERSUITE
;
166 if (ctx
->negProtocolVersion
>= SSL_Version_3_0
) {
167 /* If we're negotiating an SSL 3.0 session, use SSL 3.0 suites first */
168 for (i
= 0; i
< cipherKindCount
; i
++) {
169 cipherKind
= (SSL2CipherKind
)SSLDecodeInt(progress
, 3);
171 if (selectedCipher
!= SSL_NO_SUCH_CIPHERSUITE
)
173 if ((((UInt32
)cipherKind
) & 0xFF0000) != 0)
174 continue; /* Skip SSL 2 suites */
175 matchingCipher
= (SSLCipherSuite
)((UInt32
)cipherKind
& 0x00FFFF);
176 for (j
= 0; j
<ctx
->numValidCipherSpecs
; j
++) {
177 if (ctx
->validCipherSpecs
[j
].cipherSpec
== matchingCipher
) {
178 selectedCipher
= matchingCipher
;
181 } /* searching thru all our valid ciphers */
182 } /* for each client cipher */
183 } /* v3 or greater */
185 if(selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
) {
186 /* try again using SSL2 ciphers only */
187 progress
= cipherList
;
188 for (i
= 0; i
< cipherKindCount
; i
++) {
189 cipherKind
= (SSL2CipherKind
)SSLDecodeInt(progress
, 3);
191 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
) {
192 /* After we find one, just keep advancing progress past
194 if ((((UInt32
)cipherKind
) & 0xFF0000) != 0) {
195 /* If it's a real SSL2 spec, look for it in the list */
196 matchingCipher
= SSL_NO_SUCH_CIPHERSUITE
;
197 for (j
= 0; j
< SSL2CipherMapCount
; j
++) {
198 if (cipherKind
== SSL2CipherMap
[j
].cipherKind
) {
199 matchingCipher
= SSL2CipherMap
[j
].cipherSuite
;
203 } /* real 3-byte SSL2 suite */
205 /* if the first byte is zero, it's an encoded SSL 3 CipherSuite */
206 matchingCipher
= (SSLCipherSuite
)((UInt32
)cipherKind
& 0x00FFFF);
208 * One more restriction - if we've negotiated a v2 session,
209 * ignore this matching cipher if it's not in the SSL2 map.
211 if(ctx
->negProtocolVersion
< SSL_Version_3_0
) {
213 for (j
= 0; j
< SSL2CipherMapCount
; j
++) {
214 if (matchingCipher
== SSL2CipherMap
[j
].cipherSuite
) {
220 /* Sorry, no can do */
221 matchingCipher
= SSL_NO_SUCH_CIPHERSUITE
;
224 } /* two-byte suite */
226 /* now see if we are enabled for this cipher */
227 if (matchingCipher
!= SSL_NO_SUCH_CIPHERSUITE
) {
228 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++) {
229 if (ctx
->validCipherSpecs
[j
].cipherSpec
== matchingCipher
) {
230 selectedCipher
= matchingCipher
;
235 } /* not ignoring this suite */
236 } /* for each suite in the hello msg */
237 } /* not found in SSL3 ciphersuites */
239 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
)
240 return ERR(SSLNegotiationErr
);
242 ctx
->selectedCipher
= selectedCipher
;
243 err
= FindCipherSpec(ctx
);
247 if (sessionIDLen
> 0 && ctx
->peerID
.data
!= 0)
248 { /* Don't die on error; just treat it as an uncacheable session */
249 ERR(err
= SSLAllocBuffer(&ctx
->sessionID
, sessionIDLen
, &ctx
->sysCtx
));
251 memcpy(ctx
->sessionID
.data
, progress
, sessionIDLen
);
253 progress
+= sessionIDLen
;
255 ctx
->ssl2ChallengeLength
= challengeLen
;
256 memset(ctx
->clientRandom
, 0, SSL_CLIENT_SRVR_RAND_SIZE
);
257 memcpy(ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
- challengeLen
,
258 progress
, challengeLen
);
259 progress
+= challengeLen
;
260 CASSERT(progress
== msg
.data
+ msg
.length
);
266 * The SSL v2 spec says that the challenge string sent by the client can be
267 * between 16 and 32 bytes. However all Netscape enterprise servers actually
268 * require a 16 byte challenge. Q.v. cdnow.com, store.apple.com.
269 * Unfortunately this means that when we're trying to do a
270 * SSL_Version_3_0_With_2_0_Hello negotiation, we have to limit ourself to
271 * a 16-byte clientRandom, which we have to concatenate to 16 bytes of
272 * zeroes if we end up with a 3.0 or 3.1 connection. Thus we lose 16 bytes
275 #define SSL2_CHALLENGE_LEN 16
278 SSL2EncodeClientHello(SSLBuffer
*msg
, SSLContext
*ctx
)
281 int i
, j
, useSSL3Ciphers
, totalCipherCount
;
284 SSLBuffer sessionIdentifier
, randomData
;
286 switch (ctx
->negProtocolVersion
)
287 { case SSL_Version_Undetermined
:
288 case SSL_Version_3_0_With_2_0_Hello
:
289 /* go for it, see if server can handle upgrading */
291 /* could be SSLv3 or TLSv1 */
292 version
= ctx
->maxProtocolVersion
;
294 case SSL_Version_2_0
:
296 version
= SSL_Version_2_0
;
298 case SSL_Version_3_0_Only
:
299 case SSL_Version_3_0
:
300 case TLS_Version_1_0_Only
:
301 case TLS_Version_1_0
:
303 ASSERTMSG("Bad protocol version for sending SSL 2 Client Hello");
307 dprintf1("===SSL client: proclaiming %s capable\n",
308 protocolVersStr((SSLProtocolVersion
)version
));
311 if (useSSL3Ciphers
!= 0)
312 totalCipherCount
= ctx
->numValidCipherSpecs
;
314 totalCipherCount
= 0;
316 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
317 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++)
318 if (ctx
->validCipherSpecs
[j
].cipherSpec
== SSL2CipherMap
[i
].cipherSuite
)
319 { totalCipherCount
++;
324 sessionIdentifier
.data
= 0;
325 if (ctx
->resumableSession
.data
!= 0)
326 { if (ERR(err
= SSLRetrieveSessionID(ctx
->resumableSession
, &sessionIdentifier
, ctx
)) != 0)
328 sessionIDLen
= sessionIdentifier
.length
;
331 /* msg length = 9 + 3 * totalCipherCount + sessionIDLen + 16 bytes of challenge
332 * Use exactly 16 bytes of challenge because Netscape products have a bug
333 * that requires this length
335 if (ERR(err
= SSLAllocBuffer(msg
, 9 + (3*totalCipherCount
) + sessionIDLen
+
336 SSL2_CHALLENGE_LEN
, &ctx
->sysCtx
)) != 0)
337 { ERR(SSLFreeBuffer(&sessionIdentifier
, &ctx
->sysCtx
));
341 progress
= msg
->data
;
342 *progress
++ = ssl2_mt_client_hello
;
343 progress
= SSLEncodeInt(progress
, version
, 2);
344 progress
= SSLEncodeInt(progress
, 3*totalCipherCount
, 2);
345 progress
= SSLEncodeInt(progress
, sessionIDLen
, 2);
346 progress
= SSLEncodeInt(progress
, SSL2_CHALLENGE_LEN
, 2);
348 /* If we can send SSL3 ciphers, encode the two-byte cipher specs into three-byte
349 * CipherKinds which have a leading 0.
351 if (useSSL3Ciphers
!= 0)
352 for (i
= 0; i
< ctx
->numValidCipherSpecs
; i
++)
353 progress
= SSLEncodeInt(progress
, ctx
->validCipherSpecs
[i
].cipherSpec
, 3);
355 /* Now send those SSL2 specs for which we have implementations */
356 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
357 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++)
358 if (ctx
->validCipherSpecs
[j
].cipherSpec
== SSL2CipherMap
[i
].cipherSuite
)
359 { progress
= SSLEncodeInt(progress
, SSL2CipherMap
[i
].cipherKind
, 3);
363 if (sessionIDLen
> 0)
364 { memcpy(progress
, sessionIdentifier
.data
, sessionIDLen
);
365 progress
+= sessionIDLen
;
366 ERR(SSLFreeBuffer(&sessionIdentifier
, &ctx
->sysCtx
));
369 randomData
.data
= progress
;
370 randomData
.length
= SSL2_CHALLENGE_LEN
;
371 if ((err
= sslRand(ctx
, &randomData
)) != 0)
372 { ERR(SSLFreeBuffer(msg
, &ctx
->sysCtx
));
375 progress
+= SSL2_CHALLENGE_LEN
;
377 /* Zero out the first 16 bytes of clientRandom, and store
378 * the challenge in the second 16 bytes */
379 #if (SSL2_CHALLENGE_LEN == SSL_CLIENT_SRVR_RAND_SIZE)
380 /* this path verified to fail with Netscape Enterprise servers 1/16/02 */
381 memcpy(ctx
->clientRandom
, randomData
.data
, SSL2_CHALLENGE_LEN
);
383 memset(ctx
->clientRandom
, 0, SSL_CLIENT_SRVR_RAND_SIZE
- SSL2_CHALLENGE_LEN
);
384 memcpy(ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
- SSL2_CHALLENGE_LEN
,
385 randomData
.data
, SSL2_CHALLENGE_LEN
);
387 ctx
->ssl2ChallengeLength
= SSL2_CHALLENGE_LEN
;
389 CASSERT(progress
== msg
->data
+ msg
->length
);
395 SSL2ProcessClientMasterKey(SSLBuffer msg
, SSLContext
*ctx
)
397 SSL2CipherKind cipherKind
;
398 SSLBuffer secretData
;
399 int clearLength
, encryptedLength
, keyArgLength
;
400 UInt32 secretLength
, localKeyModulusLen
;
402 const CSSM_KEY
*decryptKey
;
403 CSSM_CSP_HANDLE decryptCspHand
;
405 if (msg
.length
< 9) {
406 errorLog0("SSL2ProcessClientMasterKey: msg.length error 1\n");
407 return ERR(SSLProtocolErr
);
409 CASSERT(ctx
->protocolSide
== SSL_ServerSide
);
412 cipherKind
= (SSL2CipherKind
)SSLDecodeInt(progress
, 3);
414 clearLength
= SSLDecodeInt(progress
, 2);
416 encryptedLength
= SSLDecodeInt(progress
, 2);
418 keyArgLength
= SSLDecodeInt(progress
, 2);
421 if (msg
.length
!= 9 + clearLength
+ encryptedLength
+ keyArgLength
) {
422 errorLog0("SSL2ProcessClientMasterKey: msg.length error 2\n");
423 return ERR(SSLProtocolErr
);
426 /* Master key == CLEAR_DATA || SECRET_DATA */
427 memcpy(ctx
->masterSecret
, progress
, clearLength
);
428 progress
+= clearLength
;
431 * Just as in SSL2EncodeServerHello, which key we use depends on the
434 if(ctx
->encryptPrivKey
) {
435 decryptKey
= ctx
->encryptPrivKey
;
436 CASSERT(ctx
->encryptKeyCsp
!= 0);
437 decryptCspHand
= ctx
->encryptKeyCsp
;
439 else if(ctx
->signingPrivKey
) {
440 decryptKey
= ctx
->signingPrivKey
;
441 CASSERT(ctx
->signingKeyCsp
!= 0);
442 decryptCspHand
= ctx
->signingKeyCsp
;
445 /* really should not happen... */
446 errorLog0("SSL2ProcessClientMasterKey: No server key!\n");
447 return SSLBadStateErr
;
449 localKeyModulusLen
= sslKeyLengthInBytes(decryptKey
);
451 if (encryptedLength
!= localKeyModulusLen
) {
452 errorLog0("SSL2ProcessClientMasterKey: encryptedLength error 1\n");
453 return ERR(SSLProtocolErr
);
456 /* Allocate enough room to hold any decrypted value */
457 if (ERR(err
= SSLAllocBuffer(&secretData
, encryptedLength
, &ctx
->sysCtx
)) != 0)
460 err
= sslRsaDecrypt(ctx
,
466 encryptedLength
, // same length for both...?
469 SSLFreeBuffer(&secretData
, &ctx
->sysCtx
);
473 progress
+= encryptedLength
;
475 if (clearLength
+ secretLength
!= ctx
->selectedCipherSpec
->cipher
->keySize
) {
476 errorLog0("SSL2ProcessClientMasterKey: length error 3\n");
477 return ERR(SSLProtocolErr
);
479 memcpy(ctx
->masterSecret
+ clearLength
, secretData
.data
, secretLength
);
480 if (ERR(err
= SSLFreeBuffer(&secretData
, &ctx
->sysCtx
)) != 0)
483 if (keyArgLength
!= ctx
->selectedCipherSpec
->cipher
->ivSize
) {
484 errorLog0("SSL2ProcessClientMasterKey: length error 4\n");
485 return ERR(SSLProtocolErr
);
488 /* Stash the IV after the master key in master secret storage */
489 memcpy(ctx
->masterSecret
+ ctx
->selectedCipherSpec
->cipher
->keySize
, progress
, keyArgLength
);
490 progress
+= keyArgLength
;
491 CASSERT(progress
= msg
.data
+ msg
.length
);
497 SSL2EncodeClientMasterKey(SSLBuffer
*msg
, SSLContext
*ctx
)
499 int length
, i
, clearLen
;
500 UInt32 outputLen
, peerKeyModulusLen
;
504 peerKeyModulusLen
= sslKeyLengthInBytes(ctx
->peerPubKey
);
506 /* Length is 10 + clear key size + encrypted output size + iv size */
508 clearLen
= ctx
->selectedCipherSpec
->cipher
->keySize
- ctx
->selectedCipherSpec
->cipher
->secretKeySize
;
510 length
+= peerKeyModulusLen
;
511 length
+= ctx
->selectedCipherSpec
->cipher
->ivSize
;
513 if (ERR(err
= SSLAllocBuffer(msg
, length
, &ctx
->sysCtx
)) != 0)
515 progress
= msg
->data
;
516 *progress
++ = ssl2_mt_client_master_key
;
517 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
518 if (ctx
->selectedCipher
== SSL2CipherMap
[i
].cipherSuite
)
520 CASSERT(i
< SSL2CipherMapCount
);
522 dprintf1("===SSL2EncodeClientMasterKey: sending cipherKind 0x%x\n",
523 SSL2CipherMap
[i
].cipherKind
);
525 progress
= SSLEncodeInt(progress
, SSL2CipherMap
[i
].cipherKind
, 3);
526 progress
= SSLEncodeInt(progress
, clearLen
, 2);
527 progress
= SSLEncodeInt(progress
, peerKeyModulusLen
, 2);
528 progress
= SSLEncodeInt(progress
, ctx
->selectedCipherSpec
->cipher
->ivSize
, 2);
530 /* Generate the keying material; we need enough data for the key and IV */
531 keyData
.data
= ctx
->masterSecret
;
532 keyData
.length
= ctx
->selectedCipherSpec
->cipher
->keySize
+ ctx
->selectedCipherSpec
->cipher
->ivSize
;
533 CASSERT(keyData
.length
<= 48); /* Must be able to store it in the masterSecret array */
534 if ((err
= sslRand(ctx
, &keyData
)) != 0)
537 memcpy(progress
, ctx
->masterSecret
, clearLen
);
538 progress
+= clearLen
;
540 /* Replace this with code to do encryption at lower level & set PKCS1 padding
541 for rollback attack */
544 * encrypt only the secret key portion of masterSecret, starting at
547 err
= sslRsaEncrypt(ctx
,
549 ctx
->peerPubKeyCsp
, // XX - maybe cspHand
550 ctx
->masterSecret
+ clearLen
,
551 ctx
->selectedCipherSpec
->cipher
->keySize
- clearLen
,
559 progress
+= outputLen
;
561 /* copy clear IV to msg buf */
562 memcpy(progress
, ctx
->masterSecret
+ ctx
->selectedCipherSpec
->cipher
->keySize
,
563 ctx
->selectedCipherSpec
->cipher
->ivSize
);
564 progress
+= ctx
->selectedCipherSpec
->cipher
->ivSize
;
566 CASSERT(progress
== msg
->data
+ msg
->length
);
572 SSL2ProcessClientFinished(SSLBuffer msg
, SSLContext
*ctx
)
573 { if (msg
.length
!= ctx
->sessionID
.length
) {
574 errorLog0("SSL2ProcessClientFinished: length error\n");
575 return ERR(SSLProtocolErr
);
577 if (memcmp(msg
.data
, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
) != 0) {
578 errorLog0("SSL2ProcessClientFinished: data compare error\n");
579 return ERR(SSLProtocolErr
);
585 SSL2EncodeClientFinished(SSLBuffer
*msg
, SSLContext
*ctx
)
588 if (ERR(err
= SSLAllocBuffer(msg
, ctx
->ssl2ConnectionIDLength
+1, &ctx
->sysCtx
)) != 0)
590 msg
->data
[0] = ssl2_mt_client_finished
;
591 memcpy(msg
->data
+1, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
);
596 SSL2ProcessServerHello(SSLBuffer msg
, SSLContext
*ctx
)
598 SSL2CertTypeCode certType
;
599 int sessionIDMatch
, certLen
, cipherSpecsLen
, connectionIDLen
;
601 SSL2CipherKind cipherKind
;
602 SSLCertificate
*cert
;
603 SSLCipherSuite matchingCipher
= 0; // avoid compiler warning
604 SSLCipherSuite selectedCipher
;
606 SSLProtocolVersion version
;
608 if (msg
.length
< 10) {
609 errorLog0("SSL2ProcessServerHello: length error\n");
610 return ERR(SSLProtocolErr
);
614 sessionIDMatch
= *progress
++;
615 certType
= (SSL2CertTypeCode
)*progress
++;
616 version
= (SSLProtocolVersion
)SSLDecodeInt(progress
, 2);
618 if (version
!= SSL_Version_2_0
) {
619 errorLog0("SSL2ProcessServerHello: version error\n");
620 return ERR(SSLProtocolErr
);
622 ctx
->negProtocolVersion
= version
;
624 dprintf0("===SSL2 client: negVersion is 2_0\n");
626 certLen
= SSLDecodeInt(progress
, 2);
628 cipherSpecsLen
= SSLDecodeInt(progress
, 2);
630 connectionIDLen
= SSLDecodeInt(progress
, 2);
633 if (connectionIDLen
< 16 || connectionIDLen
> 32 || cipherSpecsLen
% 3 != 0 ||
634 (msg
.length
!= 10 + certLen
+ cipherSpecsLen
+ connectionIDLen
) )
635 return ERR(SSLProtocolErr
);
636 if (sessionIDMatch
!= 0)
637 { if (certLen
!= 0 || cipherSpecsLen
!= 0 /* || certType != 0 */ )
638 return ERR(SSLProtocolErr
);
639 ctx
->ssl2SessionMatch
= 1;
641 ctx
->ssl2ConnectionIDLength
= connectionIDLen
;
642 memcpy(ctx
->serverRandom
, progress
, connectionIDLen
);
643 progress
+= connectionIDLen
;
646 { if (certType
!= ssl2_ct_x509_certificate
)
647 return ERR(SSLNegotiationErr
);
650 cert
= (SSLCertificate
*)sslMalloc(sizeof(SSLCertificate
));
655 if (ERR(err
= SSLAllocBuffer(&cert
->derCert
, certLen
, &ctx
->sysCtx
)) != 0)
660 memcpy(cert
->derCert
.data
, progress
, certLen
);
662 ctx
->peerCert
= cert
;
663 /* This cert never gets verified in original SSLRef3 code... */
664 if((err
= sslVerifyCertChain(ctx
, ctx
->peerCert
)) != 0) {
667 if((err
= sslPubKeyFromCert(ctx
,
670 &ctx
->peerPubKeyCsp
)) != 0)
673 selectedCipher
= SSL_NO_SUCH_CIPHERSUITE
;
674 for (i
= 0; i
< cipherSpecsLen
; i
++)
675 { cipherKind
= (SSL2CipherKind
)SSLDecodeInt(progress
, 3);
677 //dprintf1("ssl2: server supports cipherKind 0x%x\n", (UInt32)cipherKind);
678 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
) /* After we find one, just keep advancing progress past the unused ones */
679 { for (j
= 0; j
< SSL2CipherMapCount
; j
++)
680 if (cipherKind
== SSL2CipherMap
[j
].cipherKind
)
681 { matchingCipher
= SSL2CipherMap
[j
].cipherSuite
;
684 for (j
= 0; j
< ctx
->numValidCipherSpecs
; j
++)
685 if (ctx
->validCipherSpecs
[j
].cipherSpec
== matchingCipher
)
686 { selectedCipher
= matchingCipher
;
691 if (selectedCipher
== SSL_NO_SUCH_CIPHERSUITE
)
692 return ERR(SSLNegotiationErr
);
694 dprintf1("===SSL2 client: selectedCipher 0x%x\n",
695 (unsigned)selectedCipher
);
698 ctx
->selectedCipher
= selectedCipher
;
699 if (ERR(err
= FindCipherSpec(ctx
)) != 0) {
702 ctx
->ssl2ConnectionIDLength
= connectionIDLen
;
703 memcpy(ctx
->serverRandom
, progress
, connectionIDLen
);
704 progress
+= connectionIDLen
;
707 CASSERT(progress
== msg
.data
+ msg
.length
);
713 SSL2EncodeServerHello(SSLBuffer
*msg
, SSLContext
*ctx
)
715 SSLCertificate
*cert
;
716 SSLBuffer randomData
;
720 /* Create the connection ID */
721 ctx
->ssl2ConnectionIDLength
= SSL2_CONNECTION_ID_LENGTH
;
722 randomData
.data
= ctx
->serverRandom
;
723 randomData
.length
= ctx
->ssl2ConnectionIDLength
;
724 if ((err
= sslRand(ctx
, &randomData
)) != 0)
727 if (ctx
->ssl2SessionMatch
!= 0)
728 { if (ERR(err
= SSLAllocBuffer(msg
, 11 + ctx
->sessionID
.length
, &ctx
->sysCtx
)) != 0)
730 progress
= msg
->data
;
731 *progress
++ = ssl2_mt_server_hello
;
732 *progress
++ = ctx
->ssl2SessionMatch
;
733 *progress
++ = 0; /* cert type */
734 progress
= SSLEncodeInt(progress
, ctx
->negProtocolVersion
, 2);
735 progress
= SSLEncodeInt(progress
, 0, 2); /* cert len */
736 progress
= SSLEncodeInt(progress
, 0, 2); /* cipherspecs len */
737 progress
= SSLEncodeInt(progress
, ctx
->ssl2ConnectionIDLength
, 2);
738 memcpy(progress
, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
);
739 progress
+= ctx
->ssl2ConnectionIDLength
;
742 { /* First, find the last cert in the chain; it's the one we'll send */
745 * Use encryptCert if we have it, but allow for the case of app
746 * specifying one cert which can encrypt and sign.
748 if(ctx
->encryptCert
!= NULL
) {
749 cert
= ctx
->encryptCert
;
751 else if(ctx
->localCert
!= NULL
) {
752 cert
= ctx
->localCert
;
755 /* really should not happen... */
756 errorLog0("SSL2EncodeServerHello: No server cert!\n");
757 return SSLBadStateErr
;
760 while (cert
->next
!= 0)
763 if (ERR(err
= SSLAllocBuffer(msg
, 11 + cert
->derCert
.length
+ 3 + ctx
->sessionID
.length
, &ctx
->sysCtx
)) != 0)
765 progress
= msg
->data
;
766 *progress
++ = ssl2_mt_server_hello
;
767 *progress
++ = ctx
->ssl2SessionMatch
;
768 *progress
++ = ssl2_ct_x509_certificate
; /* cert type */
770 dprintf1("===SSL2 server: sending vers info %s\n",
771 protocolVersStr((SSLProtocolVersion
)ctx
->negProtocolVersion
));
773 progress
= SSLEncodeInt(progress
, ctx
->negProtocolVersion
, 2);
774 progress
= SSLEncodeInt(progress
, cert
->derCert
.length
, 2);
775 progress
= SSLEncodeInt(progress
, 3, 2); /* cipherspecs len */
776 progress
= SSLEncodeInt(progress
, ctx
->ssl2ConnectionIDLength
, 2);
777 memcpy(progress
, cert
->derCert
.data
, cert
->derCert
.length
);
778 progress
+= cert
->derCert
.length
;
779 for (i
= 0; i
< SSL2CipherMapCount
; i
++)
780 if (ctx
->selectedCipher
== SSL2CipherMap
[i
].cipherSuite
)
782 CASSERT(i
< SSL2CipherMapCount
);
783 progress
= SSLEncodeInt(progress
, SSL2CipherMap
[i
].cipherKind
, 3);
784 dprintf1("ssl2: server specifying cipherKind 0x%lx\n",
785 (UInt32
)SSL2CipherMap
[i
].cipherKind
);
786 memcpy(progress
, ctx
->serverRandom
, ctx
->ssl2ConnectionIDLength
);
787 progress
+= ctx
->ssl2ConnectionIDLength
;
790 CASSERT(progress
== msg
->data
+ msg
->length
);
795 SSL2ProcessServerVerify(SSLBuffer msg
, SSLContext
*ctx
)
796 { if (msg
.length
!= ctx
->ssl2ChallengeLength
)
797 return ERR(SSLProtocolErr
);
799 if (memcmp(msg
.data
, ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
-
800 ctx
->ssl2ChallengeLength
, ctx
->ssl2ChallengeLength
) != 0)
801 return ERR(SSLProtocolErr
);
807 SSL2EncodeServerVerify(SSLBuffer
*msg
, SSLContext
*ctx
)
810 if (ERR(err
= SSLAllocBuffer(msg
, 1 + ctx
->ssl2ChallengeLength
, &ctx
->sysCtx
)) != 0)
813 msg
->data
[0] = ssl2_mt_server_verify
;
814 memcpy(msg
->data
+1, ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
-
815 ctx
->ssl2ChallengeLength
, ctx
->ssl2ChallengeLength
);
821 SSL2ProcessServerFinished(SSLBuffer msg
, SSLContext
*ctx
)
824 if (ERR(err
= SSLAllocBuffer(&ctx
->sessionID
, msg
.length
, &ctx
->sysCtx
)) != 0)
826 memcpy(ctx
->sessionID
.data
, msg
.data
, msg
.length
);
831 SSL2EncodeServerFinished(SSLBuffer
*msg
, SSLContext
*ctx
)
834 if (ERR(err
= SSLAllocBuffer(msg
, 1 + ctx
->sessionID
.length
, &ctx
->sysCtx
)) != 0)
837 msg
->data
[0] = ssl2_mt_server_finished
;
838 memcpy(msg
->data
+1, ctx
->sessionID
.data
, ctx
->sessionID
.length
);