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  * ssl3Callouts.c - SSLv3-specific routines for SslTlsCallouts. 
  28 #include "sslMemory.h" 
  31 #include "sslDigests.h" 
  33 #include "sslAlertMessage.h" 
  42  * On input, the following are valid: 
  44  *              ClientHello.random[32] 
  45  *      ServerHello.random[32] 
  48  *               MD5(master_secret + SHA(`A' + master_secret + 
  49  *                              ServerHello.random + 
  50  *                              ClientHello.random)) + 
  51  *              MD5(master_secret + SHA(`BB' + master_secret + 
  52  *                              ServerHello.random + 
  53  *                              ClientHello.random)) + 
  54  *              MD5(master_secret + SHA(`CCC' + master_secret + 
  55  *                              ServerHello.random + 
  56  *                              ClientHello.random)) + [...]; 
  58 static OSStatus 
ssl3GenerateKeyMaterial ( 
  59         SSLBuffer key
,                                  // caller mallocs and specifies length of 
  60                                                                         //   required key material here 
  64     UInt8       leaderData
[10];     /* Max of 10 hashes 
  65                                                                          * (* 16 bytes/hash = 160 bytes of key) */ 
  66     UInt8       shaHashData
[20], md5HashData
[16]; 
  67     SSLBuffer   shaContext
, md5Context
; 
  69     size_t      i
,j
,remaining
, satisfied
; 
  70     SSLBuffer   leader
, masterSecret
, serverRandom
, clientRandom
, shaHash
, md5Hash
; 
  73         printf("GenerateKey: master "); 
  74         for(i
=0; i
<SSL_MASTER_SECRET_SIZE
; i
++) { 
  75                 printf("%02X ", ctx
->masterSecret
[i
]); 
  80     assert(key
.length 
<= 16 * sizeof(leaderData
)); 
  82     leader
.data 
= leaderData
; 
  83     masterSecret
.data 
= ctx
->masterSecret
; 
  84     masterSecret
.length 
= SSL_MASTER_SECRET_SIZE
; 
  85     serverRandom
.data 
= ctx
->serverRandom
; 
  86     serverRandom
.length 
= SSL_CLIENT_SRVR_RAND_SIZE
; 
  87     clientRandom
.data 
= ctx
->clientRandom
; 
  88     clientRandom
.length 
= SSL_CLIENT_SRVR_RAND_SIZE
; 
  89     shaHash
.data 
= shaHashData
; 
  91     md5Hash
.data 
= md5HashData
; 
  96     if ((err 
= ReadyHash(&SSLHashMD5
, &md5Context
)) != 0) 
  98     if ((err 
= ReadyHash(&SSLHashSHA1
, &shaContext
)) != 0) 
 101     keyProgress 
= key
.data
; 
 102     remaining 
= key
.length
; 
 104     for (i 
= 0; remaining 
> 0; ++i
) 
 105     {   for (j 
= 0; j 
<= i
; j
++) 
 106             leaderData
[j
] = 0x41 + i
;   /* 'A', 'BB', 'CCC', etc. */ 
 109         if ((err 
= SSLHashSHA1
.update(&shaContext
, &leader
)) != 0) 
 111         if ((err 
= SSLHashSHA1
.update(&shaContext
, &masterSecret
)) != 0) 
 113         if ((err 
= SSLHashSHA1
.update(&shaContext
, &serverRandom
)) != 0) 
 115         if ((err 
= SSLHashSHA1
.update(&shaContext
, &clientRandom
)) != 0) 
 117         if ((err 
= SSLHashSHA1
.final(&shaContext
, &shaHash
)) != 0) 
 119         if ((err 
= SSLHashMD5
.update(&md5Context
, &masterSecret
)) != 0) 
 121         if ((err 
= SSLHashMD5
.update(&md5Context
, &shaHash
)) != 0) 
 123         if ((err 
= SSLHashMD5
.final(&md5Context
, &md5Hash
)) != 0) 
 128             satisfied 
= remaining
; 
 129         memcpy(keyProgress
, md5HashData
, satisfied
); 
 130         remaining 
-= satisfied
; 
 131         keyProgress 
+= satisfied
; 
 134                         /* at top of loop, this was done in ReadyHash() */ 
 135                         if ((err 
= SSLHashMD5
.init(&md5Context
)) != 0) 
 137                         if ((err 
= SSLHashSHA1
.init(&shaContext
)) != 0) 
 142     assert(remaining 
== 0 && keyProgress 
== (key
.data 
+ key
.length
)); 
 145     SSLFreeBuffer(&md5Context
); 
 146     SSLFreeBuffer(&shaContext
); 
 149         printf("GenerateKey: DONE\n"); 
 155  * On entry: clientRandom, serverRandom, preMasterSecret valid 
 156  * On return: masterSecret valid 
 158 static OSStatus 
ssl3GenerateMasterSecret ( 
 162     SSLBuffer   shaState
, md5State
, clientRandom
, 
 163                 serverRandom
, shaHash
, md5Hash
, leader
; 
 164     UInt8       
*masterProgress
, shaHashData
[20], leaderData
[3]; 
 167     md5State
.data 
= shaState
.data 
= 0; 
 168     if ((err 
= SSLAllocBuffer(&md5State
, SSLHashMD5
.contextSize
))) 
 170     if ((err 
= SSLAllocBuffer(&shaState
, SSLHashSHA1
.contextSize
))) 
 173     clientRandom
.data 
= ctx
->clientRandom
; 
 174     clientRandom
.length 
= SSL_CLIENT_SRVR_RAND_SIZE
; 
 175     serverRandom
.data 
= ctx
->serverRandom
; 
 176     serverRandom
.length 
= SSL_CLIENT_SRVR_RAND_SIZE
; 
 177     shaHash
.data 
= shaHashData
; 
 180     masterProgress 
= ctx
->masterSecret
; 
 182     for (i 
= 1; i 
<= 3; i
++) 
 183     {   if ((err 
= SSLHashMD5
.init(&md5State
)) != 0) 
 185         if ((err 
= SSLHashSHA1
.init(&shaState
)) != 0) 
 188         leaderData
[0] = leaderData
[1] = leaderData
[2] = 0x40 + i
;   /* 'A', 'B', etc. */ 
 189         leader
.data 
= leaderData
; 
 192         if ((err 
= SSLHashSHA1
.update(&shaState
, &leader
)) != 0) 
 194         if ((err 
= SSLHashSHA1
.update(&shaState
, &ctx
->preMasterSecret
)) != 0) 
 196         if ((err 
= SSLHashSHA1
.update(&shaState
, &clientRandom
)) != 0) 
 198         if ((err 
= SSLHashSHA1
.update(&shaState
, &serverRandom
)) != 0) 
 200         if ((err 
= SSLHashSHA1
.final(&shaState
, &shaHash
)) != 0) 
 202         if ((err 
= SSLHashMD5
.update(&md5State
, &ctx
->preMasterSecret
)) != 0) 
 204         if ((err 
= SSLHashMD5
.update(&md5State
, &shaHash
)) != 0) 
 206         md5Hash
.data 
= masterProgress
; 
 208         if ((err 
= SSLHashMD5
.final(&md5State
, &md5Hash
)) != 0) 
 210         masterProgress 
+= 16; 
 215     SSLFreeBuffer(&shaState
); 
 216     SSLFreeBuffer(&md5State
); 
 220 /* common routine to compute a Mac for finished message and cert verify message */ 
 222 ssl3CalculateFinishedMessage( 
 224         SSLBuffer finished
,             // mallocd by caller 
 225         SSLBuffer shaMsgState
,          // running total 
 226         SSLBuffer md5MsgState
,          // ditto 
 227         UInt32 senderID
)                        // optional, nonzero for finished message 
 230     SSLBuffer       hash
, input
; 
 231     UInt8           sender
[4], md5Inner
[16], shaInner
[20]; 
 233     // assert(finished.length == 36); 
 236                 SSLEncodeInt(sender
, senderID
, 4); 
 239         if ((err 
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0) 
 241         if ((err 
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0) 
 244     input
.data 
= ctx
->masterSecret
; 
 245     input
.length 
= SSL_MASTER_SECRET_SIZE
; 
 246     if ((err 
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0) 
 248     if ((err 
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0) 
 250     input
.data 
= (UInt8 
*)SSLMACPad1
; 
 251     input
.length 
= SSLHashMD5
.macPadSize
; 
 252     if ((err 
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0) 
 254     input
.length 
= SSLHashSHA1
.macPadSize
; 
 255     if ((err 
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0) 
 257     hash
.data 
= md5Inner
; 
 259     if ((err 
= SSLHashMD5
.final(&md5MsgState
, &hash
)) != 0) 
 261     hash
.data 
= shaInner
; 
 263     if ((err 
= SSLHashSHA1
.final(&shaMsgState
, &hash
)) != 0) 
 265     if ((err 
= SSLHashMD5
.init(&md5MsgState
)) != 0) 
 267     if ((err 
= SSLHashSHA1
.init(&shaMsgState
)) != 0) 
 269     input
.data 
= ctx
->masterSecret
; 
 270     input
.length 
= SSL_MASTER_SECRET_SIZE
; 
 271     if ((err 
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0) 
 273     if ((err 
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0) 
 275     input
.data 
= (UInt8 
*)SSLMACPad2
; 
 276     input
.length 
= SSLHashMD5
.macPadSize
; 
 277     if ((err 
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0) 
 279     input
.length 
= SSLHashSHA1
.macPadSize
; 
 280     if ((err 
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0) 
 282     input
.data 
= md5Inner
; 
 284     if ((err 
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0) 
 286     hash
.data 
= finished
.data
; 
 288     if ((err 
= SSLHashMD5
.final(&md5MsgState
, &hash
)) != 0) 
 290     input
.data 
= shaInner
; 
 292     if ((err 
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0) 
 294     hash
.data 
= finished
.data 
+ 16; 
 296     if ((err 
= SSLHashSHA1
.final(&shaMsgState
, &hash
)) != 0) 
 304 static OSStatus 
ssl3ComputeFinishedMac ( 
 306         SSLBuffer finished
,             // output - mallocd by caller 
 307         Boolean isServer
)                       // refers to message, not us 
 310     SSLBuffer shaMsgState
, md5MsgState
; 
 312     shaMsgState
.data 
= 0; 
 313     md5MsgState
.data 
= 0; 
 314     if ((serr 
= CloneHashState(&SSLHashSHA1
, &ctx
->shaState
, &shaMsgState
)) != 0) 
 316     if ((serr 
= CloneHashState(&SSLHashMD5
, &ctx
->md5State
, &md5MsgState
)) != 0) 
 319         serr 
= ssl3CalculateFinishedMessage(ctx
, finished
, shaMsgState
, md5MsgState
, 
 320                 isServer 
? SSL_Finished_Sender_Server 
: SSL_Finished_Sender_Client
); 
 323     SSLFreeBuffer(&shaMsgState
); 
 324     SSLFreeBuffer(&md5MsgState
); 
 329 /* TODO: Factor this and ssl3ComputeFinishedMac to share more common code. */ 
 330 static OSStatus 
ssl3ComputeCertVfyMac ( 
 332         SSLBuffer 
*finished
,            // output - mallocd by caller 
 333     SSL_HashAlgorithm hash
)     //unused in this one 
 336     SSLBuffer shaMsgState
, md5MsgState
; 
 338     shaMsgState
.data 
= 0; 
 339     md5MsgState
.data 
= 0; 
 340     if ((serr 
= CloneHashState(&SSLHashSHA1
, &ctx
->shaState
, &shaMsgState
)) != 0) 
 342     if ((serr 
= CloneHashState(&SSLHashMD5
, &ctx
->md5State
, &md5MsgState
)) != 0) 
 345     assert(finished
->length 
>= SSL_MD5_DIGEST_LEN 
+ SSL_SHA1_DIGEST_LEN
); 
 346     finished
->length 
= SSL_MD5_DIGEST_LEN 
+ SSL_SHA1_DIGEST_LEN
; 
 348         serr 
= ssl3CalculateFinishedMessage(ctx
, *finished
, shaMsgState
, md5MsgState
, 0); 
 351     SSLFreeBuffer(&shaMsgState
); 
 352     SSLFreeBuffer(&md5MsgState
); 
 357 const SslTlsCallouts Ssl3Callouts 
= { 
 358         ssl3GenerateKeyMaterial
, 
 359         ssl3GenerateMasterSecret
, 
 360         ssl3ComputeFinishedMac
, 
 361         ssl3ComputeCertVfyMac