]> git.saurik.com Git - apple/security.git/blob - libsecurity_ssl/lib/ssl3Callouts.c
Security-55471.14.tar.gz
[apple/security.git] / libsecurity_ssl / lib / ssl3Callouts.c
1 /*
2 * Copyright (c) 2002,2005-2007,2010-2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * ssl3Callouts.c - SSLv3-specific routines for SslTlsCallouts.
26 */
27
28 #include "sslMemory.h"
29 #include "tls_ssl.h"
30 #include "sslUtils.h"
31 #include "sslDigests.h"
32 #include "sslDebug.h"
33 #include "sslAlertMessage.h"
34
35 #include <assert.h>
36 #include <strings.h>
37 #include <stddef.h>
38
39 #define LOG_GEN_KEY 0
40
41 /*
42 * On input, the following are valid:
43 * MasterSecret[48]
44 * ClientHello.random[32]
45 * ServerHello.random[32]
46 *
47 * key_block =
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)) + [...];
57 */
58 static OSStatus ssl3GenerateKeyMaterial (
59 SSLBuffer key, // caller mallocs and specifies length of
60 // required key material here
61 SSLContext *ctx)
62 {
63 OSStatus err;
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;
68 UInt8 *keyProgress;
69 size_t i,j,remaining, satisfied;
70 SSLBuffer leader, masterSecret, serverRandom, clientRandom, shaHash, md5Hash;
71
72 #if LOG_GEN_KEY
73 printf("GenerateKey: master ");
74 for(i=0; i<SSL_MASTER_SECRET_SIZE; i++) {
75 printf("%02X ", ctx->masterSecret[i]);
76 }
77 printf("\n");
78 #endif
79
80 assert(key.length <= 16 * sizeof(leaderData));
81
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;
90 shaHash.length = 20;
91 md5Hash.data = md5HashData;
92 md5Hash.length = 16;
93
94 md5Context.data = 0;
95 shaContext.data = 0;
96 if ((err = ReadyHash(&SSLHashMD5, &md5Context)) != 0)
97 goto fail;
98 if ((err = ReadyHash(&SSLHashSHA1, &shaContext)) != 0)
99 goto fail;
100
101 keyProgress = key.data;
102 remaining = key.length;
103
104 for (i = 0; remaining > 0; ++i)
105 { for (j = 0; j <= i; j++)
106 leaderData[j] = 0x41 + i; /* 'A', 'BB', 'CCC', etc. */
107 leader.length = i+1;
108
109 if ((err = SSLHashSHA1.update(&shaContext, &leader)) != 0)
110 goto fail;
111 if ((err = SSLHashSHA1.update(&shaContext, &masterSecret)) != 0)
112 goto fail;
113 if ((err = SSLHashSHA1.update(&shaContext, &serverRandom)) != 0)
114 goto fail;
115 if ((err = SSLHashSHA1.update(&shaContext, &clientRandom)) != 0)
116 goto fail;
117 if ((err = SSLHashSHA1.final(&shaContext, &shaHash)) != 0)
118 goto fail;
119 if ((err = SSLHashMD5.update(&md5Context, &masterSecret)) != 0)
120 goto fail;
121 if ((err = SSLHashMD5.update(&md5Context, &shaHash)) != 0)
122 goto fail;
123 if ((err = SSLHashMD5.final(&md5Context, &md5Hash)) != 0)
124 goto fail;
125
126 satisfied = 16;
127 if (remaining < 16)
128 satisfied = remaining;
129 memcpy(keyProgress, md5HashData, satisfied);
130 remaining -= satisfied;
131 keyProgress += satisfied;
132
133 if(remaining > 0) {
134 /* at top of loop, this was done in ReadyHash() */
135 if ((err = SSLHashMD5.init(&md5Context)) != 0)
136 goto fail;
137 if ((err = SSLHashSHA1.init(&shaContext)) != 0)
138 goto fail;
139 }
140 }
141
142 assert(remaining == 0 && keyProgress == (key.data + key.length));
143 err = errSecSuccess;
144 fail:
145 SSLFreeBuffer(&md5Context);
146 SSLFreeBuffer(&shaContext);
147
148 #if LOG_GEN_KEY
149 printf("GenerateKey: DONE\n");
150 #endif
151 return err;
152 }
153
154 /*
155 * On entry: clientRandom, serverRandom, preMasterSecret valid
156 * On return: masterSecret valid
157 */
158 static OSStatus ssl3GenerateMasterSecret (
159 SSLContext *ctx)
160 {
161 OSStatus err;
162 SSLBuffer shaState, md5State, clientRandom,
163 serverRandom, shaHash, md5Hash, leader;
164 UInt8 *masterProgress, shaHashData[20], leaderData[3];
165 int i;
166
167 md5State.data = shaState.data = 0;
168 if ((err = SSLAllocBuffer(&md5State, SSLHashMD5.contextSize)))
169 goto fail;
170 if ((err = SSLAllocBuffer(&shaState, SSLHashSHA1.contextSize)))
171 goto fail;
172
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;
178 shaHash.length = 20;
179
180 masterProgress = ctx->masterSecret;
181
182 for (i = 1; i <= 3; i++)
183 { if ((err = SSLHashMD5.init(&md5State)) != 0)
184 goto fail;
185 if ((err = SSLHashSHA1.init(&shaState)) != 0)
186 goto fail;
187
188 leaderData[0] = leaderData[1] = leaderData[2] = 0x40 + i; /* 'A', 'B', etc. */
189 leader.data = leaderData;
190 leader.length = i;
191
192 if ((err = SSLHashSHA1.update(&shaState, &leader)) != 0)
193 goto fail;
194 if ((err = SSLHashSHA1.update(&shaState, &ctx->preMasterSecret)) != 0)
195 goto fail;
196 if ((err = SSLHashSHA1.update(&shaState, &clientRandom)) != 0)
197 goto fail;
198 if ((err = SSLHashSHA1.update(&shaState, &serverRandom)) != 0)
199 goto fail;
200 if ((err = SSLHashSHA1.final(&shaState, &shaHash)) != 0)
201 goto fail;
202 if ((err = SSLHashMD5.update(&md5State, &ctx->preMasterSecret)) != 0)
203 goto fail;
204 if ((err = SSLHashMD5.update(&md5State, &shaHash)) != 0)
205 goto fail;
206 md5Hash.data = masterProgress;
207 md5Hash.length = 16;
208 if ((err = SSLHashMD5.final(&md5State, &md5Hash)) != 0)
209 goto fail;
210 masterProgress += 16;
211 }
212
213 err = errSecSuccess;
214 fail:
215 SSLFreeBuffer(&shaState);
216 SSLFreeBuffer(&md5State);
217 return err;
218 }
219
220 /* common routine to compute a Mac for finished message and cert verify message */
221 static OSStatus
222 ssl3CalculateFinishedMessage(
223 SSLContext *ctx,
224 SSLBuffer finished, // mallocd by caller
225 SSLBuffer shaMsgState, // running total
226 SSLBuffer md5MsgState, // ditto
227 UInt32 senderID) // optional, nonzero for finished message
228 {
229 OSStatus err;
230 SSLBuffer hash, input;
231 UInt8 sender[4], md5Inner[16], shaInner[20];
232
233 // assert(finished.length == 36);
234
235 if (senderID != 0) {
236 SSLEncodeInt(sender, senderID, 4);
237 input.data = sender;
238 input.length = 4;
239 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
240 goto fail;
241 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
242 goto fail;
243 }
244 input.data = ctx->masterSecret;
245 input.length = SSL_MASTER_SECRET_SIZE;
246 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
247 goto fail;
248 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
249 goto fail;
250 input.data = (UInt8 *)SSLMACPad1;
251 input.length = SSLHashMD5.macPadSize;
252 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
253 goto fail;
254 input.length = SSLHashSHA1.macPadSize;
255 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
256 goto fail;
257 hash.data = md5Inner;
258 hash.length = 16;
259 if ((err = SSLHashMD5.final(&md5MsgState, &hash)) != 0)
260 goto fail;
261 hash.data = shaInner;
262 hash.length = 20;
263 if ((err = SSLHashSHA1.final(&shaMsgState, &hash)) != 0)
264 goto fail;
265 if ((err = SSLHashMD5.init(&md5MsgState)) != 0)
266 goto fail;
267 if ((err = SSLHashSHA1.init(&shaMsgState)) != 0)
268 goto fail;
269 input.data = ctx->masterSecret;
270 input.length = SSL_MASTER_SECRET_SIZE;
271 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
272 goto fail;
273 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
274 goto fail;
275 input.data = (UInt8 *)SSLMACPad2;
276 input.length = SSLHashMD5.macPadSize;
277 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
278 goto fail;
279 input.length = SSLHashSHA1.macPadSize;
280 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
281 goto fail;
282 input.data = md5Inner;
283 input.length = 16;
284 if ((err = SSLHashMD5.update(&md5MsgState, &input)) != 0)
285 goto fail;
286 hash.data = finished.data;
287 hash.length = 16;
288 if ((err = SSLHashMD5.final(&md5MsgState, &hash)) != 0)
289 goto fail;
290 input.data = shaInner;
291 input.length = 20;
292 if ((err = SSLHashSHA1.update(&shaMsgState, &input)) != 0)
293 goto fail;
294 hash.data = finished.data + 16;
295 hash.length = 20;
296 if ((err = SSLHashSHA1.final(&shaMsgState, &hash)) != 0)
297 goto fail;
298
299 fail:
300 return err;
301 }
302
303
304 static OSStatus ssl3ComputeFinishedMac (
305 SSLContext *ctx,
306 SSLBuffer finished, // output - mallocd by caller
307 Boolean isServer) // refers to message, not us
308 {
309 OSStatus serr;
310 SSLBuffer shaMsgState, md5MsgState;
311
312 shaMsgState.data = 0;
313 md5MsgState.data = 0;
314 if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState)) != 0)
315 goto fail;
316 if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState)) != 0)
317 goto fail;
318
319 serr = ssl3CalculateFinishedMessage(ctx, finished, shaMsgState, md5MsgState,
320 isServer ? SSL_Finished_Sender_Server : SSL_Finished_Sender_Client);
321
322 fail:
323 SSLFreeBuffer(&shaMsgState);
324 SSLFreeBuffer(&md5MsgState);
325
326 return serr;
327 }
328
329 /* TODO: Factor this and ssl3ComputeFinishedMac to share more common code. */
330 static OSStatus ssl3ComputeCertVfyMac (
331 SSLContext *ctx,
332 SSLBuffer *finished, // output - mallocd by caller
333 SSL_HashAlgorithm hash) //unused in this one
334 {
335 OSStatus serr;
336 SSLBuffer shaMsgState, md5MsgState;
337
338 shaMsgState.data = 0;
339 md5MsgState.data = 0;
340 if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState)) != 0)
341 goto fail;
342 if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState)) != 0)
343 goto fail;
344
345 assert(finished->length >= SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN);
346 finished->length = SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN;
347
348 serr = ssl3CalculateFinishedMessage(ctx, *finished, shaMsgState, md5MsgState, 0);
349
350 fail:
351 SSLFreeBuffer(&shaMsgState);
352 SSLFreeBuffer(&md5MsgState);
353
354 return serr;
355 }
356
357 const SslTlsCallouts Ssl3Callouts = {
358 ssl3GenerateKeyMaterial,
359 ssl3GenerateMasterSecret,
360 ssl3ComputeFinishedMac,
361 ssl3ComputeCertVfyMac
362 };