]> git.saurik.com Git - apple/security.git/blob - libsecurity_ssl/lib/ssl3Callouts.c
Security-55179.1.tar.gz
[apple/security.git] / libsecurity_ssl / lib / ssl3Callouts.c
1 /*
2 * Copyright (c) 2002,2005-2007,2010-2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * ssl3Callouts.c - SSLv3-specific routines for SslTlsCallouts.
26 */
27
28 #include "sslMemory.h"
29 #include "tls_ssl.h"
30 #include "sslUtils.h"
31 #include "sslDigests.h"
32 #include "sslDebug.h"
33 #include "sslAlertMessage.h"
34
35 #include <assert.h>
36 #include <strings.h>
37 #include <stddef.h>
38
39 /*
40 * ssl3WriteRecord does not send alerts on failure, out of the assumption/fear
41 * that this might result in a loop (since sending an alert causes ssl3WriteRecord
42 * to be called).
43 *
44 * As far as I can tell, we can use this same routine for SSLv3 and TLSv1, as long
45 * as we're not trying to use the "variable length padding" feature of TLSv1.
46 * OpenSSL doesn't use that feature; for now, neither will we. Thus this routine
47 * is used for the SslTlsCallouts.writeRecord function for both protocols.
48 */
49 OSStatus ssl3WriteRecord(
50 SSLRecord rec,
51 SSLContext *ctx)
52 {
53 OSStatus err;
54 int padding = 0, i;
55 WaitingRecord *out = NULL, *queue;
56 SSLBuffer payload, mac;
57 UInt8 *charPtr;
58 UInt16 payloadSize,blockSize;
59 int head = 5;
60
61 switch(rec.protocolVersion) {
62 case DTLS_Version_1_0:
63 head += 8;
64 case SSL_Version_3_0:
65 case TLS_Version_1_0:
66 case TLS_Version_1_1:
67 case TLS_Version_1_2:
68 break;
69 default:
70 assert(0);
71 return errSSLInternal;
72 }
73 assert(rec.contents.length <= 16384);
74
75 sslLogRecordIo("type = %02x, ver = %04x, len = %ld, seq = %08x_%08x",
76 rec.contentType, rec.protocolVersion, rec.contents.length,
77 ctx->writeCipher.sequenceNum.high, ctx->writeCipher.sequenceNum.low);
78
79 /* Allocate enough room for the transmitted record, which will be:
80 * 5 bytes of header (13 for DTLS) +
81 * IV [block cipher and TLS1.1 or DTLS 1.0 only]
82 * encrypted contents +
83 * macLength +
84 * padding [block ciphers only] +
85 * padding length field (1 byte) [block ciphers only]
86 */
87 payloadSize = (UInt16) (rec.contents.length + ctx->writeCipher.macRef->hash->digestSize);
88 blockSize = ctx->writeCipher.symCipher->blockSize;
89 if (blockSize > 0)
90 {
91 padding = blockSize - (payloadSize % blockSize) - 1;
92 payloadSize += padding + 1;
93 /* TLS 1.1 and DTLS 1.0 have an extra block for IV */
94 if(ctx->negProtocolVersion >= TLS_Version_1_1) {
95 payloadSize += blockSize;
96 }
97 }
98
99 out = (WaitingRecord *)sslMalloc(offsetof(WaitingRecord, data) +
100 head + payloadSize);
101 out->next = NULL;
102 out->sent = 0;
103 out->length = head + payloadSize;
104
105 charPtr = out->data;
106 *(charPtr++) = rec.contentType;
107 charPtr = SSLEncodeInt(charPtr, rec.protocolVersion, 2);
108
109 /* DTLS sequence number */
110 if(rec.protocolVersion == DTLS_Version_1_0)
111 charPtr = SSLEncodeUInt64(charPtr,ctx->writeCipher.sequenceNum);
112
113 charPtr = SSLEncodeInt(charPtr, payloadSize, 2);
114
115 /* Also for DTLS */
116 if((ctx->negProtocolVersion >= TLS_Version_1_1) && (blockSize>0))
117 {
118 SSLBuffer randomIV;
119 randomIV.data = charPtr;
120 randomIV.length = blockSize;
121 if((err = sslRand(ctx, &randomIV)) != 0)
122 return err;
123 charPtr += blockSize;
124 }
125
126 /* Copy the contents into the output buffer */
127 memcpy(charPtr, rec.contents.data, rec.contents.length);
128 payload.data = charPtr;
129 payload.length = rec.contents.length;
130
131 charPtr += rec.contents.length;
132 /* MAC immediately follows data */
133 mac.data = charPtr;
134 mac.length = ctx->writeCipher.macRef->hash->digestSize;
135 charPtr += mac.length;
136
137 /* MAC the data */
138 if (mac.length > 0) /* Optimize away null case */
139 {
140 assert(ctx->sslTslCalls != NULL);
141 if ((err = ctx->sslTslCalls->computeMac(rec.contentType,
142 payload,
143 mac,
144 &ctx->writeCipher,
145 ctx->writeCipher.sequenceNum,
146 ctx)) != 0)
147 goto fail;
148 }
149
150 /* For TLS 1.1 and DTLS, we would need to specify the IV, but instead
151 we are clever like this: since the IV is just one block in front,
152 we encrypt it with the rest of the data. The actual transmitted IV
153 is the result of the encryption, with whatever internal IV is used.
154 This method is explained in the TLS 1.1 RFC */
155 if(ctx->negProtocolVersion >= TLS_Version_1_1)
156 {
157 if(blockSize > 0)
158 payload.data -= blockSize;
159 }
160
161 /* Update payload to reflect encrypted data: IV, contents, mac & padding */
162 payload.length = payloadSize;
163
164 /* Fill in the padding bytes & padding length field with the padding value; the
165 * protocol only requires the last byte,
166 * but filling them all in avoids leaking data
167 */
168 if (ctx->writeCipher.symCipher->blockSize > 0)
169 for (i = 1; i <= padding + 1; ++i)
170 payload.data[payload.length - i] = padding;
171
172 /* Encrypt the data */
173 if ((err = ctx->writeCipher.symCipher->encrypt(payload.data,
174 payload.data, payload.length,
175 &ctx->writeCipher,
176 ctx)) != 0)
177 goto fail;
178
179 /* Enqueue the record to be written from the idle loop */
180 if (ctx->recordWriteQueue == 0)
181 ctx->recordWriteQueue = out;
182 else
183 { queue = ctx->recordWriteQueue;
184 while (queue->next != 0)
185 queue = queue->next;
186 queue->next = out;
187 }
188
189 /* Increment the sequence number */
190 IncrementUInt64(&ctx->writeCipher.sequenceNum);
191
192 return noErr;
193
194 fail:
195 /*
196 * Only for if we fail between when the WaitingRecord is allocated and when
197 * it is queued
198 */
199 sslFree(out);
200 return err;
201 }
202
203 static OSStatus ssl3DecryptRecord(
204 UInt8 type,
205 SSLBuffer *payload,
206 SSLContext *ctx)
207 {
208 OSStatus err;
209 SSLBuffer content;
210
211 if ((ctx->readCipher.symCipher->blockSize > 0) &&
212 ((payload->length % ctx->readCipher.symCipher->blockSize) != 0))
213 { SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx);
214 return errSSLProtocol;
215 }
216
217 /* Decrypt in place */
218 if ((err = ctx->readCipher.symCipher->decrypt(payload->data,
219 payload->data, payload->length,
220 &ctx->readCipher,
221 ctx)) != 0)
222 {
223 /* Complies with TLS 1.1 - But we do it for every protocol version */
224 SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx);
225 return err;
226 }
227
228 /* Locate content within decrypted payload */
229 content.data = payload->data;
230 content.length = payload->length - ctx->readCipher.macRef->hash->digestSize;
231 if (ctx->readCipher.symCipher->blockSize > 0)
232 { /* padding can't be equal to or more than a block */
233 if (payload->data[payload->length - 1] >= ctx->readCipher.symCipher->blockSize)
234 {
235 /* Complies with TLS 1.1 - But we do it for every protocol version */
236 SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx);
237 sslErrorLog("DecryptSSLRecord: bad padding length (%d)\n",
238 (unsigned)payload->data[payload->length - 1]);
239 return errSSLDecryptionFail;
240 }
241 content.length -= 1 + payload->data[payload->length - 1];
242 /* Remove block size padding */
243 }
244
245 /* Verify MAC on payload */
246 if (ctx->readCipher.macRef->hash->digestSize > 0)
247 /* Optimize away MAC for null case */
248 if ((err = SSLVerifyMac(type, &content,
249 payload->data + content.length, ctx)) != 0)
250 { SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx);
251 return errSSLBadRecordMac;
252 }
253
254 *payload = content; /* Modify payload buffer to indicate content length */
255
256 return noErr;
257 }
258
259 /* initialize a per-CipherContext HashHmacContext for use in MACing each record */
260 static OSStatus ssl3InitMac (
261 CipherContext *cipherCtx, // macRef, macSecret valid on entry
262 // macCtx valid on return
263 SSLContext *ctx)
264 {
265 const HashReference *hash;
266 SSLBuffer *hashCtx;
267 OSStatus serr;
268
269 assert(cipherCtx->macRef != NULL);
270 hash = cipherCtx->macRef->hash;
271 assert(hash != NULL);
272
273 hashCtx = &cipherCtx->macCtx.hashCtx;
274 if(hashCtx->data != NULL) {
275 SSLFreeBuffer(hashCtx, ctx);
276 }
277 serr = SSLAllocBuffer(hashCtx, hash->contextSize, ctx);
278 if(serr) {
279 return serr;
280 }
281 return noErr;
282 }
283
284 static OSStatus ssl3FreeMac (
285 CipherContext *cipherCtx)
286 {
287 SSLBuffer *hashCtx;
288
289 assert(cipherCtx != NULL);
290 /* this can be called on a completely zeroed out CipherContext... */
291 if(cipherCtx->macRef == NULL) {
292 return noErr;
293 }
294 hashCtx = &cipherCtx->macCtx.hashCtx;
295 if(hashCtx->data != NULL) {
296 sslFree(hashCtx->data);
297 hashCtx->data = NULL;
298 }
299 hashCtx->length = 0;
300 return noErr;
301 }
302
303 static OSStatus ssl3ComputeMac (
304 UInt8 type,
305 SSLBuffer data,
306 SSLBuffer mac, // caller mallocs data
307 CipherContext *cipherCtx, // assumes macCtx, macRef
308 sslUint64 seqNo,
309 SSLContext *ctx)
310 {
311 OSStatus err;
312 UInt8 innerDigestData[SSL_MAX_DIGEST_LEN];
313 UInt8 scratchData[11], *charPtr;
314 SSLBuffer digest, digestCtx, scratch;
315 SSLBuffer secret;
316
317 const HashReference *hash;
318
319 assert(cipherCtx != NULL);
320 assert(cipherCtx->macRef != NULL);
321 hash = cipherCtx->macRef->hash;
322 assert(hash != NULL);
323 assert(hash->macPadSize <= MAX_MAC_PADDING);
324 assert(hash->digestSize <= SSL_MAX_DIGEST_LEN);
325 digestCtx = cipherCtx->macCtx.hashCtx; // may be NULL, for null cipher
326 secret.data = cipherCtx->macSecret;
327 secret.length = hash->digestSize;
328
329 /* init'd early in SSLNewContext() */
330 assert(SSLMACPad1[0] == 0x36 && SSLMACPad2[0] == 0x5C);
331
332 /*
333 * MAC = hash( MAC_write_secret + pad_2 +
334 * hash( MAC_write_secret + pad_1 + seq_num + type +
335 * length + content )
336 * )
337 */
338 if ((err = hash->init(&digestCtx, ctx)) != 0)
339 goto exit;
340 if ((err = hash->update(&digestCtx, &secret)) != 0) /* MAC secret */
341 goto exit;
342 scratch.data = (UInt8 *)SSLMACPad1;
343 scratch.length = hash->macPadSize;
344 if ((err = hash->update(&digestCtx, &scratch)) != 0) /* pad1 */
345 goto exit;
346 charPtr = scratchData;
347 charPtr = SSLEncodeUInt64(charPtr, seqNo);
348 *charPtr++ = type;
349 charPtr = SSLEncodeSize(charPtr, data.length, 2);
350 scratch.data = scratchData;
351 scratch.length = 11;
352 assert(charPtr = scratchData+11);
353 if ((err = hash->update(&digestCtx, &scratch)) != 0)
354 /* sequenceNo, type & length */
355 goto exit;
356 if ((err = hash->update(&digestCtx, &data)) != 0) /* content */
357 goto exit;
358 digest.data = innerDigestData;
359 digest.length = hash->digestSize;
360 if ((err = hash->final(&digestCtx, &digest)) != 0) /* figure inner digest */
361 goto exit;
362
363 if ((err = hash->init(&digestCtx, ctx)) != 0)
364 goto exit;
365 if ((err = hash->update(&digestCtx, &secret)) != 0) /* MAC secret */
366 goto exit;
367 scratch.data = (UInt8 *)SSLMACPad2;
368 scratch.length = hash->macPadSize;
369 if ((err = hash->update(&digestCtx, &scratch)) != 0) /* pad2 */
370 goto exit;
371 if ((err = hash->update(&digestCtx, &digest)) != 0) /* inner digest */
372 goto exit;
373 if ((err = hash->final(&digestCtx, &mac)) != 0) /* figure the mac */
374 goto exit;
375
376 err = noErr; /* redundant, I know */
377
378 exit:
379 return err;
380 }
381
382 #define LOG_GEN_KEY 0
383
384 /*
385 * On input, the following are valid:
386 * MasterSecret[48]
387 * ClientHello.random[32]
388 * ServerHello.random[32]
389 *
390 * key_block =
391 * MD5(master_secret + SHA(`A' + master_secret +
392 * ServerHello.random +
393 * ClientHello.random)) +
394 * MD5(master_secret + SHA(`BB' + master_secret +
395 * ServerHello.random +
396 * ClientHello.random)) +
397 * MD5(master_secret + SHA(`CCC' + master_secret +
398 * ServerHello.random +
399 * ClientHello.random)) + [...];
400 */
401 static OSStatus ssl3GenerateKeyMaterial (
402 SSLBuffer key, // caller mallocs and specifies length of
403 // required key material here
404 SSLContext *ctx)
405 {
406 OSStatus err;
407 UInt8 leaderData[10]; /* Max of 10 hashes
408 * (* 16 bytes/hash = 160 bytes of key) */
409 UInt8 shaHashData[20], md5HashData[16];
410 SSLBuffer shaContext, md5Context;
411 UInt8 *keyProgress;
412 size_t i,j,remaining, satisfied;
413 SSLBuffer leader, masterSecret, serverRandom, clientRandom, shaHash, md5Hash;
414
415 #if LOG_GEN_KEY
416 printf("GenerateKey: master ");
417 for(i=0; i<SSL_MASTER_SECRET_SIZE; i++) {
418 printf("%02X ", ctx->masterSecret[i]);
419 }
420 printf("\n");
421 #endif
422
423 assert(key.length <= 16 * sizeof(leaderData));
424
425 leader.data = leaderData;
426 masterSecret.data = ctx->masterSecret;
427 masterSecret.length = SSL_MASTER_SECRET_SIZE;
428 serverRandom.data = ctx->serverRandom;
429 serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
430 clientRandom.data = ctx->clientRandom;
431 clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
432 shaHash.data = shaHashData;
433 shaHash.length = 20;
434 md5Hash.data = md5HashData;
435 md5Hash.length = 16;
436
437 md5Context.data = 0;
438 shaContext.data = 0;
439 if ((err = ReadyHash(&SSLHashMD5, &md5Context, ctx)) != 0)
440 goto fail;
441 if ((err = ReadyHash(&SSLHashSHA1, &shaContext, ctx)) != 0)
442 goto fail;
443
444 keyProgress = key.data;
445 remaining = key.length;
446
447 for (i = 0; remaining > 0; ++i)
448 { for (j = 0; j <= i; j++)
449 leaderData[j] = 0x41 + i; /* 'A', 'BB', 'CCC', etc. */
450 leader.length = i+1;
451
452 if ((err = SSLHashSHA1.update(&shaContext, &leader)) != 0)
453 goto fail;
454 if ((err = SSLHashSHA1.update(&shaContext, &masterSecret)) != 0)
455 goto fail;
456 if ((err = SSLHashSHA1.update(&shaContext, &serverRandom)) != 0)
457 goto fail;
458 if ((err = SSLHashSHA1.update(&shaContext, &clientRandom)) != 0)
459 goto fail;
460 if ((err = SSLHashSHA1.final(&shaContext, &shaHash)) != 0)
461 goto fail;
462 if ((err = SSLHashMD5.update(&md5Context, &masterSecret)) != 0)
463 goto fail;
464 if ((err = SSLHashMD5.update(&md5Context, &shaHash)) != 0)
465 goto fail;
466 if ((err = SSLHashMD5.final(&md5Context, &md5Hash)) != 0)
467 goto fail;
468
469 satisfied = 16;
470 if (remaining < 16)
471 satisfied = remaining;
472 memcpy(keyProgress, md5HashData, satisfied);
473 remaining -= satisfied;
474 keyProgress += satisfied;
475
476 if(remaining > 0) {
477 /* at top of loop, this was done in ReadyHash() */
478 if ((err = SSLHashMD5.init(&md5Context, ctx)) != 0)
479 goto fail;
480 if ((err = SSLHashSHA1.init(&shaContext, ctx)) != 0)
481 goto fail;
482 }
483 }
484
485 assert(remaining == 0 && keyProgress == (key.data + key.length));
486 err = noErr;
487 fail:
488 SSLFreeBuffer(&md5Context, ctx);
489 SSLFreeBuffer(&shaContext, ctx);
490
491 #if LOG_GEN_KEY
492 printf("GenerateKey: DONE\n");
493 #endif
494 return err;
495 }
496
497 static OSStatus ssl3GenerateExportKeyAndIv (
498 SSLContext *ctx, // clientRandom, serverRandom valid
499 const SSLBuffer clientWriteKey,
500 const SSLBuffer serverWriteKey,
501 SSLBuffer finalClientWriteKey, // RETURNED, mallocd by caller
502 SSLBuffer finalServerWriteKey, // RETURNED, mallocd by caller
503 SSLBuffer finalClientIV, // RETURNED, mallocd by caller
504 SSLBuffer finalServerIV) // RETURNED, mallocd by caller
505 {
506 OSStatus err;
507 SSLBuffer hashCtx, serverRandom, clientRandom;
508
509 /* random blobs are 32 bytes */
510 serverRandom.data = ctx->serverRandom;
511 serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
512 clientRandom.data = ctx->clientRandom;
513 clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
514
515 if ((err = SSLAllocBuffer(&hashCtx, SSLHashMD5.contextSize, ctx)) != 0)
516 return err;
517 /* client write key */
518 if ((err = SSLHashMD5.init(&hashCtx, ctx)) != 0)
519 goto fail;
520 if ((err = SSLHashMD5.update(&hashCtx, &clientWriteKey)) != 0)
521 goto fail;
522 if ((err = SSLHashMD5.update(&hashCtx, &clientRandom)) != 0)
523 goto fail;
524 if ((err = SSLHashMD5.update(&hashCtx, &serverRandom)) != 0)
525 goto fail;
526 finalClientWriteKey.length = 16;
527 if ((err = SSLHashMD5.final(&hashCtx, &finalClientWriteKey)) != 0)
528 goto fail;
529
530 /* optional client IV */
531 if (ctx->selectedCipherSpec.cipher->ivSize > 0)
532 { if ((err = SSLHashMD5.init(&hashCtx, ctx)) != 0)
533 goto fail;
534 if ((err = SSLHashMD5.update(&hashCtx, &clientRandom)) != 0)
535 goto fail;
536 if ((err = SSLHashMD5.update(&hashCtx, &serverRandom)) != 0)
537 goto fail;
538 finalClientIV.length = 16;
539 if ((err = SSLHashMD5.final(&hashCtx, &finalClientIV)) != 0)
540 goto fail;
541 }
542
543 /* server write key */
544 if ((err = SSLHashMD5.init(&hashCtx, ctx)) != 0)
545 goto fail;
546 if ((err = SSLHashMD5.update(&hashCtx, &serverWriteKey)) != 0)
547 goto fail;
548 if ((err = SSLHashMD5.update(&hashCtx, &serverRandom)) != 0)
549 goto fail;
550 if ((err = SSLHashMD5.update(&hashCtx, &clientRandom)) != 0)
551 goto fail;
552 finalServerWriteKey.length = 16;
553 if ((err = SSLHashMD5.final(&hashCtx, &finalServerWriteKey)) != 0)
554 goto fail;
555
556 /* optional server IV */
557 if (ctx->selectedCipherSpec.cipher->ivSize > 0)
558 { if ((err = SSLHashMD5.init(&hashCtx, ctx)) != 0)
559 goto fail;
560 if ((err = SSLHashMD5.update(&hashCtx, &serverRandom)) != 0)
561 goto fail;
562 if ((err = SSLHashMD5.update(&hashCtx, &clientRandom)) != 0)
563 goto fail;
564 finalServerIV.length = 16;
565 if ((err = SSLHashMD5.final(&hashCtx, &finalServerIV)) != 0)
566 goto fail;
567 }
568
569 err = noErr;
570 fail:
571 SSLFreeBuffer(&hashCtx, ctx);
572 return err;
573 }
574
575 /*
576 * On entry: clientRandom, serverRandom, preMasterSecret valid
577 * On return: masterSecret valid
578 */
579 static OSStatus ssl3GenerateMasterSecret (
580 SSLContext *ctx)
581 {
582 OSStatus err;
583 SSLBuffer shaState, md5State, clientRandom,
584 serverRandom, shaHash, md5Hash, leader;
585 UInt8 *masterProgress, shaHashData[20], leaderData[3];
586 int i;
587
588 md5State.data = shaState.data = 0;
589 if ((err = SSLAllocBuffer(&md5State, SSLHashMD5.contextSize, ctx)) != 0)
590 goto fail;
591 if ((err = SSLAllocBuffer(&shaState, SSLHashSHA1.contextSize, ctx)) != 0)
592 goto fail;
593
594 clientRandom.data = ctx->clientRandom;
595 clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
596 serverRandom.data = ctx->serverRandom;
597 serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
598 shaHash.data = shaHashData;
599 shaHash.length = 20;
600
601 masterProgress = ctx->masterSecret;
602
603 for (i = 1; i <= 3; i++)
604 { if ((err = SSLHashMD5.init(&md5State, ctx)) != 0)
605 goto fail;
606 if ((err = SSLHashSHA1.init(&shaState, ctx)) != 0)
607 goto fail;
608
609 leaderData[0] = leaderData[1] = leaderData[2] = 0x40 + i; /* 'A', 'B', etc. */
610 leader.data = leaderData;
611 leader.length = i;
612
613 if ((err = SSLHashSHA1.update(&shaState, &leader)) != 0)
614 goto fail;
615 if ((err = SSLHashSHA1.update(&shaState, &ctx->preMasterSecret)) != 0)
616 goto fail;
617 if ((err = SSLHashSHA1.update(&shaState, &clientRandom)) != 0)
618 goto fail;
619 if ((err = SSLHashSHA1.update(&shaState, &serverRandom)) != 0)
620 goto fail;
621 if ((err = SSLHashSHA1.final(&shaState, &shaHash)) != 0)
622 goto fail;
623 if ((err = SSLHashMD5.update(&md5State, &ctx->preMasterSecret)) != 0)
624 goto fail;
625 if ((err = SSLHashMD5.update(&md5State, &shaHash)) != 0)
626 goto fail;
627 md5Hash.data = masterProgress;
628 md5Hash.length = 16;
629 if ((err = SSLHashMD5.final(&md5State, &md5Hash)) != 0)
630 goto fail;
631 masterProgress += 16;
632 }
633
634 err = noErr;
635 fail:
636 SSLFreeBuffer(&shaState, ctx);
637 SSLFreeBuffer(&md5State, ctx);
638 return err;
639 }
640
641 /* common routine to compute a Mac for finished message and cert verify message */
642 static OSStatus
643 ssl3CalculateFinishedMessage(
644 SSLContext *ctx,
645 SSLBuffer finished, // mallocd by caller
646 SSLBuffer shaMsgState, // running total
647 SSLBuffer md5MsgState, // ditto
648 UInt32 senderID) // optional, nonzero for finished message
649 {
650 OSStatus err;
651 SSLBuffer hash, input;
652 UInt8 sender[4], md5Inner[16], shaInner[20];
653
654 // assert(finished.length == 36);
655
656 if (senderID != 0) {
657 SSLEncodeInt(sender, senderID, 4);
658 input.data = sender;
659 input.length = 4;
660 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
661 goto fail;
662 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
663 goto fail;
664 }
665 input.data = ctx->masterSecret;
666 input.length = SSL_MASTER_SECRET_SIZE;
667 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
668 goto fail;
669 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
670 goto fail;
671 input.data = (UInt8 *)SSLMACPad1;
672 input.length = SSLHashMD5.macPadSize;
673 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
674 goto fail;
675 input.length = SSLHashSHA1.macPadSize;
676 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
677 goto fail;
678 hash.data = md5Inner;
679 hash.length = 16;
680 if ((err = SSLHashMD5.final(&md5MsgState, &hash)) != 0)
681 goto fail;
682 hash.data = shaInner;
683 hash.length = 20;
684 if ((err = SSLHashSHA1.final(&shaMsgState, &hash)) != 0)
685 goto fail;
686 if ((err = SSLHashMD5.init(&md5MsgState, ctx)) != 0)
687 goto fail;
688 if ((err = SSLHashSHA1.init(&shaMsgState, ctx)) != 0)
689 goto fail;
690 input.data = ctx->masterSecret;
691 input.length = SSL_MASTER_SECRET_SIZE;
692 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
693 goto fail;
694 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
695 goto fail;
696 input.data = (UInt8 *)SSLMACPad2;
697 input.length = SSLHashMD5.macPadSize;
698 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
699 goto fail;
700 input.length = SSLHashSHA1.macPadSize;
701 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
702 goto fail;
703 input.data = md5Inner;
704 input.length = 16;
705 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
706 goto fail;
707 hash.data = finished.data;
708 hash.length = 16;
709 if ((err = SSLHashMD5.final(&md5MsgState, &hash)) != 0)
710 goto fail;
711 input.data = shaInner;
712 input.length = 20;
713 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
714 goto fail;
715 hash.data = finished.data + 16;
716 hash.length = 20;
717 if ((err = SSLHashSHA1.final(&shaMsgState, &hash)) != 0)
718 goto fail;
719
720 fail:
721 return err;
722 }
723
724
725 static OSStatus ssl3ComputeFinishedMac (
726 SSLContext *ctx,
727 SSLBuffer finished, // output - mallocd by caller
728 Boolean isServer) // refers to message, not us
729 {
730 OSStatus serr;
731 SSLBuffer shaMsgState, md5MsgState;
732
733 shaMsgState.data = 0;
734 md5MsgState.data = 0;
735 if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState, ctx)) != 0)
736 goto fail;
737 if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState, ctx)) != 0)
738 goto fail;
739
740 serr = ssl3CalculateFinishedMessage(ctx, finished, shaMsgState, md5MsgState,
741 isServer ? SSL_Finished_Sender_Server : SSL_Finished_Sender_Client);
742
743 fail:
744 SSLFreeBuffer(&shaMsgState, ctx);
745 SSLFreeBuffer(&md5MsgState, ctx);
746
747 return serr;
748 }
749
750 /* TODO: Factor this and ssl3ComputeFinishedMac to share more common code. */
751 static OSStatus ssl3ComputeCertVfyMac (
752 SSLContext *ctx,
753 SSLBuffer *finished, // output - mallocd by caller
754 SSL_HashAlgorithm hash) //unused in this one
755 {
756 OSStatus serr;
757 SSLBuffer shaMsgState, md5MsgState;
758
759 shaMsgState.data = 0;
760 md5MsgState.data = 0;
761 if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState, ctx)) != 0)
762 goto fail;
763 if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState, ctx)) != 0)
764 goto fail;
765
766 assert(finished->length >= SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN);
767 finished->length = SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN;
768
769 serr = ssl3CalculateFinishedMessage(ctx, *finished, shaMsgState, md5MsgState, 0);
770
771 fail:
772 SSLFreeBuffer(&shaMsgState, ctx);
773 SSLFreeBuffer(&md5MsgState, ctx);
774
775 return serr;
776 }
777
778 const SslTlsCallouts Ssl3Callouts = {
779 ssl3DecryptRecord,
780 ssl3WriteRecord,
781 ssl3InitMac,
782 ssl3FreeMac,
783 ssl3ComputeMac,
784 ssl3GenerateKeyMaterial,
785 ssl3GenerateExportKeyAndIv,
786 ssl3GenerateMasterSecret,
787 ssl3ComputeFinishedMac,
788 ssl3ComputeCertVfyMac
789 };