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"
86 SSLEncodeRSAPremasterSecret(SSLContext
*ctx
)
90 if (ERR(err
= SSLAllocBuffer(&ctx
->preMasterSecret
,
91 SSL_RSA_PREMASTER_SECRET_SIZE
, &ctx
->sysCtx
)) != 0)
94 assert((ctx
->negProtocolVersion
== SSL_Version_3_0
) ||
95 (ctx
->negProtocolVersion
== TLS_Version_1_0
));
96 SSLEncodeInt(ctx
->preMasterSecret
.data
, ctx
->maxProtocolVersion
, 2);
97 randData
.data
= ctx
->preMasterSecret
.data
+2;
98 randData
.length
= SSL_RSA_PREMASTER_SECRET_SIZE
- 2;
99 if ((err
= sslRand(ctx
, &randData
)) != 0)
102 DUMP_BUFFER_NAME("premaster secret", ctx
->preMasterSecret
);
110 SSLEncodeDHPremasterSecret(SSLContext
*ctx
)
113 return SSLUnsupportedErr
;
118 SSLRandomCtx rsaRandom
;
120 /* Given the server's Diffie-Hellman parameters, prepare a public & private value,
121 * then use the public value provided by the server and our private value to
122 * generate a shared key (the premaster secret). Save our public value in
123 * ctx->dhExchangePublic to send to the server so it can calculate the matching
126 if (ERR(err
= ReadyRandom(&rsaRandom
, ctx
)) != 0)
130 { privateValue
.data
= 0;
132 if (ERR(err
= SSLAllocBuffer(&ctx
->dhExchangePublic
, ctx
->peerDHParams
.primeLen
, &ctx
->sysCtx
)) != 0)
134 if (ERR(err
= SSLAllocBuffer(&privateValue
, ctx
->dhExchangePublic
.length
- 16, &ctx
->sysCtx
)) != 0)
137 if ((rsaResult
= R_SetupDHAgreement(ctx
->dhExchangePublic
.data
, privateValue
.data
,
138 privateValue
.length
, &ctx
->peerDHParams
, &rsaRandom
)) != 0)
139 { err
= SSLUnknownErr
;
143 if (ERR(err
= SSLAllocBuffer(&ctx
->preMasterSecret
, ctx
->peerDHParams
.primeLen
, &ctx
->sysCtx
)) != 0)
146 if ((rsaResult
= R_ComputeDHAgreedKey (ctx
->preMasterSecret
.data
, ctx
->dhPeerPublic
.data
,
147 privateValue
.data
, privateValue
.length
, &ctx
->peerDHParams
)) != 0)
148 { err
= SSLUnknownErr
;
153 { unsigned int outputLen
;
155 if (ERR(err
= SSLAllocBuffer(&ctx
->dhExchangePublic
, 128, &ctx
->sysCtx
)) != 0)
157 if ((rsaResult
= B_KeyAgreePhase1(ctx
->peerDHParams
, ctx
->dhExchangePublic
.data
,
158 &outputLen
, 128, rsaRandom
, NO_SURR
)) != 0)
159 { err
= SSLUnknownErr
;
162 ctx
->dhExchangePublic
.length
= outputLen
;
163 if (ERR(err
= SSLAllocBuffer(&ctx
->preMasterSecret
, 128, &ctx
->sysCtx
)) != 0)
165 if ((rsaResult
= B_KeyAgreePhase2(ctx
->peerDHParams
, ctx
->preMasterSecret
.data
,
166 &outputLen
, 128, ctx
->dhPeerPublic
.data
, ctx
->dhPeerPublic
.length
,
168 { err
= SSLUnknownErr
;
171 ctx
->preMasterSecret
.length
= outputLen
;
175 DUMP_BUFFER_NAME("premaster secret", ctx
->preMasterSecret
);
180 ERR(SSLFreeBuffer(&privateValue
, &ctx
->sysCtx
));
181 R_RandomFinal(&rsaRandom
);
183 B_DestroyAlgorithmObject(&rsaRandom
);
189 #endif /* APPLE_DH */
192 SSLInitPendingCiphers(SSLContext
*ctx
)
195 UInt8
*keyDataProgress
, *keyPtr
, *ivPtr
;
197 CipherContext
*serverPending
, *clientPending
;
201 ctx
->readPending
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
202 ctx
->writePending
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
203 ctx
->readPending
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
204 ctx
->writePending
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
205 ctx
->readPending
.sequenceNum
.high
= ctx
->readPending
.sequenceNum
.low
= 0;
206 ctx
->writePending
.sequenceNum
.high
= ctx
->writePending
.sequenceNum
.low
= 0;
208 keyDataLen
= ctx
->selectedCipherSpec
->macAlgorithm
->hash
->digestSize
+
209 ctx
->selectedCipherSpec
->cipher
->secretKeySize
;
210 if (ctx
->selectedCipherSpec
->isExportable
== NotExportable
)
211 keyDataLen
+= ctx
->selectedCipherSpec
->cipher
->ivSize
;
212 keyDataLen
*= 2; /* two of everything */
214 if ((err
= SSLAllocBuffer(&key
, keyDataLen
, &ctx
->sysCtx
)) != 0)
216 assert(ctx
->sslTslCalls
!= NULL
);
217 if ((err
= ctx
->sslTslCalls
->generateKeyMaterial(key
, ctx
)) != 0)
220 if (ctx
->protocolSide
== SSL_ServerSide
)
221 { serverPending
= &ctx
->writePending
;
222 clientPending
= &ctx
->readPending
;
225 { serverPending
= &ctx
->readPending
;
226 clientPending
= &ctx
->writePending
;
229 keyDataProgress
= key
.data
;
230 memcpy(clientPending
->macSecret
, keyDataProgress
,
231 ctx
->selectedCipherSpec
->macAlgorithm
->hash
->digestSize
);
232 keyDataProgress
+= ctx
->selectedCipherSpec
->macAlgorithm
->hash
->digestSize
;
233 memcpy(serverPending
->macSecret
, keyDataProgress
,
234 ctx
->selectedCipherSpec
->macAlgorithm
->hash
->digestSize
);
235 keyDataProgress
+= ctx
->selectedCipherSpec
->macAlgorithm
->hash
->digestSize
;
237 /* init the reusable-per-record MAC contexts */
238 err
= ctx
->sslTslCalls
->initMac(clientPending
, ctx
);
242 err
= ctx
->sslTslCalls
->initMac(serverPending
, ctx
);
247 if (ctx
->selectedCipherSpec
->isExportable
== NotExportable
)
248 { keyPtr
= keyDataProgress
;
249 keyDataProgress
+= ctx
->selectedCipherSpec
->cipher
->secretKeySize
;
250 /* Skip server write key to get to IV */
251 ivPtr
= keyDataProgress
+ ctx
->selectedCipherSpec
->cipher
->secretKeySize
;
252 /* APPLE_CDSA changes to all symmetric cipher routines.....*/
253 if ((err
= ctx
->selectedCipherSpec
->cipher
->initialize(keyPtr
, ivPtr
,
254 clientPending
, ctx
)) != 0)
256 keyPtr
= keyDataProgress
;
257 keyDataProgress
+= ctx
->selectedCipherSpec
->cipher
->secretKeySize
;
258 /* Skip client write IV to get to server write IV */
259 ivPtr
= keyDataProgress
+ ctx
->selectedCipherSpec
->cipher
->ivSize
;
260 if ((err
= ctx
->selectedCipherSpec
->cipher
->initialize(keyPtr
, ivPtr
,
261 serverPending
, ctx
)) != 0)
265 UInt8 clientExportKey
[16], serverExportKey
[16],
266 clientExportIV
[16], serverExportIV
[16];
267 SSLBuffer clientWrite
, serverWrite
;
268 SSLBuffer finalClientWrite
, finalServerWrite
;
269 SSLBuffer finalClientIV
, finalServerIV
;
271 assert(ctx
->selectedCipherSpec
->cipher
->keySize
<= 16);
272 assert(ctx
->selectedCipherSpec
->cipher
->ivSize
<= 16);
274 /* Inputs to generateExportKeyAndIv are clientRandom, serverRandom,
275 * clientWriteKey, serverWriteKey. The first two are already present
277 * Outputs are a key and IV for each of {server, client}.
279 clientWrite
.data
= keyDataProgress
;
280 clientWrite
.length
= ctx
->selectedCipherSpec
->cipher
->secretKeySize
;
281 serverWrite
.data
= keyDataProgress
+ clientWrite
.length
;
282 serverWrite
.length
= ctx
->selectedCipherSpec
->cipher
->secretKeySize
;
283 finalClientWrite
.data
= clientExportKey
;
284 finalServerWrite
.data
= serverExportKey
;
285 finalClientIV
.data
= clientExportIV
;
286 finalServerIV
.data
= serverExportIV
;
287 finalClientWrite
.length
= 16;
288 finalServerWrite
.length
= 16;
289 /* these can be zero */
290 finalClientIV
.length
= ctx
->selectedCipherSpec
->cipher
->ivSize
;
291 finalServerIV
.length
= ctx
->selectedCipherSpec
->cipher
->ivSize
;
293 assert(ctx
->sslTslCalls
!= NULL
);
294 err
= ctx
->sslTslCalls
->generateExportKeyAndIv(ctx
, clientWrite
, serverWrite
,
295 finalClientWrite
, finalServerWrite
, finalClientIV
, finalServerIV
);
299 if ((err
= ctx
->selectedCipherSpec
->cipher
->initialize(clientExportKey
,
300 clientExportIV
, clientPending
, ctx
)) != 0)
302 if ((err
= ctx
->selectedCipherSpec
->cipher
->initialize(serverExportKey
,
303 serverExportIV
, serverPending
, ctx
)) != 0)
307 /* Ciphers are ready for use */
308 ctx
->writePending
.ready
= 1;
309 ctx
->readPending
.ready
= 1;
311 /* Ciphers get swapped by sending or receiving a change cipher spec message */
315 SSLFreeBuffer(&key
, &ctx
->sysCtx
);