]> git.saurik.com Git - apple/security.git/blob - SecureTransport/tls1Callouts.cpp
Security-179.tar.gz
[apple/security.git] / SecureTransport / tls1Callouts.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: tls1Callouts.c
21
22 Contains: TLSv1-specific routines for SslTlsCallouts.
23
24 Written by: Doug Mitchell
25 */
26
27 #include "tls_ssl.h"
28 #include "sslMemory.h"
29 #include "sslUtils.h"
30 #include "sslDigests.h"
31 #include "sslAlertMessage.h"
32 #include "sslDebug.h"
33 #include <assert.h>
34 #include <strings.h>
35
36 #define TLS_ENC_DEBUG 0
37 #if TLS_ENC_DEBUG
38 #define tlsDebug(format, args...) printf(format , ## args)
39 static void tlsDump(const char *name, void *b, unsigned len)
40 {
41 unsigned char *cp = (unsigned char *)b;
42 unsigned i, dex;
43
44 printf("%s\n", name);
45 for(dex=0; dex<len; dex++) {
46 i = cp[dex];
47 printf("%02X ", i);
48 if((dex % 16) == 15) {
49 printf("\n");
50 }
51 }
52 printf("\n");
53 }
54
55 #else
56 #define tlsDebug(s, ...)
57 #define tlsDump(name, b, len)
58 #endif /* TLS_ENC_DEBUG */
59
60 #pragma *** PRF label strings ***
61 /*
62 * Note we could optimize away a bunch of mallocs and frees if we, like openSSL,
63 * just mallocd buffers for inputs to SSLInternal_PRF() on the stack,
64 * with "known" max values for all of the inputs.
65 *
66 * At least we hard-code string lengths here instead of calling strlen at runtime...
67 */
68 #define PLS_MASTER_SECRET "master secret"
69 #define PLS_MASTER_SECRET_LEN 13
70 #define PLS_KEY_EXPAND "key expansion"
71 #define PLS_KEY_EXPAND_LEN 13
72 #define PLS_CLIENT_FINISH "client finished"
73 #define PLS_CLIENT_FINISH_LEN 15
74 #define PLS_SERVER_FINISH "server finished"
75 #define PLS_SERVER_FINISH_LEN 15
76 #define PLS_EXPORT_CLIENT_WRITE "client write key"
77 #define PLS_EXPORT_CLIENT_WRITE_LEN 16
78 #define PLS_EXPORT_SERVER_WRITE "server write key"
79 #define PLS_EXPORT_SERVER_WRITE_LEN 16
80 #define PLS_EXPORT_IV_BLOCK "IV block"
81 #define PLS_EXPORT_IV_BLOCK_LEN 8
82
83 #pragma mark *** private functions ***
84
85 /*
86 * P_Hash function defined in RFC2246, section 5.
87 */
88 static OSStatus tlsPHash(
89 SSLContext *ctx,
90 const HMACReference *hmac, // &TlsHmacSHA1, TlsHmacMD5
91 const unsigned char *secret,
92 unsigned secretLen,
93 unsigned char *seed,
94 unsigned seedLen,
95 unsigned char *out, // mallocd by caller, size >= outLen
96 unsigned outLen) // desired output size
97 {
98 unsigned char aSubI[TLS_HMAC_MAX_SIZE]; /* A(i) */
99 unsigned char digest[TLS_HMAC_MAX_SIZE];
100 HMACContextRef hmacCtx;
101 OSStatus serr;
102 unsigned digestLen = hmac->macSize;
103
104 serr = hmac->alloc(hmac, ctx, secret, secretLen, &hmacCtx);
105 if(serr) {
106 return serr;
107 }
108
109 /* A(0) = seed */
110 /* A(1) := HMAC_hash(secret, seed) */
111 serr = hmac->hmac(hmacCtx, seed, seedLen, aSubI, &digestLen);
112 if(serr) {
113 goto fail;
114 }
115 assert(digestLen = hmac->macSize);
116
117 /* starting at loopNum 1... */
118 for (;;) {
119 /*
120 * This loop's chunk = HMAC_hash(secret, A(loopNum) + seed))
121 */
122 serr = hmac->init(hmacCtx);
123 if(serr) {
124 break;
125 }
126 serr = hmac->update(hmacCtx, aSubI, digestLen);
127 if(serr) {
128 break;
129 }
130 serr = hmac->update(hmacCtx, seed, seedLen);
131 if(serr) {
132 break;
133 }
134 serr = hmac->final(hmacCtx, digest, &digestLen);
135 if(serr) {
136 break;
137 }
138 assert(digestLen = hmac->macSize);
139
140 if(outLen <= digestLen) {
141 /* last time, possible partial digest */
142 memmove(out, digest, outLen);
143 break;
144 }
145
146 memmove(out, digest, digestLen);
147 out += digestLen;
148 outLen -= digestLen;
149
150 /*
151 * A(i) = HMAC_hash(secret, A(i-1))
152 * Note there is a possible optimization involving obtaining this
153 * hmac by cloning the state of hmacCtx above after updating with
154 * aSubI, and getting the final version of that here. However CDSA
155 * does not support cloning of a MAC context (only for digest contexts).
156 */
157 serr = hmac->hmac(hmacCtx, aSubI, digestLen,
158 aSubI, &digestLen);
159 if(serr) {
160 break;
161 }
162 assert(digestLen = hmac->macSize);
163 }
164 fail:
165 hmac->free(hmacCtx);
166 memset(aSubI, 0, TLS_HMAC_MAX_SIZE);
167 memset(digest, 0, TLS_HMAC_MAX_SIZE);
168 return serr;
169 }
170
171 /*
172 * The TLS pseudorandom function, defined in RFC2246, section 5.
173 * This takes as its input a secret block, a label, and a seed, and produces
174 * a caller-specified length of pseudorandom data.
175 *
176 * Optimization TBD: make label optional, avoid malloc and two copies if it's
177 * not there, so callers can take advantage of fixed-size seeds.
178 */
179 OSStatus SSLInternal_PRF(
180 SSLContext *ctx,
181 const void *vsecret,
182 size_t secretLen,
183 const void *label, // optional, NULL implies that seed contains
184 // the label
185 size_t labelLen,
186 const void *seed,
187 size_t seedLen,
188 void *vout, // mallocd by caller, length >= outLen
189 size_t outLen)
190 {
191 OSStatus serr = errSSLInternal;
192 const unsigned char *S1, *S2; // the two seeds
193 unsigned sLen; // effective length of each seed
194 unsigned char *labelSeed = NULL; // label + seed, passed to tlsPHash
195 unsigned labelSeedLen;
196 unsigned char *tmpOut = NULL; // output of P_SHA1
197 unsigned i;
198 const unsigned char *secret = (const unsigned char *)vsecret;
199
200 /* two seeds for tlsPHash */
201 sLen = secretLen / 2; // for partitioning
202 S1 = secret;
203 S2 = &secret[sLen];
204 sLen += (secretLen & 1); // secret length odd, increment effective size
205
206 if(label != NULL) {
207 /* concatenate label and seed */
208 labelSeedLen = labelLen + seedLen;
209 labelSeed = (unsigned char *)sslMalloc(labelSeedLen);
210 if(labelSeed == NULL) {
211 return memFullErr;
212 }
213 memmove(labelSeed, label, labelLen);
214 memmove(labelSeed + labelLen, seed, seedLen);
215 }
216 else {
217 /* fast track - just use seed as is */
218 labelSeed = (unsigned char *)seed;
219 labelSeedLen = seedLen;
220 }
221
222 /* temporary output for SHA1, to be XORd with MD5 */
223 unsigned char *out = (unsigned char *)vout;
224 tmpOut = (unsigned char *)sslMalloc(outLen);
225 if(tmpOut == NULL) {
226 serr = memFullErr;
227 goto fail;
228 }
229 serr = tlsPHash(ctx, &TlsHmacMD5, S1, sLen, labelSeed, labelSeedLen,
230 out, outLen);
231 if(serr) {
232 goto fail;
233 }
234 serr = tlsPHash(ctx, &TlsHmacSHA1, S2, sLen, labelSeed, labelSeedLen,
235 tmpOut, outLen);
236 if(serr) {
237 goto fail;
238 }
239
240 /* XOR together to get final result */
241 for(i=0; i<outLen; i++) {
242 out[i] ^= tmpOut[i];
243 }
244 serr = noErr;
245
246 fail:
247 if((labelSeed != NULL) && (label != NULL)) {
248 sslFree(labelSeed);
249 }
250 if(tmpOut != NULL) {
251 sslFree(tmpOut);
252 }
253 return serr;
254 }
255
256 /* not needed; encrypt/encode is the same for both protocols as long as
257 * we don't use the "variable length padding" feature. */
258 #if 0
259 static OSStatus tls1WriteRecord(
260 SSLRecord rec,
261 SSLContext *ctx)
262 {
263 assert(0);
264 return unimpErr;
265 }
266 #endif
267
268 static OSStatus tls1DecryptRecord(
269 UInt8 type,
270 SSLBuffer *payload,
271 SSLContext *ctx)
272 {
273 OSStatus err;
274 SSLBuffer content;
275
276 if ((ctx->readCipher.symCipher->blockSize > 0) &&
277 ((payload->length % ctx->readCipher.symCipher->blockSize) != 0)) {
278 SSLFatalSessionAlert(SSL_AlertRecordOverflow, ctx);
279 return errSSLRecordOverflow;
280 }
281
282 /* Decrypt in place */
283 if ((err = ctx->readCipher.symCipher->decrypt(*payload,
284 *payload,
285 &ctx->readCipher,
286 ctx)) != 0)
287 { SSLFatalSessionAlert(SSL_AlertDecryptError, ctx);
288 return errSSLDecryptionFail;
289 }
290
291 /* Locate content within decrypted payload */
292 content.data = payload->data;
293 content.length = payload->length - ctx->readCipher.macRef->hash->digestSize;
294 if (ctx->readCipher.symCipher->blockSize > 0) {
295 /* for TLSv1, padding can be anywhere from 0 to 255 bytes */
296 UInt8 padSize = payload->data[payload->length - 1];
297 UInt8 *padChars;
298
299 /* verify that all padding bytes are equal - WARNING - OpenSSL code
300 * has a special case here dealing with some kind of bug related to
301 * even size packets...beware... */
302 if(padSize > payload->length) {
303 SSLFatalSessionAlert(SSL_AlertDecodeError, ctx);
304 sslErrorLog("tls1DecryptRecord: bad padding length (%d)\n",
305 (unsigned)payload->data[payload->length - 1]);
306 return errSSLDecryptionFail;
307 }
308 padChars = payload->data + payload->length - padSize;
309 while(padChars < (payload->data + payload->length)) {
310 if(*padChars++ != padSize) {
311 SSLFatalSessionAlert(SSL_AlertDecodeError, ctx);
312 sslErrorLog("tls1DecryptRecord: bad padding value\n");
313 return errSSLDecryptionFail;
314 }
315 }
316 /* Remove block size padding and its one-byte length */
317 content.length -= (1 + padSize);
318 }
319
320 /* Verify MAC on payload */
321 if (ctx->readCipher.macRef->hash->digestSize > 0)
322 /* Optimize away MAC for null case */
323 if ((err = SSLVerifyMac(type, content,
324 payload->data + content.length, ctx)) != 0)
325 { SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx);
326 return errSSLBadRecordMac;
327 }
328
329 *payload = content; /* Modify payload buffer to indicate content length */
330
331 return noErr;
332 }
333
334 /* initialize a per-CipherContext HashHmacContext for use in MACing each record */
335 static OSStatus tls1InitMac (
336 CipherContext *cipherCtx, // macRef, macSecret valid on entry
337 // macCtx valid on return
338 SSLContext *ctx)
339 {
340 const HMACReference *hmac;
341 OSStatus serr;
342
343 assert(cipherCtx->macRef != NULL);
344 hmac = cipherCtx->macRef->hmac;
345 assert(hmac != NULL);
346
347 if(cipherCtx->macCtx.hmacCtx != NULL) {
348 hmac->free(cipherCtx->macCtx.hmacCtx);
349 cipherCtx->macCtx.hmacCtx = NULL;
350 }
351 serr = hmac->alloc(hmac, ctx, cipherCtx->macSecret,
352 cipherCtx->macRef->hmac->macSize, &cipherCtx->macCtx.hmacCtx);
353
354 /* mac secret now stored in macCtx.hmacCtx, delete it from cipherCtx */
355 memset(cipherCtx->macSecret, 0, sizeof(cipherCtx->macSecret));
356 return serr;
357 }
358
359 static OSStatus tls1FreeMac (
360 CipherContext *cipherCtx)
361 {
362 /* this can be called on a completely zeroed out CipherContext... */
363 if(cipherCtx->macRef == NULL) {
364 return noErr;
365 }
366 assert(cipherCtx->macRef->hmac != NULL);
367
368 if(cipherCtx->macCtx.hmacCtx != NULL) {
369 cipherCtx->macRef->hmac->free(cipherCtx->macCtx.hmacCtx);
370 cipherCtx->macCtx.hmacCtx = NULL;
371 }
372 return noErr;
373 }
374
375 /*
376 * mac = HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type +
377 * TLSCompressed.version + TLSCompressed.length +
378 * TLSCompressed.fragment));
379 */
380
381 /* sequence, type, version, length */
382 #define HDR_LENGTH (8 + 1 + 2 + 2)
383 OSStatus tls1ComputeMac (
384 UInt8 type,
385 SSLBuffer data,
386 SSLBuffer mac, // caller mallocs data
387 CipherContext *cipherCtx, // assumes macCtx, macRef
388 sslUint64 seqNo,
389 SSLContext *ctx)
390 {
391 unsigned char hdr[HDR_LENGTH];
392 unsigned char *p;
393 HMACContextRef hmacCtx;
394 OSStatus serr;
395 const HMACReference *hmac;
396 unsigned macLength;
397
398 assert(cipherCtx != NULL);
399 assert(cipherCtx->macRef != NULL);
400 hmac = cipherCtx->macRef->hmac;
401 assert(hmac != NULL);
402 hmacCtx = cipherCtx->macCtx.hmacCtx; // may be NULL, for null cipher
403
404 serr = hmac->init(hmacCtx);
405 if(serr) {
406 goto fail;
407 }
408 p = SSLEncodeUInt64(hdr, seqNo);
409 *p++ = type;
410 *p++ = TLS_Version_1_0 >> 8;
411 *p++ = TLS_Version_1_0 & 0xff;
412 *p++ = data.length >> 8;
413 *p = data.length & 0xff;
414 serr = hmac->update(hmacCtx, hdr, HDR_LENGTH);
415 if(serr) {
416 goto fail;
417 }
418 serr = hmac->update(hmacCtx, data.data, data.length);
419 if(serr) {
420 goto fail;
421 }
422 macLength = mac.length;
423 serr = hmac->final(hmacCtx, mac.data, &macLength);
424 if(serr) {
425 goto fail;
426 }
427 mac.length = macLength;
428 fail:
429 return serr;
430 }
431
432 /*
433 * On input, the following are valid:
434 * MasterSecret[48]
435 * ClientHello.random[32]
436 * ServerHello.random[32]
437 *
438 * key_block = PRF(SecurityParameters.master_secret,
439 * "key expansion",
440 * SecurityParameters.server_random +
441 * SecurityParameters.client_random);
442 */
443
444 #define GKM_SEED_LEN (PLS_KEY_EXPAND_LEN + (2 * SSL_CLIENT_SRVR_RAND_SIZE))
445
446 OSStatus tls1GenerateKeyMaterial (
447 SSLBuffer key, // caller mallocs and specifies length of
448 // required key material here
449 SSLContext *ctx)
450 {
451 unsigned char seedBuf[GKM_SEED_LEN];
452 OSStatus serr;
453
454 /* use optimized label-less PRF */
455 memmove(seedBuf, PLS_KEY_EXPAND, PLS_KEY_EXPAND_LEN);
456 memmove(seedBuf + PLS_KEY_EXPAND_LEN, ctx->serverRandom,
457 SSL_CLIENT_SRVR_RAND_SIZE);
458 memmove(seedBuf + PLS_KEY_EXPAND_LEN + SSL_CLIENT_SRVR_RAND_SIZE,
459 ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE);
460 serr = SSLInternal_PRF(ctx,
461 ctx->masterSecret,
462 SSL_MASTER_SECRET_SIZE,
463 NULL, // no label
464 0,
465 seedBuf,
466 GKM_SEED_LEN,
467 key.data, // destination
468 key.length);
469 tlsDump("key expansion", key.data, key.length);
470 return serr;
471 }
472
473 /*
474 * final_client_write_key =
475 * PRF(SecurityParameters.client_write_key,
476 * "client write key",
477 * SecurityParameters.client_random +
478 * SecurityParameters.server_random);
479 * final_server_write_key =
480 * PRF(SecurityParameters.server_write_key,
481 * "server write key",
482 * SecurityParameters.client_random +
483 * SecurityParameters.server_random);
484 *
485 * iv_block = PRF("", "IV block", SecurityParameters.client_random +
486 * SecurityParameters.server_random);
487 *
488 * iv_block is broken up into:
489 *
490 * client_write_IV[SecurityParameters.IV_size]
491 * server_write_IV[SecurityParameters.IV_size]
492 */
493 OSStatus tls1GenerateExportKeyAndIv (
494 SSLContext *ctx, // clientRandom, serverRandom valid
495 const SSLBuffer clientWriteKey,
496 const SSLBuffer serverWriteKey,
497 SSLBuffer finalClientWriteKey, // RETURNED, mallocd by caller
498 SSLBuffer finalServerWriteKey, // RETURNED, mallocd by caller
499 SSLBuffer finalClientIV, // RETURNED, mallocd by caller
500 SSLBuffer finalServerIV) // RETURNED, mallocd by caller
501 {
502 unsigned char randBuf[2 * SSL_CLIENT_SRVR_RAND_SIZE];
503 OSStatus serr;
504 unsigned char *ivBlock;
505 char *nullKey = "";
506
507 /* all three PRF calls use the same seed */
508 memmove(randBuf, ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE);
509 memmove(randBuf + SSL_CLIENT_SRVR_RAND_SIZE,
510 ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE);
511
512 serr = SSLInternal_PRF(ctx,
513 clientWriteKey.data,
514 clientWriteKey.length,
515 (const unsigned char *)PLS_EXPORT_CLIENT_WRITE,
516 PLS_EXPORT_CLIENT_WRITE_LEN,
517 randBuf,
518 2 * SSL_CLIENT_SRVR_RAND_SIZE,
519 finalClientWriteKey.data, // destination
520 finalClientWriteKey.length);
521 if(serr) {
522 return serr;
523 }
524 serr = SSLInternal_PRF(ctx,
525 serverWriteKey.data,
526 serverWriteKey.length,
527 (const unsigned char *)PLS_EXPORT_SERVER_WRITE,
528 PLS_EXPORT_SERVER_WRITE_LEN,
529 randBuf,
530 2 * SSL_CLIENT_SRVR_RAND_SIZE,
531 finalServerWriteKey.data, // destination
532 finalServerWriteKey.length);
533 if(serr) {
534 return serr;
535 }
536 if((finalClientIV.length == 0) && (finalServerIV.length == 0)) {
537 /* skip remainder as optimization */
538 return noErr;
539 }
540 ivBlock = (unsigned char *)sslMalloc(finalClientIV.length + finalServerIV.length);
541 if(ivBlock == NULL) {
542 return memFullErr;
543 }
544 serr = SSLInternal_PRF(ctx,
545 (const unsigned char *)nullKey,
546 0,
547 (const unsigned char *)PLS_EXPORT_IV_BLOCK,
548 PLS_EXPORT_IV_BLOCK_LEN,
549 randBuf,
550 2 * SSL_CLIENT_SRVR_RAND_SIZE,
551 ivBlock, // destination
552 finalClientIV.length + finalServerIV.length);
553 if(serr) {
554 goto done;
555 }
556 memmove(finalClientIV.data, ivBlock, finalClientIV.length);
557 memmove(finalServerIV.data, ivBlock + finalClientIV.length, finalServerIV.length);
558 done:
559 sslFree(ivBlock);
560 return serr;
561 }
562
563 /*
564 * On entry: clientRandom, serverRandom, preMasterSecret valid
565 * On return: masterSecret valid
566 *
567 * master_secret = PRF(pre_master_secret, "master secret",
568 * ClientHello.random + ServerHello.random)
569 * [0..47];
570 */
571
572 OSStatus tls1GenerateMasterSecret (
573 SSLContext *ctx)
574 {
575 unsigned char randBuf[2 * SSL_CLIENT_SRVR_RAND_SIZE];
576 OSStatus serr;
577
578 memmove(randBuf, ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE);
579 memmove(randBuf + SSL_CLIENT_SRVR_RAND_SIZE,
580 ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE);
581 serr = SSLInternal_PRF(ctx,
582 ctx->preMasterSecret.data,
583 ctx->preMasterSecret.length,
584 (const unsigned char *)PLS_MASTER_SECRET,
585 PLS_MASTER_SECRET_LEN,
586 randBuf,
587 2 * SSL_CLIENT_SRVR_RAND_SIZE,
588 ctx->masterSecret, // destination
589 SSL_MASTER_SECRET_SIZE);
590 tlsDump("master secret", ctx->masterSecret, SSL_MASTER_SECRET_SIZE);
591 return serr;
592 }
593
594 /*
595 * Given digests contexts representing the running total of all handshake messages,
596 * calculate mac for "finished" message.
597 *
598 * verify_data = 12 bytes =
599 * PRF(master_secret, finished_label, MD5(handshake_messages) +
600 * SHA-1(handshake_messages)) [0..11];
601 */
602 OSStatus tls1ComputeFinishedMac (
603 SSLContext *ctx,
604 SSLBuffer finished, // output - mallocd by caller
605 SSLBuffer shaMsgState, // clone of running digest of all handshake msgs
606 SSLBuffer md5MsgState, // ditto
607 Boolean isServer)
608 {
609 unsigned char digests[SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN];
610 SSLBuffer digBuf;
611 char *finLabel;
612 unsigned finLabelLen;
613 OSStatus serr;
614
615 if(isServer) {
616 finLabel = PLS_SERVER_FINISH;
617 finLabelLen = PLS_SERVER_FINISH_LEN;
618 }
619 else {
620 finLabel = PLS_CLIENT_FINISH;
621 finLabelLen = PLS_CLIENT_FINISH_LEN;
622 }
623
624 /* concatenate two digest results */
625 digBuf.data = digests;
626 digBuf.length = SSL_MD5_DIGEST_LEN;
627 serr = SSLHashMD5.final(md5MsgState, digBuf);
628 if(serr) {
629 return serr;
630 }
631 digBuf.data += SSL_MD5_DIGEST_LEN;
632 digBuf.length = SSL_SHA1_DIGEST_LEN;
633 serr = SSLHashSHA1.final(shaMsgState, digBuf);
634 if(serr) {
635 return serr;
636 }
637 return SSLInternal_PRF(ctx,
638 ctx->masterSecret,
639 SSL_MASTER_SECRET_SIZE,
640 (const unsigned char *)finLabel,
641 finLabelLen,
642 digests,
643 SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN,
644 finished.data, // destination
645 finished.length);
646 }
647
648 /*
649 * This one is trivial.
650 *
651 * mac := MD5(handshake_messages) + SHA(handshake_messages);
652 *
653 * I don't know why this one doesn't use an HMAC or the master secret (as SSLv3
654 * does).
655 */
656 OSStatus tls1ComputeCertVfyMac (
657 SSLContext *ctx,
658 SSLBuffer finished, // output - mallocd by caller
659 SSLBuffer shaMsgState, // clone of running digest of all handshake msgs
660 SSLBuffer md5MsgState) // ditto
661 {
662 SSLBuffer digBuf;
663 OSStatus serr;
664
665 assert(finished.length == (SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN));
666 digBuf.data = finished.data;
667 digBuf.length = SSL_MD5_DIGEST_LEN;
668 serr = SSLHashMD5.final(md5MsgState, digBuf);
669 if(serr) {
670 return serr;
671 }
672 digBuf.data = finished.data + SSL_MD5_DIGEST_LEN;
673 digBuf.length = SSL_SHA1_DIGEST_LEN;
674 return SSLHashSHA1.final(shaMsgState, digBuf);
675 }
676
677 const SslTlsCallouts Tls1Callouts = {
678 tls1DecryptRecord,
679 ssl3WriteRecord,
680 tls1InitMac,
681 tls1FreeMac,
682 tls1ComputeMac,
683 tls1GenerateKeyMaterial,
684 tls1GenerateExportKeyAndIv,
685 tls1GenerateMasterSecret,
686 tls1ComputeFinishedMac,
687 tls1ComputeCertVfyMac
688 };