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