]> git.saurik.com Git - apple/security.git/blob - SecureTransport/sslHandshake.cpp
2ef0abe2592405c5a38f21e0a0f19c3d43d987d2
[apple/security.git] / SecureTransport / sslHandshake.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
19 /*
20 File: sslHandshake.cpp
21
22 Contains: SSL 3.0 handshake state machine.
23
24 Written by: Doug Mitchell
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29
30 #include "sslContext.h"
31 #include "sslHandshake.h"
32 #include "sslMemory.h"
33 #include "sslAlertMessage.h"
34 #include "sslSession.h"
35 #include "sslUtils.h"
36 #include "sslDebug.h"
37 #include "appleCdsa.h"
38 #include "sslDigests.h"
39
40 #include <string.h>
41 #include <assert.h>
42
43 #define REQUEST_CERT_CORRECT 0
44
45 static OSStatus SSLProcessHandshakeMessage(SSLHandshakeMsg message, SSLContext *ctx);
46
47 OSStatus
48 SSLProcessHandshakeRecord(SSLRecord rec, SSLContext *ctx)
49 { OSStatus err;
50 sint32 remaining;
51 UInt8 *p;
52 SSLHandshakeMsg message;
53 SSLBuffer messageData;
54
55 if (ctx->fragmentedMessageCache.data != 0)
56 { if ((err = SSLReallocBuffer(ctx->fragmentedMessageCache,
57 ctx->fragmentedMessageCache.length + rec.contents.length,
58 ctx)) != 0)
59 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
60 return err;
61 }
62 memcpy(ctx->fragmentedMessageCache.data + ctx->fragmentedMessageCache.length,
63 rec.contents.data, rec.contents.length);
64 remaining = ctx->fragmentedMessageCache.length;
65 p = ctx->fragmentedMessageCache.data;
66 }
67 else
68 { remaining = rec.contents.length;
69 p = rec.contents.data;
70 }
71
72 while (remaining > 0)
73 { if (remaining < 4)
74 break; /* we must have at least a header */
75
76 messageData.data = p;
77 message.type = (SSLHandshakeType)*p++;
78 message.contents.length = SSLDecodeInt(p, 3);
79 if (((int)(message.contents.length + 4)) > remaining)
80 break;
81
82 p += 3;
83 message.contents.data = p;
84 p += message.contents.length;
85 messageData.length = 4 + message.contents.length;
86 assert(p == messageData.data + messageData.length);
87
88 /* message fragmentation */
89 remaining -= messageData.length;
90 if ((err = SSLProcessHandshakeMessage(message, ctx)) != 0)
91 return err;
92
93 if (message.type != SSL_HdskHelloRequest)
94 { if ((err = SSLHashSHA1.update(ctx->shaState, messageData)) != 0 ||
95 (err = SSLHashMD5.update(ctx->md5State, messageData)) != 0)
96 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
97 return err;
98 }
99 }
100
101 if ((err = SSLAdvanceHandshake(message.type, ctx)) != 0)
102 return err;
103 }
104
105 if (remaining > 0) /* Fragmented handshake message */
106 { /* If there isn't a cache, allocate one */
107 if (ctx->fragmentedMessageCache.data == 0)
108 { if ((err = SSLAllocBuffer(ctx->fragmentedMessageCache, remaining, ctx)) != 0)
109 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
110 return err;
111 }
112 }
113 if (p != ctx->fragmentedMessageCache.data)
114 { memcpy(ctx->fragmentedMessageCache.data, p, remaining);
115 ctx->fragmentedMessageCache.length = remaining;
116 }
117 }
118 else if (ctx->fragmentedMessageCache.data != 0)
119 { if ((err = SSLFreeBuffer(ctx->fragmentedMessageCache, ctx)) != 0)
120 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
121 return err;
122 }
123 }
124
125 return noErr;
126 }
127
128 static OSStatus
129 SSLProcessHandshakeMessage(SSLHandshakeMsg message, SSLContext *ctx)
130 { OSStatus err;
131
132 err = noErr;
133 SSLLogHdskMsg(message.type, 0);
134 switch (message.type)
135 { case SSL_HdskHelloRequest:
136 if (ctx->protocolSide != SSL_ClientSide)
137 goto wrongMessage;
138 if (message.contents.length > 0)
139 err = errSSLProtocol;
140 break;
141 case SSL_HdskClientHello:
142 if (ctx->state != SSL_HdskStateServerUninit)
143 goto wrongMessage;
144 err = SSLProcessClientHello(message.contents, ctx);
145 break;
146 case SSL_HdskServerHello:
147 if (ctx->state != SSL_HdskStateServerHello &&
148 ctx->state != SSL_HdskStateServerHelloUnknownVersion)
149 goto wrongMessage;
150 err = SSLProcessServerHello(message.contents, ctx);
151 break;
152 case SSL_HdskCert:
153 if (ctx->state != SSL_HdskStateCert &&
154 ctx->state != SSL_HdskStateClientCert)
155 goto wrongMessage;
156 err = SSLProcessCertificate(message.contents, ctx);
157 if(ctx->protocolSide == SSL_ServerSide) {
158 if(err) {
159 ctx->clientCertState = kSSLClientCertRejected;
160 }
161 else if(ctx->peerCert != NULL) {
162 /*
163 * This still might change if cert verify msg
164 * fails. Note we avoid going to state
165 * if we get en empty cert message which is
166 * otherwise valid.
167 */
168 ctx->clientCertState = kSSLClientCertSent;
169 }
170 }
171 break;
172 case SSL_HdskCertRequest:
173 if (((ctx->state != SSL_HdskStateHelloDone) &&
174 (ctx->state != SSL_HdskStateKeyExchange))
175 || ctx->certRequested)
176 goto wrongMessage;
177 err = SSLProcessCertificateRequest(message.contents, ctx);
178 break;
179 case SSL_HdskServerKeyExchange:
180 /*
181 * Since this message is optional, and completely at the
182 * server's discretion, we need to be able to handle this
183 * in one of two states...
184 */
185 switch(ctx->state) {
186 case SSL_HdskStateKeyExchange: /* explicitly waiting for this */
187 case SSL_HdskStateHelloDone:
188 break;
189 default:
190 goto wrongMessage;
191 }
192 err = SSLProcessServerKeyExchange(message.contents, ctx);
193 break;
194 case SSL_HdskServerHelloDone:
195 if (ctx->state != SSL_HdskStateHelloDone)
196 goto wrongMessage;
197 err = SSLProcessServerHelloDone(message.contents, ctx);
198 break;
199 case SSL_HdskCertVerify:
200 if (ctx->state != SSL_HdskStateClientCertVerify)
201 goto wrongMessage;
202 err = SSLProcessCertificateVerify(message.contents, ctx);
203 assert(ctx->protocolSide == SSL_ServerSide);
204 if(err) {
205 ctx->clientCertState = kSSLClientCertRejected;
206 }
207 break;
208 case SSL_HdskClientKeyExchange:
209 if (ctx->state != SSL_HdskStateClientKeyExchange)
210 goto wrongMessage;
211 err = SSLProcessKeyExchange(message.contents, ctx);
212 break;
213 case SSL_HdskFinished:
214 if (ctx->state != SSL_HdskStateFinished)
215 goto wrongMessage;
216 err = SSLProcessFinished(message.contents, ctx);
217 break;
218 default:
219 goto wrongMessage;
220 break;
221 }
222
223 if (err)
224 { if (err == errSSLProtocol)
225 SSLFatalSessionAlert(SSL_AlertIllegalParam, ctx);
226 else if (err == errSSLNegotiation)
227 SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx);
228 else
229 SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
230 }
231 return err;
232
233 wrongMessage:
234 SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx);
235 return errSSLProtocol;
236 }
237
238 OSStatus
239 SSLAdvanceHandshake(SSLHandshakeType processed, SSLContext *ctx)
240 { OSStatus err;
241 SSLBuffer sessionIdentifier;
242
243 switch (processed)
244 { case SSL_HdskHelloRequest:
245 /*
246 * Reset the client auth state machine in case this is
247 * a renegotiation.
248 */
249 ctx->certRequested = 0;
250 ctx->certSent = 0;
251 ctx->certReceived = 0;
252 ctx->x509Requested = 0;
253 ctx->clientCertState = kSSLClientCertNone;
254 if ((err = SSLPrepareAndQueueMessage(SSLEncodeClientHello, ctx)) != 0)
255 return err;
256 SSLChangeHdskState(ctx, SSL_HdskStateServerHello);
257 break;
258 case SSL_HdskClientHello:
259 assert(ctx->protocolSide == SSL_ServerSide);
260 if (ctx->sessionID.data != 0)
261 /* If session ID != 0, client is trying to resume */
262 { if (ctx->resumableSession.data != 0)
263 { if ((err = SSLRetrieveSessionID(ctx->resumableSession,
264 &sessionIdentifier, ctx)) != 0)
265 return err;
266 if (sessionIdentifier.length == ctx->sessionID.length &&
267 memcmp(sessionIdentifier.data, ctx->sessionID.data,
268 ctx->sessionID.length) == 0)
269 { /* Everything matches; resume the session */
270 sslLogResumSessDebug("===RESUMING SSL3 server-side session");
271 if ((err = SSLInstallSessionFromData(ctx->resumableSession,
272 ctx)) != 0)
273 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
274 return err;
275 }
276 if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHello,
277 ctx)) != 0)
278 return err;
279 if ((err = SSLInitPendingCiphers(ctx)) != 0 ||
280 (err = SSLFreeBuffer(sessionIdentifier, ctx)) != 0)
281 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
282 return err;
283 }
284 if ((err =
285 SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec,
286 ctx)) != 0)
287 return err;
288 /* Install new cipher spec on write side */
289 if ((err = SSLDisposeCipherSuite(&ctx->writeCipher,
290 ctx)) != 0)
291 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
292 return err;
293 }
294 ctx->writeCipher = ctx->writePending;
295 ctx->writeCipher.ready = 0;
296 /* Can't send data until Finished is sent */
297 memset(&ctx->writePending, 0, sizeof(CipherContext));
298 /* Zero out old data */
299 if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage,
300 ctx)) != 0)
301 return err;
302 /* Finished has been sent; enable data t6ransfer on
303 * write channel */
304 ctx->writeCipher.ready = 1;
305 SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
306 break;
307 }
308 else {
309 sslLogResumSessDebug(
310 "===FAILED TO RESUME SSL3 server-side session");
311 }
312 if ((err = SSLFreeBuffer(sessionIdentifier, ctx)) != 0 ||
313 (err = SSLDeleteSessionData(ctx)) != 0)
314 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
315 return err;
316 }
317 }
318 if ((err = SSLFreeBuffer(ctx->sessionID, ctx)) != 0)
319 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
320 return err;
321 }
322 }
323
324 /*
325 * If we get here, we're not resuming; generate a new session ID
326 * if we know our peer
327 */
328 if (ctx->peerID.data != 0)
329 { /* Ignore errors; just treat as uncached session */
330 assert(ctx->sessionID.data == 0);
331 err = SSLAllocBuffer(ctx->sessionID, SSL_SESSION_ID_LEN, ctx);
332 if (err == 0)
333 {
334 if((err = sslRand(ctx, &ctx->sessionID)) != 0)
335 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
336 return err;
337 }
338 }
339 }
340
341 if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHello, ctx)) != 0)
342 return err;
343 switch (ctx->selectedCipherSpec->keyExchangeMethod)
344 { case SSL_NULL_auth:
345 #if APPLE_DH
346 case SSL_DH_anon:
347 case SSL_DH_anon_EXPORT:
348 if(ctx->clientAuth == kAlwaysAuthenticate) {
349 /* app requires this; abort */
350 SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx);
351 return errSSLNegotiation;
352 }
353 ctx->tryClientAuth = false;
354 /* DH server side needs work */
355 break;
356 #endif /* APPLE_DH */
357 default: /* everything else */
358 if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate,
359 ctx)) != 0)
360 return err;
361 break;
362 }
363 /*
364 * At this point we decide whether to send a server key exchange
365 * method. For Apple servers, I think we'll ALWAYS do this, because
366 * of key usage restrictions (can't decrypt and sign with the same
367 * private key), but conceptually in this code, we do it if
368 * enabled by the presence of encryptPrivKey.
369 */
370 #if SSL_SERVER_KEYEXCH_HACK
371 /*
372 * This is currently how we work with Netscape. It requires
373 * a CSP which can handle private keys which can both
374 * sign and decrypt.
375 */
376 if((ctx->selectedCipherSpec->keyExchangeMethod != SSL_RSA) &&
377 (ctx->encryptPrivKey != NULL)) {
378 err = SSLPrepareAndQueueMessage(SSLEncodeServerKeyExchange, ctx);
379 if(err) {
380 return err;
381 }
382 }
383 #else /* !SSL_SERVER_KEYEXCH_HACK */
384 /*
385 * This is, I believe the "right" way, but Netscape doesn't
386 * work this way.
387 */
388 if (ctx->encryptPrivKey != NULL) {
389 err = SSLPrepareAndQueueMessage(SSLEncodeServerKeyExchange, ctx);
390 if(err) {
391 return err;
392 }
393 }
394 #endif /* SSL_SERVER_KEYEXCH_HACK */
395
396 if (ctx->tryClientAuth)
397 { if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificateRequest,
398 ctx)) != 0)
399 return err;
400 ctx->certRequested = 1;
401 ctx->clientCertState = kSSLClientCertRequested;
402 }
403 if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHelloDone, ctx)) != 0)
404 return err;
405 if (ctx->certRequested) {
406 SSLChangeHdskState(ctx, SSL_HdskStateClientCert);
407 }
408 else {
409 SSLChangeHdskState(ctx, SSL_HdskStateClientKeyExchange);
410 }
411 break;
412 case SSL_HdskServerHello:
413 if (ctx->resumableSession.data != 0 && ctx->sessionID.data != 0)
414 { if ((err = SSLRetrieveSessionID(ctx->resumableSession,
415 &sessionIdentifier, ctx)) != 0)
416 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
417 return err;
418 }
419 if (sessionIdentifier.length == ctx->sessionID.length &&
420 memcmp(sessionIdentifier.data, ctx->sessionID.data,
421 ctx->sessionID.length) == 0)
422 { /* Everything matches; resume the session */
423 sslLogResumSessDebug("===RESUMING SSL3 client-side session");
424 if ((err = SSLInstallSessionFromData(ctx->resumableSession,
425 ctx)) != 0 ||
426 (err = SSLInitPendingCiphers(ctx)) != 0 ||
427 (err = SSLFreeBuffer(sessionIdentifier, ctx)) != 0)
428 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
429 return err;
430 }
431 SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
432 break;
433 }
434 else {
435 sslLogResumSessDebug("===FAILED TO RESUME SSL3 client-side "
436 "session");
437 }
438 if ((err = SSLFreeBuffer(sessionIdentifier, ctx)) != 0)
439 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
440 return err;
441 }
442 }
443 switch (ctx->selectedCipherSpec->keyExchangeMethod)
444 {
445 /* these require a key exchange message */
446 case SSL_NULL_auth:
447 case SSL_DH_anon:
448 case SSL_DH_anon_EXPORT:
449 SSLChangeHdskState(ctx, SSL_HdskStateKeyExchange);
450 break;
451 case SSL_RSA:
452 case SSL_DH_DSS:
453 case SSL_DH_DSS_EXPORT:
454 case SSL_DH_RSA:
455 case SSL_DH_RSA_EXPORT:
456 case SSL_RSA_EXPORT:
457 case SSL_DHE_DSS:
458 case SSL_DHE_DSS_EXPORT:
459 case SSL_DHE_RSA:
460 case SSL_DHE_RSA_EXPORT:
461 case SSL_Fortezza:
462 SSLChangeHdskState(ctx, SSL_HdskStateCert);
463 break;
464 default:
465 assert("Unknown key exchange method");
466 break;
467 }
468 break;
469 case SSL_HdskCert:
470 if (ctx->state == SSL_HdskStateCert)
471 switch (ctx->selectedCipherSpec->keyExchangeMethod)
472 { case SSL_RSA:
473 /*
474 * I really think the two RSA cases should be
475 * handled the same here - the server key exchange is
476 * optional, and is up to the server.
477 * Note this isn't the same as SSL_SERVER_KEYEXCH_HACK;
478 * we're a client here.
479 */
480 case SSL_RSA_EXPORT:
481 case SSL_DH_DSS:
482 case SSL_DH_DSS_EXPORT:
483 case SSL_DH_RSA:
484 case SSL_DH_RSA_EXPORT:
485 SSLChangeHdskState(ctx, SSL_HdskStateHelloDone);
486 break;
487 case SSL_DHE_DSS:
488 case SSL_DHE_DSS_EXPORT:
489 case SSL_DHE_RSA:
490 case SSL_DHE_RSA_EXPORT:
491 case SSL_Fortezza:
492 SSLChangeHdskState(ctx, SSL_HdskStateKeyExchange);
493 break;
494 default:
495 assert("Unknown or unexpected key exchange method");
496 break;
497 }
498 else if (ctx->state == SSL_HdskStateClientCert)
499 { SSLChangeHdskState(ctx, SSL_HdskStateClientKeyExchange);
500 if (ctx->peerCert != 0)
501 ctx->certReceived = 1;
502 }
503 break;
504 case SSL_HdskCertRequest:
505 /* state stays in SSL_HdskStateHelloDone; distinction is in
506 * ctx->certRequested */
507 if (ctx->peerCert == 0)
508 { SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx);
509 return errSSLProtocol;
510 }
511 ctx->certRequested = 1;
512 ctx->clientCertState = kSSLClientCertRequested;
513 break;
514 case SSL_HdskServerKeyExchange:
515 SSLChangeHdskState(ctx, SSL_HdskStateHelloDone);
516 break;
517 case SSL_HdskServerHelloDone:
518 if (ctx->certRequested) {
519 /*
520 * Server wants a client authentication cert - do
521 * we have one?
522 */
523 if (ctx->localCert != 0 && ctx->x509Requested) {
524 if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate,
525 ctx)) != 0) {
526 return err;
527 }
528 }
529 else {
530 /* response for no cert depends on protocol version */
531 if(ctx->negProtocolVersion == TLS_Version_1_0) {
532 /* TLS: send empty cert msg */
533 if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate,
534 ctx)) != 0) {
535 return err;
536 }
537 }
538 else {
539 /* SSL3: "no cert" alert */
540 if ((err = SSLSendAlert(SSL_AlertLevelWarning, SSL_AlertNoCert,
541 ctx)) != 0) {
542 return err;
543 }
544 }
545 } /* no cert to send */
546 } /* server requested a cert */
547 if ((err = SSLPrepareAndQueueMessage(SSLEncodeKeyExchange, ctx)) != 0)
548 return err;
549 assert(ctx->sslTslCalls != NULL);
550 if ((err = ctx->sslTslCalls->generateMasterSecret(ctx)) != 0 ||
551 (err = SSLInitPendingCiphers(ctx)) != 0)
552 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
553 return err;
554 }
555 memset(ctx->preMasterSecret.data, 0, ctx->preMasterSecret.length);
556 if ((err = SSLFreeBuffer(ctx->preMasterSecret, ctx)) != 0) {
557 return err;
558 }
559 if (ctx->certSent) {
560 if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificateVerify,
561 ctx)) != 0) {
562 return err;
563 }
564 }
565 if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec,
566 ctx)) != 0) {
567 return err;
568 }
569 /* Install new cipher spec on write side */
570 if ((err = SSLDisposeCipherSuite(&ctx->writeCipher, ctx)) != 0)
571 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
572 return err;
573 }
574 ctx->writeCipher = ctx->writePending;
575 /* Can't send data until Finished is sent */
576 ctx->writeCipher.ready = 0;
577
578 /* Zero out old data */
579 memset(&ctx->writePending, 0, sizeof(CipherContext));
580 ctx->writePending.encrypting = 1;
581 if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, ctx)) != 0)
582 return err;
583 /* Finished has been sent; enable data transfer on write channel */
584 ctx->writeCipher.ready = 1;
585 SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
586 break;
587 case SSL_HdskCertVerify:
588 SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
589 break;
590 case SSL_HdskClientKeyExchange:
591 assert(ctx->sslTslCalls != NULL);
592 if ((err = ctx->sslTslCalls->generateMasterSecret(ctx)) != 0 ||
593 (err = SSLInitPendingCiphers(ctx)) != 0)
594 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
595 return err;
596 }
597 memset(ctx->preMasterSecret.data, 0, ctx->preMasterSecret.length);
598 if ((err = SSLFreeBuffer(ctx->preMasterSecret, ctx)) != 0)
599 return err;
600 if (ctx->certReceived) {
601 SSLChangeHdskState(ctx, SSL_HdskStateClientCertVerify);
602 }
603 else {
604 SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
605 }
606 break;
607 case SSL_HdskFinished:
608 /* Handshake is over; enable data transfer on read channel */
609 ctx->readCipher.ready = 1;
610 /* If writePending is set, we haven't yet sent a finished message;
611 * send it */
612 if (ctx->writePending.ready != 0)
613 { if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec,
614 ctx)) != 0)
615 return err;
616
617 /* Install new cipher spec on write side */
618 if ((err = SSLDisposeCipherSuite(&ctx->writeCipher, ctx)) != 0)
619 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
620 return err;
621 }
622 ctx->writeCipher = ctx->writePending;
623 ctx->writeCipher.ready = 0;
624 /* Can't send data until Finished is sent */
625 memset(&ctx->writePending, 0, sizeof(CipherContext));
626 /* Zero out old data */
627 if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage,
628 ctx)) != 0)
629 return err;
630 ctx->writeCipher.ready = 1;
631 }
632 if (ctx->protocolSide == SSL_ServerSide) {
633 SSLChangeHdskState(ctx, SSL2_HdskStateServerReady);
634 }
635 else {
636 SSLChangeHdskState(ctx, SSL2_HdskStateClientReady);
637 }
638 if (ctx->peerID.data != 0)
639 SSLAddSessionData(ctx);
640 break;
641 default:
642 assert("Unknown State");
643 break;
644 }
645
646 return noErr;
647 }
648
649 OSStatus
650 SSLPrepareAndQueueMessage(EncodeMessageFunc msgFunc, SSLContext *ctx)
651 { OSStatus err;
652 SSLRecord rec;
653
654 if ((err = msgFunc(rec, ctx)) != 0)
655 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
656 goto fail;
657 }
658
659 if (rec.contentType == SSL_RecordTypeHandshake)
660 { if ((err = SSLHashSHA1.update(ctx->shaState, rec.contents)) != 0 ||
661 (err = SSLHashMD5.update(ctx->md5State, rec.contents)) != 0)
662 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
663 goto fail;
664 }
665 SSLLogHdskMsg((SSLHandshakeType)rec.contents.data[0], 1);
666 }
667
668 assert(ctx->sslTslCalls != NULL);
669 if ((err = ctx->sslTslCalls->writeRecord(rec, ctx)) != 0)
670 goto fail;
671
672 err = noErr;
673 fail:
674 SSLFreeBuffer(rec.contents, ctx);
675
676 return err;
677 }
678
679 OSStatus
680 SSL3ReceiveSSL2ClientHello(SSLRecord rec, SSLContext *ctx)
681 { OSStatus err;
682
683 if ((err = SSLInitMessageHashes(ctx)) != 0)
684 return err;
685
686 if ((err = SSLHashSHA1.update(ctx->shaState, rec.contents)) != 0 ||
687 (err = SSLHashMD5.update(ctx->md5State, rec.contents)) != 0)
688 { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
689 return err;
690 }
691
692 if ((err = SSLAdvanceHandshake(SSL_HdskClientHello, ctx)) != 0)
693 return err;
694
695 return noErr;
696 }
697
698 /* log changes in handshake state */
699 #ifndef NDEBUG
700 #include <stdio.h>
701
702 char *hdskStateToStr(SSLHandshakeState state)
703 {
704 static char badStr[100];
705
706 switch(state) {
707 case SSL_HdskStateUninit:
708 return "Uninit";
709 case SSL_HdskStateServerUninit:
710 return "ServerUninit";
711 case SSL_HdskStateClientUninit:
712 return "ClientUninit";
713 case SSL_HdskStateGracefulClose:
714 return "GracefulClose";
715 case SSL_HdskStateErrorClose:
716 return "ErrorClose";
717 case SSL_HdskStateNoNotifyClose:
718 return "NoNotifyClose";
719 case SSL_HdskStateServerHello:
720 return "ServerHello";
721 case SSL_HdskStateServerHelloUnknownVersion:
722 return "ServerHelloUnknownVersion";
723 case SSL_HdskStateKeyExchange:
724 return "KeyExchange";
725 case SSL_HdskStateCert:
726 return "Cert";
727 case SSL_HdskStateHelloDone:
728 return "HelloDone";
729 case SSL_HdskStateClientCert:
730 return "ClientCert";
731 case SSL_HdskStateClientKeyExchange:
732 return "ClientKeyExchange";
733 case SSL_HdskStateClientCertVerify:
734 return "ClientCertVerify";
735 case SSL_HdskStateChangeCipherSpec:
736 return "ChangeCipherSpec";
737 case SSL_HdskStateFinished:
738 return "Finished";
739 case SSL2_HdskStateClientMasterKey:
740 return "SSL2_ClientMasterKey";
741 case SSL2_HdskStateClientFinished:
742 return "SSL2_ClientFinished";
743 case SSL2_HdskStateServerHello:
744 return "SSL2_ServerHello";
745 case SSL2_HdskStateServerVerify:
746 return "SSL2_ServerVerify";
747 case SSL2_HdskStateServerFinished:
748 return "SSL2_ServerFinished";
749 case SSL2_HdskStateServerReady:
750 return "SSL2_ServerReady";
751 case SSL2_HdskStateClientReady:
752 return "SSL2_ClientReady";
753 default:
754 sprintf(badStr, "Unknown state (%d(d)", state);
755 return badStr;
756 }
757 }
758
759 void SSLChangeHdskState(SSLContext *ctx, SSLHandshakeState newState)
760 {
761 /* FIXME - this ifndef should not be necessary */
762 #ifndef NDEBUG
763 sslHdskStateDebug("...hdskState = %s", hdskStateToStr(newState));
764 #endif
765 ctx->state = newState;
766 }
767
768
769 /* log handshake messages */
770
771 static char *hdskMsgToStr(SSLHandshakeType msg)
772 {
773 static char badStr[100];
774
775 switch(msg) {
776 case SSL_HdskHelloRequest:
777 return "SSL_HdskHelloRequest";
778 case SSL_HdskClientHello:
779 return "SSL_HdskClientHello";
780 case SSL_HdskServerHello:
781 return "SSL_HdskServerHello";
782 case SSL_HdskCert:
783 return "SSL_HdskCert";
784 case SSL_HdskServerKeyExchange:
785 return "SSL_HdskServerKeyExchange";
786 case SSL_HdskCertRequest:
787 return "SSL_HdskCertRequest";
788 case SSL_HdskServerHelloDone:
789 return "SSL_HdskServerHelloDone";
790 case SSL_HdskCertVerify:
791 return "SSL_HdskCertVerify";
792 case SSL_HdskClientKeyExchange:
793 return "SSL_HdskClientKeyExchange";
794 case SSL_HdskFinished:
795 return "SSL_HdskFinished";
796 case SSL_HdskNoCertAlert:
797 return "SSL_HdskNoCertAlert";
798 default:
799 sprintf(badStr, "Unknown state (%d(d)", msg);
800 return badStr;
801 }
802 }
803
804 void SSLLogHdskMsg(SSLHandshakeType msg, char sent)
805 {
806 sslHdskMsgDebug("---%s handshake msg %s",
807 hdskMsgToStr(msg), (sent ? "sent" : "recv"));
808 }
809
810 #endif /* NDEBUG */
811