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