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