]> git.saurik.com Git - apple/security.git/blob - SecureTransport/sslKeyExchange.cpp
6ea3fab5e1b357872ef3455c8f493781d0ec8d0b
[apple/security.git] / SecureTransport / sslKeyExchange.cpp
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: sslKeyExchange.c
21
22 Contains: Support for key exchange and server key exchange
23
24 Written by: Doug Mitchell
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29
30 #include "sslContext.h"
31 #include "sslHandshake.h"
32 #include "sslMemory.h"
33 #include "sslDebug.h"
34 #include "sslUtils.h"
35 #include "appleCdsa.h"
36 #include "sslDigests.h"
37
38 #include <assert.h>
39 #include <string.h>
40
41 /*
42 * Client RSA Key Exchange msgs actually start with a two-byte
43 * length field, contrary to the first version of RFC 2246, dated
44 * January 1999. See RFC 2246, March 2002, section 7.4.7.1 for
45 * updated requirements.
46 */
47 #define RSA_CLIENT_KEY_ADD_LENGTH 1
48
49 typedef CSSM_KEY_PTR SSLRSAPrivateKey;
50
51 static OSStatus SSLEncodeRSAServerKeyExchange(SSLRecord &keyExch, SSLContext *ctx);
52 static OSStatus SSLEncodeRSAKeyParams(SSLBuffer *keyParams, SSLRSAPrivateKey *key, SSLContext *ctx);
53 static OSStatus SSLProcessRSAServerKeyExchange(SSLBuffer message, SSLContext *ctx);
54 static OSStatus SSLDecodeRSAKeyExchange(SSLBuffer keyExchange, SSLContext *ctx);
55 static OSStatus SSLEncodeRSAKeyExchange(SSLRecord &keyExchange, SSLContext *ctx);
56 #if APPLE_DH
57 static OSStatus SSLEncodeDHanonServerKeyExchange(SSLRecord &keyExch, SSLContext *ctx);
58 static OSStatus SSLEncodeDHanonKeyExchange(SSLRecord &keyExchange, SSLContext *ctx);
59 static OSStatus SSLDecodeDHanonKeyExchange(SSLBuffer keyExchange, SSLContext *ctx);
60 static OSStatus SSLProcessDHanonServerKeyExchange(SSLBuffer message, SSLContext *ctx);
61 #endif
62
63 OSStatus
64 SSLEncodeServerKeyExchange(SSLRecord &keyExch, SSLContext *ctx)
65 { OSStatus err;
66
67 switch (ctx->selectedCipherSpec->keyExchangeMethod)
68 { case SSL_RSA:
69 case SSL_RSA_EXPORT:
70 if ((err = SSLEncodeRSAServerKeyExchange(keyExch, ctx)) != 0)
71 return err;
72 break;
73 #if APPLE_DH
74 case SSL_DH_anon:
75 if ((err = SSLEncodeDHanonServerKeyExchange(keyExch, ctx)) != 0)
76 return err;
77 break;
78 #endif
79 default:
80 return unimpErr;
81 }
82
83 return noErr;
84 }
85
86 static OSStatus
87 SSLEncodeRSAServerKeyExchange(SSLRecord &keyExch, SSLContext *ctx)
88 { OSStatus err;
89 UInt8 *charPtr;
90 int length;
91 UInt32 outputLen, localKeyModulusLen;
92 UInt8 hashes[36];
93 SSLBuffer exportKey,clientRandom,serverRandom,hashCtx, hash;
94
95 exportKey.data = 0;
96 hashCtx.data = 0;
97
98 /* we have a public key here... */
99 assert(ctx->encryptPubKey != NULL);
100 assert(ctx->protocolSide == SSL_ServerSide);
101
102 if ((err = SSLEncodeRSAKeyParams(&exportKey, &ctx->encryptPubKey, ctx)) != 0)
103 goto fail;
104
105 assert(ctx->signingPubKey != NULL);
106 localKeyModulusLen = sslKeyLengthInBytes(ctx->signingPubKey);
107
108 length = exportKey.length + 2 + localKeyModulusLen;
109 /* RSA ouputs a block as long as the modulus */
110
111 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
112 (ctx->negProtocolVersion == TLS_Version_1_0));
113 keyExch.protocolVersion = ctx->negProtocolVersion;
114 keyExch.contentType = SSL_RecordTypeHandshake;
115 if ((err = SSLAllocBuffer(keyExch.contents, length+4, ctx)) != 0)
116 goto fail;
117
118 charPtr = keyExch.contents.data;
119 *charPtr++ = SSL_HdskServerKeyExchange;
120 charPtr = SSLEncodeInt(charPtr, length, 3);
121
122 memcpy(charPtr, exportKey.data, exportKey.length);
123 charPtr += exportKey.length;
124
125 clientRandom.data = ctx->clientRandom;
126 clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
127 serverRandom.data = ctx->serverRandom;
128 serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
129
130 hash.data = &hashes[0];
131 hash.length = 16;
132 if ((err = ReadyHash(SSLHashMD5, hashCtx, ctx)) != 0)
133 goto fail;
134 if ((err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
135 goto fail;
136 if ((err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
137 goto fail;
138 if ((err = SSLHashMD5.update(hashCtx, exportKey)) != 0)
139 goto fail;
140 if ((err = SSLHashMD5.final(hashCtx, hash)) != 0)
141 goto fail;
142 if ((err = SSLFreeBuffer(hashCtx, ctx)) != 0)
143 goto fail;
144
145 hash.data = &hashes[16];
146 hash.length = 20;
147 if ((err = ReadyHash(SSLHashSHA1, hashCtx, ctx)) != 0)
148 goto fail;
149 if ((err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0)
150 goto fail;
151 if ((err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0)
152 goto fail;
153 if ((err = SSLHashSHA1.update(hashCtx, exportKey)) != 0)
154 goto fail;
155 if ((err = SSLHashSHA1.final(hashCtx, hash)) != 0)
156 goto fail;
157 if ((err = SSLFreeBuffer(hashCtx, ctx)) != 0)
158 goto fail;
159
160 charPtr = SSLEncodeInt(charPtr, localKeyModulusLen, 2);
161 err = sslRsaRawSign(ctx,
162 ctx->signingPrivKey,
163 ctx->signingKeyCsp,
164 hashes,
165 36,
166 charPtr,
167 length,
168 &outputLen);
169 if(err) {
170 goto fail;
171 }
172 assert(outputLen == localKeyModulusLen);
173
174 err = noErr;
175
176 fail:
177 SSLFreeBuffer(hashCtx, ctx);
178 SSLFreeBuffer(exportKey, ctx);
179
180 return err;
181 }
182
183 static OSStatus
184 SSLEncodeRSAKeyParams(SSLBuffer *keyParams, SSLRSAPrivateKey *key, SSLContext *ctx)
185 { OSStatus err;
186 SSLBuffer modulus, exponent;
187 UInt8 *charPtr;
188
189 err = sslGetPubKeyBits(ctx,
190 *key,
191 ctx->encryptKeyCsp,
192 &modulus,
193 &exponent);
194 if(err) {
195 SSLFreeBuffer(modulus, ctx);
196 SSLFreeBuffer(exponent, ctx);
197 return err;
198 }
199
200 if ((err = SSLAllocBuffer(*keyParams, modulus.length + exponent.length + 4, ctx)) != 0)
201 return err;
202 charPtr = keyParams->data;
203 charPtr = SSLEncodeInt(charPtr, modulus.length, 2);
204 memcpy(charPtr, modulus.data, modulus.length);
205 charPtr += modulus.length;
206 charPtr = SSLEncodeInt(charPtr, exponent.length, 2);
207 memcpy(charPtr, exponent.data, exponent.length);
208
209 /* these were mallocd by sslGetPubKeyBits() */
210 SSLFreeBuffer(modulus, ctx);
211 SSLFreeBuffer(exponent, ctx);
212 return noErr;
213 }
214
215 #if APPLE_DH
216 static OSStatus
217 SSLEncodeDHanonServerKeyExchange(SSLRecord &keyExch, SSLContext *ctx)
218 { OSStatus err;
219 UInt32 length;
220 UInt8 *charPtr;
221 SSLRandomCtx random;
222 int rsaErr;
223
224 #if RSAREF
225 length = 6 + ctx->dhAnonParams.primeLen + ctx->dhAnonParams.generatorLen +
226 ctx->dhExchangePublic.length;
227
228 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
229 (ctx->negProtocolVersion == TLS_Version_1_0));
230 keyExch.protocolVersion = ctx->negProtocolVersion;
231 keyExch.contentType = SSL_RecordTypeHandshake;
232 if ((err = SSLAllocBuffer(keyExch.contents, length+4, ctx)) != 0)
233 return err;
234
235 charPtr = keyExch.contents.data;
236 *charPtr++ = SSL_HdskServerKeyExchange;
237 charPtr = SSLEncodeInt(charPtr, length, 3);
238
239 charPtr = SSLEncodeInt(charPtr, ctx->dhAnonParams.primeLen, 2);
240 memcpy(charPtr, ctx->dhAnonParams.prime, ctx->dhAnonParams.primeLen);
241 charPtr += ctx->dhAnonParams.primeLen;
242
243 charPtr = SSLEncodeInt(charPtr, ctx->dhAnonParams.generatorLen, 2);
244 memcpy(charPtr, ctx->dhAnonParams.generator, ctx->dhAnonParams.generatorLen);
245 charPtr += ctx->dhAnonParams.generatorLen;
246
247 if ((err = SSLAllocBuffer(ctx->dhExchangePublic,
248 ctx->peerDHParams.primeLen, ctx)) != 0)
249 return err;
250 if ((err = SSLAllocBuffer(ctx->dhPrivate,
251 ctx->dhExchangePublic.length - 16, ctx)) != 0)
252 return err;
253
254 if ((err = ReadyRandom(&random, ctx)) != 0)
255 return err;
256
257 if ((rsaErr = R_SetupDHAgreement(ctx->dhExchangePublic.data, ctx->dhPrivate.data,
258 ctx->dhPrivate.length, &ctx->dhAnonParams, &random)) != 0)
259 { err = SSLUnknownErr;
260 return err;
261 }
262
263 charPtr = SSLEncodeInt(charPtr, ctx->dhExchangePublic.length, 2);
264 memcpy(charPtr, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length);
265 charPtr += ctx->dhExchangePublic.length;
266
267 #elif BSAFE
268 { A_DH_KEY_AGREE_PARAMS *params;
269 unsigned int outputLen;
270
271 if ((rsaErr = B_GetAlgorithmInfo((POINTER*)&params, ctx->dhAnonParams, AI_DHKeyAgree)) != 0)
272 return SSLUnknownErr;
273 if ((err = ReadyRandom(&random, ctx)) != 0)
274 return err;
275 if ((err = SSLAllocBuffer(ctx->dhExchangePublic, 128, ctx)) != 0)
276 return err;
277 if ((rsaErr = B_KeyAgreePhase1(ctx->dhAnonParams, ctx->dhExchangePublic.data,
278 &outputLen, 128, random, NO_SURR)) != 0)
279 { err = SSLUnknownErr;
280 return err;
281 }
282 ctx->dhExchangePublic.length = outputLen;
283
284 length = 6 + params->prime.len + params->base.len + ctx->dhExchangePublic.length;
285
286 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
287 (ctx->negProtocolVersion == TLS_Version_1_0));
288 keyExch.protocolVersion = ctx->negProtocolVersion;
289 keyExch.contentType = SSL_RecordTypeHandshake;
290 if ((err = SSLAllocBuffer(keyExch.contents, length+4, ctx)) != 0)
291 return err;
292
293 charPtr = keyExch.contents.data;
294 *charPtr++ = SSL_HdskServerKeyExchange;
295 charPtr = SSLEncodeInt(charPtr, length, 3);
296
297 charPtr = SSLEncodeInt(charPtr, params->prime.len, 2);
298 memcpy(charPtr, params->prime.data, params->prime.len);
299 charPtr += params->prime.len;
300
301 charPtr = SSLEncodeInt(charPtr, params->base.len, 2);
302 memcpy(charPtr, params->base.data, params->base.len);
303 charPtr += params->base.len;
304
305 charPtr = SSLEncodeInt(charPtr, ctx->dhExchangePublic.length, 2);
306 memcpy(charPtr, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length);
307 charPtr += ctx->dhExchangePublic.length;
308 }
309 #endif /* RSAREF / BSAFE */
310
311 assert(charPtr == keyExch.contents.data + keyExch.contents.length);
312
313 return noErr;
314 }
315
316 #endif /* APPLE_DH */
317
318 OSStatus
319 SSLProcessServerKeyExchange(SSLBuffer message, SSLContext *ctx)
320 { OSStatus err;
321
322 switch (ctx->selectedCipherSpec->keyExchangeMethod)
323 { case SSL_RSA:
324 case SSL_RSA_EXPORT:
325 if ((err = SSLProcessRSAServerKeyExchange(message, ctx)) != 0)
326 return err;
327 break;
328 #if APPLE_DH
329 case SSL_DH_anon:
330 if ((err = SSLProcessDHanonServerKeyExchange(message, ctx)) != 0)
331 return err;
332 break;
333 #endif
334 default:
335 return unimpErr;
336 }
337
338 return noErr;
339 }
340
341 static OSStatus
342 SSLProcessRSAServerKeyExchange(SSLBuffer message, SSLContext *ctx)
343 {
344 OSStatus err;
345 SSLBuffer tempPubKey, hashOut, hashCtx, clientRandom, serverRandom;
346 UInt16 modulusLen, exponentLen, signatureLen;
347 UInt8 *charPtr, *modulus, *exponent, *signature;
348 UInt8 hash[36];
349 SSLBuffer signedHashes;
350
351 signedHashes.data = 0;
352 hashCtx.data = 0;
353
354 if (message.length < 2) {
355 sslErrorLog("SSLProcessRSAServerKeyExchange: msg len error 2\n");
356 return errSSLProtocol;
357 }
358 charPtr = message.data;
359 modulusLen = SSLDecodeInt(charPtr, 2);
360 modulus = charPtr + 2;
361 charPtr += 2+modulusLen;
362 if (message.length < (unsigned)(4 + modulusLen)) {
363 sslErrorLog("SSLProcessRSAServerKeyExchange: msg len error 2\n");
364 return errSSLProtocol;
365 }
366 exponentLen = SSLDecodeInt(charPtr, 2);
367 exponent = charPtr + 2;
368 charPtr += 2+exponentLen;
369 if (message.length < (unsigned)(6 + modulusLen + exponentLen)) {
370 sslErrorLog("SSLProcessRSAServerKeyExchange: msg len error 2\n");
371 return errSSLProtocol;
372 }
373 signatureLen = SSLDecodeInt(charPtr, 2);
374 signature = charPtr + 2;
375 if (message.length != (unsigned)(6 + modulusLen + exponentLen + signatureLen)) {
376 sslErrorLog("SSLProcessRSAServerKeyExchange: msg len error 3\n");
377 return errSSLProtocol;
378 }
379
380 clientRandom.data = ctx->clientRandom;
381 clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
382 serverRandom.data = ctx->serverRandom;
383 serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
384 tempPubKey.data = message.data;
385 tempPubKey.length = modulusLen + exponentLen + 4;
386 hashOut.data = hash;
387
388 hashOut.length = 16;
389 if ((err = ReadyHash(SSLHashMD5, hashCtx, ctx)) != 0)
390 goto fail;
391 if ((err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
392 goto fail;
393 if ((err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
394 goto fail;
395 if ((err = SSLHashMD5.update(hashCtx, tempPubKey)) != 0)
396 goto fail;
397 if ((err = SSLHashMD5.final(hashCtx, hashOut)) != 0)
398 goto fail;
399
400 /*
401 * SHA hash goes right after the MD5 hash
402 */
403 hashOut.data = hash + 16;
404 hashOut.length = 20;
405 if ((err = SSLFreeBuffer(hashCtx, ctx)) != 0)
406 goto fail;
407
408 if ((err = ReadyHash(SSLHashSHA1, hashCtx, ctx)) != 0)
409 goto fail;
410 if ((err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0)
411 goto fail;
412 if ((err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0)
413 goto fail;
414 if ((err = SSLHashSHA1.update(hashCtx, tempPubKey)) != 0)
415 goto fail;
416 if ((err = SSLHashSHA1.final(hashCtx, hashOut)) != 0)
417 goto fail;
418
419 err = sslRsaRawVerify(ctx,
420 ctx->peerPubKey,
421 ctx->peerPubKeyCsp,
422 hash, /* plaintext */
423 36, /* plaintext length */
424 signature,
425 signatureLen);
426 if(err) {
427 sslErrorLog("SSLProcessRSAServerKeyExchange: sslRsaRawVerify returned %d\n",
428 (int)err);
429 goto fail;
430 }
431
432 /* Signature matches; now replace server key with new key */
433 {
434 SSLBuffer modBuf;
435 SSLBuffer expBuf;
436
437 /* first free existing peerKey */
438 sslFreeKey(ctx->peerPubKeyCsp,
439 &ctx->peerPubKey,
440 NULL); /* no KCItem */
441
442 /* and cook up a new one from raw bits */
443 modBuf.data = modulus;
444 modBuf.length = modulusLen;
445 expBuf.data = exponent;
446 expBuf.length = exponentLen;
447 err = sslGetPubKeyFromBits(ctx,
448 &modBuf,
449 &expBuf,
450 &ctx->peerPubKey,
451 &ctx->peerPubKeyCsp);
452 }
453 fail:
454 SSLFreeBuffer(signedHashes, ctx);
455 SSLFreeBuffer(hashCtx, ctx);
456 return err;
457 }
458
459 #if APPLE_DH
460 static OSStatus
461 SSLProcessDHanonServerKeyExchange(SSLBuffer message, SSLContext *ctx)
462 { OSStatus err;
463 UInt8 *charPtr;
464 unsigned int totalLength;
465
466 if (message.length < 6) {
467 sslErrorLog("SSLProcessDHanonServerKeyExchange error: msg len %d\n",
468 message.length);
469 return errSSLProtocol;
470 }
471 charPtr = message.data;
472 totalLength = 0;
473
474 #if RSAREF
475 { SSLBuffer alloc;
476 UInt8 *prime, *generator, *publicVal;
477
478 ctx->peerDHParams.primeLen = SSLDecodeInt(charPtr, 2);
479 charPtr += 2;
480 prime = charPtr;
481 charPtr += ctx->peerDHParams.primeLen;
482 totalLength += ctx->peerDHParams.primeLen;
483 if (message.length < 6 + totalLength)
484 return errSSLProtocol;
485
486 ctx->peerDHParams.generatorLen = SSLDecodeInt(charPtr, 2);
487 charPtr += 2;
488 generator = charPtr;
489 charPtr += ctx->peerDHParams.generatorLen;
490 totalLength += ctx->peerDHParams.generatorLen;
491 if (message.length < 6 + totalLength)
492 return errSSLProtocol;
493
494 ctx->dhPeerPublic.length = SSLDecodeInt(charPtr, 2);
495 charPtr += 2;
496 publicVal = charPtr;
497 charPtr += ctx->dhPeerPublic.length;
498 totalLength += ctx->dhPeerPublic.length;
499 if (message.length != 6 + totalLength)
500 return errSSLProtocol;
501
502 assert(charPtr == message.data + message.length);
503
504 if ((err = SSLAllocBuffer(alloc, ctx->peerDHParams.primeLen +
505 ctx->peerDHParams.generatorLen, ctx)) != 0)
506 return err;
507
508 ctx->peerDHParams.prime = alloc.data;
509 memcpy(ctx->peerDHParams.prime, prime, ctx->peerDHParams.primeLen);
510 ctx->peerDHParams.generator = alloc.data + ctx->peerDHParams.primeLen;
511 memcpy(ctx->peerDHParams.generator, generator, ctx->peerDHParams.generatorLen);
512
513 if ((err = SSLAllocBuffer(ctx->dhPeerPublic,
514 ctx->dhPeerPublic.length, ctx)) != 0)
515 return err;
516
517 memcpy(ctx->dhPeerPublic.data, publicVal, ctx->dhPeerPublic.length);
518 }
519 #elif BSAFE
520 { int rsaErr;
521 unsigned char *publicVal;
522 A_DH_KEY_AGREE_PARAMS params;
523 B_ALGORITHM_METHOD *chooser[] = { &AM_DH_KEY_AGREE, 0 };
524
525 params.prime.len = SSLDecodeInt(charPtr, 2);
526 charPtr += 2;
527 params.prime.data = charPtr;
528 charPtr += params.prime.len;
529 totalLength += params.prime.len;
530 if (message.length < 6 + totalLength)
531 return errSSLProtocol;
532
533 params.base.len = SSLDecodeInt(charPtr, 2);
534 charPtr += 2;
535 params.base.data = charPtr;
536 charPtr += params.base.len;
537 totalLength += params.base.len;
538 if (message.length < 6 + totalLength)
539 return errSSLProtocol;
540
541 ctx->dhPeerPublic.length = SSLDecodeInt(charPtr, 2);
542 if ((err = SSLAllocBuffer(ctx->dhPeerPublic, ctx->dhPeerPublic.length, ctx)) != 0)
543 return err;
544
545 charPtr += 2;
546 publicVal = charPtr;
547 charPtr += ctx->dhPeerPublic.length;
548 totalLength += ctx->dhPeerPublic.length;
549 memcpy(ctx->dhPeerPublic.data, publicVal, ctx->dhPeerPublic.length);
550 if (message.length != 6 + totalLength)
551 return errSSLProtocol;
552
553 params.exponentBits = 8 * ctx->dhPeerPublic.length - 1;
554
555 if ((rsaErr = B_CreateAlgorithmObject(&ctx->peerDHParams)) != 0)
556 return SSLUnknownErr;
557 if ((rsaErr = B_SetAlgorithmInfo(ctx->peerDHParams, AI_DHKeyAgree, (POINTER)&params)) != 0)
558 return SSLUnknownErr;
559 if ((rsaErr = B_KeyAgreeInit(ctx->peerDHParams, (B_KEY_OBJ) 0, chooser, NO_SURR)) != 0)
560 return SSLUnknownErr;
561 }
562 #endif
563
564 return noErr;
565 }
566
567 #endif
568
569 OSStatus
570 SSLProcessKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
571 { OSStatus err;
572
573 switch (ctx->selectedCipherSpec->keyExchangeMethod)
574 { case SSL_RSA:
575 case SSL_RSA_EXPORT:
576 if ((err = SSLDecodeRSAKeyExchange(keyExchange, ctx)) != 0)
577 return err;
578 break;
579 #if APPLE_DH
580 case SSL_DH_anon:
581 if ((err = SSLDecodeDHanonKeyExchange(keyExchange, ctx)) != 0)
582 return err;
583 break;
584 #endif
585 default:
586 return unimpErr;
587 }
588
589 return noErr;
590 }
591
592 static OSStatus
593 SSLDecodeRSAKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
594 { OSStatus err;
595 SSLBuffer result;
596 UInt32 outputLen, localKeyModulusLen;
597 CSSM_KEY_PTR *key;
598 SSLProtocolVersion version;
599 Boolean useEncryptKey = false;
600 UInt8 *src = NULL;
601
602
603 /* different key names, also need CSP handle */
604 CSSM_CSP_HANDLE cspHand;
605
606 assert(ctx->protocolSide == SSL_ServerSide);
607
608 #if SSL_SERVER_KEYEXCH_HACK
609 /*
610 * the way we work with Netscape.
611 * FIXME - maybe we should *require* an encryptPrivKey in this
612 * situation?
613 */
614 if((ctx->selectedCipherSpec->keyExchangeMethod == SSL_RSA_EXPORT) &&
615 (ctx->encryptPrivKey != NULL)) {
616 useEncryptKey = true;
617 }
618
619 #else /* !SSL_SERVER_KEYEXCH_HACK */
620 /* The "correct" way, I think, which doesn't work with Netscape */
621 if (ctx->encryptPrivKey) {
622 useEncryptKey = true;
623 }
624 #endif /* SSL_SERVER_KEYEXCH_HACK */
625 if (useEncryptKey) {
626 key = &ctx->encryptPrivKey;
627 cspHand = ctx->encryptKeyCsp;
628 }
629 else {
630 key = &ctx->signingPrivKey;
631 cspHand = ctx->signingKeyCsp;
632 }
633
634 localKeyModulusLen = sslKeyLengthInBytes(*key);
635
636 /*
637 * We have to tolerate incoming key exchange msgs with and without the
638 * two-byte "encrypted length" field.
639 */
640 if (keyExchange.length == localKeyModulusLen) {
641 /* no length encoded */
642 src = keyExchange.data;
643 }
644 else if((keyExchange.length == (localKeyModulusLen + 2)) &&
645 (ctx->negProtocolVersion >= TLS_Version_1_0)) {
646 /* TLS only - skip the length bytes */
647 src = keyExchange.data + 2;
648 }
649 else {
650 sslErrorLog("SSLDecodeRSAKeyExchange: length error (exp %u got %u)\n",
651 (unsigned)localKeyModulusLen, (unsigned)keyExchange.length);
652 return errSSLProtocol;
653 }
654 err = SSLAllocBuffer(result, localKeyModulusLen, ctx);
655 if(err != 0) {
656 return err;
657 }
658
659 err = sslRsaDecrypt(ctx,
660 *key,
661 cspHand,
662 src,
663 localKeyModulusLen,
664 result.data,
665 48,
666 &outputLen);
667 if(err) {
668 goto fail;
669 }
670
671 if (outputLen != 48)
672 {
673 sslErrorLog("SSLDecodeRSAKeyExchange: outputLen error\n");
674 err = errSSLProtocol;
675 goto fail;
676 }
677 result.length = outputLen;
678
679 version = (SSLProtocolVersion)SSLDecodeInt(result.data, 2);
680 /* Modify this check to check against our maximum version with
681 * protocol revisions */
682 if (version > ctx->negProtocolVersion && version < SSL_Version_3_0) {
683 sslErrorLog("SSLDecodeRSAKeyExchange: version error\n");
684 err = errSSLProtocol;
685 goto fail;
686 }
687 if ((err = SSLAllocBuffer(ctx->preMasterSecret,
688 SSL_RSA_PREMASTER_SECRET_SIZE, ctx)) != 0)
689 goto fail;
690 memcpy(ctx->preMasterSecret.data, result.data,
691 SSL_RSA_PREMASTER_SECRET_SIZE);
692
693 err = noErr;
694 fail:
695 SSLFreeBuffer(result, ctx);
696 return err;
697 }
698
699 #if APPLE_DH
700 static OSStatus
701 SSLDecodeDHanonKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
702 { OSStatus err;
703 unsigned int publicLen;
704 int rsaResult;
705
706 publicLen = SSLDecodeInt(keyExchange.data, 2);
707
708 #if RSAREF
709 if (keyExchange.length != publicLen + 2 ||
710 publicLen != ctx->dhAnonParams.primeLen)
711 return errSSLProtocol;
712
713 if ((err = SSLAllocBuffer(ctx->preMasterSecret, ctx->dhAnonParams.primeLen, ctx)) != 0)
714 return err;
715
716 if ((rsaResult = R_ComputeDHAgreedKey (ctx->preMasterSecret.data, ctx->dhPeerPublic.data,
717 ctx->dhPrivate.data, ctx->dhPrivate.length, &ctx->dhAnonParams)) != 0)
718 { err = SSLUnknownErr;
719 return err;
720 }
721
722 #elif BSAFE
723 { unsigned int amount;
724 if (keyExchange.length != publicLen + 2)
725 return errSSLProtocol;
726
727 if ((err = SSLAllocBuffer(ctx->preMasterSecret, 128, ctx)) != 0)
728 return err;
729
730 if ((rsaResult = B_KeyAgreePhase2(ctx->dhAnonParams, ctx->preMasterSecret.data,
731 &amount, 128, keyExchange.data+2, publicLen, NO_SURR)) != 0)
732 return err;
733
734 ctx->preMasterSecret.length = amount;
735 }
736 #endif
737
738 return noErr;
739 }
740 #endif /* APPLE_DH */
741
742 OSStatus
743 SSLEncodeKeyExchange(SSLRecord &keyExchange, SSLContext *ctx)
744 { OSStatus err;
745
746 assert(ctx->protocolSide == SSL_ClientSide);
747
748 switch (ctx->selectedCipherSpec->keyExchangeMethod)
749 { case SSL_RSA:
750 case SSL_RSA_EXPORT:
751 if ((err = SSLEncodeRSAKeyExchange(keyExchange, ctx)) != 0)
752 return err;
753 break;
754 #if APPLE_DH
755 case SSL_DH_anon:
756 if ((err = SSLEncodeDHanonKeyExchange(keyExchange, ctx)) != 0)
757 return err;
758 break;
759 #endif
760 default:
761 return unimpErr;
762 }
763
764 return noErr;
765 }
766
767 static OSStatus
768 SSLEncodeRSAKeyExchange(SSLRecord &keyExchange, SSLContext *ctx)
769 { OSStatus err;
770 UInt32 outputLen, peerKeyModulusLen;
771 UInt32 bufLen;
772 UInt8 *dst;
773 bool encodeLen = false;
774
775 if ((err = SSLEncodeRSAPremasterSecret(ctx)) != 0)
776 return err;
777
778 keyExchange.contentType = SSL_RecordTypeHandshake;
779 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
780 (ctx->negProtocolVersion == TLS_Version_1_0));
781 keyExchange.protocolVersion = ctx->negProtocolVersion;
782
783 peerKeyModulusLen = sslKeyLengthInBytes(ctx->peerPubKey);
784 bufLen = peerKeyModulusLen + 4;
785 #if RSA_CLIENT_KEY_ADD_LENGTH
786 if(ctx->negProtocolVersion >= TLS_Version_1_0) {
787 bufLen += 2;
788 encodeLen = true;
789 }
790 #endif
791 if ((err = SSLAllocBuffer(keyExchange.contents,
792 bufLen,ctx)) != 0)
793 {
794 return err;
795 }
796 dst = keyExchange.contents.data + 4;
797 if(encodeLen) {
798 dst += 2;
799 }
800 keyExchange.contents.data[0] = SSL_HdskClientKeyExchange;
801
802 /* this is the record payload length */
803 SSLEncodeInt(keyExchange.contents.data + 1, bufLen - 4, 3);
804 if(encodeLen) {
805 /* the length of the encrypted pre_master_secret */
806 SSLEncodeInt(keyExchange.contents.data + 4,
807 peerKeyModulusLen, 2);
808 }
809 err = sslRsaEncrypt(ctx,
810 ctx->peerPubKey,
811 /* FIXME - maybe this should be ctx->cspHand */
812 ctx->peerPubKeyCsp,
813 ctx->preMasterSecret.data,
814 SSL_RSA_PREMASTER_SECRET_SIZE,
815 dst,
816 peerKeyModulusLen,
817 &outputLen);
818 if(err) {
819 return err;
820 }
821
822 assert(outputLen == encodeLen ?
823 keyExchange.contents.length - 6 :
824 keyExchange.contents.length - 4 );
825
826 return noErr;
827 }
828
829 #if APPLE_DH
830 static OSStatus
831 SSLEncodeDHanonKeyExchange(SSLRecord &keyExchange, SSLContext *ctx)
832 { OSStatus err;
833 unsigned int outputLen;
834
835 if ((err = SSLEncodeDHPremasterSecret(ctx)) != 0)
836 return err;
837
838 outputLen = ctx->dhExchangePublic.length + 2;
839
840 keyExchange.contentType = SSL_RecordTypeHandshake;
841 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
842 (ctx->negProtocolVersion == TLS_Version_1_0));
843 keyExchange.protocolVersion = ctx->negProtocolVersion;
844
845 if ((err = SSLAllocBuffer(keyExchange.contents,outputLen + 4,ctx)) != 0)
846 return err;
847
848 keyExchange.contents.data[0] = SSL_HdskClientKeyExchange;
849 SSLEncodeInt(keyExchange.contents.data+1, ctx->dhExchangePublic.length+2, 3);
850
851 SSLEncodeInt(keyExchange.contents.data+4, ctx->dhExchangePublic.length, 2);
852 memcpy(keyExchange.contents.data+6, ctx->dhExchangePublic.data, ctx->dhExchangePublic.length);
853
854 return noErr;
855 }
856 #endif
857
858 OSStatus
859 SSLEncodeRSAPremasterSecret(SSLContext *ctx)
860 { SSLBuffer randData;
861 OSStatus err;
862
863 if ((err = SSLAllocBuffer(ctx->preMasterSecret,
864 SSL_RSA_PREMASTER_SECRET_SIZE, ctx)) != 0)
865 return err;
866
867 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
868 (ctx->negProtocolVersion == TLS_Version_1_0));
869 SSLEncodeInt(ctx->preMasterSecret.data, ctx->maxProtocolVersion, 2);
870 randData.data = ctx->preMasterSecret.data+2;
871 randData.length = SSL_RSA_PREMASTER_SECRET_SIZE - 2;
872 if ((err = sslRand(ctx, &randData)) != 0)
873 return err;
874 return noErr;
875 }
876
877 #if APPLE_DH
878
879 OSStatus
880 SSLEncodeDHPremasterSecret(SSLContext *ctx)
881 {
882 #if !APPLE_DH
883 return unimpErr;
884 #else
885
886 OSStatus err;
887 int rsaResult;
888 SSLRandomCtx rsaRandom;
889
890 /* Given the server's Diffie-Hellman parameters, prepare a public & private value,
891 * then use the public value provided by the server and our private value to
892 * generate a shared key (the premaster secret). Save our public value in
893 * ctx->dhExchangePublic to send to the server so it can calculate the matching
894 * key on its end
895 */
896 if ((err = ReadyRandom(&rsaRandom, ctx)) != 0)
897 return err;
898
899 #if RSAREF
900 { privateValue.data = 0;
901
902 if ((err = SSLAllocBuffer(ctx->dhExchangePublic, ctx->peerDHParams.primeLen, ctx)) != 0)
903 goto fail;
904 if ((err = SSLAllocBuffer(privateValue, ctx->dhExchangePublic.length - 16, ctx)) != 0)
905 goto fail;
906
907 if ((rsaResult = R_SetupDHAgreement(ctx->dhExchangePublic.data, privateValue.data,
908 privateValue.length, &ctx->peerDHParams, &rsaRandom)) != 0)
909 { err = SSLUnknownErr;
910 goto fail;
911 }
912
913 if ((err = SSLAllocBuffer(ctx->preMasterSecret, ctx->peerDHParams.primeLen, ctx)) != 0)
914 goto fail;
915
916 if ((rsaResult = R_ComputeDHAgreedKey (ctx->preMasterSecret.data, ctx->dhPeerPublic.data,
917 privateValue.data, privateValue.length, &ctx->peerDHParams)) != 0)
918 { err = SSLUnknownErr;
919 goto fail;
920 }
921 }
922 #elif BSAFE
923 { unsigned int outputLen;
924
925 if ((err = SSLAllocBuffer(ctx->dhExchangePublic, 128, ctx)) != 0)
926 goto fail;
927 if ((rsaResult = B_KeyAgreePhase1(ctx->peerDHParams, ctx->dhExchangePublic.data,
928 &outputLen, 128, rsaRandom, NO_SURR)) != 0)
929 { err = SSLUnknownErr;
930 goto fail;
931 }
932 ctx->dhExchangePublic.length = outputLen;
933 if ((err = SSLAllocBuffer(ctx->preMasterSecret, 128, ctx)) != 0)
934 goto fail;
935 if ((rsaResult = B_KeyAgreePhase2(ctx->peerDHParams, ctx->preMasterSecret.data,
936 &outputLen, 128, ctx->dhPeerPublic.data, ctx->dhPeerPublic.length,
937 NO_SURR)) != 0)
938 { err = SSLUnknownErr;
939 goto fail;
940 }
941 ctx->preMasterSecret.length = outputLen;
942 }
943 #endif
944
945 err = noErr;
946 fail:
947 #if RSAREF
948 SSLFreeBuffer(privateValue, ctx);
949 R_RandomFinal(&rsaRandom);
950 #elif BSAFE
951 B_DestroyAlgorithmObject(&rsaRandom);
952 #endif
953 return err;
954 #endif
955 }
956
957 #endif /* APPLE_DH */
958
959 OSStatus
960 SSLInitPendingCiphers(SSLContext *ctx)
961 { OSStatus err;
962 SSLBuffer key;
963 UInt8 *keyDataProgress, *keyPtr, *ivPtr;
964 int keyDataLen;
965 CipherContext *serverPending, *clientPending;
966
967 key.data = 0;
968
969 ctx->readPending.macRef = ctx->selectedCipherSpec->macAlgorithm;
970 ctx->writePending.macRef = ctx->selectedCipherSpec->macAlgorithm;
971 ctx->readPending.symCipher = ctx->selectedCipherSpec->cipher;
972 ctx->writePending.symCipher = ctx->selectedCipherSpec->cipher;
973 ctx->readPending.sequenceNum.high = ctx->readPending.sequenceNum.low = 0;
974 ctx->writePending.sequenceNum.high = ctx->writePending.sequenceNum.low = 0;
975
976 keyDataLen = ctx->selectedCipherSpec->macAlgorithm->hash->digestSize +
977 ctx->selectedCipherSpec->cipher->secretKeySize;
978 if (ctx->selectedCipherSpec->isExportable == NotExportable)
979 keyDataLen += ctx->selectedCipherSpec->cipher->ivSize;
980 keyDataLen *= 2; /* two of everything */
981
982 if ((err = SSLAllocBuffer(key, keyDataLen, ctx)) != 0)
983 return err;
984 assert(ctx->sslTslCalls != NULL);
985 if ((err = ctx->sslTslCalls->generateKeyMaterial(key, ctx)) != 0)
986 goto fail;
987
988 if (ctx->protocolSide == SSL_ServerSide)
989 { serverPending = &ctx->writePending;
990 clientPending = &ctx->readPending;
991 }
992 else
993 { serverPending = &ctx->readPending;
994 clientPending = &ctx->writePending;
995 }
996
997 keyDataProgress = key.data;
998 memcpy(clientPending->macSecret, keyDataProgress,
999 ctx->selectedCipherSpec->macAlgorithm->hash->digestSize);
1000 keyDataProgress += ctx->selectedCipherSpec->macAlgorithm->hash->digestSize;
1001 memcpy(serverPending->macSecret, keyDataProgress,
1002 ctx->selectedCipherSpec->macAlgorithm->hash->digestSize);
1003 keyDataProgress += ctx->selectedCipherSpec->macAlgorithm->hash->digestSize;
1004
1005 /* init the reusable-per-record MAC contexts */
1006 err = ctx->sslTslCalls->initMac(clientPending, ctx);
1007 if(err) {
1008 goto fail;
1009 }
1010 err = ctx->sslTslCalls->initMac(serverPending, ctx);
1011 if(err) {
1012 goto fail;
1013 }
1014
1015 if (ctx->selectedCipherSpec->isExportable == NotExportable)
1016 { keyPtr = keyDataProgress;
1017 keyDataProgress += ctx->selectedCipherSpec->cipher->secretKeySize;
1018 /* Skip server write key to get to IV */
1019 ivPtr = keyDataProgress + ctx->selectedCipherSpec->cipher->secretKeySize;
1020 if ((err = ctx->selectedCipherSpec->cipher->initialize(keyPtr, ivPtr,
1021 clientPending, ctx)) != 0)
1022 goto fail;
1023 keyPtr = keyDataProgress;
1024 keyDataProgress += ctx->selectedCipherSpec->cipher->secretKeySize;
1025 /* Skip client write IV to get to server write IV */
1026 ivPtr = keyDataProgress + ctx->selectedCipherSpec->cipher->ivSize;
1027 if ((err = ctx->selectedCipherSpec->cipher->initialize(keyPtr, ivPtr,
1028 serverPending, ctx)) != 0)
1029 goto fail;
1030 }
1031 else {
1032 UInt8 clientExportKey[16], serverExportKey[16],
1033 clientExportIV[16], serverExportIV[16];
1034 SSLBuffer clientWrite, serverWrite;
1035 SSLBuffer finalClientWrite, finalServerWrite;
1036 SSLBuffer finalClientIV, finalServerIV;
1037
1038 assert(ctx->selectedCipherSpec->cipher->keySize <= 16);
1039 assert(ctx->selectedCipherSpec->cipher->ivSize <= 16);
1040
1041 /* Inputs to generateExportKeyAndIv are clientRandom, serverRandom,
1042 * clientWriteKey, serverWriteKey. The first two are already present
1043 * in ctx.
1044 * Outputs are a key and IV for each of {server, client}.
1045 */
1046 clientWrite.data = keyDataProgress;
1047 clientWrite.length = ctx->selectedCipherSpec->cipher->secretKeySize;
1048 serverWrite.data = keyDataProgress + clientWrite.length;
1049 serverWrite.length = ctx->selectedCipherSpec->cipher->secretKeySize;
1050 finalClientWrite.data = clientExportKey;
1051 finalServerWrite.data = serverExportKey;
1052 finalClientIV.data = clientExportIV;
1053 finalServerIV.data = serverExportIV;
1054 finalClientWrite.length = 16;
1055 finalServerWrite.length = 16;
1056 /* these can be zero */
1057 finalClientIV.length = ctx->selectedCipherSpec->cipher->ivSize;
1058 finalServerIV.length = ctx->selectedCipherSpec->cipher->ivSize;
1059
1060 assert(ctx->sslTslCalls != NULL);
1061 err = ctx->sslTslCalls->generateExportKeyAndIv(ctx, clientWrite, serverWrite,
1062 finalClientWrite, finalServerWrite, finalClientIV, finalServerIV);
1063 if(err) {
1064 goto fail;
1065 }
1066 if ((err = ctx->selectedCipherSpec->cipher->initialize(clientExportKey,
1067 clientExportIV, clientPending, ctx)) != 0)
1068 goto fail;
1069 if ((err = ctx->selectedCipherSpec->cipher->initialize(serverExportKey,
1070 serverExportIV, serverPending, ctx)) != 0)
1071 goto fail;
1072 }
1073
1074 /* Ciphers are ready for use */
1075 ctx->writePending.ready = 1;
1076 ctx->readPending.ready = 1;
1077
1078 /* Ciphers get swapped by sending or receiving a change cipher spec message */
1079
1080 err = noErr;
1081 fail:
1082 SSLFreeBuffer(key, ctx);
1083 return err;
1084 }
1085