]> git.saurik.com Git - apple/security.git/blob - SecureTransport/hdskkeys.c
Security-54.1.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 #include <assert.h>
84
85 SSLErr
86 SSLEncodeRSAPremasterSecret(SSLContext *ctx)
87 { SSLBuffer randData;
88 SSLErr err;
89
90 if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret,
91 SSL_RSA_PREMASTER_SECRET_SIZE, &ctx->sysCtx)) != 0)
92 return err;
93
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)
100 return err;
101
102 DUMP_BUFFER_NAME("premaster secret", ctx->preMasterSecret);
103
104 return SSLNoErr;
105 }
106
107 #if APPLE_DH
108
109 SSLErr
110 SSLEncodeDHPremasterSecret(SSLContext *ctx)
111 {
112 #if !APPLE_DH
113 return SSLUnsupportedErr;
114 #else
115
116 SSLErr err;
117 int rsaResult;
118 SSLRandomCtx rsaRandom;
119
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
124 * key on its end
125 */
126 if (ERR(err = ReadyRandom(&rsaRandom, ctx)) != 0)
127 return err;
128
129 #if RSAREF
130 { privateValue.data = 0;
131
132 if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, ctx->peerDHParams.primeLen, &ctx->sysCtx)) != 0)
133 goto fail;
134 if (ERR(err = SSLAllocBuffer(&privateValue, ctx->dhExchangePublic.length - 16, &ctx->sysCtx)) != 0)
135 goto fail;
136
137 if ((rsaResult = R_SetupDHAgreement(ctx->dhExchangePublic.data, privateValue.data,
138 privateValue.length, &ctx->peerDHParams, &rsaRandom)) != 0)
139 { err = SSLUnknownErr;
140 goto fail;
141 }
142
143 if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, ctx->peerDHParams.primeLen, &ctx->sysCtx)) != 0)
144 goto fail;
145
146 if ((rsaResult = R_ComputeDHAgreedKey (ctx->preMasterSecret.data, ctx->dhPeerPublic.data,
147 privateValue.data, privateValue.length, &ctx->peerDHParams)) != 0)
148 { err = SSLUnknownErr;
149 goto fail;
150 }
151 }
152 #elif BSAFE
153 { unsigned int outputLen;
154
155 if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, 128, &ctx->sysCtx)) != 0)
156 goto fail;
157 if ((rsaResult = B_KeyAgreePhase1(ctx->peerDHParams, ctx->dhExchangePublic.data,
158 &outputLen, 128, rsaRandom, NO_SURR)) != 0)
159 { err = SSLUnknownErr;
160 goto fail;
161 }
162 ctx->dhExchangePublic.length = outputLen;
163 if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, 128, &ctx->sysCtx)) != 0)
164 goto fail;
165 if ((rsaResult = B_KeyAgreePhase2(ctx->peerDHParams, ctx->preMasterSecret.data,
166 &outputLen, 128, ctx->dhPeerPublic.data, ctx->dhPeerPublic.length,
167 NO_SURR)) != 0)
168 { err = SSLUnknownErr;
169 goto fail;
170 }
171 ctx->preMasterSecret.length = outputLen;
172 }
173 #endif
174
175 DUMP_BUFFER_NAME("premaster secret", ctx->preMasterSecret);
176
177 err = SSLNoErr;
178 fail:
179 #if RSAREF
180 ERR(SSLFreeBuffer(&privateValue, &ctx->sysCtx));
181 R_RandomFinal(&rsaRandom);
182 #elif BSAFE
183 B_DestroyAlgorithmObject(&rsaRandom);
184 #endif
185 return err;
186 #endif
187 }
188
189 #endif /* APPLE_DH */
190
191 SSLErr
192 SSLInitPendingCiphers(SSLContext *ctx)
193 { SSLErr err;
194 SSLBuffer key;
195 UInt8 *keyDataProgress, *keyPtr, *ivPtr;
196 int keyDataLen;
197 CipherContext *serverPending, *clientPending;
198
199 key.data = 0;
200
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;
207
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 */
213
214 if ((err = SSLAllocBuffer(&key, keyDataLen, &ctx->sysCtx)) != 0)
215 return err;
216 assert(ctx->sslTslCalls != NULL);
217 if ((err = ctx->sslTslCalls->generateKeyMaterial(key, ctx)) != 0)
218 goto fail;
219
220 if (ctx->protocolSide == SSL_ServerSide)
221 { serverPending = &ctx->writePending;
222 clientPending = &ctx->readPending;
223 }
224 else
225 { serverPending = &ctx->readPending;
226 clientPending = &ctx->writePending;
227 }
228
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;
236
237 /* init the reusable-per-record MAC contexts */
238 err = ctx->sslTslCalls->initMac(clientPending, ctx);
239 if(err) {
240 goto fail;
241 }
242 err = ctx->sslTslCalls->initMac(serverPending, ctx);
243 if(err) {
244 goto fail;
245 }
246
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)
255 goto fail;
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)
262 goto fail;
263 }
264 else {
265 UInt8 clientExportKey[16], serverExportKey[16],
266 clientExportIV[16], serverExportIV[16];
267 SSLBuffer clientWrite, serverWrite;
268 SSLBuffer finalClientWrite, finalServerWrite;
269 SSLBuffer finalClientIV, finalServerIV;
270
271 assert(ctx->selectedCipherSpec->cipher->keySize <= 16);
272 assert(ctx->selectedCipherSpec->cipher->ivSize <= 16);
273
274 /* Inputs to generateExportKeyAndIv are clientRandom, serverRandom,
275 * clientWriteKey, serverWriteKey. The first two are already present
276 * in ctx.
277 * Outputs are a key and IV for each of {server, client}.
278 */
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;
292
293 assert(ctx->sslTslCalls != NULL);
294 err = ctx->sslTslCalls->generateExportKeyAndIv(ctx, clientWrite, serverWrite,
295 finalClientWrite, finalServerWrite, finalClientIV, finalServerIV);
296 if(err) {
297 goto fail;
298 }
299 if ((err = ctx->selectedCipherSpec->cipher->initialize(clientExportKey,
300 clientExportIV, clientPending, ctx)) != 0)
301 goto fail;
302 if ((err = ctx->selectedCipherSpec->cipher->initialize(serverExportKey,
303 serverExportIV, serverPending, ctx)) != 0)
304 goto fail;
305 }
306
307 /* Ciphers are ready for use */
308 ctx->writePending.ready = 1;
309 ctx->readPending.ready = 1;
310
311 /* Ciphers get swapped by sending or receiving a change cipher spec message */
312
313 err = SSLNoErr;
314 fail:
315 SSLFreeBuffer(&key, &ctx->sysCtx);
316 return err;
317 }
318