]> git.saurik.com Git - apple/security.git/blob - SecureTransport/hdskkeys.c
Security-28.tar.gz
[apple/security.git] / SecureTransport / hdskkeys.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 File: hdskkeys.c
21
22 Contains: Key calculation and encoding
23
24 Written by: Doug Mitchell, based on Netscape SSLRef 3.0
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29 /* *********************************************************************
30 File: hdskkeys.c
31
32 SSLRef 3.0 Final -- 11/19/96
33
34 Copyright (c)1996 by Netscape Communications Corp.
35
36 By retrieving this software you are bound by the licensing terms
37 disclosed in the file "LICENSE.txt". Please read it, and if you don't
38 accept the terms, delete this software.
39
40 SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
41 View, California <http://home.netscape.com/> and Consensus Development
42 Corporation of Berkeley, California <http://www.consensus.com/>.
43
44 *********************************************************************
45
46 File: hdskkeys.c Key calculation and encoding
47
48 Contains code for encoding premaster secrets, generating master
49 secrets from premaster secrets & key data generation from master
50 secrets and following initialization of ciphers.
51
52 ****************************************************************** */
53
54 #ifndef _SSLCTX_H_
55 #include "sslctx.h"
56 #endif
57
58 #ifndef _SSLHDSHK_H_
59 #include "sslhdshk.h"
60 #endif
61
62 #ifndef _SSLALLOC_H_
63 #include "sslalloc.h"
64 #endif
65
66 #ifndef _SSL_DEBUG_H_
67 #include "sslDebug.h"
68 #endif
69
70 #ifndef _SSLUTIL_H_
71 #include "sslutil.h"
72 #endif
73
74 #ifndef _APPLE_CDSA_H_
75 #include "appleCdsa.h"
76 #endif
77
78 #ifndef _DIGESTS_H_
79 #include "digests.h"
80 #endif
81
82 #include <string.h>
83
84 static SSLErr SSLGenerateKeyMaterial(SSLBuffer key, SSLContext *ctx);
85
86 SSLErr
87 SSLEncodeRSAPremasterSecret(SSLContext *ctx)
88 { SSLBuffer randData;
89 SSLErr err;
90
91 if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, 48, &ctx->sysCtx)) != 0)
92 return err;
93
94 SSLEncodeInt(ctx->preMasterSecret.data, SSL_Version_3_0, 2);
95 randData.data = ctx->preMasterSecret.data+2;
96 randData.length = 46;
97 #ifdef _APPLE_CDSA_
98 if ((err = sslRand(ctx, &randData)) != 0)
99 #else
100 if ((err = ctx->sysCtx.random(randData, ctx->sysCtx.randomRef)) != 0)
101 #endif
102 return err;
103
104 DUMP_BUFFER_NAME("premaster secret", ctx->preMasterSecret);
105
106 return SSLNoErr;
107 }
108
109 #if APPLE_DH
110
111 SSLErr
112 SSLEncodeDHPremasterSecret(SSLContext *ctx)
113 {
114 #if !APPLE_DH
115 return SSLUnsupportedErr;
116 #else
117
118 SSLErr err;
119 int rsaResult;
120 SSLRandomCtx rsaRandom;
121 #if RSAREF
122 SSLBuffer privateValue;
123 #endif
124
125 /* Given the server's Diffie-Hellman parameters, prepare a public & private value,
126 * then use the public value provided by the server and our private value to
127 * generate a shared key (the premaster secret). Save our public value in
128 * ctx->dhExchangePublic to send to the server so it can calculate the matching
129 * key on its end
130 */
131 if (ERR(err = ReadyRandom(&rsaRandom, ctx)) != 0)
132 return err;
133
134 #if RSAREF
135 { privateValue.data = 0;
136
137 if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, ctx->peerDHParams.primeLen, &ctx->sysCtx)) != 0)
138 goto fail;
139 if (ERR(err = SSLAllocBuffer(&privateValue, ctx->dhExchangePublic.length - 16, &ctx->sysCtx)) != 0)
140 goto fail;
141
142 if ((rsaResult = R_SetupDHAgreement(ctx->dhExchangePublic.data, privateValue.data,
143 privateValue.length, &ctx->peerDHParams, &rsaRandom)) != 0)
144 { err = SSLUnknownErr;
145 goto fail;
146 }
147
148 if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, ctx->peerDHParams.primeLen, &ctx->sysCtx)) != 0)
149 goto fail;
150
151 if ((rsaResult = R_ComputeDHAgreedKey (ctx->preMasterSecret.data, ctx->dhPeerPublic.data,
152 privateValue.data, privateValue.length, &ctx->peerDHParams)) != 0)
153 { err = SSLUnknownErr;
154 goto fail;
155 }
156 }
157 #elif BSAFE
158 { unsigned int outputLen;
159
160 if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, 128, &ctx->sysCtx)) != 0)
161 goto fail;
162 if ((rsaResult = B_KeyAgreePhase1(ctx->peerDHParams, ctx->dhExchangePublic.data,
163 &outputLen, 128, rsaRandom, NO_SURR)) != 0)
164 { err = SSLUnknownErr;
165 goto fail;
166 }
167 ctx->dhExchangePublic.length = outputLen;
168 if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, 128, &ctx->sysCtx)) != 0)
169 goto fail;
170 if ((rsaResult = B_KeyAgreePhase2(ctx->peerDHParams, ctx->preMasterSecret.data,
171 &outputLen, 128, ctx->dhPeerPublic.data, ctx->dhPeerPublic.length,
172 NO_SURR)) != 0)
173 { err = SSLUnknownErr;
174 goto fail;
175 }
176 ctx->preMasterSecret.length = outputLen;
177 }
178 #endif
179
180 DUMP_BUFFER_NAME("premaster secret", ctx->preMasterSecret);
181
182 err = SSLNoErr;
183 fail:
184 #if RSAREF
185 ERR(SSLFreeBuffer(&privateValue, &ctx->sysCtx));
186 R_RandomFinal(&rsaRandom);
187 #elif BSAFE
188 B_DestroyAlgorithmObject(&rsaRandom);
189 #endif
190 return err;
191 #endif
192 }
193
194 #endif /* APPLE_DH */
195
196 SSLErr
197 SSLCalculateMasterSecret(SSLContext *ctx)
198 { SSLErr err;
199 SSLBuffer shaState, md5State, clientRandom,
200 serverRandom, shaHash, md5Hash, leader;
201 UInt8 *masterProgress, shaHashData[20], leaderData[3];
202 int i;
203
204 md5State.data = shaState.data = 0;
205 if ((err = SSLAllocBuffer(&md5State, SSLHashMD5.contextSize, &ctx->sysCtx)) != 0)
206 goto fail;
207 if ((err = SSLAllocBuffer(&shaState, SSLHashSHA1.contextSize, &ctx->sysCtx)) != 0)
208 goto fail;
209
210 clientRandom.data = ctx->clientRandom;
211 clientRandom.length = 32;
212 serverRandom.data = ctx->serverRandom;
213 serverRandom.length = 32;
214 shaHash.data = shaHashData;
215 shaHash.length = 20;
216
217 masterProgress = ctx->masterSecret;
218
219 for (i = 1; i <= 3; i++)
220 { if ((err = SSLHashMD5.init(md5State)) != 0)
221 goto fail;
222 if ((err = SSLHashSHA1.init(shaState)) != 0)
223 goto fail;
224
225 leaderData[0] = leaderData[1] = leaderData[2] = 0x40 + i; /* 'A', 'B', etc. */
226 leader.data = leaderData;
227 leader.length = i;
228
229 if ((err = SSLHashSHA1.update(shaState, leader)) != 0)
230 goto fail;
231 if ((err = SSLHashSHA1.update(shaState, ctx->preMasterSecret)) != 0)
232 goto fail;
233 if ((err = SSLHashSHA1.update(shaState, clientRandom)) != 0)
234 goto fail;
235 if ((err = SSLHashSHA1.update(shaState, serverRandom)) != 0)
236 goto fail;
237 if ((err = SSLHashSHA1.final(shaState, shaHash)) != 0)
238 goto fail;
239 if ((err = SSLHashMD5.update(md5State, ctx->preMasterSecret)) != 0)
240 goto fail;
241 if ((err = SSLHashMD5.update(md5State, shaHash)) != 0)
242 goto fail;
243 md5Hash.data = masterProgress;
244 md5Hash.length = 16;
245 if ((err = SSLHashMD5.final(md5State, md5Hash)) != 0)
246 goto fail;
247 masterProgress += 16;
248 }
249
250 DUMP_DATA_NAME("master secret",ctx->masterSecret, 48);
251
252 err = SSLNoErr;
253 fail:
254 SSLFreeBuffer(&shaState, &ctx->sysCtx);
255 SSLFreeBuffer(&md5State, &ctx->sysCtx);
256 return err;
257 }
258
259 SSLErr
260 SSLInitPendingCiphers(SSLContext *ctx)
261 { SSLErr err;
262 SSLBuffer key, hashCtx;
263 UInt8 *keyDataProgress, *keyPtr, *ivPtr;
264 int keyDataLen;
265 CipherContext *serverPending, *clientPending;
266
267 key.data = hashCtx.data = 0;
268
269 ctx->readPending.hash = ctx->selectedCipherSpec->macAlgorithm;
270 ctx->writePending.hash = ctx->selectedCipherSpec->macAlgorithm;
271 ctx->readPending.symCipher = ctx->selectedCipherSpec->cipher;
272 ctx->writePending.symCipher = ctx->selectedCipherSpec->cipher;
273 ctx->readPending.sequenceNum.high = ctx->readPending.sequenceNum.low = 0;
274 ctx->writePending.sequenceNum.high = ctx->writePending.sequenceNum.low = 0;
275
276 keyDataLen = ctx->selectedCipherSpec->macAlgorithm->digestSize +
277 ctx->selectedCipherSpec->cipher->secretKeySize;
278 if (ctx->selectedCipherSpec->isExportable == NotExportable)
279 keyDataLen += ctx->selectedCipherSpec->cipher->ivSize;
280 keyDataLen *= 2; /* two of everything */
281
282 if ((err = SSLAllocBuffer(&key, keyDataLen, &ctx->sysCtx)) != 0)
283 return err;
284 if ((err = SSLGenerateKeyMaterial(key, ctx)) != 0)
285 goto fail;
286 DUMP_BUFFER_NAME("key data",key);
287
288 if (ctx->protocolSide == SSL_ServerSide)
289 { serverPending = &ctx->writePending;
290 clientPending = &ctx->readPending;
291 }
292 else
293 { serverPending = &ctx->readPending;
294 clientPending = &ctx->writePending;
295 }
296
297 keyDataProgress = key.data;
298 memcpy(clientPending->macSecret, keyDataProgress, ctx->selectedCipherSpec->macAlgorithm->digestSize);
299 DUMP_DATA_NAME("client write mac secret", keyDataProgress, ctx->selectedCipherSpec->macAlgorithm->digestSize);
300 keyDataProgress += ctx->selectedCipherSpec->macAlgorithm->digestSize;
301 memcpy(serverPending->macSecret, keyDataProgress, ctx->selectedCipherSpec->macAlgorithm->digestSize);
302 DUMP_DATA_NAME("server write mac secret", keyDataProgress, ctx->selectedCipherSpec->macAlgorithm->digestSize);
303 keyDataProgress += ctx->selectedCipherSpec->macAlgorithm->digestSize;
304
305 if (ctx->selectedCipherSpec->isExportable == NotExportable)
306 { keyPtr = keyDataProgress;
307 keyDataProgress += ctx->selectedCipherSpec->cipher->secretKeySize;
308 /* Skip server write key to get to IV */
309 ivPtr = keyDataProgress + ctx->selectedCipherSpec->cipher->secretKeySize;
310 /* APPLE_CDSA changes to all symmetric cipher routines.....*/
311 if ((err = ctx->selectedCipherSpec->cipher->initialize(keyPtr, ivPtr,
312 clientPending, ctx)) != 0)
313 goto fail;
314 DUMP_DATA_NAME("client write key", keyPtr, ctx->selectedCipherSpec->cipher->secretKeySize);
315 DUMP_DATA_NAME("client write iv", ivPtr, ctx->selectedCipherSpec->cipher->ivSize);
316 keyPtr = keyDataProgress;
317 keyDataProgress += ctx->selectedCipherSpec->cipher->secretKeySize;
318 /* Skip client write IV to get to server write IV */
319 ivPtr = keyDataProgress + ctx->selectedCipherSpec->cipher->ivSize;
320 if ((err = ctx->selectedCipherSpec->cipher->initialize(keyPtr, ivPtr,
321 serverPending, ctx)) != 0)
322 goto fail;
323 DUMP_DATA_NAME("server write key", keyPtr, ctx->selectedCipherSpec->cipher->secretKeySize);
324 DUMP_DATA_NAME("server write iv", ivPtr, ctx->selectedCipherSpec->cipher->ivSize);
325 }
326 else
327 { UInt8 exportKey[16], exportIV[16];
328 SSLBuffer hashOutput, clientWrite, serverWrite, clientRandom,
329 serverRandom;
330
331 CASSERT(ctx->selectedCipherSpec->cipher->keySize <= 16);
332 CASSERT(ctx->selectedCipherSpec->cipher->ivSize <= 16);
333
334 clientWrite.data = keyDataProgress;
335 clientWrite.length = ctx->selectedCipherSpec->cipher->secretKeySize;
336 serverWrite.data = keyDataProgress + clientWrite.length;
337 serverWrite.length = ctx->selectedCipherSpec->cipher->secretKeySize;
338 clientRandom.data = ctx->clientRandom;
339 clientRandom.length = 32;
340 serverRandom.data = ctx->serverRandom;
341 serverRandom.length = 32;
342
343 if ((err = SSLAllocBuffer(&hashCtx, SSLHashMD5.contextSize, &ctx->sysCtx)) != 0)
344 goto fail;
345 if ((err = SSLHashMD5.init(hashCtx)) != 0)
346 goto fail;
347 if ((err = SSLHashMD5.update(hashCtx, clientWrite)) != 0)
348 goto fail;
349 if ((err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
350 goto fail;
351 if ((err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
352 goto fail;
353 hashOutput.data = exportKey;
354 hashOutput.length = 16;
355 if ((err = SSLHashMD5.final(hashCtx, hashOutput)) != 0)
356 goto fail;
357
358 if (ctx->selectedCipherSpec->cipher->ivSize > 0)
359 { if ((err = SSLHashMD5.init(hashCtx)) != 0)
360 goto fail;
361 if ((err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
362 goto fail;
363 if ((err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
364 goto fail;
365 hashOutput.data = exportIV;
366 hashOutput.length = 16;
367 if ((err = SSLHashMD5.final(hashCtx, hashOutput)) != 0)
368 goto fail;
369 }
370 if ((err = ctx->selectedCipherSpec->cipher->initialize(exportKey, exportIV,
371 clientPending, ctx)) != 0)
372 goto fail;
373
374 if ((err = SSLHashMD5.init(hashCtx)) != 0)
375 goto fail;
376 if ((err = SSLHashMD5.update(hashCtx, serverWrite)) != 0)
377 goto fail;
378 if ((err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
379 goto fail;
380 if ((err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
381 goto fail;
382 hashOutput.data = exportKey;
383 hashOutput.length = 16;
384 if ((err = SSLHashMD5.final(hashCtx, hashOutput)) != 0)
385 goto fail;
386
387 if (ctx->selectedCipherSpec->cipher->ivSize > 0)
388 { if ((err = SSLHashMD5.init(hashCtx)) != 0)
389 goto fail;
390 if ((err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
391 goto fail;
392 if ((err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
393 goto fail;
394 hashOutput.data = exportIV;
395 hashOutput.length = 16;
396 if ((err = SSLHashMD5.final(hashCtx, hashOutput)) != 0)
397 goto fail;
398 }
399 if ((err = ctx->selectedCipherSpec->cipher->initialize(exportKey, exportIV,
400 serverPending, ctx)) != 0)
401 goto fail;
402 }
403
404 /* Ciphers are ready for use */
405 ctx->writePending.ready = 1;
406 ctx->readPending.ready = 1;
407
408 /* Ciphers get swapped by sending or receiving a change cipher spec message */
409
410 err = SSLNoErr;
411 fail:
412 SSLFreeBuffer(&key, &ctx->sysCtx);
413 SSLFreeBuffer(&hashCtx, &ctx->sysCtx);
414 return err;
415 }
416
417 static SSLErr
418 SSLGenerateKeyMaterial(SSLBuffer key, SSLContext *ctx)
419 { SSLErr err;
420 UInt8 leaderData[10]; /* Max of 10 hashes (* 16 bytes/hash = 160 bytes of key) */
421 UInt8 shaHashData[20], md5HashData[16];
422 SSLBuffer shaContext, md5Context;
423 UInt8 *keyProgress;
424 int i,j,remaining, satisfied;
425 SSLBuffer leader, masterSecret, serverRandom, clientRandom, shaHash, md5Hash;
426
427 CASSERT(key.length <= 16 * sizeof(leaderData));
428
429 leader.data = leaderData;
430 masterSecret.data = ctx->masterSecret;
431 masterSecret.length = 48;
432 serverRandom.data = ctx->serverRandom;
433 serverRandom.length = 32;
434 clientRandom.data = ctx->clientRandom;
435 clientRandom.length = 32;
436 shaHash.data = shaHashData;
437 shaHash.length = 20;
438 md5Hash.data = md5HashData;
439 md5Hash.length = 20;
440
441 md5Context.data = 0;
442 shaContext.data = 0;
443 if ((err = ReadyHash(&SSLHashMD5, &md5Context, ctx)) != 0)
444 goto fail;
445 if ((err = ReadyHash(&SSLHashSHA1, &shaContext, ctx)) != 0)
446 goto fail;
447
448 keyProgress = key.data;
449 remaining = key.length;
450
451 for (i = 0; remaining > 0; ++i)
452 { for (j = 0; j <= i; j++)
453 leaderData[j] = 0x41 + i; /* 'A', 'BB', 'CCC', etc. */
454 leader.length = i+1;
455
456 if ((err = SSLHashSHA1.update(shaContext, leader)) != 0)
457 goto fail;
458 if ((err = SSLHashSHA1.update(shaContext, masterSecret)) != 0)
459 goto fail;
460 if ((err = SSLHashSHA1.update(shaContext, serverRandom)) != 0)
461 goto fail;
462 if ((err = SSLHashSHA1.update(shaContext, clientRandom)) != 0)
463 goto fail;
464 if ((err = SSLHashSHA1.final(shaContext, shaHash)) != 0)
465 goto fail;
466 if ((err = SSLHashMD5.update(md5Context, masterSecret)) != 0)
467 goto fail;
468 if ((err = SSLHashMD5.update(md5Context, shaHash)) != 0)
469 goto fail;
470 if ((err = SSLHashMD5.final(md5Context, md5Hash)) != 0)
471 goto fail;
472
473 satisfied = 16;
474 if (remaining < 16)
475 satisfied = remaining;
476 memcpy(keyProgress, md5HashData, satisfied);
477 remaining -= satisfied;
478 keyProgress += satisfied;
479
480 if ((err = SSLHashMD5.init(md5Context)) != 0)
481 goto fail;
482 if ((err = SSLHashSHA1.init(shaContext)) != 0)
483 goto fail;
484 }
485
486 CASSERT(remaining == 0 && keyProgress == (key.data + key.length));
487 err = SSLNoErr;
488 fail:
489 SSLFreeBuffer(&md5Context, &ctx->sysCtx);
490 SSLFreeBuffer(&shaContext, &ctx->sysCtx);
491
492 return err;
493 }
494
495 #ifndef _APPLE_CDSA_
496 /* I'm not sure what this is for */
497 SSLErr
498 ReadyRandom(SSLRandomCtx *rsaRandom, SSLContext *ctx)
499 { SSLErr err;
500 SSLBuffer randomSeedBuf;
501 UInt8 randomSeed[32];
502 int rsaResult;
503 #if RSAREF
504 unsigned int bytesNeeded;
505
506 if (R_RandomInit(rsaRandom) != 0)
507 return ERR(SSLUnknownErr);
508 if (R_GetRandomBytesNeeded(&bytesNeeded, rsaRandom) != 0)
509 return ERR(SSLUnknownErr);
510
511 randomSeedBuf.data = randomSeed;
512 randomSeedBuf.length = 32;
513
514 while (bytesNeeded > 0)
515 { if (ERR(err = ctx->sysCtx.random(randomSeedBuf, ctx->sysCtx.randomRef)) != 0)
516 return err;
517 if ((rsaResult = R_RandomUpdate(rsaRandom, randomSeed, 32)) != 0)
518 return ERR(SSLUnknownErr);
519
520 if (bytesNeeded >= 32)
521 bytesNeeded -= 32;
522 else
523 bytesNeeded = 0;
524 }
525 #elif BSAFE
526 static B_ALGORITHM_OBJ random;
527 B_ALGORITHM_METHOD *chooser[] = { &AM_MD5_RANDOM, 0 };
528
529 if ((rsaResult = B_CreateAlgorithmObject(rsaRandom)) != 0)
530 return ERR(SSLUnknownErr);
531 if ((rsaResult = B_SetAlgorithmInfo(*rsaRandom, AI_MD5Random, 0)) != 0)
532 return ERR(SSLUnknownErr);
533 if ((rsaResult = B_RandomInit(*rsaRandom, chooser, NO_SURR)) != 0)
534 return ERR(SSLUnknownErr);
535 randomSeedBuf.data = randomSeed;
536 randomSeedBuf.length = 32;
537 if (ERR(err = ctx->sysCtx.random(randomSeedBuf, ctx->sysCtx.randomRef)) != 0)
538 return err;
539 if ((rsaResult = B_RandomUpdate(*rsaRandom, randomSeedBuf.data, randomSeedBuf.length, NO_SURR)) != 0)
540 return ERR(SSLUnknownErr);
541 #endif /* RSAREF / BSAFE */
542
543 return SSLNoErr;
544 }
545 #endif /* APPLE_CDSA */