]> git.saurik.com Git - apple/security.git/blob - SecureTransport/ssl2prot.c
b96cb60f971b7879cf234c1ab140ea2fe15a1e85
[apple/security.git] / SecureTransport / ssl2prot.c
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: ssl2prot.c
21
22 Contains: Protocol engine for SSL 2
23
24 Written by: Doug Mitchell, based on Netscape SSLRef 3.0
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29 /* *********************************************************************
30 File: ssl2prot.c
31
32 SSLRef 3.0 Final -- 11/19/96
33
34 Copyright (c)1996 by Netscape Communications Corp.
35
36 By retrieving this software you are bound by the licensing terms
37 disclosed in the file "LICENSE.txt". Please read it, and if you don't
38 accept the terms, delete this software.
39
40 SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
41 View, California <http://home.netscape.com/> and Consensus Development
42 Corporation of Berkeley, California <http://www.consensus.com/>.
43
44 *********************************************************************
45
46 File: ssl2prot.c Protocol engine for SSL 2
47
48 This is the heart of the SSL 2 implementation, including the state
49 engine for proceeding through the handshake and the necessary code
50 for installing negotiated keys and algorithms.
51
52 ****************************************************************** */
53
54 #ifndef _SSL_H_
55 #include "ssl.h"
56 #endif
57
58 #ifndef _SSL2_H_
59 #include "ssl2.h"
60 #endif
61
62 #ifndef _SSLREC_H_
63 #include "sslrec.h"
64 #endif
65
66 #ifndef _SSLALLOC_H_
67 #include "sslalloc.h"
68 #endif
69
70 #ifndef _SSLCTX_H_
71 #include "sslctx.h"
72 #endif
73
74 #ifndef _SSLHDSHK_H_
75 #include "sslhdshk.h"
76 #endif
77
78 #ifndef _SSLSESS_H_
79 #include "sslsess.h"
80 #endif
81
82 #ifndef _SSLALERT_H_
83 #include "sslalert.h"
84 #endif
85
86 #ifndef _SSL_DEBUG_H_
87 #include "sslDebug.h"
88 #endif
89
90 #ifndef _APPLE_CDSA_H_
91 #include "appleCdsa.h"
92 #endif
93
94 #include <string.h>
95
96 #if LOG_HDSK_MSG
97
98 static char *sslHdskMsgToStr(SSL2MessageType msg)
99 {
100 static char badStr[100];
101
102 switch(msg) {
103 case ssl2_mt_error:
104 return "ssl2_mt_error";
105 case ssl2_mt_client_hello:
106 return "ssl2_mt_client_hello";
107 case ssl2_mt_client_master_key:
108 return "ssl2_mt_client_master_key";
109 case ssl2_mt_client_finished:
110 return "ssl2_mt_client_finished";
111 case ssl2_mt_server_hello:
112 return "ssl2_mt_server_hello";
113 case ssl2_mt_server_verify:
114 return "ssl2_mt_server_verify";
115 case ssl2_mt_server_finished:
116 return "ssl2_mt_server_finished";
117 case ssl2_mt_request_certificate:
118 return "ssl2_mt_request_certificate";
119 case ssl2_mt_client_certificate:
120 return "ssl2_mt_client_certificate";
121 case ssl2_mt_kickstart_handshake:
122 return "ssl2_mt_kickstart_handshake";
123 default:
124 sprintf(badStr, "Unknown msg (%d(d)", msg);
125 return badStr;
126 }
127 }
128
129 static void logSsl2Msg(SSL2MessageType msg, char sent)
130 {
131 char *ms = sslHdskMsgToStr(msg);
132 printf("...msg %s: %s\n", (sent ? "sent" : "recd"), ms);
133 }
134
135 #else /* SSL_DEBUG */
136
137 #define logSsl2Msg(m, s)
138
139 #endif
140
141 SSLErr
142 SSL2ProcessMessage(SSLRecord rec, SSLContext *ctx)
143 { SSLErr err = 0;
144 SSL2MessageType msg;
145 SSLBuffer contents;
146
147 if (rec.contents.length < 2)
148 return ERR(SSLProtocolErr);
149
150 msg = (SSL2MessageType)rec.contents.data[0];
151 contents.data = rec.contents.data + 1;
152 contents.length = rec.contents.length - 1;
153
154 logSsl2Msg(msg, 0);
155
156 switch (msg)
157 { case ssl2_mt_error:
158 #if _APPLE_CDSA_
159 /* ref code returned an unitialized local err here */
160 err = SSLConnectionClosedError;
161 #endif
162 break;
163 case ssl2_mt_client_hello:
164 if (ctx->state != HandshakeServerUninit)
165 return ERR(SSLProtocolErr);
166 ERR(err = SSL2ProcessClientHello(contents, ctx));
167 if (err == SSLNegotiationErr)
168 ERR(SSL2SendError(ssl2_pe_no_cipher, ctx));
169 break;
170 case ssl2_mt_client_master_key:
171 if (ctx->state != HandshakeSSL2ClientMasterKey)
172 return ERR(SSLProtocolErr);
173 ERR(err = SSL2ProcessClientMasterKey(contents, ctx));
174 break;
175 case ssl2_mt_client_finished:
176 if (ctx->state != HandshakeSSL2ClientFinished)
177 return ERR(SSLProtocolErr);
178 ERR(err = SSL2ProcessClientFinished(contents, ctx));
179 break;
180 case ssl2_mt_server_hello:
181 if (ctx->state != HandshakeSSL2ServerHello &&
182 ctx->state != HandshakeServerHelloUnknownVersion)
183 return ERR(SSLProtocolErr);
184 ERR(err = SSL2ProcessServerHello(contents, ctx));
185 if (err == SSLNegotiationErr)
186 ERR(SSL2SendError(ssl2_pe_no_cipher, ctx));
187 break;
188 case ssl2_mt_server_verify:
189 if (ctx->state != HandshakeSSL2ServerVerify)
190 return ERR(SSLProtocolErr);
191 ERR(err = SSL2ProcessServerVerify(contents, ctx));
192 break;
193 case ssl2_mt_server_finished:
194 if (ctx->state != HandshakeSSL2ServerFinished) {
195 #if LOG_HDSK_STATE
196 errorLog1("ssl2_mt_server_finished; state %s\n",
197 hdskStateToStr(ctx->state));
198 #endif
199 return ERR(SSLProtocolErr);
200 }
201 ERR(err = SSL2ProcessServerFinished(contents, ctx));
202 break;
203 case ssl2_mt_request_certificate:
204 /* Don't process the request; we don't support client certification */
205 break;
206 case ssl2_mt_client_certificate:
207 return ERR(SSLProtocolErr);
208 break;
209 default:
210 DEBUGVAL1("Unknown message %d", msg);
211 return ERR(SSLProtocolErr);
212 break;
213 }
214
215 if (err == 0)
216 { /* FIXME - use requested or negotiated protocol version here? */
217 if (msg == ssl2_mt_client_hello && ctx->negProtocolVersion == SSL_Version_3_0)
218 { /* Promote this message to SSL 3 protocol */
219 if (ERR(err = SSL3ReceiveSSL2ClientHello(rec, ctx)) != 0)
220 return err;
221 }
222 else
223 ERR(err = SSL2AdvanceHandshake(msg, ctx));
224 }
225 return err;
226 }
227
228 SSLErr
229 SSL2AdvanceHandshake(SSL2MessageType msg, SSLContext *ctx)
230 { SSLErr err;
231
232 err = SSLNoErr;
233
234 switch (msg)
235 { case ssl2_mt_kickstart_handshake:
236 if (ctx->negProtocolVersion == SSL_Version_3_0_With_2_0_Hello ||
237 ctx->negProtocolVersion == SSL_Version_Undetermined)
238 if (ERR(err = SSLInitMessageHashes(ctx)) != 0)
239 return err;
240 if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeClientHello, ctx)) != 0)
241 return err;
242 switch (ctx->negProtocolVersion)
243 { case SSL_Version_Undetermined:
244 SSLChangeHdskState(ctx, HandshakeServerHelloUnknownVersion);
245 break;
246 case SSL_Version_3_0_With_2_0_Hello:
247 ctx->negProtocolVersion = SSL_Version_3_0;
248 #if LOG_NEGOTIATE
249 dprintf0("===SSL client kickstart: negVersion is 3_0\n");
250 #endif
251 SSLChangeHdskState(ctx, HandshakeServerHello);
252 break;
253 case SSL_Version_2_0:
254 SSLChangeHdskState(ctx, HandshakeSSL2ServerHello);
255 break;
256 case SSL_Version_3_0_Only:
257 case SSL_Version_3_0:
258 default:
259 ASSERTMSG("Bad protocol version for sending SSL 2 Client Hello");
260 break;
261 }
262 break;
263 case ssl2_mt_client_hello:
264 if (ERR(err = SSL2CompareSessionIDs(ctx)) != 0)
265 return err;
266 if (ctx->ssl2SessionMatch == 0)
267 if (ERR(err = SSL2GenerateSessionID(ctx)) != 0)
268 return err;
269 if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeServerHello, ctx)) != 0)
270 return err;
271 if (ctx->ssl2SessionMatch == 0)
272 { SSLChangeHdskState(ctx, HandshakeSSL2ClientMasterKey);
273 break;
274 }
275 if (ERR(err = SSL2InstallSessionKey(ctx)) != 0)
276 return err;
277 /* Fall through for matching session; lame, but true */
278 case ssl2_mt_client_master_key:
279 if (ERR(err = SSL2InitCiphers(ctx)) != 0)
280 return err;
281 if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeServerVerify, ctx)) != 0)
282 return err;
283 if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeServerFinished, ctx)) != 0)
284 return err;
285 SSLChangeHdskState(ctx, HandshakeSSL2ClientFinished);
286 break;
287 case ssl2_mt_server_hello:
288 if (ctx->ssl2SessionMatch == 0)
289 { if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeClientMasterKey, ctx)) != 0)
290 return err;
291 }
292 else
293 { if (ERR(err = SSL2InstallSessionKey(ctx)) != 0)
294 return err;
295 }
296 if (ERR(err = SSL2InitCiphers(ctx)) != 0)
297 return err;
298 if (ERR(err = SSL2PrepareAndQueueMessage(SSL2EncodeClientFinished, ctx)) != 0)
299 return err;
300 SSLChangeHdskState(ctx, HandshakeSSL2ServerVerify);
301 break;
302 case ssl2_mt_client_finished:
303 /* Handshake is complete; turn ciphers on */
304 ctx->writeCipher.ready = 1;
305 ctx->readCipher.ready = 1;
306 #if _APPLE_CDSA_
307 /* original code never got out of ssl2_mt_client_finished state */
308 CASSERT(ctx->protocolSide == SSL_ServerSide);
309 SSLChangeHdskState(ctx, HandshakeServerReady);
310 #endif /* _APPLE_CDSA_ */
311 if (ctx->peerID.data != 0)
312 ERR(SSLAddSessionID(ctx));
313 break;
314 case ssl2_mt_server_verify:
315 SSLChangeHdskState(ctx, HandshakeSSL2ServerFinished);
316 break;
317 case ssl2_mt_request_certificate:
318 if (ERR(err = SSL2SendError(ssl2_pe_no_certificate, ctx)) != 0)
319 return err;
320 break;
321 case ssl2_mt_server_finished:
322 /* Handshake is complete; turn ciphers on */
323 ctx->writeCipher.ready = 1;
324 ctx->readCipher.ready = 1;
325 #if _APPLE_CDSA_
326 /* original code never got out of ssl2_mt_server_finished state */
327 CASSERT(ctx->protocolSide == SSL_ClientSide);
328 SSLChangeHdskState(ctx, HandshakeClientReady);
329 #endif /* _APPLE_CDSA_ */
330 if (ctx->peerID.data != 0)
331 ERR(SSLAddSessionID(ctx));
332 break;
333 case ssl2_mt_error:
334 case ssl2_mt_client_certificate:
335 return ERR(SSLProtocolErr);
336 break;
337 }
338
339 return SSLNoErr;
340 }
341
342 SSLErr
343 SSL2PrepareAndQueueMessage(EncodeSSL2MessageFunc encodeFunc, SSLContext *ctx)
344 { SSLErr err;
345 SSLRecord rec;
346
347 rec.contentType = SSL_version_2_0_record;
348 rec.protocolVersion = SSL_Version_2_0;
349 if (ERR(err = encodeFunc(&rec.contents, ctx)) != 0)
350 return err;
351
352 logSsl2Msg((SSL2MessageType)rec.contents.data[0], 1);
353
354 if (ERR(err = SSLWriteRecord(rec, ctx)) != 0)
355 { ERR(SSLFreeBuffer(&rec.contents, &ctx->sysCtx));
356 return err;
357 }
358
359 if (ctx->negProtocolVersion == SSL_Version_3_0_With_2_0_Hello ||
360 ctx->negProtocolVersion == SSL_Version_Undetermined)
361 if (ERR(err = SSLHashSHA1.update(ctx->shaState, rec.contents)) != 0 ||
362 ERR(err = SSLHashMD5.update(ctx->md5State, rec.contents)) != 0)
363 return err;
364
365 ERR(err = SSLFreeBuffer(&rec.contents, &ctx->sysCtx));
366 return err;
367 }
368
369 SSLErr
370 SSL2CompareSessionIDs(SSLContext *ctx)
371 { SSLErr err;
372 SSLBuffer sessionIdentifier;
373
374 ctx->ssl2SessionMatch = 0;
375
376 if (ctx->resumableSession.data == 0)
377 return SSLNoErr;
378
379 if (ERR(err = SSLRetrieveSessionIDIdentifier(ctx->resumableSession,
380 &sessionIdentifier, ctx)) != 0)
381 return err;
382
383 if (sessionIdentifier.length == ctx->sessionID.length &&
384 memcmp(sessionIdentifier.data, ctx->sessionID.data, sessionIdentifier.length) == 0)
385 ctx->ssl2SessionMatch = 1;
386
387 if (ERR(err = SSLFreeBuffer(&sessionIdentifier, &ctx->sysCtx)) != 0)
388 return err;
389
390 return SSLNoErr;
391 }
392
393 SSLErr
394 SSL2InstallSessionKey(SSLContext *ctx)
395 { SSLErr err;
396
397 CASSERT(ctx->ssl2SessionMatch != 0);
398 CASSERT(ctx->resumableSession.data != 0);
399 if (ERR(err = SSLInstallSessionID(ctx->resumableSession, ctx)) != 0)
400 return err;
401 return SSLNoErr;
402 }
403
404 SSLErr
405 SSL2GenerateSessionID(SSLContext *ctx)
406 { SSLErr err;
407
408 if (ERR(err = SSLFreeBuffer(&ctx->sessionID, &ctx->sysCtx)) != 0)
409 return err;
410 if (ERR(err = SSLAllocBuffer(&ctx->sessionID, SSL_SESSION_ID_LEN, &ctx->sysCtx)) != 0)
411 return err;
412 #ifdef _APPLE_CDSA_
413 if ((err = sslRand(ctx, &ctx->sessionID)) != 0)
414 #else
415 if (ERR(err = ctx->sysCtx.random(ctx->sessionID, ctx->sysCtx.randomRef)) != 0)
416 #endif
417 return err;
418 return SSLNoErr;
419 }
420
421 SSLErr
422 SSL2InitCiphers(SSLContext *ctx)
423 { SSLErr err;
424 int keyMaterialLen;
425 SSLBuffer keyData;
426 uint8 variantChar, *progress, *readKey, *writeKey, *iv;
427 SSLBuffer hashDigest, hashContext, masterKey, challenge, connectionID, variantData;
428
429 keyMaterialLen = 2 * ctx->selectedCipherSpec->cipher->keySize;
430 if (ERR(err = SSLAllocBuffer(&keyData, keyMaterialLen, &ctx->sysCtx)) != 0)
431 return err;
432
433 /* Can't have % in assertion string... */
434 #if SSL_DEBUG
435 {
436 UInt32 keyModDigestSize = keyMaterialLen % SSLHashMD5.digestSize;
437 CASSERT(keyModDigestSize == 0);
438 }
439 #endif
440
441 masterKey.data = ctx->masterSecret;
442 masterKey.length = ctx->selectedCipherSpec->cipher->keySize;
443 challenge.data = ctx->clientRandom + 32 - ctx->ssl2ChallengeLength;
444 challenge.length = ctx->ssl2ChallengeLength;
445 connectionID.data = ctx->serverRandom;
446 connectionID.length = ctx->ssl2ConnectionIDLength;
447 variantData.data = &variantChar;
448 variantData.length = 1;
449 if (ERR(err = SSLAllocBuffer(&hashContext, SSLHashMD5.contextSize, &ctx->sysCtx)) != 0)
450 { ERR(SSLFreeBuffer(&keyData, &ctx->sysCtx));
451 return err;
452 }
453
454 variantChar = 0x30; /* '0' */
455 progress = keyData.data;
456 while (keyMaterialLen)
457 { hashDigest.data = progress;
458 hashDigest.length = SSLHashMD5.digestSize;
459 if (ERR(err = SSLHashMD5.init(hashContext)) != 0 ||
460 ERR(err = SSLHashMD5.update(hashContext, masterKey)) != 0 ||
461 ERR(err = SSLHashMD5.update(hashContext, variantData)) != 0 ||
462 ERR(err = SSLHashMD5.update(hashContext, challenge)) != 0 ||
463 ERR(err = SSLHashMD5.update(hashContext, connectionID)) != 0 ||
464 ERR(err = SSLHashMD5.final(hashContext, hashDigest)) != 0)
465 { SSLFreeBuffer(&keyData, &ctx->sysCtx);
466 SSLFreeBuffer(&hashContext, &ctx->sysCtx);
467 return err;
468 }
469 progress += hashDigest.length;
470 ++variantChar;
471 keyMaterialLen -= hashDigest.length;
472 }
473
474 CASSERT(progress == keyData.data + keyData.length);
475
476 if (ERR(err = SSLFreeBuffer(&hashContext, &ctx->sysCtx)) != 0)
477 { ERR(SSLFreeBuffer(&keyData, &ctx->sysCtx));
478 return err;
479 }
480
481 ctx->readPending.hash = ctx->selectedCipherSpec->macAlgorithm;
482 ctx->writePending.hash = ctx->selectedCipherSpec->macAlgorithm;
483 ctx->readPending.symCipher = ctx->selectedCipherSpec->cipher;
484 ctx->writePending.symCipher = ctx->selectedCipherSpec->cipher;
485 ctx->readPending.sequenceNum = ctx->readCipher.sequenceNum;
486 ctx->writePending.sequenceNum = ctx->writeCipher.sequenceNum;
487
488 if (ctx->protocolSide == SSL_ServerSide)
489 { writeKey = keyData.data;
490 readKey = keyData.data + ctx->selectedCipherSpec->cipher->keySize;
491 }
492 else
493 { readKey = keyData.data;
494 writeKey = keyData.data + ctx->selectedCipherSpec->cipher->keySize;
495 }
496
497 iv = ctx->masterSecret + ctx->selectedCipherSpec->cipher->keySize;
498
499 /* APPLE_CDSA symmetric cipher changes....*/
500 if (ERR(err = ctx->readPending.symCipher->initialize(readKey, iv,
501 &ctx->readPending, ctx)) != 0 ||
502 ERR(err = ctx->writePending.symCipher->initialize(writeKey, iv,
503 &ctx->writePending, ctx)) != 0)
504 { ERR(SSLFreeBuffer(&keyData, &ctx->sysCtx));
505 return err;
506 }
507
508 /*
509 * HEY! macSecret is only 20 bytes. This blows up when key size
510 * is greater than 20, e.g., 3DES.
511 * I'll increase the size of macSecret to 24, 'cause it appears
512 * from the SSL v23 spec that the macSecret really the same size as
513 * CLIENT-WRITE-KEY and SERVER-READ-KEY (see 1.2 of the spec).
514 */
515 memcpy(ctx->readPending.macSecret, readKey, ctx->selectedCipherSpec->cipher->keySize);
516 memcpy(ctx->writePending.macSecret, writeKey, ctx->selectedCipherSpec->cipher->keySize);
517
518 if (ERR(err = SSLFreeBuffer(&keyData, &ctx->sysCtx)) != 0)
519 return err;
520
521 ctx->readCipher = ctx->readPending;
522 ctx->writeCipher = ctx->writePending;
523 memset(&ctx->readPending, 0, sizeof(CipherContext)); /* Zero out old data */
524 memset(&ctx->writePending, 0, sizeof(CipherContext)); /* Zero out old data */
525
526 return SSLNoErr;
527 }