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(
292 bool decryption_failed_or_bad_record_mac
= false;
294 if ((ctx
->readCipher
.symCipher
->blockSize
> 0) &&
295 ((payload
->length
% ctx
->readCipher
.symCipher
->blockSize
) != 0)) {
296 SSLFatalSessionAlert(SSL_AlertRecordOverflow
, ctx
);
297 return errSSLRecordOverflow
;
300 /* Decrypt in place */
301 if ((err
= ctx
->readCipher
.symCipher
->decrypt(payload
->data
,
302 payload
->data
, payload
->length
,
306 /* note: we no longer send a SSL_AlertDecryptError here;
307 * all subsequent failures result in SSL_AlertBadRecordMac
308 * being sent at the end of the function, to avoid leaking
309 * differences between padding and decryption failures. */
310 decryption_failed_or_bad_record_mac
= true;
313 /* Locate content within decrypted payload */
315 /* TLS 1.1 and DTLS 1.0 block ciphers */
316 if((ctx
->negProtocolVersion
>=TLS_Version_1_1
) && (ctx
->readCipher
.symCipher
->blockSize
>0))
318 content
.data
= payload
->data
+ ctx
->readCipher
.symCipher
->blockSize
;
319 content
.length
= payload
->length
- (ctx
->readCipher
.macRef
->hash
->digestSize
+ ctx
->readCipher
.symCipher
->blockSize
);
321 content
.data
= payload
->data
;
322 content
.length
= payload
->length
- ctx
->readCipher
.macRef
->hash
->digestSize
;
325 if (ctx
->readCipher
.symCipher
->blockSize
> 0) {
326 /* for TLSv1, padding can be anywhere from 0 to 255 bytes */
327 UInt8 padSize
= payload
->data
[payload
->length
- 1];
330 /* verify that all padding bytes are equal - WARNING - OpenSSL code
331 * has a special case here dealing with some kind of bug related to
332 * even size packets...beware... */
333 if(padSize
> payload
->length
) {
334 /* This is TLS 1.1 compliant - Do it for all protocols versions */
335 sslErrorLog("tls1DecryptRecord: bad padding length (%d)\n",
336 (unsigned)payload
->data
[payload
->length
- 1]);
337 decryption_failed_or_bad_record_mac
= true;
339 padChars
= payload
->data
+ payload
->length
- padSize
;
340 while(padChars
< (payload
->data
+ payload
->length
)) {
341 if(*padChars
++ != padSize
) {
342 /* This is TLS 1.1 compliant - Do it for all protocols versions */
343 sslErrorLog("tls1DecryptRecord: bad padding value\n");
344 decryption_failed_or_bad_record_mac
= true;
347 /* Remove block size padding and its one-byte length */
348 content
.length
-= (1 + padSize
);
351 /* Verify MAC on payload */
352 if (ctx
->readCipher
.macRef
->hash
->digestSize
> 0)
353 /* Optimize away MAC for null case */
354 if ((err
= SSLVerifyMac(type
, &content
,
355 content
.data
+ content
.length
, ctx
)) != 0)
357 decryption_failed_or_bad_record_mac
= true;
360 if (decryption_failed_or_bad_record_mac
) {
361 SSLFatalSessionAlert(SSL_AlertBadRecordMac
, ctx
);
362 return errSSLDecryptionFail
;
365 *payload
= content
; /* Modify payload buffer to indicate content length */
370 /* initialize a per-CipherContext HashHmacContext for use in MACing each record */
371 static OSStatus
tls1InitMac (
372 CipherContext
*cipherCtx
, // macRef, macSecret valid on entry
373 // macCtx valid on return
376 const HMACReference
*hmac
;
379 assert(cipherCtx
->macRef
!= NULL
);
380 hmac
= cipherCtx
->macRef
->hmac
;
381 assert(hmac
!= NULL
);
383 if(cipherCtx
->macCtx
.hmacCtx
!= NULL
) {
384 hmac
->free(cipherCtx
->macCtx
.hmacCtx
);
385 cipherCtx
->macCtx
.hmacCtx
= NULL
;
387 serr
= hmac
->alloc(hmac
, ctx
, cipherCtx
->macSecret
,
388 cipherCtx
->macRef
->hmac
->macSize
, &cipherCtx
->macCtx
.hmacCtx
);
390 /* mac secret now stored in macCtx.hmacCtx, delete it from cipherCtx */
391 memset(cipherCtx
->macSecret
, 0, sizeof(cipherCtx
->macSecret
));
395 static OSStatus
tls1FreeMac (
396 CipherContext
*cipherCtx
)
398 /* this can be called on a completely zeroed out CipherContext... */
399 if(cipherCtx
->macRef
== NULL
) {
402 assert(cipherCtx
->macRef
->hmac
!= NULL
);
404 if(cipherCtx
->macCtx
.hmacCtx
!= NULL
) {
405 cipherCtx
->macRef
->hmac
->free(cipherCtx
->macCtx
.hmacCtx
);
406 cipherCtx
->macCtx
.hmacCtx
= NULL
;
412 * mac = HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type +
413 * TLSCompressed.version + TLSCompressed.length +
414 * TLSCompressed.fragment));
417 /* sequence, type, version, length */
418 #define HDR_LENGTH (8 + 1 + 2 + 2)
419 static OSStatus
tls1ComputeMac (
422 SSLBuffer mac
, // caller mallocs data
423 CipherContext
*cipherCtx
, // assumes macCtx, macRef
427 uint8_t hdr
[HDR_LENGTH
];
429 HMACContextRef hmacCtx
;
431 const HMACReference
*hmac
;
434 assert(cipherCtx
!= NULL
);
435 assert(cipherCtx
->macRef
!= NULL
);
436 hmac
= cipherCtx
->macRef
->hmac
;
437 assert(hmac
!= NULL
);
438 hmacCtx
= cipherCtx
->macCtx
.hmacCtx
; // may be NULL, for null cipher
440 serr
= hmac
->init(hmacCtx
);
444 p
= SSLEncodeUInt64(hdr
, seqNo
);
446 *p
++ = ctx
->negProtocolVersion
>> 8;
447 *p
++ = ctx
->negProtocolVersion
& 0xff;
448 *p
++ = data
.length
>> 8;
449 *p
= data
.length
& 0xff;
450 serr
= hmac
->update(hmacCtx
, hdr
, HDR_LENGTH
);
454 serr
= hmac
->update(hmacCtx
, data
.data
, data
.length
);
458 macLength
= mac
.length
;
459 serr
= hmac
->final(hmacCtx
, mac
.data
, &macLength
);
463 mac
.length
= macLength
;
469 * On input, the following are valid:
471 * ClientHello.random[32]
472 * ServerHello.random[32]
474 * key_block = PRF(SecurityParameters.master_secret,
476 * SecurityParameters.server_random +
477 * SecurityParameters.client_random);
480 #define GKM_SEED_LEN (PLS_KEY_EXPAND_LEN + (2 * SSL_CLIENT_SRVR_RAND_SIZE))
482 static OSStatus
tls1GenerateKeyMaterial (
483 SSLBuffer key
, // caller mallocs and specifies length of
484 // required key material here
487 unsigned char seedBuf
[GKM_SEED_LEN
];
490 /* use optimized label-less PRF */
491 memmove(seedBuf
, PLS_KEY_EXPAND
, PLS_KEY_EXPAND_LEN
);
492 memmove(seedBuf
+ PLS_KEY_EXPAND_LEN
, ctx
->serverRandom
,
493 SSL_CLIENT_SRVR_RAND_SIZE
);
494 memmove(seedBuf
+ PLS_KEY_EXPAND_LEN
+ SSL_CLIENT_SRVR_RAND_SIZE
,
495 ctx
->clientRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
496 serr
= SSLInternal_PRF(ctx
,
498 SSL_MASTER_SECRET_SIZE
,
503 key
.data
, // destination
505 tlsDump("key expansion", key
.data
, key
.length
);
510 * final_client_write_key =
511 * PRF(SecurityParameters.client_write_key,
512 * "client write key",
513 * SecurityParameters.client_random +
514 * SecurityParameters.server_random);
515 * final_server_write_key =
516 * PRF(SecurityParameters.server_write_key,
517 * "server write key",
518 * SecurityParameters.client_random +
519 * SecurityParameters.server_random);
521 * iv_block = PRF("", "IV block", SecurityParameters.client_random +
522 * SecurityParameters.server_random);
524 * iv_block is broken up into:
526 * client_write_IV[SecurityParameters.IV_size]
527 * server_write_IV[SecurityParameters.IV_size]
529 static OSStatus
tls1GenerateExportKeyAndIv (
530 SSLContext
*ctx
, // clientRandom, serverRandom valid
531 const SSLBuffer clientWriteKey
,
532 const SSLBuffer serverWriteKey
,
533 SSLBuffer finalClientWriteKey
, // RETURNED, mallocd by caller
534 SSLBuffer finalServerWriteKey
, // RETURNED, mallocd by caller
535 SSLBuffer finalClientIV
, // RETURNED, mallocd by caller
536 SSLBuffer finalServerIV
) // RETURNED, mallocd by caller
538 unsigned char randBuf
[2 * SSL_CLIENT_SRVR_RAND_SIZE
];
540 unsigned char *ivBlock
;
543 /* all three PRF calls use the same seed */
544 memmove(randBuf
, ctx
->clientRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
545 memmove(randBuf
+ SSL_CLIENT_SRVR_RAND_SIZE
,
546 ctx
->serverRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
548 serr
= SSLInternal_PRF(ctx
,
550 clientWriteKey
.length
,
551 (const unsigned char *)PLS_EXPORT_CLIENT_WRITE
,
552 PLS_EXPORT_CLIENT_WRITE_LEN
,
554 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
555 finalClientWriteKey
.data
, // destination
556 finalClientWriteKey
.length
);
560 serr
= SSLInternal_PRF(ctx
,
562 serverWriteKey
.length
,
563 (const unsigned char *)PLS_EXPORT_SERVER_WRITE
,
564 PLS_EXPORT_SERVER_WRITE_LEN
,
566 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
567 finalServerWriteKey
.data
, // destination
568 finalServerWriteKey
.length
);
572 if((finalClientIV
.length
== 0) && (finalServerIV
.length
== 0)) {
573 /* skip remainder as optimization */
576 ivBlock
= (unsigned char *)sslMalloc(finalClientIV
.length
+ finalServerIV
.length
);
577 if(ivBlock
== NULL
) {
580 serr
= SSLInternal_PRF(ctx
,
581 (const unsigned char *)nullKey
,
583 (const unsigned char *)PLS_EXPORT_IV_BLOCK
,
584 PLS_EXPORT_IV_BLOCK_LEN
,
586 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
587 ivBlock
, // destination
588 finalClientIV
.length
+ finalServerIV
.length
);
592 memmove(finalClientIV
.data
, ivBlock
, finalClientIV
.length
);
593 memmove(finalServerIV
.data
, ivBlock
+ finalClientIV
.length
, finalServerIV
.length
);
600 * On entry: clientRandom, serverRandom, preMasterSecret valid
601 * On return: masterSecret valid
603 * master_secret = PRF(pre_master_secret, "master secret",
604 * ClientHello.random + ServerHello.random)
608 static OSStatus
tls1GenerateMasterSecret (
611 unsigned char randBuf
[2 * SSL_CLIENT_SRVR_RAND_SIZE
];
614 memmove(randBuf
, ctx
->clientRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
615 memmove(randBuf
+ SSL_CLIENT_SRVR_RAND_SIZE
,
616 ctx
->serverRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
617 serr
= SSLInternal_PRF(ctx
,
618 ctx
->preMasterSecret
.data
,
619 ctx
->preMasterSecret
.length
,
620 (const unsigned char *)PLS_MASTER_SECRET
,
621 PLS_MASTER_SECRET_LEN
,
623 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
624 ctx
->masterSecret
, // destination
625 SSL_MASTER_SECRET_SIZE
);
626 tlsDump("master secret", ctx
->masterSecret
, SSL_MASTER_SECRET_SIZE
);
631 * Given digests contexts representing the running total of all handshake messages,
632 * calculate mac for "finished" message.
634 * verify_data = 12 bytes =
635 * PRF(master_secret, finished_label, MD5(handshake_messages) +
636 * SHA-1(handshake_messages)) [0..11];
638 static OSStatus
tls1ComputeFinishedMac (
640 SSLBuffer finished
, // output - mallocd by caller
643 unsigned char digests
[SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
];
646 unsigned finLabelLen
;
648 SSLBuffer shaMsgState
, md5MsgState
;
650 shaMsgState
.data
= 0;
651 md5MsgState
.data
= 0;
652 if ((serr
= CloneHashState(&SSLHashSHA1
, &ctx
->shaState
, &shaMsgState
, ctx
)) != 0)
654 if ((serr
= CloneHashState(&SSLHashMD5
, &ctx
->md5State
, &md5MsgState
, ctx
)) != 0)
658 finLabel
= PLS_SERVER_FINISH
;
659 finLabelLen
= PLS_SERVER_FINISH_LEN
;
662 finLabel
= PLS_CLIENT_FINISH
;
663 finLabelLen
= PLS_CLIENT_FINISH_LEN
;
666 /* concatenate two digest results */
667 digBuf
.data
= digests
;
668 digBuf
.length
= SSL_MD5_DIGEST_LEN
;
669 serr
= SSLHashMD5
.final(&md5MsgState
, &digBuf
);
673 digBuf
.data
+= SSL_MD5_DIGEST_LEN
;
674 digBuf
.length
= SSL_SHA1_DIGEST_LEN
;
675 serr
= SSLHashSHA1
.final(&shaMsgState
, &digBuf
);
679 serr
= SSLInternal_PRF(ctx
,
681 SSL_MASTER_SECRET_SIZE
,
682 (const unsigned char *)finLabel
,
685 SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
,
686 finished
.data
, // destination
690 SSLFreeBuffer(&shaMsgState
, ctx
);
691 SSLFreeBuffer(&md5MsgState
, ctx
);
697 * Given digests contexts representing the running total of all handshake messages,
698 * calculate mac for "finished" message.
700 * verify_data = 12 bytes =
701 * PRF(master_secret, finished_label, SHA256(handshake_messages)) [0..11];
703 static OSStatus
tls12ComputeFinishedMac (
705 SSLBuffer finished
, // output - mallocd by caller
708 unsigned char digest
[SSL_MAX_DIGEST_LEN
];
711 unsigned finLabelLen
;
714 const HashReference
*hashRef
;
715 const SSLBuffer
*ctxHashState
;
717 /* The PRF used in the finished message is based on the cipherspec */
718 if (ctx
->selectedCipherSpec
.macAlgorithm
->hmac
->alg
== HA_SHA384
) {
719 hashRef
= &SSLHashSHA384
;
720 ctxHashState
= &ctx
->sha512State
;
722 hashRef
= &SSLHashSHA256
;
723 ctxHashState
= &ctx
->sha256State
;
727 if ((serr
= CloneHashState(hashRef
, ctxHashState
, &hashState
, ctx
)) != 0)
730 finLabel
= PLS_SERVER_FINISH
;
731 finLabelLen
= PLS_SERVER_FINISH_LEN
;
734 finLabel
= PLS_CLIENT_FINISH
;
735 finLabelLen
= PLS_CLIENT_FINISH_LEN
;
738 /* concatenate two digest results */
739 digBuf
.data
= digest
;
740 digBuf
.length
= hashRef
->digestSize
;
741 if ((serr
= hashRef
->final(&hashState
, &digBuf
)) != 0)
743 serr
= SSLInternal_PRF(ctx
,
745 SSL_MASTER_SECRET_SIZE
,
746 (const unsigned char *)finLabel
,
750 finished
.data
, // destination
753 SSLFreeBuffer(&hashState
, ctx
);
758 * This one is trivial.
760 * mac := MD5(handshake_messages) + SHA(handshake_messages);
762 * I don't know why this one doesn't use an HMAC or the master secret (as SSLv3
765 static OSStatus
tls1ComputeCertVfyMac (
767 SSLBuffer
*finished
, // output - mallocd by caller
768 SSL_HashAlgorithm hash
) //unused in this one
770 SSLBuffer digBuf
, shaMsgState
, md5MsgState
;
773 shaMsgState
.data
= 0;
774 md5MsgState
.data
= 0;
776 if ((serr
= CloneHashState(&SSLHashSHA1
, &ctx
->shaState
, &shaMsgState
, ctx
)) != 0)
778 if ((serr
= CloneHashState(&SSLHashMD5
, &ctx
->md5State
, &md5MsgState
, ctx
)) != 0)
781 if ((ctx
->protocolSide
== kSSLServerSide
&& sslPubKeyGetAlgorithmID(ctx
->peerPubKey
) == kSecECDSAAlgorithmID
) ||
782 (ctx
->protocolSide
== kSSLClientSide
&& ctx
->negAuthType
== SSLClientAuth_ECDSASign
)) {
783 /* Only take SHA1 regardless of TLSv1.0 or TLSv1.1 If we are the server
784 and our peer signed with an ECDSA key, or if we are the client and
785 are about to sign with ECDSA. */
786 assert(finished
->length
>= SSL_SHA1_DIGEST_LEN
);
787 digBuf
.data
= finished
->data
;
788 finished
->length
= SSL_SHA1_DIGEST_LEN
;
790 /* Put MD5 follow by SHA1 hash in buffer. */
791 assert(finished
->length
>= (SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
));
792 digBuf
.data
= finished
->data
;
793 digBuf
.length
= SSL_MD5_DIGEST_LEN
;
794 if ((serr
= SSLHashMD5
.final(&md5MsgState
, &digBuf
)) != 0)
796 digBuf
.data
= finished
->data
+ SSL_MD5_DIGEST_LEN
;
797 finished
->length
= SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
;
800 digBuf
.length
= SSL_SHA1_DIGEST_LEN
;
801 serr
= SSLHashSHA1
.final(&shaMsgState
, &digBuf
);
804 SSLFreeBuffer(&shaMsgState
, ctx
);
805 SSLFreeBuffer(&md5MsgState
, ctx
);
810 static OSStatus
tls12ComputeCertVfyMac (
812 SSLBuffer
*finished
, // output - mallocd by caller
813 SSL_HashAlgorithm hash
)
815 const SSLBuffer
*ctxHashState
;
816 const HashReference
*hashRef
;
823 case SSL_HashAlgorithmSHA1
:
824 hashRef
= &SSLHashSHA1
;
825 ctxHashState
= &ctx
->shaState
;
827 case SSL_HashAlgorithmSHA256
:
828 hashRef
= &SSLHashSHA256
;
829 ctxHashState
= &ctx
->sha256State
;
831 case SSL_HashAlgorithmSHA384
:
832 hashRef
= &SSLHashSHA384
;
833 ctxHashState
= &ctx
->sha512State
;
839 if ((serr
= CloneHashState(hashRef
, ctxHashState
, &hashState
, ctx
)) != 0)
842 assert(finished
->length
>= (hashRef
->digestSize
));
843 finished
->length
= hashRef
->digestSize
;
844 serr
= hashRef
->final(&hashState
, finished
);
847 SSLFreeBuffer(&hashState
, ctx
);
853 const SslTlsCallouts Tls1Callouts
= {
859 tls1GenerateKeyMaterial
,
860 tls1GenerateExportKeyAndIv
,
861 tls1GenerateMasterSecret
,
862 tls1ComputeFinishedMac
,
863 tls1ComputeCertVfyMac
867 const SslTlsCallouts Tls12Callouts
= {
873 tls1GenerateKeyMaterial
,
874 tls1GenerateExportKeyAndIv
,
875 tls1GenerateMasterSecret
,
876 tls12ComputeFinishedMac
,
877 tls12ComputeCertVfyMac