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.
28 #include "SecureTransport.h"
31 #include "sslMemory.h"
33 #include "sslDigests.h"
34 #include "sslAlertMessage.h"
35 #include "sslCrypto.h"
41 #define TLS_ENC_DEBUG 0
43 #define tlsDebug(format, args...) printf(format , ## args)
44 static void tlsDump(const char *name
, void *b
, unsigned len
)
46 unsigned char *cp
= (unsigned char *)b
;
50 for(dex
=0; dex
<len
; dex
++) {
53 if((dex
% 16) == 15) {
61 #define tlsDebug(s, ...)
62 #define tlsDump(name, b, len)
63 #endif /* TLS_ENC_DEBUG */
66 // MARK: PRF label strings
68 * Note we could optimize away a bunch of mallocs and frees if we, like openSSL,
69 * just mallocd buffers for inputs to SSLInternal_PRF() on the stack,
70 * with "known" max values for all of the inputs.
72 * At least we hard-code string lengths here instead of calling strlen at runtime...
74 #define PLS_MASTER_SECRET "master secret"
75 #define PLS_MASTER_SECRET_LEN 13
76 #define PLS_KEY_EXPAND "key expansion"
77 #define PLS_KEY_EXPAND_LEN 13
78 #define PLS_CLIENT_FINISH "client finished"
79 #define PLS_CLIENT_FINISH_LEN 15
80 #define PLS_SERVER_FINISH "server finished"
81 #define PLS_SERVER_FINISH_LEN 15
82 #define PLS_EXPORT_CLIENT_WRITE "client write key"
83 #define PLS_EXPORT_CLIENT_WRITE_LEN 16
84 #define PLS_EXPORT_SERVER_WRITE "server write key"
85 #define PLS_EXPORT_SERVER_WRITE_LEN 16
86 #define PLS_EXPORT_IV_BLOCK "IV block"
87 #define PLS_EXPORT_IV_BLOCK_LEN 8
90 // MARK: private functions
93 * P_Hash function defined in RFC2246, section 5.
95 static OSStatus
tlsPHash(
97 const HMACReference
*hmac
, // &TlsHmacSHA1, TlsHmacMD5
98 const uint8_t *secret
,
102 uint8_t *out
, // mallocd by caller, size >= outLen
103 size_t outLen
) // desired output size
105 unsigned char aSubI
[TLS_HMAC_MAX_SIZE
]; /* A(i) */
106 unsigned char digest
[TLS_HMAC_MAX_SIZE
];
107 HMACContextRef hmacCtx
;
109 size_t digestLen
= hmac
->macSize
;
111 serr
= hmac
->alloc(hmac
, secret
, secretLen
, &hmacCtx
);
117 /* A(1) := HMAC_hash(secret, seed) */
118 serr
= hmac
->hmac(hmacCtx
, seed
, seedLen
, aSubI
, &digestLen
);
122 assert(digestLen
= hmac
->macSize
);
124 /* starting at loopNum 1... */
127 * This loop's chunk = HMAC_hash(secret, A(loopNum) + seed))
129 serr
= hmac
->init(hmacCtx
);
133 serr
= hmac
->update(hmacCtx
, aSubI
, digestLen
);
137 serr
= hmac
->update(hmacCtx
, seed
, seedLen
);
141 serr
= hmac
->final(hmacCtx
, digest
, &digestLen
);
145 assert(digestLen
= hmac
->macSize
);
147 if(outLen
<= digestLen
) {
148 /* last time, possible partial digest */
149 memmove(out
, digest
, outLen
);
153 memmove(out
, digest
, digestLen
);
158 * A(i) = HMAC_hash(secret, A(i-1))
159 * Note there is a possible optimization involving obtaining this
160 * hmac by cloning the state of hmacCtx above after updating with
161 * aSubI, and getting the final version of that here. However CDSA
162 * does not support cloning of a MAC context (only for digest contexts).
164 serr
= hmac
->hmac(hmacCtx
, aSubI
, digestLen
,
169 assert(digestLen
= hmac
->macSize
);
173 memset(aSubI
, 0, TLS_HMAC_MAX_SIZE
);
174 memset(digest
, 0, TLS_HMAC_MAX_SIZE
);
179 * The TLS pseudorandom function, defined in RFC2246, section 5.
180 * This takes as its input a secret block, a label, and a seed, and produces
181 * a caller-specified length of pseudorandom data.
183 * Optimization TBD: make label optional, avoid malloc and two copies if it's
184 * not there, so callers can take advantage of fixed-size seeds.
186 OSStatus
SSLInternal_PRF(
190 const void *label
, // optional, NULL implies that seed contains
195 void *vout
, // mallocd by caller, length >= outLen
198 OSStatus serr
= errSSLInternal
;
199 const unsigned char *S1
, *S2
; // the two seeds
200 size_t sLen
; // effective length of each seed
201 unsigned char *labelSeed
= NULL
; // label + seed, passed to tlsPHash
203 unsigned char *tmpOut
= NULL
; // output of P_SHA1
205 const unsigned char *secret
= (const unsigned char *)vsecret
;
208 /* concatenate label and seed */
209 labelSeedLen
= labelLen
+ seedLen
;
210 labelSeed
= (unsigned char *)sslMalloc(labelSeedLen
);
211 if(labelSeed
== NULL
) {
212 return errSecAllocate
;
214 memmove(labelSeed
, label
, labelLen
);
215 memmove(labelSeed
+ labelLen
, seed
, seedLen
);
218 /* fast track - just use seed as is */
219 labelSeed
= (unsigned char *)seed
;
220 labelSeedLen
= seedLen
;
223 unsigned char *out
= (unsigned char *)vout
;
224 if(sslVersionIsLikeTls12(ctx
)) {
225 const HMACReference
*mac
= &TlsHmacSHA256
;
226 if (ctx
->selectedCipherSpecParams
.macAlg
== HA_SHA384
) {
227 mac
= &TlsHmacSHA384
;
229 serr
= tlsPHash(ctx
, mac
, secret
, secretLen
, labelSeed
, labelSeedLen
,
235 /* two seeds for tlsPHash */
236 sLen
= secretLen
/ 2; // for partitioning
239 sLen
+= (secretLen
& 1); // secret length odd, increment effective size
241 /* temporary output for SHA1, to be XORd with MD5 */
242 tmpOut
= (unsigned char *)sslMalloc(outLen
);
244 serr
= errSecAllocate
;
248 serr
= tlsPHash(ctx
, &TlsHmacMD5
, S1
, sLen
, labelSeed
, labelSeedLen
,
253 serr
= tlsPHash(ctx
, &TlsHmacSHA1
, S2
, sLen
, labelSeed
, labelSeedLen
,
259 /* XOR together to get final result */
260 for(i
=0; i
<outLen
; i
++) {
265 serr
= errSecSuccess
;
267 if((labelSeed
!= NULL
) && (label
!= NULL
)) {
277 * On input, the following are valid:
279 * ClientHello.random[32]
280 * ServerHello.random[32]
282 * key_block = PRF(SecurityParameters.master_secret,
284 * SecurityParameters.server_random +
285 * SecurityParameters.client_random);
288 #define GKM_SEED_LEN (PLS_KEY_EXPAND_LEN + (2 * SSL_CLIENT_SRVR_RAND_SIZE))
290 static OSStatus
tls1GenerateKeyMaterial (
291 SSLBuffer key
, // caller mallocs and specifies length of
292 // required key material here
295 unsigned char seedBuf
[GKM_SEED_LEN
];
298 /* use optimized label-less PRF */
299 memmove(seedBuf
, PLS_KEY_EXPAND
, PLS_KEY_EXPAND_LEN
);
300 memmove(seedBuf
+ PLS_KEY_EXPAND_LEN
, ctx
->serverRandom
,
301 SSL_CLIENT_SRVR_RAND_SIZE
);
302 memmove(seedBuf
+ PLS_KEY_EXPAND_LEN
+ SSL_CLIENT_SRVR_RAND_SIZE
,
303 ctx
->clientRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
304 serr
= SSLInternal_PRF(ctx
,
306 SSL_MASTER_SECRET_SIZE
,
311 key
.data
, // destination
313 tlsDump("key expansion", key
.data
, key
.length
);
318 * On entry: clientRandom, serverRandom, preMasterSecret valid
319 * On return: masterSecret valid
321 * master_secret = PRF(pre_master_secret, "master secret",
322 * ClientHello.random + ServerHello.random)
326 static OSStatus
tls1GenerateMasterSecret (
329 unsigned char randBuf
[2 * SSL_CLIENT_SRVR_RAND_SIZE
];
332 memmove(randBuf
, ctx
->clientRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
333 memmove(randBuf
+ SSL_CLIENT_SRVR_RAND_SIZE
,
334 ctx
->serverRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
335 serr
= SSLInternal_PRF(ctx
,
336 ctx
->preMasterSecret
.data
,
337 ctx
->preMasterSecret
.length
,
338 (const unsigned char *)PLS_MASTER_SECRET
,
339 PLS_MASTER_SECRET_LEN
,
341 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
342 ctx
->masterSecret
, // destination
343 SSL_MASTER_SECRET_SIZE
);
344 tlsDump("master secret", ctx
->masterSecret
, SSL_MASTER_SECRET_SIZE
);
349 * Given digests contexts representing the running total of all handshake messages,
350 * calculate mac for "finished" message.
352 * verify_data = 12 bytes =
353 * PRF(master_secret, finished_label, MD5(handshake_messages) +
354 * SHA-1(handshake_messages)) [0..11];
356 static OSStatus
tls1ComputeFinishedMac (
358 SSLBuffer finished
, // output - mallocd by caller
361 unsigned char digests
[SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
];
364 unsigned finLabelLen
;
366 SSLBuffer shaMsgState
, md5MsgState
;
368 shaMsgState
.data
= 0;
369 md5MsgState
.data
= 0;
370 if ((serr
= CloneHashState(&SSLHashSHA1
, &ctx
->shaState
, &shaMsgState
)) != 0)
372 if ((serr
= CloneHashState(&SSLHashMD5
, &ctx
->md5State
, &md5MsgState
)) != 0)
376 finLabel
= PLS_SERVER_FINISH
;
377 finLabelLen
= PLS_SERVER_FINISH_LEN
;
380 finLabel
= PLS_CLIENT_FINISH
;
381 finLabelLen
= PLS_CLIENT_FINISH_LEN
;
384 /* concatenate two digest results */
385 digBuf
.data
= digests
;
386 digBuf
.length
= SSL_MD5_DIGEST_LEN
;
387 serr
= SSLHashMD5
.final(&md5MsgState
, &digBuf
);
391 digBuf
.data
+= SSL_MD5_DIGEST_LEN
;
392 digBuf
.length
= SSL_SHA1_DIGEST_LEN
;
393 serr
= SSLHashSHA1
.final(&shaMsgState
, &digBuf
);
397 serr
= SSLInternal_PRF(ctx
,
399 SSL_MASTER_SECRET_SIZE
,
400 (const unsigned char *)finLabel
,
403 SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
,
404 finished
.data
, // destination
408 SSLFreeBuffer(&shaMsgState
);
409 SSLFreeBuffer(&md5MsgState
);
415 * Given digests contexts representing the running total of all handshake messages,
416 * calculate mac for "finished" message.
418 * verify_data = 12 bytes =
419 * PRF(master_secret, finished_label, SHA256(handshake_messages)) [0..11];
421 static OSStatus
tls12ComputeFinishedMac (
423 SSLBuffer finished
, // output - mallocd by caller
426 unsigned char digest
[SSL_MAX_DIGEST_LEN
];
429 unsigned finLabelLen
;
432 const HashReference
*hashRef
;
433 const SSLBuffer
*ctxHashState
;
435 /* The PRF used in the finished message is based on the cipherspec */
436 if (ctx
->selectedCipherSpecParams
.macAlg
== HA_SHA384
) {
437 hashRef
= &SSLHashSHA384
;
438 ctxHashState
= &ctx
->sha512State
;
440 hashRef
= &SSLHashSHA256
;
441 ctxHashState
= &ctx
->sha256State
;
445 if ((serr
= CloneHashState(hashRef
, ctxHashState
, &hashState
)) != 0)
448 finLabel
= PLS_SERVER_FINISH
;
449 finLabelLen
= PLS_SERVER_FINISH_LEN
;
452 finLabel
= PLS_CLIENT_FINISH
;
453 finLabelLen
= PLS_CLIENT_FINISH_LEN
;
456 /* concatenate two digest results */
457 digBuf
.data
= digest
;
458 digBuf
.length
= hashRef
->digestSize
;
459 if ((serr
= hashRef
->final(&hashState
, &digBuf
)) != 0)
461 serr
= SSLInternal_PRF(ctx
,
463 SSL_MASTER_SECRET_SIZE
,
464 (const unsigned char *)finLabel
,
468 finished
.data
, // destination
471 SSLFreeBuffer(&hashState
);
476 * This one is trivial.
478 * mac := MD5(handshake_messages) + SHA(handshake_messages);
480 * I don't know why this one doesn't use an HMAC or the master secret (as SSLv3
483 static OSStatus
tls1ComputeCertVfyMac (
485 SSLBuffer
*finished
, // output - mallocd by caller
486 SSL_HashAlgorithm hash
) //unused in this one
488 SSLBuffer digBuf
, shaMsgState
, md5MsgState
;
491 shaMsgState
.data
= 0;
492 md5MsgState
.data
= 0;
494 if ((serr
= CloneHashState(&SSLHashSHA1
, &ctx
->shaState
, &shaMsgState
)) != 0)
496 if ((serr
= CloneHashState(&SSLHashMD5
, &ctx
->md5State
, &md5MsgState
)) != 0)
499 if ((ctx
->protocolSide
== kSSLServerSide
&& sslPubKeyGetAlgorithmID(ctx
->peerPubKey
) == kSecECDSAAlgorithmID
) ||
500 (ctx
->protocolSide
== kSSLClientSide
&& ctx
->negAuthType
== SSLClientAuth_ECDSASign
)) {
501 /* Only take SHA1 regardless of TLSv1.0 or TLSv1.1 If we are the server
502 and our peer signed with an ECDSA key, or if we are the client and
503 are about to sign with ECDSA. */
504 assert(finished
->length
>= SSL_SHA1_DIGEST_LEN
);
505 digBuf
.data
= finished
->data
;
506 finished
->length
= SSL_SHA1_DIGEST_LEN
;
508 /* Put MD5 follow by SHA1 hash in buffer. */
509 assert(finished
->length
>= (SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
));
510 digBuf
.data
= finished
->data
;
511 digBuf
.length
= SSL_MD5_DIGEST_LEN
;
512 if ((serr
= SSLHashMD5
.final(&md5MsgState
, &digBuf
)) != 0)
514 digBuf
.data
= finished
->data
+ SSL_MD5_DIGEST_LEN
;
515 finished
->length
= SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
;
518 digBuf
.length
= SSL_SHA1_DIGEST_LEN
;
519 serr
= SSLHashSHA1
.final(&shaMsgState
, &digBuf
);
522 SSLFreeBuffer(&shaMsgState
);
523 SSLFreeBuffer(&md5MsgState
);
528 static OSStatus
tls12ComputeCertVfyMac (
530 SSLBuffer
*finished
, // output - mallocd by caller
531 SSL_HashAlgorithm hash
)
533 const SSLBuffer
*ctxHashState
;
534 const HashReference
*hashRef
;
541 case SSL_HashAlgorithmSHA1
:
542 hashRef
= &SSLHashSHA1
;
543 ctxHashState
= &ctx
->shaState
;
545 case SSL_HashAlgorithmSHA256
:
546 hashRef
= &SSLHashSHA256
;
547 ctxHashState
= &ctx
->sha256State
;
549 case SSL_HashAlgorithmSHA384
:
550 hashRef
= &SSLHashSHA384
;
551 ctxHashState
= &ctx
->sha512State
;
554 return errSSLInternal
;
558 if ((serr
= CloneHashState(hashRef
, ctxHashState
, &hashState
)) != 0)
561 assert(finished
->length
>= (hashRef
->digestSize
));
562 finished
->length
= hashRef
->digestSize
;
563 serr
= hashRef
->final(&hashState
, finished
);
566 SSLFreeBuffer(&hashState
);
572 const SslTlsCallouts Tls1Callouts
= {
573 tls1GenerateKeyMaterial
,
574 tls1GenerateMasterSecret
,
575 tls1ComputeFinishedMac
,
576 tls1ComputeCertVfyMac
579 const SslTlsCallouts Tls12Callouts
= {
580 tls1GenerateKeyMaterial
,
581 tls1GenerateMasterSecret
,
582 tls12ComputeFinishedMac
,
583 tls12ComputeCertVfyMac