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