]> git.saurik.com Git - apple/security.git/blob - SecureTransport/ssl2Message.cpp
Security-54.1.9.tar.gz
[apple/security.git] / SecureTransport / ssl2Message.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18 #include "ssl.h"
19 #include "ssl2.h"
20 #include "sslRecord.h"
21 #include "sslMemory.h"
22 #include "sslContext.h"
23 #include "sslAlertMessage.h"
24 #include "sslHandshake.h"
25 #include "sslSession.h"
26 #include "sslDebug.h"
27 #include "cipherSpecs.h"
28 #include "appleCdsa.h"
29 #include "sslUtils.h"
30
31 #include <string.h>
32 #include <assert.h>
33
34 OSStatus
35 SSL2ProcessClientHello(SSLBuffer msg, SSLContext *ctx)
36 { OSStatus err;
37 UInt8 *charPtr, *cipherList;
38 unsigned i, j, cipherKindCount, sessionIDLen, challengeLen;
39 SSL2CipherKind cipherKind;
40 SSLCipherSuite matchingCipher, selectedCipher;
41 SSLProtocolVersion version;
42
43 if (msg.length < 27) {
44 sslErrorLog("SSL2ProcessClientHello: msg len error 1\n");
45 return errSSLProtocol;
46 }
47
48 charPtr = msg.data;
49
50 version = (SSLProtocolVersion)SSLDecodeInt(charPtr, 2);
51 if (version > ctx->maxProtocolVersion) {
52 version = ctx->maxProtocolVersion;
53 }
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)
57 {
58 /* FIXME - this ifndef should not be necessary */
59 #ifndef NDEBUG
60 sslLogNegotiateDebug("===SSL2 server: negVersion was undetermined; "
61 "is %s", protocolVersStr(version));
62 #endif
63 ctx->negProtocolVersion = version;
64 if(version >= TLS_Version_1_0) {
65 ctx->sslTslCalls = &Tls1Callouts;
66 }
67 else {
68 /* default from context init */
69 assert(ctx->sslTslCalls == &Ssl3Callouts);
70 }
71 }
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;
76 }
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;
82 }
83
84 charPtr += 2;
85 cipherKindCount = SSLDecodeInt(charPtr, 2);
86 charPtr += 2;
87 if (cipherKindCount % 3 != 0) {
88 sslErrorLog("SSL2ProcessClientHello: cipherKindCount error\n");
89 return errSSLProtocol;
90 }
91 cipherKindCount /= 3;
92 sessionIDLen = SSLDecodeInt(charPtr, 2);
93 charPtr += 2;
94 challengeLen = SSLDecodeInt(charPtr, 2);
95 charPtr += 2;
96
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;
102 }
103 cipherList = charPtr;
104 selectedCipher = SSL_NO_SUCH_CIPHERSUITE;
105
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);
110 charPtr += 3;
111 if (selectedCipher != SSL_NO_SUCH_CIPHERSUITE)
112 continue;
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;
119 break;
120 }
121 } /* searching thru all our valid ciphers */
122 } /* for each client cipher */
123 } /* v3 or greater */
124
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);
130 charPtr += 3;
131 if (selectedCipher == SSL_NO_SUCH_CIPHERSUITE) {
132 /* After we find one, just keep advancing ptr past
133 * the unused ones */
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;
140 break;
141 }
142 }
143 } /* real 3-byte SSL2 suite */
144 else {
145 /* if the first byte is zero, it's an encoded SSL 3 CipherSuite */
146 matchingCipher = (SSLCipherSuite)((UInt32)cipherKind & 0x00FFFF);
147 /*
148 * One more restriction - if we've negotiated a v2 session,
149 * ignore this matching cipher if it's not in the SSL2 map.
150 */
151 if(ctx->negProtocolVersion < SSL_Version_3_0) {
152 int isInMap = 0;
153 for (j = 0; j < SSL2CipherMapCount; j++) {
154 if (matchingCipher == SSL2CipherMap[j].cipherSuite) {
155 isInMap = 1;
156 break;
157 }
158 }
159 if(!isInMap) {
160 /* Sorry, no can do */
161 matchingCipher = SSL_NO_SUCH_CIPHERSUITE;
162 }
163 } /* SSL2 check */
164 } /* two-byte suite */
165
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;
171 break;
172 }
173 }
174 }
175 } /* not ignoring this suite */
176 } /* for each suite in the hello msg */
177 } /* not found in SSL3 ciphersuites */
178
179 if (selectedCipher == SSL_NO_SUCH_CIPHERSUITE)
180 return errSSLNegotiation;
181
182 ctx->selectedCipher = selectedCipher;
183 err = FindCipherSpec(ctx);
184 if(err != 0) {
185 return err;
186 }
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);
190 if (err == 0)
191 memcpy(ctx->sessionID.data, charPtr, sessionIDLen);
192 }
193 charPtr += sessionIDLen;
194
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);
201
202 return noErr;
203 }
204
205 /*
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
213 * of entropy.
214 */
215 #define SSL2_CHALLENGE_LEN 16
216
217 OSStatus
218 SSL2EncodeClientHello(SSLBuffer &msg, SSLContext *ctx)
219 { OSStatus err;
220 UInt8 *charPtr;
221 unsigned i, j;
222 int useSSL3Ciphers = 0;
223 int totalCipherCount;
224 int sessionIDLen;
225 UInt16 version;
226 SSLBuffer sessionIdentifier, randomData;
227
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 */
232 useSSL3Ciphers = 1;
233 /* could be SSLv3 or TLSv1 */
234 version = ctx->maxProtocolVersion;
235 break;
236 case SSL_Version_2_0:
237 useSSL3Ciphers = 0;
238 version = SSL_Version_2_0;
239 break;
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:
244 default:
245 assert("Bad protocol version for sending SSL 2 Client Hello");
246 return errSSLInternal;
247 }
248 /* FIXME - this ifndef should not be necessary */
249 #ifndef NDEBUG
250 sslLogNegotiateDebug("===SSL client: proclaiming %s capable",
251 protocolVersStr((SSLProtocolVersion)version));
252 #endif
253
254 if (useSSL3Ciphers != 0)
255 totalCipherCount = ctx->numValidCipherSpecs;
256 else
257 totalCipherCount = 0;
258
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++;
263 break;
264 }
265
266 sessionIDLen = 0;
267 sessionIdentifier.data = 0;
268 if (ctx->resumableSession.data != 0)
269 { if ((err = SSLRetrieveSessionID(ctx->resumableSession, &sessionIdentifier, ctx)) != 0)
270 return err;
271 sessionIDLen = sessionIdentifier.length;
272 }
273
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
277 */
278 if ((err = SSLAllocBuffer(msg, 9 + (3*totalCipherCount) + sessionIDLen +
279 SSL2_CHALLENGE_LEN, ctx)) != 0)
280 { SSLFreeBuffer(sessionIdentifier, ctx);
281 return err;
282 }
283
284 charPtr = msg.data;
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);
290
291 /* If we can send SSL3 ciphers, encode the two-byte cipher specs into three-byte
292 * CipherKinds which have a leading 0.
293 */
294 if (useSSL3Ciphers != 0)
295 for (i = 0; i < ctx->numValidCipherSpecs; i++)
296 charPtr = SSLEncodeInt(charPtr, ctx->validCipherSpecs[i].cipherSpec, 3);
297
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);
303 break;
304 }
305
306 if (sessionIDLen > 0)
307 { memcpy(charPtr, sessionIdentifier.data, sessionIDLen);
308 charPtr += sessionIDLen;
309 SSLFreeBuffer(sessionIdentifier, ctx);
310 }
311
312 randomData.data = charPtr;
313 randomData.length = SSL2_CHALLENGE_LEN;
314 if ((err = sslRand(ctx, &randomData)) != 0)
315 { SSLFreeBuffer(msg, ctx);
316 return err;
317 }
318 charPtr += SSL2_CHALLENGE_LEN;
319
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);
325 #else
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);
329 #endif
330 ctx->ssl2ChallengeLength = SSL2_CHALLENGE_LEN;
331
332 assert(charPtr == msg.data + msg.length);
333
334 return noErr;
335 }
336
337 OSStatus
338 SSL2ProcessClientMasterKey(SSLBuffer msg, SSLContext *ctx)
339 { OSStatus err;
340 SSL2CipherKind cipherKind;
341 SSLBuffer secretData;
342 unsigned clearLength, encryptedLength, keyArgLength;
343 UInt32 secretLength, localKeyModulusLen;
344 UInt8 *charPtr;
345 const CSSM_KEY *decryptKey;
346 CSSM_CSP_HANDLE decryptCspHand;
347
348 if (msg.length < 9) {
349 sslErrorLog("SSL2ProcessClientMasterKey: msg.length error 1\n");
350 return errSSLProtocol;
351 }
352 assert(ctx->protocolSide == SSL_ServerSide);
353
354 charPtr = msg.data;
355 cipherKind = (SSL2CipherKind)SSLDecodeInt(charPtr, 3);
356 charPtr += 3;
357 clearLength = SSLDecodeInt(charPtr, 2);
358 charPtr += 2;
359 encryptedLength = SSLDecodeInt(charPtr, 2);
360 charPtr += 2;
361 keyArgLength = SSLDecodeInt(charPtr, 2);
362 charPtr += 2;
363
364 if (msg.length != 9 + clearLength + encryptedLength + keyArgLength) {
365 sslErrorLog("SSL2ProcessClientMasterKey: msg.length error 2\n");
366 return errSSLProtocol;
367 }
368
369 /* Master key == CLEAR_DATA || SECRET_DATA */
370 memcpy(ctx->masterSecret, charPtr, clearLength);
371 charPtr += clearLength;
372
373 /*
374 * Just as in SSL2EncodeServerHello, which key we use depends on the
375 * app's config.
376 */
377 if(ctx->encryptPrivKey) {
378 decryptKey = ctx->encryptPrivKey;
379 assert(ctx->encryptKeyCsp != 0);
380 decryptCspHand = ctx->encryptKeyCsp;
381 }
382 else if(ctx->signingPrivKey) {
383 decryptKey = ctx->signingPrivKey;
384 assert(ctx->signingKeyCsp != 0);
385 decryptCspHand = ctx->signingKeyCsp;
386 }
387 else {
388 /* really should not happen... */
389 sslErrorLog("SSL2ProcessClientMasterKey: No server key!\n");
390 return badReqErr;
391 }
392 localKeyModulusLen = sslKeyLengthInBytes(decryptKey);
393
394 if (encryptedLength != localKeyModulusLen) {
395 sslErrorLog("SSL2ProcessClientMasterKey: encryptedLength error 1\n");
396 return errSSLProtocol;
397 }
398
399 /* Allocate enough room to hold any decrypted value */
400 if ((err = SSLAllocBuffer(secretData, encryptedLength, ctx)) != 0)
401 return err;
402
403 err = sslRsaDecrypt(ctx,
404 decryptKey,
405 decryptCspHand,
406 charPtr,
407 encryptedLength,
408 secretData.data,
409 encryptedLength, // same length for both...?
410 &secretLength);
411 if(err) {
412 SSLFreeBuffer(secretData, ctx);
413 return err;
414 }
415
416 charPtr += encryptedLength;
417
418 if (clearLength + secretLength != ctx->selectedCipherSpec->cipher->keySize) {
419 sslErrorLog("SSL2ProcessClientMasterKey: length error 3\n");
420 return errSSLProtocol;
421 }
422 memcpy(ctx->masterSecret + clearLength, secretData.data, secretLength);
423 if ((err = SSLFreeBuffer(secretData, ctx)) != 0)
424 return err;
425
426 if (keyArgLength != ctx->selectedCipherSpec->cipher->ivSize) {
427 sslErrorLog("SSL2ProcessClientMasterKey: length error 4\n");
428 return errSSLProtocol;
429 }
430
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);
435
436 return noErr;
437 }
438
439 OSStatus
440 SSL2EncodeClientMasterKey(SSLBuffer &msg, SSLContext *ctx)
441 { OSStatus err;
442 unsigned length, i, clearLen;
443 UInt32 outputLen, peerKeyModulusLen;
444 SSLBuffer keyData;
445 UInt8 *charPtr;
446
447 peerKeyModulusLen = sslKeyLengthInBytes(ctx->peerPubKey);
448
449 /* Length is 10 + clear key size + encrypted output size + iv size */
450 length = 10;
451 clearLen = ctx->selectedCipherSpec->cipher->keySize - ctx->selectedCipherSpec->cipher->secretKeySize;
452 length += clearLen;
453 length += peerKeyModulusLen;
454 length += ctx->selectedCipherSpec->cipher->ivSize;
455
456 if ((err = SSLAllocBuffer(msg, length, ctx)) != 0)
457 return err;
458 charPtr = msg.data;
459 *charPtr++ = SSL2_MsgClientMasterKey;
460 for (i = 0; i < SSL2CipherMapCount; i++)
461 if (ctx->selectedCipher == SSL2CipherMap[i].cipherSuite)
462 break;
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);
470
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)
476 return err;
477
478 memcpy(charPtr, ctx->masterSecret, clearLen);
479 charPtr += clearLen;
480
481 /* Replace this with code to do encryption at lower level & set PKCS1 padding
482 for rollback attack */
483
484 /*
485 * encrypt only the secret key portion of masterSecret, starting at
486 * clearLen bytes
487 */
488 err = sslRsaEncrypt(ctx,
489 ctx->peerPubKey,
490 ctx->peerPubKeyCsp, // XX - maybe cspHand
491 ctx->masterSecret + clearLen,
492 ctx->selectedCipherSpec->cipher->keySize - clearLen,
493 charPtr,
494 peerKeyModulusLen,
495 &outputLen);
496 if(err) {
497 return err;
498 }
499
500 charPtr += outputLen;
501
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;
506
507 assert(charPtr == msg.data + msg.length);
508
509 return noErr;
510 }
511
512 OSStatus
513 SSL2ProcessClientFinished(SSLBuffer msg, SSLContext *ctx)
514 { if (msg.length != ctx->sessionID.length) {
515 sslErrorLog("SSL2ProcessClientFinished: length error\n");
516 return errSSLProtocol;
517 }
518 if (memcmp(msg.data, ctx->serverRandom, ctx->ssl2ConnectionIDLength) != 0) {
519 sslErrorLog("SSL2ProcessClientFinished: data compare error\n");
520 return errSSLProtocol;
521 }
522 return noErr;
523 }
524
525 OSStatus
526 SSL2EncodeClientFinished(SSLBuffer &msg, SSLContext *ctx)
527 { OSStatus err;
528
529 if ((err = SSLAllocBuffer(msg, ctx->ssl2ConnectionIDLength+1, ctx)) != 0)
530 return err;
531 msg.data[0] = SSL2_MsgClientFinished;
532 memcpy(msg.data+1, ctx->serverRandom, ctx->ssl2ConnectionIDLength);
533 return noErr;
534 }
535
536 OSStatus
537 SSL2ProcessServerHello(SSLBuffer msg, SSLContext *ctx)
538 { OSStatus err;
539 SSL2CertTypeCode certType;
540 unsigned sessionIDMatch, certLen, cipherSpecsLen, connectionIDLen;
541 unsigned i, j;
542 SSL2CipherKind cipherKind;
543 SSLCertificate *cert;
544 SSLCipherSuite matchingCipher = 0; // avoid compiler warning
545 SSLCipherSuite selectedCipher;
546 UInt8 *charPtr;
547 SSLProtocolVersion version;
548
549 if (msg.length < 10) {
550 sslErrorLog("SSL2ProcessServerHello: length error\n");
551 return errSSLProtocol;
552 }
553 charPtr = msg.data;
554
555 sessionIDMatch = *charPtr++;
556 certType = (SSL2CertTypeCode)*charPtr++;
557 version = (SSLProtocolVersion)SSLDecodeInt(charPtr, 2);
558 charPtr += 2;
559 if (version != SSL_Version_2_0) {
560 sslErrorLog("SSL2ProcessServerHello: version error\n");
561 return errSSLProtocol;
562 }
563 ctx->negProtocolVersion = version;
564 sslLogNegotiateDebug("===SSL2 client: negVersion is 2_0");
565 certLen = SSLDecodeInt(charPtr, 2);
566 charPtr += 2;
567 cipherSpecsLen = SSLDecodeInt(charPtr, 2);
568 charPtr += 2;
569 connectionIDLen = SSLDecodeInt(charPtr, 2);
570 charPtr += 2;
571
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;
579
580 ctx->ssl2ConnectionIDLength = connectionIDLen;
581 memcpy(ctx->serverRandom, charPtr, connectionIDLen);
582 charPtr += connectionIDLen;
583 }
584 else
585 { if (certType != SSL2_CertTypeX509)
586 return errSSLNegotiation;
587 cipherSpecsLen /= 3;
588
589 cert = (SSLCertificate *)sslMalloc(sizeof(SSLCertificate));
590 if(cert == NULL) {
591 return memFullErr;
592 }
593 cert->next = 0;
594 if ((err = SSLAllocBuffer(cert->derCert, certLen, ctx)) != 0)
595 {
596 sslFree(cert);
597 return err;
598 }
599 memcpy(cert->derCert.data, charPtr, certLen);
600 charPtr += certLen;
601 ctx->peerCert = cert;
602 if((err = sslVerifyCertChain(ctx, *ctx->peerCert)) != 0) {
603 return err;
604 }
605 if((err = sslPubKeyFromCert(ctx,
606 cert->derCert,
607 &ctx->peerPubKey,
608 &ctx->peerPubKeyCsp)) != 0)
609 return err;
610
611 selectedCipher = SSL_NO_SUCH_CIPHERSUITE;
612 for (i = 0; i < cipherSpecsLen; i++)
613 { cipherKind = (SSL2CipherKind)SSLDecodeInt(charPtr, 3);
614 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;
619 break;
620 }
621 for (j = 0; j < ctx->numValidCipherSpecs; j++)
622 if (ctx->validCipherSpecs[j].cipherSpec == matchingCipher)
623 { selectedCipher = matchingCipher;
624 break;
625 }
626 }
627 }
628 if (selectedCipher == SSL_NO_SUCH_CIPHERSUITE)
629 return errSSLNegotiation;
630 sslLogNegotiateDebug("===SSL2 client: selectedCipher 0x%x",
631 (unsigned)selectedCipher);
632
633 ctx->selectedCipher = selectedCipher;
634 if ((err = FindCipherSpec(ctx)) != 0) {
635 return err;
636 }
637 ctx->ssl2ConnectionIDLength = connectionIDLen;
638 memcpy(ctx->serverRandom, charPtr, connectionIDLen);
639 charPtr += connectionIDLen;
640 }
641
642 assert(charPtr == msg.data + msg.length);
643
644 return noErr;
645 }
646
647 OSStatus
648 SSL2EncodeServerHello(SSLBuffer &msg, SSLContext *ctx)
649 { OSStatus err;
650 SSLCertificate *cert;
651 SSLBuffer randomData;
652 UInt8 *charPtr;
653 unsigned i;
654
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)
660 return err;
661
662 if (ctx->ssl2SessionMatch != 0)
663 { if ((err = SSLAllocBuffer(msg, 11 + ctx->sessionID.length, ctx)) != 0)
664 return err;
665 charPtr = msg.data;
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;
675 }
676 else
677 { /* First, find the last cert in the chain; it's the one we'll send */
678
679 /*
680 * Use encryptCert if we have it, but allow for the case of app
681 * specifying one cert which can encrypt and sign.
682 */
683 if(ctx->encryptCert != NULL) {
684 cert = ctx->encryptCert;
685 }
686 else if(ctx->localCert != NULL) {
687 cert = ctx->localCert;
688 }
689 else {
690 /* really should not happen... */
691 sslErrorLog("SSL2EncodeServerHello: No server cert!\n");
692 return badReqErr;
693 }
694
695 while (cert->next != 0)
696 cert = cert->next;
697
698 if ((err = SSLAllocBuffer(msg, 11 + cert->derCert.length + 3 + ctx->sessionID.length, ctx)) != 0)
699 return err;
700 charPtr = msg.data;
701 *charPtr++ = SSL2_MsgServerHello;
702 *charPtr++ = ctx->ssl2SessionMatch;
703 *charPtr++ = SSL2_CertTypeX509; /* cert type */
704
705 /* FIXME - this ifndef should not be necessary */
706 #ifndef NDEBUG
707 sslLogNegotiateDebug("===SSL2 server: sending vers info %s",
708 protocolVersStr((SSLProtocolVersion)ctx->negProtocolVersion));
709 #endif
710
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)
719 break;
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;
726 }
727
728 assert(charPtr == msg.data + msg.length);
729 return noErr;
730 }
731
732 OSStatus
733 SSL2ProcessServerVerify(SSLBuffer msg, SSLContext *ctx)
734 { if (msg.length != ctx->ssl2ChallengeLength)
735 return errSSLProtocol;
736
737 if (memcmp(msg.data, ctx->clientRandom + SSL_CLIENT_SRVR_RAND_SIZE -
738 ctx->ssl2ChallengeLength, ctx->ssl2ChallengeLength) != 0)
739 return errSSLProtocol;
740
741 return noErr;
742 }
743
744 OSStatus
745 SSL2EncodeServerVerify(SSLBuffer &msg, SSLContext *ctx)
746 { OSStatus err;
747
748 if ((err = SSLAllocBuffer(msg, 1 + ctx->ssl2ChallengeLength, ctx)) != 0)
749 return err;
750
751 msg.data[0] = SSL2_MsgServerVerify;
752 memcpy(msg.data+1, ctx->clientRandom + SSL_CLIENT_SRVR_RAND_SIZE -
753 ctx->ssl2ChallengeLength, ctx->ssl2ChallengeLength);
754
755 return noErr;
756 }
757
758 OSStatus
759 SSL2ProcessServerFinished(SSLBuffer msg, SSLContext *ctx)
760 { OSStatus err;
761
762 if ((err = SSLAllocBuffer(ctx->sessionID, msg.length, ctx)) != 0)
763 return err;
764 memcpy(ctx->sessionID.data, msg.data, msg.length);
765 return noErr;
766 }
767
768 OSStatus
769 SSL2EncodeServerFinished(SSLBuffer &msg, SSLContext *ctx)
770 { OSStatus err;
771
772 if ((err = SSLAllocBuffer(msg, 1 + ctx->sessionID.length, ctx)) != 0)
773 return err;
774
775 msg.data[0] = SSL2_MsgServerFinished;
776 memcpy(msg.data+1, ctx->sessionID.data, ctx->sessionID.length);
777
778 return noErr;
779 }