]>
git.saurik.com Git - apple/security.git/blob - SecureTransport/hdskkeys.c
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
22 Contains: Key calculation and encoding
24 Written by: Doug Mitchell, based on Netscape SSLRef 3.0
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
29 /* *********************************************************************
32 SSLRef 3.0 Final -- 11/19/96
34 Copyright (c)1996 by Netscape Communications Corp.
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.
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/>.
44 *********************************************************************
46 File: hdskkeys.c Key calculation and encoding
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.
52 ****************************************************************** */
74 #ifndef _APPLE_CDSA_H_
75 #include "appleCdsa.h"
84 static SSLErr
SSLGenerateKeyMaterial(SSLBuffer key
, SSLContext
*ctx
);
87 SSLEncodeRSAPremasterSecret(SSLContext
*ctx
)
91 if (ERR(err
= SSLAllocBuffer(&ctx
->preMasterSecret
, 48, &ctx
->sysCtx
)) != 0)
94 SSLEncodeInt(ctx
->preMasterSecret
.data
, SSL_Version_3_0
, 2);
95 randData
.data
= ctx
->preMasterSecret
.data
+2;
98 if ((err
= sslRand(ctx
, &randData
)) != 0)
100 if ((err
= ctx
->sysCtx
.random(randData
, ctx
->sysCtx
.randomRef
)) != 0)
104 DUMP_BUFFER_NAME("premaster secret", ctx
->preMasterSecret
);
112 SSLEncodeDHPremasterSecret(SSLContext
*ctx
)
115 return SSLUnsupportedErr
;
120 SSLRandomCtx rsaRandom
;
122 SSLBuffer privateValue
;
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
131 if (ERR(err
= ReadyRandom(&rsaRandom
, ctx
)) != 0)
135 { privateValue
.data
= 0;
137 if (ERR(err
= SSLAllocBuffer(&ctx
->dhExchangePublic
, ctx
->peerDHParams
.primeLen
, &ctx
->sysCtx
)) != 0)
139 if (ERR(err
= SSLAllocBuffer(&privateValue
, ctx
->dhExchangePublic
.length
- 16, &ctx
->sysCtx
)) != 0)
142 if ((rsaResult
= R_SetupDHAgreement(ctx
->dhExchangePublic
.data
, privateValue
.data
,
143 privateValue
.length
, &ctx
->peerDHParams
, &rsaRandom
)) != 0)
144 { err
= SSLUnknownErr
;
148 if (ERR(err
= SSLAllocBuffer(&ctx
->preMasterSecret
, ctx
->peerDHParams
.primeLen
, &ctx
->sysCtx
)) != 0)
151 if ((rsaResult
= R_ComputeDHAgreedKey (ctx
->preMasterSecret
.data
, ctx
->dhPeerPublic
.data
,
152 privateValue
.data
, privateValue
.length
, &ctx
->peerDHParams
)) != 0)
153 { err
= SSLUnknownErr
;
158 { unsigned int outputLen
;
160 if (ERR(err
= SSLAllocBuffer(&ctx
->dhExchangePublic
, 128, &ctx
->sysCtx
)) != 0)
162 if ((rsaResult
= B_KeyAgreePhase1(ctx
->peerDHParams
, ctx
->dhExchangePublic
.data
,
163 &outputLen
, 128, rsaRandom
, NO_SURR
)) != 0)
164 { err
= SSLUnknownErr
;
167 ctx
->dhExchangePublic
.length
= outputLen
;
168 if (ERR(err
= SSLAllocBuffer(&ctx
->preMasterSecret
, 128, &ctx
->sysCtx
)) != 0)
170 if ((rsaResult
= B_KeyAgreePhase2(ctx
->peerDHParams
, ctx
->preMasterSecret
.data
,
171 &outputLen
, 128, ctx
->dhPeerPublic
.data
, ctx
->dhPeerPublic
.length
,
173 { err
= SSLUnknownErr
;
176 ctx
->preMasterSecret
.length
= outputLen
;
180 DUMP_BUFFER_NAME("premaster secret", ctx
->preMasterSecret
);
185 ERR(SSLFreeBuffer(&privateValue
, &ctx
->sysCtx
));
186 R_RandomFinal(&rsaRandom
);
188 B_DestroyAlgorithmObject(&rsaRandom
);
194 #endif /* APPLE_DH */
197 SSLCalculateMasterSecret(SSLContext
*ctx
)
199 SSLBuffer shaState
, md5State
, clientRandom
,
200 serverRandom
, shaHash
, md5Hash
, leader
;
201 UInt8
*masterProgress
, shaHashData
[20], leaderData
[3];
204 md5State
.data
= shaState
.data
= 0;
205 if ((err
= SSLAllocBuffer(&md5State
, SSLHashMD5
.contextSize
, &ctx
->sysCtx
)) != 0)
207 if ((err
= SSLAllocBuffer(&shaState
, SSLHashSHA1
.contextSize
, &ctx
->sysCtx
)) != 0)
210 clientRandom
.data
= ctx
->clientRandom
;
211 clientRandom
.length
= 32;
212 serverRandom
.data
= ctx
->serverRandom
;
213 serverRandom
.length
= 32;
214 shaHash
.data
= shaHashData
;
217 masterProgress
= ctx
->masterSecret
;
219 for (i
= 1; i
<= 3; i
++)
220 { if ((err
= SSLHashMD5
.init(md5State
)) != 0)
222 if ((err
= SSLHashSHA1
.init(shaState
)) != 0)
225 leaderData
[0] = leaderData
[1] = leaderData
[2] = 0x40 + i
; /* 'A', 'B', etc. */
226 leader
.data
= leaderData
;
229 if ((err
= SSLHashSHA1
.update(shaState
, leader
)) != 0)
231 if ((err
= SSLHashSHA1
.update(shaState
, ctx
->preMasterSecret
)) != 0)
233 if ((err
= SSLHashSHA1
.update(shaState
, clientRandom
)) != 0)
235 if ((err
= SSLHashSHA1
.update(shaState
, serverRandom
)) != 0)
237 if ((err
= SSLHashSHA1
.final(shaState
, shaHash
)) != 0)
239 if ((err
= SSLHashMD5
.update(md5State
, ctx
->preMasterSecret
)) != 0)
241 if ((err
= SSLHashMD5
.update(md5State
, shaHash
)) != 0)
243 md5Hash
.data
= masterProgress
;
245 if ((err
= SSLHashMD5
.final(md5State
, md5Hash
)) != 0)
247 masterProgress
+= 16;
250 DUMP_DATA_NAME("master secret",ctx
->masterSecret
, 48);
254 SSLFreeBuffer(&shaState
, &ctx
->sysCtx
);
255 SSLFreeBuffer(&md5State
, &ctx
->sysCtx
);
260 SSLInitPendingCiphers(SSLContext
*ctx
)
262 SSLBuffer key
, hashCtx
;
263 UInt8
*keyDataProgress
, *keyPtr
, *ivPtr
;
265 CipherContext
*serverPending
, *clientPending
;
267 key
.data
= hashCtx
.data
= 0;
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;
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 */
282 if ((err
= SSLAllocBuffer(&key
, keyDataLen
, &ctx
->sysCtx
)) != 0)
284 if ((err
= SSLGenerateKeyMaterial(key
, ctx
)) != 0)
286 DUMP_BUFFER_NAME("key data",key
);
288 if (ctx
->protocolSide
== SSL_ServerSide
)
289 { serverPending
= &ctx
->writePending
;
290 clientPending
= &ctx
->readPending
;
293 { serverPending
= &ctx
->readPending
;
294 clientPending
= &ctx
->writePending
;
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
;
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)
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)
323 DUMP_DATA_NAME("server write key", keyPtr
, ctx
->selectedCipherSpec
->cipher
->secretKeySize
);
324 DUMP_DATA_NAME("server write iv", ivPtr
, ctx
->selectedCipherSpec
->cipher
->ivSize
);
327 { UInt8 exportKey
[16], exportIV
[16];
328 SSLBuffer hashOutput
, clientWrite
, serverWrite
, clientRandom
,
331 CASSERT(ctx
->selectedCipherSpec
->cipher
->keySize
<= 16);
332 CASSERT(ctx
->selectedCipherSpec
->cipher
->ivSize
<= 16);
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;
343 if ((err
= SSLAllocBuffer(&hashCtx
, SSLHashMD5
.contextSize
, &ctx
->sysCtx
)) != 0)
345 if ((err
= SSLHashMD5
.init(hashCtx
)) != 0)
347 if ((err
= SSLHashMD5
.update(hashCtx
, clientWrite
)) != 0)
349 if ((err
= SSLHashMD5
.update(hashCtx
, clientRandom
)) != 0)
351 if ((err
= SSLHashMD5
.update(hashCtx
, serverRandom
)) != 0)
353 hashOutput
.data
= exportKey
;
354 hashOutput
.length
= 16;
355 if ((err
= SSLHashMD5
.final(hashCtx
, hashOutput
)) != 0)
358 if (ctx
->selectedCipherSpec
->cipher
->ivSize
> 0)
359 { if ((err
= SSLHashMD5
.init(hashCtx
)) != 0)
361 if ((err
= SSLHashMD5
.update(hashCtx
, clientRandom
)) != 0)
363 if ((err
= SSLHashMD5
.update(hashCtx
, serverRandom
)) != 0)
365 hashOutput
.data
= exportIV
;
366 hashOutput
.length
= 16;
367 if ((err
= SSLHashMD5
.final(hashCtx
, hashOutput
)) != 0)
370 if ((err
= ctx
->selectedCipherSpec
->cipher
->initialize(exportKey
, exportIV
,
371 clientPending
, ctx
)) != 0)
374 if ((err
= SSLHashMD5
.init(hashCtx
)) != 0)
376 if ((err
= SSLHashMD5
.update(hashCtx
, serverWrite
)) != 0)
378 if ((err
= SSLHashMD5
.update(hashCtx
, serverRandom
)) != 0)
380 if ((err
= SSLHashMD5
.update(hashCtx
, clientRandom
)) != 0)
382 hashOutput
.data
= exportKey
;
383 hashOutput
.length
= 16;
384 if ((err
= SSLHashMD5
.final(hashCtx
, hashOutput
)) != 0)
387 if (ctx
->selectedCipherSpec
->cipher
->ivSize
> 0)
388 { if ((err
= SSLHashMD5
.init(hashCtx
)) != 0)
390 if ((err
= SSLHashMD5
.update(hashCtx
, serverRandom
)) != 0)
392 if ((err
= SSLHashMD5
.update(hashCtx
, clientRandom
)) != 0)
394 hashOutput
.data
= exportIV
;
395 hashOutput
.length
= 16;
396 if ((err
= SSLHashMD5
.final(hashCtx
, hashOutput
)) != 0)
399 if ((err
= ctx
->selectedCipherSpec
->cipher
->initialize(exportKey
, exportIV
,
400 serverPending
, ctx
)) != 0)
404 /* Ciphers are ready for use */
405 ctx
->writePending
.ready
= 1;
406 ctx
->readPending
.ready
= 1;
408 /* Ciphers get swapped by sending or receiving a change cipher spec message */
412 SSLFreeBuffer(&key
, &ctx
->sysCtx
);
413 SSLFreeBuffer(&hashCtx
, &ctx
->sysCtx
);
418 SSLGenerateKeyMaterial(SSLBuffer key
, SSLContext
*ctx
)
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
;
424 int i
,j
,remaining
, satisfied
;
425 SSLBuffer leader
, masterSecret
, serverRandom
, clientRandom
, shaHash
, md5Hash
;
427 CASSERT(key
.length
<= 16 * sizeof(leaderData
));
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
;
438 md5Hash
.data
= md5HashData
;
443 if ((err
= ReadyHash(&SSLHashMD5
, &md5Context
, ctx
)) != 0)
445 if ((err
= ReadyHash(&SSLHashSHA1
, &shaContext
, ctx
)) != 0)
448 keyProgress
= key
.data
;
449 remaining
= key
.length
;
451 for (i
= 0; remaining
> 0; ++i
)
452 { for (j
= 0; j
<= i
; j
++)
453 leaderData
[j
] = 0x41 + i
; /* 'A', 'BB', 'CCC', etc. */
456 if ((err
= SSLHashSHA1
.update(shaContext
, leader
)) != 0)
458 if ((err
= SSLHashSHA1
.update(shaContext
, masterSecret
)) != 0)
460 if ((err
= SSLHashSHA1
.update(shaContext
, serverRandom
)) != 0)
462 if ((err
= SSLHashSHA1
.update(shaContext
, clientRandom
)) != 0)
464 if ((err
= SSLHashSHA1
.final(shaContext
, shaHash
)) != 0)
466 if ((err
= SSLHashMD5
.update(md5Context
, masterSecret
)) != 0)
468 if ((err
= SSLHashMD5
.update(md5Context
, shaHash
)) != 0)
470 if ((err
= SSLHashMD5
.final(md5Context
, md5Hash
)) != 0)
475 satisfied
= remaining
;
476 memcpy(keyProgress
, md5HashData
, satisfied
);
477 remaining
-= satisfied
;
478 keyProgress
+= satisfied
;
480 if ((err
= SSLHashMD5
.init(md5Context
)) != 0)
482 if ((err
= SSLHashSHA1
.init(shaContext
)) != 0)
486 CASSERT(remaining
== 0 && keyProgress
== (key
.data
+ key
.length
));
489 SSLFreeBuffer(&md5Context
, &ctx
->sysCtx
);
490 SSLFreeBuffer(&shaContext
, &ctx
->sysCtx
);
496 /* I'm not sure what this is for */
498 ReadyRandom(SSLRandomCtx
*rsaRandom
, SSLContext
*ctx
)
500 SSLBuffer randomSeedBuf
;
501 UInt8 randomSeed
[32];
504 unsigned int bytesNeeded
;
506 if (R_RandomInit(rsaRandom
) != 0)
507 return ERR(SSLUnknownErr
);
508 if (R_GetRandomBytesNeeded(&bytesNeeded
, rsaRandom
) != 0)
509 return ERR(SSLUnknownErr
);
511 randomSeedBuf
.data
= randomSeed
;
512 randomSeedBuf
.length
= 32;
514 while (bytesNeeded
> 0)
515 { if (ERR(err
= ctx
->sysCtx
.random(randomSeedBuf
, ctx
->sysCtx
.randomRef
)) != 0)
517 if ((rsaResult
= R_RandomUpdate(rsaRandom
, randomSeed
, 32)) != 0)
518 return ERR(SSLUnknownErr
);
520 if (bytesNeeded
>= 32)
526 static B_ALGORITHM_OBJ random
;
527 B_ALGORITHM_METHOD
*chooser
[] = { &AM_MD5_RANDOM
, 0 };
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)
539 if ((rsaResult
= B_RandomUpdate(*rsaRandom
, randomSeedBuf
.data
, randomSeedBuf
.length
, NO_SURR
)) != 0)
540 return ERR(SSLUnknownErr
);
541 #endif /* RSAREF / BSAFE */
545 #endif /* APPLE_CDSA */