2 * Copyright (c) 2002,2005-2007,2010-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * tls1Callouts.c - TLSv1-specific routines for SslTlsCallouts.
29 #include "sslMemory.h"
31 #include "sslDigests.h"
32 #include "sslAlertMessage.h"
33 #include "sslCrypto.h"
38 #define TLS_ENC_DEBUG 0
40 #define tlsDebug(format, args...) printf(format , ## args)
41 static void tlsDump(const char *name
, void *b
, unsigned len
)
43 unsigned char *cp
= (unsigned char *)b
;
47 for(dex
=0; dex
<len
; dex
++) {
50 if((dex
% 16) == 15) {
58 #define tlsDebug(s, ...)
59 #define tlsDump(name, b, len)
60 #endif /* TLS_ENC_DEBUG */
63 #pragma mark PRF label strings
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.
69 * At least we hard-code string lengths here instead of calling strlen at runtime...
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
87 #pragma mark private functions
90 * P_Hash function defined in RFC2246, section 5.
92 static OSStatus
tlsPHash(
94 const HMACReference
*hmac
, // &TlsHmacSHA1, TlsHmacMD5
95 const uint8_t *secret
,
99 uint8_t *out
, // mallocd by caller, size >= outLen
100 size_t outLen
) // desired output size
102 unsigned char aSubI
[TLS_HMAC_MAX_SIZE
]; /* A(i) */
103 unsigned char digest
[TLS_HMAC_MAX_SIZE
];
104 HMACContextRef hmacCtx
;
106 size_t digestLen
= hmac
->macSize
;
108 serr
= hmac
->alloc(hmac
, ctx
, secret
, secretLen
, &hmacCtx
);
114 /* A(1) := HMAC_hash(secret, seed) */
115 serr
= hmac
->hmac(hmacCtx
, seed
, seedLen
, aSubI
, &digestLen
);
119 assert(digestLen
= hmac
->macSize
);
121 /* starting at loopNum 1... */
124 * This loop's chunk = HMAC_hash(secret, A(loopNum) + seed))
126 serr
= hmac
->init(hmacCtx
);
130 serr
= hmac
->update(hmacCtx
, aSubI
, digestLen
);
134 serr
= hmac
->update(hmacCtx
, seed
, seedLen
);
138 serr
= hmac
->final(hmacCtx
, digest
, &digestLen
);
142 assert(digestLen
= hmac
->macSize
);
144 if(outLen
<= digestLen
) {
145 /* last time, possible partial digest */
146 memmove(out
, digest
, outLen
);
150 memmove(out
, digest
, digestLen
);
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).
161 serr
= hmac
->hmac(hmacCtx
, aSubI
, digestLen
,
166 assert(digestLen
= hmac
->macSize
);
170 memset(aSubI
, 0, TLS_HMAC_MAX_SIZE
);
171 memset(digest
, 0, TLS_HMAC_MAX_SIZE
);
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.
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.
183 OSStatus
SSLInternal_PRF(
187 const void *label
, // optional, NULL implies that seed contains
192 void *vout
, // mallocd by caller, length >= outLen
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
200 unsigned char *tmpOut
= NULL
; // output of P_SHA1
202 const unsigned char *secret
= (const unsigned char *)vsecret
;
205 /* concatenate label and seed */
206 labelSeedLen
= labelLen
+ seedLen
;
207 labelSeed
= (unsigned char *)sslMalloc(labelSeedLen
);
208 if(labelSeed
== NULL
) {
211 memmove(labelSeed
, label
, labelLen
);
212 memmove(labelSeed
+ labelLen
, seed
, seedLen
);
215 /* fast track - just use seed as is */
216 labelSeed
= (unsigned char *)seed
;
217 labelSeedLen
= seedLen
;
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
;
226 serr
= tlsPHash(ctx
, mac
, secret
, secretLen
, labelSeed
, labelSeedLen
,
232 /* two seeds for tlsPHash */
233 sLen
= secretLen
/ 2; // for partitioning
236 sLen
+= (secretLen
& 1); // secret length odd, increment effective size
238 /* temporary output for SHA1, to be XORd with MD5 */
239 tmpOut
= (unsigned char *)sslMalloc(outLen
);
245 serr
= tlsPHash(ctx
, &TlsHmacMD5
, S1
, sLen
, labelSeed
, labelSeedLen
,
250 serr
= tlsPHash(ctx
, &TlsHmacSHA1
, S2
, sLen
, labelSeed
, labelSeedLen
,
256 /* XOR together to get final result */
257 for(i
=0; i
<outLen
; i
++) {
264 if((labelSeed
!= NULL
) && (label
!= NULL
)) {
273 /* not needed; encrypt/encode is the same for both protocols as long as
274 * we don't use the "variable length padding" feature. */
276 static OSStatus
tls1WriteRecord(
285 static OSStatus
tls1DecryptRecord(
293 if ((ctx
->readCipher
.symCipher
->blockSize
> 0) &&
294 ((payload
->length
% ctx
->readCipher
.symCipher
->blockSize
) != 0)) {
295 SSLFatalSessionAlert(SSL_AlertRecordOverflow
, ctx
);
296 return errSSLRecordOverflow
;
299 /* Decrypt in place */
300 if ((err
= ctx
->readCipher
.symCipher
->decrypt(payload
->data
,
301 payload
->data
, payload
->length
,
304 { SSLFatalSessionAlert(SSL_AlertDecryptError
, ctx
);
305 return errSSLDecryptionFail
;
308 /* Locate content within decrypted payload */
310 /* TLS 1.1 and DTLS 1.0 block ciphers */
311 if((ctx
->negProtocolVersion
>=TLS_Version_1_1
) && (ctx
->readCipher
.symCipher
->blockSize
>0))
313 content
.data
= payload
->data
+ ctx
->readCipher
.symCipher
->blockSize
;
314 content
.length
= payload
->length
- (ctx
->readCipher
.macRef
->hash
->digestSize
+ ctx
->readCipher
.symCipher
->blockSize
);
316 content
.data
= payload
->data
;
317 content
.length
= payload
->length
- ctx
->readCipher
.macRef
->hash
->digestSize
;
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];
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
;
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
;
344 /* Remove block size padding and its one-byte length */
345 content
.length
-= (1 + padSize
);
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
;
357 *payload
= content
; /* Modify payload buffer to indicate content length */
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
368 const HMACReference
*hmac
;
371 assert(cipherCtx
->macRef
!= NULL
);
372 hmac
= cipherCtx
->macRef
->hmac
;
373 assert(hmac
!= NULL
);
375 if(cipherCtx
->macCtx
.hmacCtx
!= NULL
) {
376 hmac
->free(cipherCtx
->macCtx
.hmacCtx
);
377 cipherCtx
->macCtx
.hmacCtx
= NULL
;
379 serr
= hmac
->alloc(hmac
, ctx
, cipherCtx
->macSecret
,
380 cipherCtx
->macRef
->hmac
->macSize
, &cipherCtx
->macCtx
.hmacCtx
);
382 /* mac secret now stored in macCtx.hmacCtx, delete it from cipherCtx */
383 memset(cipherCtx
->macSecret
, 0, sizeof(cipherCtx
->macSecret
));
387 static OSStatus
tls1FreeMac (
388 CipherContext
*cipherCtx
)
390 /* this can be called on a completely zeroed out CipherContext... */
391 if(cipherCtx
->macRef
== NULL
) {
394 assert(cipherCtx
->macRef
->hmac
!= NULL
);
396 if(cipherCtx
->macCtx
.hmacCtx
!= NULL
) {
397 cipherCtx
->macRef
->hmac
->free(cipherCtx
->macCtx
.hmacCtx
);
398 cipherCtx
->macCtx
.hmacCtx
= NULL
;
404 * mac = HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type +
405 * TLSCompressed.version + TLSCompressed.length +
406 * TLSCompressed.fragment));
409 /* sequence, type, version, length */
410 #define HDR_LENGTH (8 + 1 + 2 + 2)
411 static OSStatus
tls1ComputeMac (
414 SSLBuffer mac
, // caller mallocs data
415 CipherContext
*cipherCtx
, // assumes macCtx, macRef
419 uint8_t hdr
[HDR_LENGTH
];
421 HMACContextRef hmacCtx
;
423 const HMACReference
*hmac
;
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
432 serr
= hmac
->init(hmacCtx
);
436 p
= SSLEncodeUInt64(hdr
, seqNo
);
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
);
446 serr
= hmac
->update(hmacCtx
, data
.data
, data
.length
);
450 macLength
= mac
.length
;
451 serr
= hmac
->final(hmacCtx
, mac
.data
, &macLength
);
455 mac
.length
= macLength
;
461 * On input, the following are valid:
463 * ClientHello.random[32]
464 * ServerHello.random[32]
466 * key_block = PRF(SecurityParameters.master_secret,
468 * SecurityParameters.server_random +
469 * SecurityParameters.client_random);
472 #define GKM_SEED_LEN (PLS_KEY_EXPAND_LEN + (2 * SSL_CLIENT_SRVR_RAND_SIZE))
474 static OSStatus
tls1GenerateKeyMaterial (
475 SSLBuffer key
, // caller mallocs and specifies length of
476 // required key material here
479 unsigned char seedBuf
[GKM_SEED_LEN
];
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
,
490 SSL_MASTER_SECRET_SIZE
,
495 key
.data
, // destination
497 tlsDump("key expansion", key
.data
, key
.length
);
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);
513 * iv_block = PRF("", "IV block", SecurityParameters.client_random +
514 * SecurityParameters.server_random);
516 * iv_block is broken up into:
518 * client_write_IV[SecurityParameters.IV_size]
519 * server_write_IV[SecurityParameters.IV_size]
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
530 unsigned char randBuf
[2 * SSL_CLIENT_SRVR_RAND_SIZE
];
532 unsigned char *ivBlock
;
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
);
540 serr
= SSLInternal_PRF(ctx
,
542 clientWriteKey
.length
,
543 (const unsigned char *)PLS_EXPORT_CLIENT_WRITE
,
544 PLS_EXPORT_CLIENT_WRITE_LEN
,
546 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
547 finalClientWriteKey
.data
, // destination
548 finalClientWriteKey
.length
);
552 serr
= SSLInternal_PRF(ctx
,
554 serverWriteKey
.length
,
555 (const unsigned char *)PLS_EXPORT_SERVER_WRITE
,
556 PLS_EXPORT_SERVER_WRITE_LEN
,
558 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
559 finalServerWriteKey
.data
, // destination
560 finalServerWriteKey
.length
);
564 if((finalClientIV
.length
== 0) && (finalServerIV
.length
== 0)) {
565 /* skip remainder as optimization */
568 ivBlock
= (unsigned char *)sslMalloc(finalClientIV
.length
+ finalServerIV
.length
);
569 if(ivBlock
== NULL
) {
572 serr
= SSLInternal_PRF(ctx
,
573 (const unsigned char *)nullKey
,
575 (const unsigned char *)PLS_EXPORT_IV_BLOCK
,
576 PLS_EXPORT_IV_BLOCK_LEN
,
578 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
579 ivBlock
, // destination
580 finalClientIV
.length
+ finalServerIV
.length
);
584 memmove(finalClientIV
.data
, ivBlock
, finalClientIV
.length
);
585 memmove(finalServerIV
.data
, ivBlock
+ finalClientIV
.length
, finalServerIV
.length
);
592 * On entry: clientRandom, serverRandom, preMasterSecret valid
593 * On return: masterSecret valid
595 * master_secret = PRF(pre_master_secret, "master secret",
596 * ClientHello.random + ServerHello.random)
600 static OSStatus
tls1GenerateMasterSecret (
603 unsigned char randBuf
[2 * SSL_CLIENT_SRVR_RAND_SIZE
];
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
,
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
);
623 * Given digests contexts representing the running total of all handshake messages,
624 * calculate mac for "finished" message.
626 * verify_data = 12 bytes =
627 * PRF(master_secret, finished_label, MD5(handshake_messages) +
628 * SHA-1(handshake_messages)) [0..11];
630 static OSStatus
tls1ComputeFinishedMac (
632 SSLBuffer finished
, // output - mallocd by caller
635 unsigned char digests
[SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
];
638 unsigned finLabelLen
;
640 SSLBuffer shaMsgState
, md5MsgState
;
642 shaMsgState
.data
= 0;
643 md5MsgState
.data
= 0;
644 if ((serr
= CloneHashState(&SSLHashSHA1
, &ctx
->shaState
, &shaMsgState
, ctx
)) != 0)
646 if ((serr
= CloneHashState(&SSLHashMD5
, &ctx
->md5State
, &md5MsgState
, ctx
)) != 0)
650 finLabel
= PLS_SERVER_FINISH
;
651 finLabelLen
= PLS_SERVER_FINISH_LEN
;
654 finLabel
= PLS_CLIENT_FINISH
;
655 finLabelLen
= PLS_CLIENT_FINISH_LEN
;
658 /* concatenate two digest results */
659 digBuf
.data
= digests
;
660 digBuf
.length
= SSL_MD5_DIGEST_LEN
;
661 serr
= SSLHashMD5
.final(&md5MsgState
, &digBuf
);
665 digBuf
.data
+= SSL_MD5_DIGEST_LEN
;
666 digBuf
.length
= SSL_SHA1_DIGEST_LEN
;
667 serr
= SSLHashSHA1
.final(&shaMsgState
, &digBuf
);
671 serr
= SSLInternal_PRF(ctx
,
673 SSL_MASTER_SECRET_SIZE
,
674 (const unsigned char *)finLabel
,
677 SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
,
678 finished
.data
, // destination
682 SSLFreeBuffer(&shaMsgState
, ctx
);
683 SSLFreeBuffer(&md5MsgState
, ctx
);
689 * Given digests contexts representing the running total of all handshake messages,
690 * calculate mac for "finished" message.
692 * verify_data = 12 bytes =
693 * PRF(master_secret, finished_label, SHA256(handshake_messages)) [0..11];
695 static OSStatus
tls12ComputeFinishedMac (
697 SSLBuffer finished
, // output - mallocd by caller
700 unsigned char digest
[SSL_MAX_DIGEST_LEN
];
703 unsigned finLabelLen
;
706 const HashReference
*hashRef
;
707 const SSLBuffer
*ctxHashState
;
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
;
714 hashRef
= &SSLHashSHA256
;
715 ctxHashState
= &ctx
->sha256State
;
719 if ((serr
= CloneHashState(hashRef
, ctxHashState
, &hashState
, ctx
)) != 0)
722 finLabel
= PLS_SERVER_FINISH
;
723 finLabelLen
= PLS_SERVER_FINISH_LEN
;
726 finLabel
= PLS_CLIENT_FINISH
;
727 finLabelLen
= PLS_CLIENT_FINISH_LEN
;
730 /* concatenate two digest results */
731 digBuf
.data
= digest
;
732 digBuf
.length
= hashRef
->digestSize
;
733 if ((serr
= hashRef
->final(&hashState
, &digBuf
)) != 0)
735 serr
= SSLInternal_PRF(ctx
,
737 SSL_MASTER_SECRET_SIZE
,
738 (const unsigned char *)finLabel
,
742 finished
.data
, // destination
745 SSLFreeBuffer(&hashState
, ctx
);
750 * This one is trivial.
752 * mac := MD5(handshake_messages) + SHA(handshake_messages);
754 * I don't know why this one doesn't use an HMAC or the master secret (as SSLv3
757 static OSStatus
tls1ComputeCertVfyMac (
759 SSLBuffer
*finished
, // output - mallocd by caller
760 SSL_HashAlgorithm hash
) //unused in this one
762 SSLBuffer digBuf
, shaMsgState
, md5MsgState
;
765 shaMsgState
.data
= 0;
766 md5MsgState
.data
= 0;
768 if ((serr
= CloneHashState(&SSLHashSHA1
, &ctx
->shaState
, &shaMsgState
, ctx
)) != 0)
770 if ((serr
= CloneHashState(&SSLHashMD5
, &ctx
->md5State
, &md5MsgState
, ctx
)) != 0)
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
;
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)
788 digBuf
.data
= finished
->data
+ SSL_MD5_DIGEST_LEN
;
789 finished
->length
= SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
;
792 digBuf
.length
= SSL_SHA1_DIGEST_LEN
;
793 serr
= SSLHashSHA1
.final(&shaMsgState
, &digBuf
);
796 SSLFreeBuffer(&shaMsgState
, ctx
);
797 SSLFreeBuffer(&md5MsgState
, ctx
);
802 static OSStatus
tls12ComputeCertVfyMac (
804 SSLBuffer
*finished
, // output - mallocd by caller
805 SSL_HashAlgorithm hash
)
807 const SSLBuffer
*ctxHashState
;
808 const HashReference
*hashRef
;
815 case SSL_HashAlgorithmSHA1
:
816 hashRef
= &SSLHashSHA1
;
817 ctxHashState
= &ctx
->shaState
;
819 case SSL_HashAlgorithmSHA256
:
820 hashRef
= &SSLHashSHA256
;
821 ctxHashState
= &ctx
->sha256State
;
823 case SSL_HashAlgorithmSHA384
:
824 hashRef
= &SSLHashSHA384
;
825 ctxHashState
= &ctx
->sha512State
;
831 if ((serr
= CloneHashState(hashRef
, ctxHashState
, &hashState
, ctx
)) != 0)
834 assert(finished
->length
>= (hashRef
->digestSize
));
835 finished
->length
= hashRef
->digestSize
;
836 serr
= hashRef
->final(&hashState
, finished
);
839 SSLFreeBuffer(&hashState
, ctx
);
845 const SslTlsCallouts Tls1Callouts
= {
851 tls1GenerateKeyMaterial
,
852 tls1GenerateExportKeyAndIv
,
853 tls1GenerateMasterSecret
,
854 tls1ComputeFinishedMac
,
855 tls1ComputeCertVfyMac
859 const SslTlsCallouts Tls12Callouts
= {
865 tls1GenerateKeyMaterial
,
866 tls1GenerateExportKeyAndIv
,
867 tls1GenerateMasterSecret
,
868 tls12ComputeFinishedMac
,
869 tls12ComputeCertVfyMac