]> git.saurik.com Git - apple/security.git/blob - SecureTransport/hdskkyex.c
9900d1b73e00c4e38f51ef79153284ba09555729
[apple/security.git] / SecureTransport / hdskkyex.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: hdskkyex.c
21
22 Contains: Support for key exchange and server key exchange
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: hdskkyex.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: hdskkyex.c Support for key exchange and server key exchange
47
48 Encoding and decoding of key exchange and server key exchange
49 messages in both the Diffie-Hellman and RSA variants; also, includes
50 the necessary crypto library calls to support this negotiation.
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 <assert.h>
83 #include <string.h>
84
85 /*
86 * Client RSA Key Exchange msgs actually start with a two-byte
87 * length field, contrary to the first version of RFC 2246, dated
88 * January 1999. See RFC 2246, March 2002, section 7.4.7.1 for
89 * updated requirements.
90 */
91 #define RSA_CLIENT_KEY_ADD_LENGTH 1
92
93 typedef CSSM_KEY_PTR SSLRSAPrivateKey;
94
95 static SSLErr SSLEncodeRSAServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx);
96 static SSLErr SSLEncodeRSAKeyParams(SSLBuffer *keyParams, SSLRSAPrivateKey *key, SSLContext *ctx);
97 static SSLErr SSLProcessRSAServerKeyExchange(SSLBuffer message, SSLContext *ctx);
98 static SSLErr SSLDecodeRSAKeyExchange(SSLBuffer keyExchange, SSLContext *ctx);
99 static SSLErr SSLEncodeRSAKeyExchange(SSLRecord *keyExchange, SSLContext *ctx);
100 #if APPLE_DH
101 static SSLErr SSLEncodeDHanonServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx);
102 static SSLErr SSLEncodeDHanonKeyExchange(SSLRecord *keyExchange, SSLContext *ctx);
103 static SSLErr SSLDecodeDHanonKeyExchange(SSLBuffer keyExchange, SSLContext *ctx);
104 static SSLErr SSLProcessDHanonServerKeyExchange(SSLBuffer message, SSLContext *ctx);
105 #endif
106
107 SSLErr
108 SSLEncodeServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx)
109 { SSLErr err;
110
111 switch (ctx->selectedCipherSpec->keyExchangeMethod)
112 { case SSL_RSA:
113 case SSL_RSA_EXPORT:
114 if (ERR(err = SSLEncodeRSAServerKeyExchange(keyExch, ctx)) != 0)
115 return err;
116 break;
117 #if APPLE_DH
118 case SSL_DH_anon:
119 if (ERR(err = SSLEncodeDHanonServerKeyExchange(keyExch, ctx)) != 0)
120 return err;
121 break;
122 #endif
123 default:
124 return ERR(SSLUnsupportedErr);
125 }
126
127 return SSLNoErr;
128 }
129
130 static SSLErr
131 SSLEncodeRSAServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx)
132 { SSLErr err;
133 UInt8 *progress;
134 int length;
135 UInt32 outputLen, localKeyModulusLen;
136 UInt8 hashes[36];
137 SSLBuffer exportKey,clientRandom,serverRandom,hashCtx, hash;
138
139 exportKey.data = 0;
140 hashCtx.data = 0;
141
142 /* we have a public key here... */
143 CASSERT(ctx->encryptPubKey != NULL);
144 CASSERT(ctx->protocolSide == SSL_ServerSide);
145
146 if ((err = SSLEncodeRSAKeyParams(&exportKey, &ctx->encryptPubKey, ctx)) != 0)
147 goto fail;
148
149 CASSERT(ctx->signingPubKey != NULL);
150 localKeyModulusLen = sslKeyLengthInBytes(ctx->signingPubKey);
151
152 length = exportKey.length + 2 + localKeyModulusLen; /* RSA ouputs a block as long as the modulus */
153
154 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
155 (ctx->negProtocolVersion == TLS_Version_1_0));
156 keyExch->protocolVersion = ctx->negProtocolVersion;
157 keyExch->contentType = SSL_handshake;
158 if (ERR(err = SSLAllocBuffer(&keyExch->contents, length+4, &ctx->sysCtx)) != 0)
159 goto fail;
160
161 progress = keyExch->contents.data;
162 *progress++ = SSL_server_key_exchange;
163 progress = SSLEncodeInt(progress, length, 3);
164
165 memcpy(progress, exportKey.data, exportKey.length);
166 progress += exportKey.length;
167
168 clientRandom.data = ctx->clientRandom;
169 clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
170 serverRandom.data = ctx->serverRandom;
171 serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
172
173 hash.data = &hashes[0];
174 hash.length = 16;
175 if (ERR(err = ReadyHash(&SSLHashMD5, &hashCtx, ctx)) != 0)
176 goto fail;
177 if (ERR(err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
178 goto fail;
179 if (ERR(err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
180 goto fail;
181 if (ERR(err = SSLHashMD5.update(hashCtx, exportKey)) != 0)
182 goto fail;
183 if (ERR(err = SSLHashMD5.final(hashCtx, hash)) != 0)
184 goto fail;
185 if (ERR(err = SSLFreeBuffer(&hashCtx, &ctx->sysCtx)) != 0)
186 goto fail;
187
188 hash.data = &hashes[16];
189 hash.length = 20;
190 if (ERR(err = ReadyHash(&SSLHashSHA1, &hashCtx, ctx)) != 0)
191 goto fail;
192 if (ERR(err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0)
193 goto fail;
194 if (ERR(err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0)
195 goto fail;
196 if (ERR(err = SSLHashSHA1.update(hashCtx, exportKey)) != 0)
197 goto fail;
198 if (ERR(err = SSLHashSHA1.final(hashCtx, hash)) != 0)
199 goto fail;
200 if (ERR(err = SSLFreeBuffer(&hashCtx, &ctx->sysCtx)) != 0)
201 goto fail;
202
203 progress = SSLEncodeInt(progress, localKeyModulusLen, 2);
204 err = sslRsaRawSign(ctx,
205 ctx->signingPrivKey,
206 ctx->signingKeyCsp,
207 hashes,
208 36,
209 progress,
210 length,
211 &outputLen);
212 if(err) {
213 goto fail;
214 }
215 CASSERT(outputLen == localKeyModulusLen);
216
217 err = SSLNoErr;
218
219 fail:
220 ERR(SSLFreeBuffer(&hashCtx, &ctx->sysCtx));
221 ERR(SSLFreeBuffer(&exportKey, &ctx->sysCtx));
222
223 return err;
224 }
225
226 static SSLErr
227 SSLEncodeRSAKeyParams(SSLBuffer *keyParams, SSLRSAPrivateKey *key, SSLContext *ctx)
228 { SSLErr err;
229 SSLBuffer modulus, exponent;
230 UInt8 *progress;
231
232 err = sslGetPubKeyBits(ctx,
233 *key,
234 ctx->encryptKeyCsp,
235 &modulus,
236 &exponent);
237 if(err) {
238 SSLFreeBuffer(&modulus, &ctx->sysCtx);
239 SSLFreeBuffer(&exponent, &ctx->sysCtx);
240 return err;
241 }
242
243 if (ERR(err = SSLAllocBuffer(keyParams, modulus.length + exponent.length + 4, &ctx->sysCtx)) != 0)
244 return err;
245 progress = keyParams->data;
246 progress = SSLEncodeInt(progress, modulus.length, 2);
247 memcpy(progress, modulus.data, modulus.length);
248 progress += modulus.length;
249 progress = SSLEncodeInt(progress, exponent.length, 2);
250 memcpy(progress, exponent.data, exponent.length);
251
252 /* these were mallocd by sslGetPubKeyBits() */
253 SSLFreeBuffer(&modulus, &ctx->sysCtx);
254 SSLFreeBuffer(&exponent, &ctx->sysCtx);
255 return SSLNoErr;
256 }
257
258 #if APPLE_DH
259 static SSLErr
260 SSLEncodeDHanonServerKeyExchange(SSLRecord *keyExch, SSLContext *ctx)
261 { SSLErr err;
262 UInt32 length;
263 UInt8 *progress;
264 SSLRandomCtx random;
265 int rsaErr;
266
267 #if RSAREF
268 length = 6 + ctx->dhAnonParams.primeLen + ctx->dhAnonParams.generatorLen +
269 ctx->dhExchangePublic.length;
270
271 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
272 (ctx->negProtocolVersion == TLS_Version_1_0));
273 keyExch->protocolVersion = ctx->negProtocolVersion;
274 keyExch->contentType = SSL_handshake;
275 if (ERR(err = SSLAllocBuffer(&keyExch->contents, length+4, &ctx->sysCtx)) != 0)
276 return err;
277
278 progress = keyExch->contents.data;
279 *progress++ = SSL_server_key_exchange;
280 progress = SSLEncodeInt(progress, length, 3);
281
282 progress = SSLEncodeInt(progress, ctx->dhAnonParams.primeLen, 2);
283 memcpy(progress, ctx->dhAnonParams.prime, ctx->dhAnonParams.primeLen);
284 progress += ctx->dhAnonParams.primeLen;
285
286 progress = SSLEncodeInt(progress, ctx->dhAnonParams.generatorLen, 2);
287 memcpy(progress, ctx->dhAnonParams.generator, ctx->dhAnonParams.generatorLen);
288 progress += ctx->dhAnonParams.generatorLen;
289
290 if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, ctx->peerDHParams.primeLen, &ctx->sysCtx)) != 0)
291 return err;
292 if (ERR(err = SSLAllocBuffer(&ctx->dhPrivate, ctx->dhExchangePublic.length - 16, &ctx->sysCtx)) != 0)
293 return err;
294
295 if (ERR(err = ReadyRandom(&random, ctx)) != 0)
296 return err;
297
298 if ((rsaErr = R_SetupDHAgreement(ctx->dhExchangePublic.data, ctx->dhPrivate.data,
299 ctx->dhPrivate.length, &ctx->dhAnonParams, &random)) != 0)
300 { err = SSLUnknownErr;
301 return err;
302 }
303
304 progress = SSLEncodeInt(progress, ctx->dhExchangePublic.length, 2);
305 memcpy(progress, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length);
306 progress += ctx->dhExchangePublic.length;
307
308 #elif BSAFE
309 { A_DH_KEY_AGREE_PARAMS *params;
310 unsigned int outputLen;
311
312 if ((rsaErr = B_GetAlgorithmInfo((POINTER*)&params, ctx->dhAnonParams, AI_DHKeyAgree)) != 0)
313 return SSLUnknownErr;
314 if (ERR(err = ReadyRandom(&random, ctx)) != 0)
315 return err;
316 if (ERR(err = SSLAllocBuffer(&ctx->dhExchangePublic, 128, &ctx->sysCtx)) != 0)
317 return err;
318 if ((rsaErr = B_KeyAgreePhase1(ctx->dhAnonParams, ctx->dhExchangePublic.data,
319 &outputLen, 128, random, NO_SURR)) != 0)
320 { err = SSLUnknownErr;
321 return err;
322 }
323 ctx->dhExchangePublic.length = outputLen;
324
325 length = 6 + params->prime.len + params->base.len + ctx->dhExchangePublic.length;
326
327 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
328 (ctx->negProtocolVersion == TLS_Version_1_0));
329 keyExch->protocolVersion = ctx->negProtocolVersion;
330 keyExch->contentType = SSL_handshake;
331 if (ERR(err = SSLAllocBuffer(&keyExch->contents, length+4, &ctx->sysCtx)) != 0)
332 return err;
333
334 progress = keyExch->contents.data;
335 *progress++ = SSL_server_key_exchange;
336 progress = SSLEncodeInt(progress, length, 3);
337
338 progress = SSLEncodeInt(progress, params->prime.len, 2);
339 memcpy(progress, params->prime.data, params->prime.len);
340 progress += params->prime.len;
341
342 progress = SSLEncodeInt(progress, params->base.len, 2);
343 memcpy(progress, params->base.data, params->base.len);
344 progress += params->base.len;
345
346 progress = SSLEncodeInt(progress, ctx->dhExchangePublic.length, 2);
347 memcpy(progress, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length);
348 progress += ctx->dhExchangePublic.length;
349 }
350 #endif /* RSAREF / BSAFE */
351
352 ASSERT(progress == keyExch->contents.data + keyExch->contents.length);
353
354 return SSLNoErr;
355 }
356
357 #endif /* APPLE_DH */
358
359 SSLErr
360 SSLProcessServerKeyExchange(SSLBuffer message, SSLContext *ctx)
361 { SSLErr err;
362
363 switch (ctx->selectedCipherSpec->keyExchangeMethod)
364 { case SSL_RSA:
365 case SSL_RSA_EXPORT:
366 if (ERR(err = SSLProcessRSAServerKeyExchange(message, ctx)) != 0)
367 return err;
368 break;
369 #if APPLE_DH
370 case SSL_DH_anon:
371 if (ERR(err = SSLProcessDHanonServerKeyExchange(message, ctx)) != 0)
372 return err;
373 break;
374 #endif
375 default:
376 return ERR(SSLUnsupportedErr);
377 }
378
379 return SSLNoErr;
380 }
381
382 static SSLErr
383 SSLProcessRSAServerKeyExchange(SSLBuffer message, SSLContext *ctx)
384 {
385 SSLErr err;
386 SSLBuffer tempPubKey, hashOut, hashCtx, clientRandom, serverRandom;
387 UInt16 modulusLen, exponentLen, signatureLen;
388 UInt8 *progress, *modulus, *exponent, *signature;
389 UInt8 hash[36];
390 SSLBuffer signedHashes;
391
392 signedHashes.data = 0;
393 hashCtx.data = 0;
394
395 if (message.length < 2) {
396 errorLog0("SSLProcessRSAServerKeyExchange: msg len error 2\n");
397 return ERR(SSLProtocolErr);
398 }
399 progress = message.data;
400 modulusLen = SSLDecodeInt(progress, 2);
401 modulus = progress + 2;
402 progress += 2+modulusLen;
403 if (message.length < 4 + modulusLen) {
404 errorLog0("SSLProcessRSAServerKeyExchange: msg len error 2\n");
405 return ERR(SSLProtocolErr);
406 }
407 exponentLen = SSLDecodeInt(progress, 2);
408 exponent = progress + 2;
409 progress += 2+exponentLen;
410 if (message.length < 6 + modulusLen + exponentLen) {
411 errorLog0("SSLProcessRSAServerKeyExchange: msg len error 2\n");
412 return ERR(SSLProtocolErr);
413 }
414 signatureLen = SSLDecodeInt(progress, 2);
415 signature = progress + 2;
416 if (message.length != 6 + modulusLen + exponentLen + signatureLen) {
417 errorLog0("SSLProcessRSAServerKeyExchange: msg len error 3\n");
418 return ERR(SSLProtocolErr);
419 }
420
421 clientRandom.data = ctx->clientRandom;
422 clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
423 serverRandom.data = ctx->serverRandom;
424 serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
425 tempPubKey.data = message.data;
426 tempPubKey.length = modulusLen + exponentLen + 4;
427 hashOut.data = hash;
428
429 hashOut.length = 16;
430 if (ERR(err = ReadyHash(&SSLHashMD5, &hashCtx, ctx)) != 0)
431 goto fail;
432 if (ERR(err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
433 goto fail;
434 if (ERR(err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
435 goto fail;
436 if (ERR(err = SSLHashMD5.update(hashCtx, tempPubKey)) != 0)
437 goto fail;
438 if (ERR(err = SSLHashMD5.final(hashCtx, hashOut)) != 0)
439 goto fail;
440
441 /*
442 * SHA hash goes right after the MD5 hash
443 */
444 hashOut.data = hash + 16;
445 hashOut.length = 20;
446 if (ERR(err = SSLFreeBuffer(&hashCtx, &ctx->sysCtx)) != 0)
447 goto fail;
448
449 if (ERR(err = ReadyHash(&SSLHashSHA1, &hashCtx, ctx)) != 0)
450 goto fail;
451 if (ERR(err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0)
452 goto fail;
453 if (ERR(err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0)
454 goto fail;
455 if (ERR(err = SSLHashSHA1.update(hashCtx, tempPubKey)) != 0)
456 goto fail;
457 if (ERR(err = SSLHashSHA1.final(hashCtx, hashOut)) != 0)
458 goto fail;
459
460 err = sslRsaRawVerify(ctx,
461 ctx->peerPubKey,
462 ctx->peerPubKeyCsp,
463 hash, /* plaintext */
464 36, /* plaintext length */
465 signature,
466 signatureLen);
467 if(err) {
468 errorLog1("SSLProcessRSAServerKeyExchange: sslRsaRawVerify returned %d\n",
469 err);
470 goto fail;
471 }
472
473 /* Signature matches; now replace server key with new key */
474 {
475 SSLBuffer modBuf;
476 SSLBuffer expBuf;
477
478 /* first free existing peerKey */
479 sslFreeKey(ctx->peerPubKeyCsp,
480 &ctx->peerPubKey,
481 NULL); /* no KCItem */
482
483 /* and cook up a new one from raw bits */
484 modBuf.data = modulus;
485 modBuf.length = modulusLen;
486 expBuf.data = exponent;
487 expBuf.length = exponentLen;
488 err = sslGetPubKeyFromBits(ctx,
489 &modBuf,
490 &expBuf,
491 &ctx->peerPubKey,
492 &ctx->peerPubKeyCsp);
493 }
494 fail:
495 ERR(SSLFreeBuffer(&signedHashes, &ctx->sysCtx));
496 ERR(SSLFreeBuffer(&hashCtx, &ctx->sysCtx));
497 return err;
498 }
499
500 #if APPLE_DH
501 static SSLErr
502 SSLProcessDHanonServerKeyExchange(SSLBuffer message, SSLContext *ctx)
503 { SSLErr err;
504 UInt8 *progress;
505 unsigned int totalLength;
506
507 if (message.length < 6) {
508 errorLog1("SSLProcessDHanonServerKeyExchange error: msg len %d\n",
509 message.length);
510 return ERR(SSLProtocolErr);
511 }
512 progress = message.data;
513 totalLength = 0;
514
515 #if RSAREF
516 { SSLBuffer alloc;
517 UInt8 *prime, *generator, *publicVal;
518
519 ctx->peerDHParams.primeLen = SSLDecodeInt(progress, 2);
520 progress += 2;
521 prime = progress;
522 progress += ctx->peerDHParams.primeLen;
523 totalLength += ctx->peerDHParams.primeLen;
524 if (message.length < 6 + totalLength)
525 return ERR(SSLProtocolErr);
526
527 ctx->peerDHParams.generatorLen = SSLDecodeInt(progress, 2);
528 progress += 2;
529 generator = progress;
530 progress += ctx->peerDHParams.generatorLen;
531 totalLength += ctx->peerDHParams.generatorLen;
532 if (message.length < 6 + totalLength)
533 return ERR(SSLProtocolErr);
534
535 ctx->dhPeerPublic.length = SSLDecodeInt(progress, 2);
536 progress += 2;
537 publicVal = progress;
538 progress += ctx->dhPeerPublic.length;
539 totalLength += ctx->dhPeerPublic.length;
540 if (message.length != 6 + totalLength)
541 return ERR(SSLProtocolErr);
542
543 ASSERT(progress == message.data + message.length);
544
545 if (ERR(err = SSLAllocBuffer(&alloc, ctx->peerDHParams.primeLen +
546 ctx->peerDHParams.generatorLen, &ctx->sysCtx)) != 0)
547 return err;
548
549 ctx->peerDHParams.prime = alloc.data;
550 memcpy(ctx->peerDHParams.prime, prime, ctx->peerDHParams.primeLen);
551 ctx->peerDHParams.generator = alloc.data + ctx->peerDHParams.primeLen;
552 memcpy(ctx->peerDHParams.generator, generator, ctx->peerDHParams.generatorLen);
553
554 if (ERR(err = SSLAllocBuffer(&ctx->dhPeerPublic,
555 ctx->dhPeerPublic.length, &ctx->sysCtx)) != 0)
556 return err;
557
558 memcpy(ctx->dhPeerPublic.data, publicVal, ctx->dhPeerPublic.length);
559 }
560 #elif BSAFE
561 { int rsaErr;
562 unsigned char *publicVal;
563 A_DH_KEY_AGREE_PARAMS params;
564 B_ALGORITHM_METHOD *chooser[] = { &AM_DH_KEY_AGREE, 0 };
565
566 params.prime.len = SSLDecodeInt(progress, 2);
567 progress += 2;
568 params.prime.data = progress;
569 progress += params.prime.len;
570 totalLength += params.prime.len;
571 if (message.length < 6 + totalLength)
572 return ERR(SSLProtocolErr);
573
574 params.base.len = SSLDecodeInt(progress, 2);
575 progress += 2;
576 params.base.data = progress;
577 progress += params.base.len;
578 totalLength += params.base.len;
579 if (message.length < 6 + totalLength)
580 return ERR(SSLProtocolErr);
581
582 ctx->dhPeerPublic.length = SSLDecodeInt(progress, 2);
583 if (ERR(err = SSLAllocBuffer(&ctx->dhPeerPublic, ctx->dhPeerPublic.length, &ctx->sysCtx)) != 0)
584 return err;
585
586 progress += 2;
587 publicVal = progress;
588 progress += ctx->dhPeerPublic.length;
589 totalLength += ctx->dhPeerPublic.length;
590 memcpy(ctx->dhPeerPublic.data, publicVal, ctx->dhPeerPublic.length);
591 if (message.length != 6 + totalLength)
592 return ERR(SSLProtocolErr);
593
594 params.exponentBits = 8 * ctx->dhPeerPublic.length - 1;
595
596 if ((rsaErr = B_CreateAlgorithmObject(&ctx->peerDHParams)) != 0)
597 return SSLUnknownErr;
598 if ((rsaErr = B_SetAlgorithmInfo(ctx->peerDHParams, AI_DHKeyAgree, (POINTER)&params)) != 0)
599 return SSLUnknownErr;
600 if ((rsaErr = B_KeyAgreeInit(ctx->peerDHParams, (B_KEY_OBJ) 0, chooser, NO_SURR)) != 0)
601 return SSLUnknownErr;
602 }
603 #endif
604
605 return SSLNoErr;
606 }
607
608 #endif
609
610 SSLErr
611 SSLProcessKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
612 { SSLErr err;
613
614 switch (ctx->selectedCipherSpec->keyExchangeMethod)
615 { case SSL_RSA:
616 case SSL_RSA_EXPORT:
617 if (ERR(err = SSLDecodeRSAKeyExchange(keyExchange, ctx)) != 0)
618 return err;
619 break;
620 #if APPLE_DH
621 case SSL_DH_anon:
622 if (ERR(err = SSLDecodeDHanonKeyExchange(keyExchange, ctx)) != 0)
623 return err;
624 break;
625 #endif
626 default:
627 return ERR(SSLUnsupportedErr);
628 }
629
630 return SSLNoErr;
631 }
632
633 static SSLErr
634 SSLDecodeRSAKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
635 { SSLErr err;
636 SSLBuffer result;
637 UInt32 outputLen, localKeyModulusLen;
638 CSSM_KEY_PTR *key;
639 SSLProtocolVersion version;
640 Boolean useEncryptKey = false;
641 UInt8 *src = NULL;
642
643
644 /* different key names, also need CSP handle */
645 CSSM_CSP_HANDLE cspHand;
646
647 CASSERT(ctx->protocolSide == SSL_ServerSide);
648
649 /*
650 * FIXME - The original SSLRef looked at
651 * ctx->selectedCipherSpec->keyExchangeMethod to decide which
652 * key to use (exportKey or localKey). I really don't think we
653 * want to use that - it's constant. We need to look at
654 * whether the app specified encrypting certs, right?
655 */
656 #if SSL_SERVER_KEYEXCH_HACK
657 /*
658 * the way we work with Netscape.
659 * FIXME - maybe we should *require* an encryptPrivKey in this
660 * situation?
661 */
662 if((ctx->selectedCipherSpec->keyExchangeMethod == SSL_RSA_EXPORT) &&
663 (ctx->encryptPrivKey != NULL)) {
664 useEncryptKey = true;
665 }
666
667 #else /* !SSL_SERVER_KEYEXCH_HACK */
668 /* The "correct" way, I think, which doesn't work with Netscape */
669 if (ctx->encryptPrivKey) {
670 useEncryptKey = true;
671 }
672 #endif /* SSL_SERVER_KEYEXCH_HACK */
673 if (useEncryptKey) {
674 key = &ctx->encryptPrivKey;
675 cspHand = ctx->encryptKeyCsp;
676 }
677 else {
678 key = &ctx->signingPrivKey;
679 cspHand = ctx->signingKeyCsp;
680 }
681
682 localKeyModulusLen = sslKeyLengthInBytes(*key);
683
684 /*
685 * We have to tolerate incoming key exchange msgs with and without the
686 * two-byte "encrypted length" field.
687 */
688 if (keyExchange.length == localKeyModulusLen) {
689 /* no length encoded */
690 src = keyExchange.data;
691 }
692 else if((keyExchange.length == (localKeyModulusLen + 2)) &&
693 (ctx->negProtocolVersion >= TLS_Version_1_0)) {
694 /* TLS only - skip the length bytes */
695 src = keyExchange.data + 2;
696 }
697 else {
698 errorLog2("SSLDecodeRSAKeyExchange: length error (exp %u got %u)\n",
699 (unsigned)localKeyModulusLen, (unsigned)keyExchange.length);
700 return ERR(SSLProtocolErr);
701 }
702 err = SSLAllocBuffer(&result, localKeyModulusLen, &ctx->sysCtx);
703 if(err != 0) {
704 return err;
705 }
706
707 err = sslRsaDecrypt(ctx,
708 *key,
709 cspHand,
710 src,
711 localKeyModulusLen,
712 result.data,
713 48,
714 &outputLen);
715 if(err) {
716 goto fail;
717 }
718
719 if (outputLen != 48)
720 {
721 errorLog0("SSLDecodeRSAKeyExchange: outputLen error\n");
722 ERR(err = SSLProtocolErr);
723 goto fail;
724 }
725 result.length = outputLen;
726
727 version = (SSLProtocolVersion)SSLDecodeInt(result.data, 2);
728 /* Modify this check to check against our maximum version with protocol revisions */
729 if (version > ctx->negProtocolVersion && version < SSL_Version_3_0) {
730 errorLog0("SSLDecodeRSAKeyExchange: version error\n");
731 ERR(err = SSLProtocolErr);
732 goto fail;
733 }
734 if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret,
735 SSL_RSA_PREMASTER_SECRET_SIZE, &ctx->sysCtx)) != 0)
736 goto fail;
737 memcpy(ctx->preMasterSecret.data, result.data,
738 SSL_RSA_PREMASTER_SECRET_SIZE);
739
740 err = SSLNoErr;
741 fail:
742 ERR(SSLFreeBuffer(&result, &ctx->sysCtx));
743 return err;
744 }
745
746 #if APPLE_DH
747 static SSLErr
748 SSLDecodeDHanonKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
749 { SSLErr err;
750 unsigned int publicLen;
751 int rsaResult;
752
753 publicLen = SSLDecodeInt(keyExchange.data, 2);
754
755 #if RSAREF
756 if (keyExchange.length != publicLen + 2 ||
757 publicLen != ctx->dhAnonParams.primeLen)
758 return ERR(SSLProtocolErr);
759
760 if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, ctx->dhAnonParams.primeLen, &ctx->sysCtx)) != 0)
761 return err;
762
763 if ((rsaResult = R_ComputeDHAgreedKey (ctx->preMasterSecret.data, ctx->dhPeerPublic.data,
764 ctx->dhPrivate.data, ctx->dhPrivate.length, &ctx->dhAnonParams)) != 0)
765 { err = SSLUnknownErr;
766 return err;
767 }
768
769 #elif BSAFE
770 { unsigned int amount;
771 if (keyExchange.length != publicLen + 2)
772 return ERR(SSLProtocolErr);
773
774 if (ERR(err = SSLAllocBuffer(&ctx->preMasterSecret, 128, &ctx->sysCtx)) != 0)
775 return err;
776
777 if ((rsaResult = B_KeyAgreePhase2(ctx->dhAnonParams, ctx->preMasterSecret.data,
778 &amount, 128, keyExchange.data+2, publicLen, NO_SURR)) != 0)
779 return err;
780
781 ctx->preMasterSecret.length = amount;
782 }
783 #endif
784
785 return SSLNoErr;
786 }
787 #endif /* APPLE_DH */
788
789 SSLErr
790 SSLEncodeKeyExchange(SSLRecord *keyExchange, SSLContext *ctx)
791 { SSLErr err;
792
793 CASSERT(ctx->protocolSide == SSL_ClientSide);
794
795 switch (ctx->selectedCipherSpec->keyExchangeMethod)
796 { case SSL_RSA:
797 case SSL_RSA_EXPORT:
798 if (ERR(err = SSLEncodeRSAKeyExchange(keyExchange, ctx)) != 0)
799 return err;
800 break;
801 #if APPLE_DH
802 case SSL_DH_anon:
803 if (ERR(err = SSLEncodeDHanonKeyExchange(keyExchange, ctx)) != 0)
804 return err;
805 break;
806 #endif
807 default:
808 return ERR(SSLUnsupportedErr);
809 }
810
811 return SSLNoErr;
812 }
813
814 static SSLErr
815 SSLEncodeRSAKeyExchange(SSLRecord *keyExchange, SSLContext *ctx)
816 { SSLErr err;
817 UInt32 outputLen, peerKeyModulusLen;
818 UInt32 bufLen;
819 UInt8 *dst;
820 bool encodeLen = false;
821
822 if (ERR(err = SSLEncodeRSAPremasterSecret(ctx)) != 0)
823 return err;
824
825 keyExchange->contentType = SSL_handshake;
826 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
827 (ctx->negProtocolVersion == TLS_Version_1_0));
828 keyExchange->protocolVersion = ctx->negProtocolVersion;
829
830 peerKeyModulusLen = sslKeyLengthInBytes(ctx->peerPubKey);
831 bufLen = peerKeyModulusLen + 4;
832 #if RSA_CLIENT_KEY_ADD_LENGTH
833 if(ctx->negProtocolVersion >= TLS_Version_1_0) {
834 bufLen += 2;
835 encodeLen = true;
836 }
837 #endif
838 if (ERR(err = SSLAllocBuffer(&keyExchange->contents,
839 bufLen,&ctx->sysCtx)) != 0)
840 {
841 return err;
842 }
843 dst = keyExchange->contents.data + 4;
844 if(encodeLen) {
845 dst += 2;
846 }
847 keyExchange->contents.data[0] = SSL_client_key_exchange;
848
849 /* this is the record payload length */
850 SSLEncodeInt(keyExchange->contents.data + 1, bufLen - 4, 3);
851 if(encodeLen) {
852 /* the length of the encrypted pre_master_secret */
853 SSLEncodeInt(keyExchange->contents.data + 4,
854 peerKeyModulusLen, 2);
855 }
856 err = sslRsaEncrypt(ctx,
857 ctx->peerPubKey,
858 /* FIXME - maybe this should be ctx->cspHand */
859 ctx->peerPubKeyCsp,
860 ctx->preMasterSecret.data,
861 SSL_RSA_PREMASTER_SECRET_SIZE,
862 dst,
863 peerKeyModulusLen,
864 &outputLen);
865 if(err) {
866 return err;
867 }
868
869 CASSERT(outputLen == encodeLen ?
870 keyExchange->contents.length - 6 :
871 keyExchange->contents.length - 4 );
872
873 return SSLNoErr;
874 }
875
876 #if APPLE_DH
877 static SSLErr
878 SSLEncodeDHanonKeyExchange(SSLRecord *keyExchange, SSLContext *ctx)
879 { SSLErr err;
880 unsigned int outputLen;
881
882 if (ERR(err = SSLEncodeDHPremasterSecret(ctx)) != 0)
883 return err;
884
885 outputLen = ctx->dhExchangePublic.length + 2;
886
887 keyExchange->contentType = SSL_handshake;
888 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
889 (ctx->negProtocolVersion == TLS_Version_1_0));
890 keyExchange->protocolVersion = ctx->negProtocolVersion;
891
892 if (ERR(err = SSLAllocBuffer(&keyExchange->contents,outputLen + 4,&ctx->sysCtx)) != 0)
893 return err;
894
895 keyExchange->contents.data[0] = SSL_client_key_exchange;
896 SSLEncodeInt(keyExchange->contents.data+1, ctx->dhExchangePublic.length+2, 3);
897
898 SSLEncodeInt(keyExchange->contents.data+4, ctx->dhExchangePublic.length, 2);
899 memcpy(keyExchange->contents.data+6, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length);
900
901 return SSLNoErr;
902 }
903 #endif
904