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