]> git.saurik.com Git - apple/security.git/blob - SecureTransport/sslKeyExchange.cpp
cf7c77b6b72c751b1c31a3953002e383db42f890
[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 #include "ModuleAttacher.h"
38 #include "sslBER.h"
39
40 #include <assert.h>
41 #include <string.h>
42
43 #include <Security/globalizer.h>
44 #include <Security/threading.h>
45
46 #pragma mark -
47 #pragma mark *** forward static declarations ***
48 static OSStatus SSLGenServerDHParamsAndKey(SSLContext *ctx);
49 static OSStatus SSLEncodeDHKeyParams(SSLContext *ctx, UInt8 *charPtr);
50 static OSStatus SSLDecodeDHKeyParams(SSLContext *ctx, UInt8 *&charPtr,
51 UInt32 length);
52
53 #define DH_PARAM_DUMP 0
54 #if DH_PARAM_DUMP
55
56 static void dumpBuf(const char *name, SSLBuffer &buf)
57 {
58 printf("%s:\n", name);
59 UInt8 *cp = buf.data;
60 UInt8 *endCp = cp + buf.length;
61
62 do {
63 for(unsigned i=0; i<16; i++) {
64 printf("%02x ", *cp++);
65 if(cp == endCp) {
66 break;
67 }
68 }
69 if(cp == endCp) {
70 break;
71 }
72 printf("\n");
73 } while(cp < endCp);
74 printf("\n");
75 }
76 #else
77 #define dumpBuf(n, b)
78 #endif /* DH_PARAM_DUMP */
79
80 #if APPLE_DH
81
82 #pragma mark -
83 #pragma mark *** local D-H parameter generator ***
84 /*
85 * Process-wide server-supplied Diffie-Hellman parameters.
86 * This might be overridden by some API_supplied parameters
87 * in the future.
88 */
89 class ServerDhParams
90 {
91 public:
92 ServerDhParams();
93 ~ServerDhParams();
94 const SSLBuffer &prime() { return mPrime; }
95 const SSLBuffer &generator() { return mGenerator; }
96 const SSLBuffer &paramBlock() { return mParamBlock; }
97
98 private:
99 /* these two for sending over the wire */
100 SSLBuffer mPrime;
101 SSLBuffer mGenerator;
102 /* this one for sending to the CSP at key gen time */
103 SSLBuffer mParamBlock;
104 };
105
106 ServerDhParams::ServerDhParams()
107 {
108 mPrime.data = NULL;
109 mPrime.length = 0;
110 mGenerator.data = NULL;
111 mGenerator.length = 0;
112 mParamBlock.data = NULL;
113 mParamBlock.length = 0;
114
115 CSSM_CSP_HANDLE cspHand;
116 CSSM_CL_HANDLE clHand; // not used here, just for
117 // attachToModules()
118 CSSM_TP_HANDLE tpHand; // ditto
119 CSSM_RETURN crtn;
120
121 crtn = attachToModules(&cspHand, &clHand, &tpHand);
122 if(crtn) {
123 MacOSError::throwMe(errSSLModuleAttach);
124 }
125
126 CSSM_CC_HANDLE ccHandle;
127 CSSM_DATA cParams = {0, NULL};
128
129 crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
130 CSSM_ALGID_DH,
131 SSL_DH_DEFAULT_PRIME_SIZE,
132 NULL, // Seed
133 NULL, // Salt
134 NULL, // StartDate
135 NULL, // EndDate
136 &cParams, // Params, may be NULL
137 &ccHandle);
138 if(crtn) {
139 stPrintCdsaError("ServerDhParams CSSM_CSP_CreateKeyGenContext", crtn);
140 MacOSError::throwMe(errSSLCrypto);
141 }
142
143 /* explicitly generate params and save them */
144 sslDhDebug("^^^generating Diffie-Hellman parameters...");
145 crtn = CSSM_GenerateAlgorithmParams(ccHandle,
146 SSL_DH_DEFAULT_PRIME_SIZE, &cParams);
147 if(crtn) {
148 stPrintCdsaError("ServerDhParams CSSM_GenerateAlgorithmParams", crtn);
149 CSSM_DeleteContext(ccHandle);
150 MacOSError::throwMe(errSSLCrypto);
151 }
152 CSSM_TO_SSLBUF(&cParams, &mParamBlock);
153 OSStatus ortn = sslDecodeDhParams(&mParamBlock, &mPrime, &mGenerator);
154 if(ortn) {
155 sslErrorLog("ServerDhParams: param decode error\n");
156 MacOSError::throwMe(ortn);
157 }
158 CSSM_DeleteContext(ccHandle);
159 }
160
161 ServerDhParams::~ServerDhParams()
162 {
163 sslFree(mPrime.data);
164 sslFree(mGenerator.data);
165 sslFree(mParamBlock.data);
166 }
167
168 /* the single global thing */
169 static ModuleNexus<ServerDhParams> serverDhParams;
170
171 #endif /* APPLE_DH */
172
173 #pragma mark -
174 #pragma mark *** RSA key exchange ***
175
176 /*
177 * Client RSA Key Exchange msgs actually start with a two-byte
178 * length field, contrary to the first version of RFC 2246, dated
179 * January 1999. See RFC 2246, March 2002, section 7.4.7.1 for
180 * updated requirements.
181 */
182 #define RSA_CLIENT_KEY_ADD_LENGTH 1
183
184 typedef CSSM_KEY_PTR SSLRSAPrivateKey;
185
186 static OSStatus
187 SSLEncodeRSAKeyParams(SSLBuffer *keyParams, SSLRSAPrivateKey *key, SSLContext *ctx)
188 { OSStatus err;
189 SSLBuffer modulus, exponent;
190 UInt8 *charPtr;
191
192 if(err = attachToCsp(ctx)) {
193 return err;
194 }
195
196 /* Note currently ALL public keys are raw, obtained from the CL... */
197 assert((*key)->KeyHeader.BlobType == CSSM_KEYBLOB_RAW);
198 err = sslGetPubKeyBits(ctx,
199 *key,
200 ctx->cspHand,
201 &modulus,
202 &exponent);
203 if(err) {
204 SSLFreeBuffer(modulus, ctx);
205 SSLFreeBuffer(exponent, ctx);
206 return err;
207 }
208
209 if ((err = SSLAllocBuffer(*keyParams,
210 modulus.length + exponent.length + 4, ctx)) != 0) {
211 return err;
212 }
213 charPtr = keyParams->data;
214 charPtr = SSLEncodeInt(charPtr, modulus.length, 2);
215 memcpy(charPtr, modulus.data, modulus.length);
216 charPtr += modulus.length;
217 charPtr = SSLEncodeInt(charPtr, exponent.length, 2);
218 memcpy(charPtr, exponent.data, exponent.length);
219
220 /* these were mallocd by sslGetPubKeyBits() */
221 SSLFreeBuffer(modulus, ctx);
222 SSLFreeBuffer(exponent, ctx);
223 return noErr;
224 }
225
226 static OSStatus
227 SSLEncodeRSAPremasterSecret(SSLContext *ctx)
228 { SSLBuffer randData;
229 OSStatus err;
230 SSLProtocolVersion maxVersion;
231
232 if ((err = SSLAllocBuffer(ctx->preMasterSecret,
233 SSL_RSA_PREMASTER_SECRET_SIZE, ctx)) != 0)
234 return err;
235
236 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
237 (ctx->negProtocolVersion == TLS_Version_1_0));
238 sslGetMaxProtVersion(ctx, &maxVersion);
239 SSLEncodeInt(ctx->preMasterSecret.data, maxVersion, 2);
240 randData.data = ctx->preMasterSecret.data+2;
241 randData.length = SSL_RSA_PREMASTER_SECRET_SIZE - 2;
242 if ((err = sslRand(ctx, &randData)) != 0)
243 return err;
244 return noErr;
245 }
246
247 /*
248 * Generate a server key exchange message signed by our RSA or DSA private key.
249 */
250 static OSStatus
251 SSLEncodeSignedServerKeyExchange(SSLRecord &keyExch, SSLContext *ctx)
252 { OSStatus err;
253 UInt8 *charPtr;
254 int outputLen;
255 UInt8 hashes[SSL_SHA1_DIGEST_LEN + SSL_MD5_DIGEST_LEN];
256 SSLBuffer exchangeParams,clientRandom,serverRandom,hashCtx, hash;
257 UInt8 *dataToSign;
258 UInt32 dataToSignLen;
259 bool isRsa = true;
260 UInt32 maxSigLen;
261 UInt32 actSigLen;
262 SSLBuffer signature;
263 const CSSM_KEY *cssmKey;
264
265 assert(ctx->protocolSide == SSL_ServerSide);
266 assert(ctx->signingPubKey != NULL);
267 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
268 (ctx->negProtocolVersion == TLS_Version_1_0));
269 exchangeParams.data = 0;
270 hashCtx.data = 0;
271 signature.data = 0;
272
273 /* Set up parameter block to hash ==> exchangeParams */
274 switch(ctx->selectedCipherSpec->keyExchangeMethod) {
275 case SSL_RSA:
276 case SSL_RSA_EXPORT:
277 /*
278 * Parameter block = encryption public key.
279 * If app hasn't supplied a separate encryption cert, abort.
280 */
281 if(ctx->encryptPubKey == NULL) {
282 sslErrorLog("RSAServerKeyExchange: no encrypt cert\n");
283 return errSSLBadConfiguration;
284 }
285 err = SSLEncodeRSAKeyParams(&exchangeParams,
286 &ctx->encryptPubKey, ctx);
287 break;
288
289 #if APPLE_DH
290 case SSL_DHE_DSS:
291 case SSL_DHE_DSS_EXPORT:
292 isRsa = false;
293 /* and fall through */
294 case SSL_DHE_RSA:
295 case SSL_DHE_RSA_EXPORT:
296 {
297 /*
298 * Parameter block = {prime, generator, public key}
299 * Obtain D-H parameters (if we don't have them) and a key pair.
300 */
301 err = SSLGenServerDHParamsAndKey(ctx);
302 if(err) {
303 return err;
304 }
305 UInt32 len = ctx->dhParamsPrime.length +
306 ctx->dhParamsGenerator.length +
307 ctx->dhExchangePublic.length + 6 /* 3 length fields */;
308 err = SSLAllocBuffer(exchangeParams, len, ctx);
309 if(err) {
310 goto fail;
311 }
312 err = SSLEncodeDHKeyParams(ctx, exchangeParams.data);
313 break;
314 }
315 #endif /* APPLE_DH */
316 default:
317 /* shouldn't be here */
318 assert(0);
319 return errSSLInternal;
320 }
321 if(err) {
322 goto fail;
323 }
324
325 /* cook up hash(es) for raw sign */
326 clientRandom.data = ctx->clientRandom;
327 clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
328 serverRandom.data = ctx->serverRandom;
329 serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
330
331 if(isRsa) {
332 /* skip this if signing with DSA */
333 dataToSign = hashes;
334 dataToSignLen = SSL_SHA1_DIGEST_LEN + SSL_MD5_DIGEST_LEN;
335 hash.data = &hashes[0];
336 hash.length = SSL_MD5_DIGEST_LEN;
337
338 if ((err = ReadyHash(SSLHashMD5, hashCtx, ctx)) != 0)
339 goto fail;
340 if ((err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
341 goto fail;
342 if ((err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
343 goto fail;
344 if ((err = SSLHashMD5.update(hashCtx, exchangeParams)) != 0)
345 goto fail;
346 if ((err = SSLHashMD5.final(hashCtx, hash)) != 0)
347 goto fail;
348 if ((err = SSLFreeBuffer(hashCtx, ctx)) != 0)
349 goto fail;
350 }
351 else {
352 /* DSA - just use the SHA1 hash */
353 dataToSign = &hashes[SSL_MD5_DIGEST_LEN];
354 dataToSignLen = SSL_SHA1_DIGEST_LEN;
355 }
356 hash.data = &hashes[SSL_MD5_DIGEST_LEN];
357 hash.length = SSL_SHA1_DIGEST_LEN;
358 if ((err = ReadyHash(SSLHashSHA1, hashCtx, ctx)) != 0)
359 goto fail;
360 if ((err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0)
361 goto fail;
362 if ((err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0)
363 goto fail;
364 if ((err = SSLHashSHA1.update(hashCtx, exchangeParams)) != 0)
365 goto fail;
366 if ((err = SSLHashSHA1.final(hashCtx, hash)) != 0)
367 goto fail;
368 if ((err = SSLFreeBuffer(hashCtx, ctx)) != 0)
369 goto fail;
370
371 /* preallocate a buffer for signing */
372 err = SecKeyGetCSSMKey(ctx->signingPrivKeyRef, &cssmKey);
373 if(err) {
374 sslErrorLog("SSLEncodeSignedServerKeyExchange: SecKeyGetCSSMKey err %d\n",
375 (int)err);
376 goto fail;
377 }
378 err = sslGetMaxSigSize(cssmKey, maxSigLen);
379 if(err) {
380 goto fail;
381 }
382 err = SSLAllocBuffer(signature, maxSigLen, ctx);
383 if(err) {
384 goto fail;
385 }
386
387 err = sslRawSign(ctx,
388 ctx->signingPrivKeyRef,
389 dataToSign, // one or two hashes
390 dataToSignLen,
391 signature.data,
392 maxSigLen,
393 &actSigLen);
394 if(err) {
395 goto fail;
396 }
397 assert(actSigLen <= maxSigLen);
398
399 /* package it all up */
400 outputLen = exchangeParams.length + 2 + actSigLen;
401 keyExch.protocolVersion = ctx->negProtocolVersion;
402 keyExch.contentType = SSL_RecordTypeHandshake;
403 if ((err = SSLAllocBuffer(keyExch.contents, outputLen+4, ctx)) != 0)
404 goto fail;
405
406 charPtr = keyExch.contents.data;
407 *charPtr++ = SSL_HdskServerKeyExchange;
408 charPtr = SSLEncodeInt(charPtr, outputLen, 3);
409
410 memcpy(charPtr, exchangeParams.data, exchangeParams.length);
411 charPtr += exchangeParams.length;
412 charPtr = SSLEncodeInt(charPtr, actSigLen, 2);
413 memcpy(charPtr, signature.data, actSigLen);
414 assert((charPtr + actSigLen) ==
415 (keyExch.contents.data + keyExch.contents.length));
416
417 err = noErr;
418
419 fail:
420 SSLFreeBuffer(hashCtx, ctx);
421 SSLFreeBuffer(exchangeParams, ctx);
422 SSLFreeBuffer(signature, ctx);
423 return err;
424 }
425
426 /*
427 * Decode and verify a server key exchange message signed by server's
428 * public key.
429 */
430 static OSStatus
431 SSLDecodeSignedServerKeyExchange(SSLBuffer message, SSLContext *ctx)
432 {
433 OSStatus err;
434 SSLBuffer hashOut, hashCtx, clientRandom, serverRandom;
435 UInt16 modulusLen, exponentLen, signatureLen;
436 UInt8 *modulus, *exponent, *signature;
437 UInt8 hashes[SSL_SHA1_DIGEST_LEN + SSL_MD5_DIGEST_LEN];
438 SSLBuffer signedHashes;
439 UInt8 *dataToSign;
440 UInt32 dataToSignLen;
441 bool isRsa = true;
442
443 assert(ctx->protocolSide == SSL_ClientSide);
444 signedHashes.data = 0;
445 hashCtx.data = 0;
446
447 if (message.length < 2) {
448 sslErrorLog("SSLDecodeSignedServerKeyExchange: msg len error 1\n");
449 return errSSLProtocol;
450 }
451
452 /* first extract the key-exchange-method-specific parameters */
453 UInt8 *charPtr = message.data;
454 UInt8 *endCp = charPtr + message.length;
455 switch(ctx->selectedCipherSpec->keyExchangeMethod) {
456 case SSL_RSA:
457 case SSL_RSA_EXPORT:
458 modulusLen = SSLDecodeInt(charPtr, 2);
459 charPtr += 2;
460 if((charPtr + modulusLen) > endCp) {
461 sslErrorLog("signedServerKeyExchange: msg len error 2\n");
462 return errSSLProtocol;
463 }
464 modulus = charPtr;
465 charPtr += modulusLen;
466
467 exponentLen = SSLDecodeInt(charPtr, 2);
468 charPtr += 2;
469 if((charPtr + exponentLen) > endCp) {
470 sslErrorLog("signedServerKeyExchange: msg len error 3\n");
471 return errSSLProtocol;
472 }
473 exponent = charPtr;
474 charPtr += exponentLen;
475 break;
476 #if APPLE_DH
477 case SSL_DHE_DSS:
478 case SSL_DHE_DSS_EXPORT:
479 isRsa = false;
480 /* and fall through */
481 case SSL_DHE_RSA:
482 case SSL_DHE_RSA_EXPORT:
483 err = SSLDecodeDHKeyParams(ctx, charPtr, message.length);
484 if(err) {
485 return err;
486 }
487 break;
488 #endif /* APPLE_DH */
489 default:
490 assert(0);
491 return errSSLInternal;
492 }
493
494 /* this is what's hashed */
495 SSLBuffer signedParams;
496 signedParams.data = message.data;
497 signedParams.length = charPtr - message.data;
498
499 signatureLen = SSLDecodeInt(charPtr, 2);
500 charPtr += 2;
501 if((charPtr + signatureLen) != endCp) {
502 sslErrorLog("signedServerKeyExchange: msg len error 4\n");
503 return errSSLProtocol;
504 }
505 signature = charPtr;
506
507 clientRandom.data = ctx->clientRandom;
508 clientRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
509 serverRandom.data = ctx->serverRandom;
510 serverRandom.length = SSL_CLIENT_SRVR_RAND_SIZE;
511
512 if(isRsa) {
513 /* skip this if signing with DSA */
514 dataToSign = hashes;
515 dataToSignLen = SSL_SHA1_DIGEST_LEN + SSL_MD5_DIGEST_LEN;
516 hashOut.data = hashes;
517 hashOut.length = SSL_MD5_DIGEST_LEN;
518
519 if ((err = ReadyHash(SSLHashMD5, hashCtx, ctx)) != 0)
520 goto fail;
521 if ((err = SSLHashMD5.update(hashCtx, clientRandom)) != 0)
522 goto fail;
523 if ((err = SSLHashMD5.update(hashCtx, serverRandom)) != 0)
524 goto fail;
525 if ((err = SSLHashMD5.update(hashCtx, signedParams)) != 0)
526 goto fail;
527 if ((err = SSLHashMD5.final(hashCtx, hashOut)) != 0)
528 goto fail;
529 }
530 else {
531 /* DSA - just use the SHA1 hash */
532 dataToSign = &hashes[SSL_MD5_DIGEST_LEN];
533 dataToSignLen = SSL_SHA1_DIGEST_LEN;
534 }
535 hashOut.data = hashes + SSL_MD5_DIGEST_LEN;
536 hashOut.length = SSL_SHA1_DIGEST_LEN;
537 if ((err = SSLFreeBuffer(hashCtx, ctx)) != 0)
538 goto fail;
539
540 if ((err = ReadyHash(SSLHashSHA1, hashCtx, ctx)) != 0)
541 goto fail;
542 if ((err = SSLHashSHA1.update(hashCtx, clientRandom)) != 0)
543 goto fail;
544 if ((err = SSLHashSHA1.update(hashCtx, serverRandom)) != 0)
545 goto fail;
546 if ((err = SSLHashSHA1.update(hashCtx, signedParams)) != 0)
547 goto fail;
548 if ((err = SSLHashSHA1.final(hashCtx, hashOut)) != 0)
549 goto fail;
550
551 err = sslRawVerify(ctx,
552 ctx->peerPubKey,
553 ctx->peerPubKeyCsp,
554 dataToSign, /* plaintext */
555 dataToSignLen, /* plaintext length */
556 signature,
557 signatureLen);
558 if(err) {
559 sslErrorLog("SSLDecodeSignedServerKeyExchange: sslRawVerify "
560 "returned %d\n", (int)err);
561 goto fail;
562 }
563
564 /* Signature matches; now replace server key with new key */
565 switch(ctx->selectedCipherSpec->keyExchangeMethod) {
566 case SSL_RSA:
567 case SSL_RSA_EXPORT:
568 {
569 SSLBuffer modBuf;
570 SSLBuffer expBuf;
571
572 /* first free existing peerKey */
573 sslFreeKey(ctx->peerPubKeyCsp,
574 &ctx->peerPubKey,
575 NULL); /* no KCItem */
576
577 /* and cook up a new one from raw bits */
578 modBuf.data = modulus;
579 modBuf.length = modulusLen;
580 expBuf.data = exponent;
581 expBuf.length = exponentLen;
582 err = sslGetPubKeyFromBits(ctx,
583 &modBuf,
584 &expBuf,
585 &ctx->peerPubKey,
586 &ctx->peerPubKeyCsp);
587 break;
588 }
589 case SSL_DHE_RSA:
590 case SSL_DHE_RSA_EXPORT:
591 case SSL_DHE_DSS:
592 case SSL_DHE_DSS_EXPORT:
593 break; /* handled above */
594 default:
595 assert(0); /* handled above */
596 }
597 fail:
598 SSLFreeBuffer(signedHashes, ctx);
599 SSLFreeBuffer(hashCtx, ctx);
600 return err;
601 }
602
603 static OSStatus
604 SSLDecodeRSAKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
605 { OSStatus err;
606 UInt32 outputLen, localKeyModulusLen;
607 SSLProtocolVersion version;
608 Boolean useEncryptKey = false;
609 UInt8 *src = NULL;
610 SecKeyRef keyRef = NULL;
611 const CSSM_KEY *cssmKey;
612
613 assert(ctx->protocolSide == SSL_ServerSide);
614
615 #if SSL_SERVER_KEYEXCH_HACK
616 /*
617 * the way we work with Netscape.
618 * FIXME - maybe we should *require* an encryptPrivKey in this
619 * situation?
620 */
621 if((ctx->selectedCipherSpec->keyExchangeMethod == SSL_RSA_EXPORT) &&
622 (ctx->encryptPrivKey != NULL)) {
623 useEncryptKey = true;
624 }
625
626 #else /* !SSL_SERVER_KEYEXCH_HACK */
627 /* The "correct" way, I think, which doesn't work with Netscape */
628 if (ctx->encryptPrivKeyRef) {
629 useEncryptKey = true;
630 }
631 #endif /* SSL_SERVER_KEYEXCH_HACK */
632 if (useEncryptKey) {
633 keyRef = ctx->encryptPrivKeyRef;
634 /* FIXME: when 3420180 is implemented, pick appropriate creds here */
635 }
636 else {
637 keyRef = ctx->signingPrivKeyRef;
638 /* FIXME: when 3420180 is implemented, pick appropriate creds here */
639 }
640 err = SecKeyGetCSSMKey(keyRef, &cssmKey);
641 if(err) {
642 sslErrorLog("SSLDecodeRSAKeyExchange: SecKeyGetCSSMKey err %d\n",
643 (int)err);
644 return err;
645 }
646
647 localKeyModulusLen = sslKeyLengthInBytes(cssmKey);
648
649 /*
650 * We have to tolerate incoming key exchange msgs with and without the
651 * two-byte "encrypted length" field.
652 */
653 if (keyExchange.length == localKeyModulusLen) {
654 /* no length encoded */
655 src = keyExchange.data;
656 }
657 else if((keyExchange.length == (localKeyModulusLen + 2)) &&
658 (ctx->negProtocolVersion >= TLS_Version_1_0)) {
659 /* TLS only - skip the length bytes */
660 src = keyExchange.data + 2;
661 }
662 else {
663 sslErrorLog("SSLDecodeRSAKeyExchange: length error (exp %u got %u)\n",
664 (unsigned)localKeyModulusLen, (unsigned)keyExchange.length);
665 return errSSLProtocol;
666 }
667 err = SSLAllocBuffer(ctx->preMasterSecret, SSL_RSA_PREMASTER_SECRET_SIZE, ctx);
668 if(err != 0) {
669 return err;
670 }
671
672 /*
673 * From this point on, to defend against the Bleichenbacher attack
674 * and its Klima-Pokorny-Rosa variant, any errors we detect are *not*
675 * reported to the caller or the peer. If we detect any error during
676 * decryption (e.g., bad PKCS1 padding) or in the testing of the version
677 * number in the premaster secret, we proceed by generating a random
678 * premaster secret, with the correct version number, and tell our caller
679 * that everything is fine. This session will fail as soon as the
680 * finished messages are sent, since we will be using a bogus premaster
681 * secret (and hence bogus session and MAC keys). Meanwhile we have
682 * not provided any side channel information relating to the cause of
683 * the failure.
684 *
685 * See http://eprint.iacr.org/2003/052/ for more info.
686 */
687 err = sslRsaDecrypt(ctx,
688 keyRef,
689 src,
690 localKeyModulusLen, // ciphertext len
691 ctx->preMasterSecret.data,
692 SSL_RSA_PREMASTER_SECRET_SIZE, // plaintext buf available
693 &outputLen);
694
695 if(err != noErr) {
696 /* possible Bleichenbacher attack */
697 sslLogNegotiateDebug("SSLDecodeRSAKeyExchange: RSA decrypt fail");
698 }
699 else if(outputLen != SSL_RSA_PREMASTER_SECRET_SIZE) {
700 sslLogNegotiateDebug("SSLDecodeRSAKeyExchange: premaster secret size error");
701 err = errSSLProtocol; // not passed back to caller
702 }
703
704 if(err == noErr) {
705 /*
706 * Two legal values here - the one we actually negotiated (which is
707 * technically incorrect but not uncommon), and the one the client
708 * sent as its preferred version in the client hello msg.
709 */
710 version = (SSLProtocolVersion)SSLDecodeInt(ctx->preMasterSecret.data, 2);
711 if((version != ctx->negProtocolVersion) &&
712 (version != ctx->clientReqProtocol)) {
713 /* possible Klima-Pokorny-Rosa attack */
714 sslLogNegotiateDebug("SSLDecodeRSAKeyExchange: version error");
715 err = errSSLProtocol;
716 }
717 }
718 if(err != noErr) {
719 /*
720 * Obfuscate failures for defense against Bleichenbacher and
721 * Klima-Pokorny-Rosa attacks.
722 */
723 SSLEncodeInt(ctx->preMasterSecret.data, ctx->negProtocolVersion, 2);
724 SSLBuffer tmpBuf;
725 tmpBuf.data = ctx->preMasterSecret.data + 2;
726 tmpBuf.length = SSL_RSA_PREMASTER_SECRET_SIZE - 2;
727 /* must ignore failures here */
728 sslRand(ctx, &tmpBuf);
729 }
730
731 /* in any case, save premaster secret (good or bogus) and proceed */
732 return noErr;
733 }
734
735 static OSStatus
736 SSLEncodeRSAKeyExchange(SSLRecord &keyExchange, SSLContext *ctx)
737 { OSStatus err;
738 UInt32 outputLen, peerKeyModulusLen;
739 UInt32 bufLen;
740 UInt8 *dst;
741 bool encodeLen = false;
742
743 assert(ctx->protocolSide == SSL_ClientSide);
744 if ((err = SSLEncodeRSAPremasterSecret(ctx)) != 0)
745 return err;
746
747 keyExchange.contentType = SSL_RecordTypeHandshake;
748 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
749 (ctx->negProtocolVersion == TLS_Version_1_0));
750 keyExchange.protocolVersion = ctx->negProtocolVersion;
751
752 peerKeyModulusLen = sslKeyLengthInBytes(ctx->peerPubKey);
753 bufLen = peerKeyModulusLen + 4;
754 #if RSA_CLIENT_KEY_ADD_LENGTH
755 if(ctx->negProtocolVersion >= TLS_Version_1_0) {
756 bufLen += 2;
757 encodeLen = true;
758 }
759 #endif
760 if ((err = SSLAllocBuffer(keyExchange.contents,
761 bufLen,ctx)) != 0)
762 {
763 return err;
764 }
765 dst = keyExchange.contents.data + 4;
766 if(encodeLen) {
767 dst += 2;
768 }
769 keyExchange.contents.data[0] = SSL_HdskClientKeyExchange;
770
771 /* this is the record payload length */
772 SSLEncodeInt(keyExchange.contents.data + 1, bufLen - 4, 3);
773 if(encodeLen) {
774 /* the length of the encrypted pre_master_secret */
775 SSLEncodeInt(keyExchange.contents.data + 4,
776 peerKeyModulusLen, 2);
777 }
778 err = sslRsaEncrypt(ctx,
779 ctx->peerPubKey,
780 /* FIXME - maybe this should be ctx->cspHand */
781 ctx->peerPubKeyCsp,
782 ctx->preMasterSecret.data,
783 SSL_RSA_PREMASTER_SECRET_SIZE,
784 dst,
785 peerKeyModulusLen,
786 &outputLen);
787 if(err) {
788 return err;
789 }
790
791 assert(outputLen == encodeLen ?
792 keyExchange.contents.length - 6 :
793 keyExchange.contents.length - 4 );
794
795 return noErr;
796 }
797
798
799 #if APPLE_DH
800
801 #pragma mark -
802 #pragma mark *** Diffie-Hellman key exchange ***
803
804 /*
805 * Diffie-Hellman setup, server side. On successful return, the
806 * following SSLContext members are valid:
807 *
808 * dhParamsPrime
809 * dhParamsGenerator
810 * dhPrivate
811 * dhExchangePublic
812 */
813 static OSStatus
814 SSLGenServerDHParamsAndKey(
815 SSLContext *ctx)
816 {
817 OSStatus ortn;
818 assert(ctx->protocolSide == SSL_ServerSide);
819
820 /*
821 * Obtain D-H parameters if we don't have them.
822 */
823 if(ctx->dhParamsPrime.data == NULL) {
824 assert(ctx->dhParamsGenerator.data == NULL);
825 const SSLBuffer &pr = serverDhParams().prime();
826 ortn = SSLCopyBuffer(pr, ctx->dhParamsPrime);
827 if(ortn) {
828 return ortn;
829 }
830 const SSLBuffer &gen = serverDhParams().generator();
831 ortn = SSLCopyBuffer(gen, ctx->dhParamsGenerator);
832 if(ortn) {
833 return ortn;
834 }
835 const SSLBuffer &block = serverDhParams().paramBlock();
836 ortn = SSLCopyBuffer(block, ctx->dhParamsEncoded);
837 if(ortn) {
838 return ortn;
839 }
840 }
841
842 /* generate per-session D-H key pair */
843 sslFreeKey(ctx->cspHand, &ctx->dhPrivate, NULL);
844 SSLFreeBuffer(ctx->dhExchangePublic, ctx);
845 ctx->dhPrivate = (CSSM_KEY *)sslMalloc(sizeof(CSSM_KEY));
846 CSSM_KEY pubKey;
847 ortn = sslDhGenerateKeyPair(ctx,
848 ctx->dhParamsEncoded,
849 ctx->dhParamsPrime.length * 8,
850 &pubKey, ctx->dhPrivate);
851 if(ortn) {
852 return ortn;
853 }
854 CSSM_TO_SSLBUF(&pubKey.KeyData, &ctx->dhExchangePublic);
855 return noErr;
856 }
857
858 /*
859 * Encode DH params and public key in caller-supplied buffer.
860 */
861 static OSStatus
862 SSLEncodeDHKeyParams(
863 SSLContext *ctx,
864 UInt8 *charPtr)
865 {
866 assert(ctx->protocolSide == SSL_ServerSide);
867 assert(ctx->dhParamsPrime.data != NULL);
868 assert(ctx->dhParamsGenerator.data != NULL);
869 assert(ctx->dhExchangePublic.data != NULL);
870
871 charPtr = SSLEncodeInt(charPtr, ctx->dhParamsPrime.length, 2);
872 memcpy(charPtr, ctx->dhParamsPrime.data, ctx->dhParamsPrime.length);
873 charPtr += ctx->dhParamsPrime.length;
874
875 charPtr = SSLEncodeInt(charPtr, ctx->dhParamsGenerator.length, 2);
876 memcpy(charPtr, ctx->dhParamsGenerator.data,
877 ctx->dhParamsGenerator.length);
878 charPtr += ctx->dhParamsGenerator.length;
879
880 charPtr = SSLEncodeInt(charPtr, ctx->dhExchangePublic.length, 2);
881 memcpy(charPtr, ctx->dhExchangePublic.data,
882 ctx->dhExchangePublic.length);
883
884 dumpBuf("server prime", ctx->dhParamsPrime);
885 dumpBuf("server generator", ctx->dhParamsGenerator);
886 dumpBuf("server pub key", ctx->dhExchangePublic);
887 return noErr;
888 }
889
890 /*
891 * Decode DH params and server public key.
892 */
893 static OSStatus
894 SSLDecodeDHKeyParams(
895 SSLContext *ctx,
896 UInt8 *&charPtr, // IN/OUT
897 UInt32 length)
898 {
899 OSStatus err = noErr;
900
901 assert(ctx->protocolSide == SSL_ClientSide);
902 UInt8 *endCp = charPtr + length;
903
904 /* Allow reuse via renegotiation */
905 SSLFreeBuffer(ctx->dhParamsPrime, ctx);
906 SSLFreeBuffer(ctx->dhParamsGenerator, ctx);
907 SSLFreeBuffer(ctx->dhPeerPublic, ctx);
908
909 /* Prime, with a two-byte length */
910 UInt32 len = SSLDecodeInt(charPtr, 2);
911 charPtr += 2;
912 if((charPtr + len) > endCp) {
913 return errSSLProtocol;
914 }
915 err = SSLAllocBuffer(ctx->dhParamsPrime, len, ctx);
916 if(err) {
917 return err;
918 }
919 memmove(ctx->dhParamsPrime.data, charPtr, len);
920 charPtr += len;
921
922 /* Generator, with a two-byte length */
923 len = SSLDecodeInt(charPtr, 2);
924 charPtr += 2;
925 if((charPtr + len) > endCp) {
926 return errSSLProtocol;
927 }
928 err = SSLAllocBuffer(ctx->dhParamsGenerator, len, ctx);
929 if(err) {
930 return err;
931 }
932 memmove(ctx->dhParamsGenerator.data, charPtr, len);
933 charPtr += len;
934
935 /* peer public key, with a two-byte length */
936 len = SSLDecodeInt(charPtr, 2);
937 charPtr += 2;
938 err = SSLAllocBuffer(ctx->dhPeerPublic, len, ctx);
939 if(err) {
940 return err;
941 }
942 memmove(ctx->dhPeerPublic.data, charPtr, len);
943 charPtr += len;
944
945 dumpBuf("client peer pub", ctx->dhPeerPublic);
946 dumpBuf("client prime", ctx->dhParamsPrime);
947 dumpBuf("client generator", ctx->dhParamsGenerator);
948
949 return err;
950 }
951
952 /*
953 * Given the server's Diffie-Hellman parameters, generate our
954 * own DH key pair, and perform key exchange using the server's
955 * public key and our private key. The result is the premaster
956 * secret.
957 *
958 * SSLContext members valid on entry:
959 * dhParamsPrime
960 * dhParamsGenerator
961 * dhPeerPublic
962 *
963 * SSLContext members valid on successful return:
964 * dhPrivate
965 * dhExchangePublic
966 * preMasterSecret
967 */
968 static OSStatus
969 SSLGenClientDHKeyAndExchange(SSLContext *ctx)
970 {
971 OSStatus ortn;
972
973 assert(ctx->protocolSide == SSL_ClientSide);
974 if((ctx->dhParamsPrime.data == NULL) ||
975 (ctx->dhParamsGenerator.data == NULL) ||
976 (ctx->dhPeerPublic.data == NULL)) {
977 sslErrorLog("SSLGenClientDHKeyAndExchange: incomplete server params\n");
978 return errSSLProtocol;
979 }
980
981 /* generate two keys */
982 CSSM_KEY pubKey;
983 ctx->dhPrivate = (CSSM_KEY *)sslMalloc(sizeof(CSSM_KEY));
984 ortn = sslDhGenKeyPairClient(ctx,
985 ctx->dhParamsPrime, ctx->dhParamsGenerator,
986 &pubKey, ctx->dhPrivate);
987 if(ortn) {
988 sslFree(ctx->dhPrivate);
989 ctx->dhPrivate = NULL;
990 return ortn;
991 }
992
993 /* do the exchange, size of prime */
994 ortn = sslDhKeyExchange(ctx, ctx->dhParamsPrime.length * 8,
995 &ctx->preMasterSecret);
996 if(ortn) {
997 return ortn;
998 }
999 CSSM_TO_SSLBUF(&pubKey.KeyData, &ctx->dhExchangePublic);
1000 return noErr;
1001 }
1002
1003 static OSStatus
1004 SSLEncodeDHanonServerKeyExchange(SSLRecord &keyExch, SSLContext *ctx)
1005 {
1006 OSStatus ortn = noErr;
1007
1008 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
1009 (ctx->negProtocolVersion == TLS_Version_1_0));
1010 assert(ctx->protocolSide == SSL_ServerSide);
1011
1012 /*
1013 * Obtain D-H parameters (if we don't have them) and a key pair.
1014 */
1015 ortn = SSLGenServerDHParamsAndKey(ctx);
1016 if(ortn) {
1017 return ortn;
1018 }
1019
1020 UInt32 length = 6 +
1021 ctx->dhParamsPrime.length +
1022 ctx->dhParamsGenerator.length + ctx->dhExchangePublic.length;
1023
1024 keyExch.protocolVersion = ctx->negProtocolVersion;
1025 keyExch.contentType = SSL_RecordTypeHandshake;
1026 if ((ortn = SSLAllocBuffer(keyExch.contents, length+4, ctx)) != 0)
1027 return ortn;
1028
1029 UInt8 *charPtr = keyExch.contents.data;
1030 *charPtr++ = SSL_HdskServerKeyExchange;
1031 charPtr = SSLEncodeInt(charPtr, length, 3);
1032
1033 /* encode prime, generator, our public key */
1034 return SSLEncodeDHKeyParams(ctx, charPtr);
1035 }
1036
1037
1038 static OSStatus
1039 SSLDecodeDHanonServerKeyExchange(SSLBuffer message, SSLContext *ctx)
1040 {
1041 OSStatus err = noErr;
1042
1043 assert(ctx->protocolSide == SSL_ClientSide);
1044 if (message.length < 6) {
1045 sslErrorLog("SSLDecodeDHanonServerKeyExchange error: msg len %u\n",
1046 (unsigned)message.length);
1047 return errSSLProtocol;
1048 }
1049 UInt8 *charPtr = message.data;
1050 err = SSLDecodeDHKeyParams(ctx, charPtr, message.length);
1051 if(err == noErr) {
1052 if((message.data + message.length) != charPtr) {
1053 err = errSSLProtocol;
1054 }
1055 }
1056 return err;
1057 }
1058
1059 static OSStatus
1060 SSLDecodeDHClientKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
1061 {
1062 OSStatus ortn = noErr;
1063 unsigned int publicLen;
1064
1065 assert(ctx->protocolSide == SSL_ServerSide);
1066 if(ctx->dhParamsPrime.data == NULL) {
1067 /* should never happen */
1068 assert(0);
1069 return errSSLInternal;
1070 }
1071
1072 /* this message simply contains the client's public DH key */
1073 UInt8 *charPtr = keyExchange.data;
1074 publicLen = SSLDecodeInt(charPtr, 2);
1075 charPtr += 2;
1076 if((keyExchange.length != publicLen + 2) ||
1077 (publicLen > ctx->dhParamsPrime.length)) {
1078 return errSSLProtocol;
1079 }
1080 SSLFreeBuffer(ctx->dhPeerPublic, ctx); // allow reuse via renegotiation
1081 ortn = SSLAllocBuffer(ctx->dhPeerPublic, publicLen, ctx);
1082 if(ortn) {
1083 return ortn;
1084 }
1085 memmove(ctx->dhPeerPublic.data, charPtr, publicLen);
1086
1087 /* DH Key exchange, result --> premaster secret */
1088 SSLFreeBuffer(ctx->preMasterSecret, ctx);
1089 ortn = sslDhKeyExchange(ctx, ctx->dhParamsPrime.length * 8,
1090 &ctx->preMasterSecret);
1091
1092 dumpBuf("server peer pub", ctx->dhPeerPublic);
1093 dumpBuf("server premaster", ctx->preMasterSecret);
1094 return ortn;
1095 }
1096
1097 static OSStatus
1098 SSLEncodeDHClientKeyExchange(SSLRecord &keyExchange, SSLContext *ctx)
1099 { OSStatus err;
1100 unsigned int outputLen;
1101
1102 assert(ctx->protocolSide == SSL_ClientSide);
1103 if ((err = SSLGenClientDHKeyAndExchange(ctx)) != 0)
1104 return err;
1105
1106 outputLen = ctx->dhExchangePublic.length + 2;
1107
1108 keyExchange.contentType = SSL_RecordTypeHandshake;
1109 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
1110 (ctx->negProtocolVersion == TLS_Version_1_0));
1111 keyExchange.protocolVersion = ctx->negProtocolVersion;
1112
1113 if ((err = SSLAllocBuffer(keyExchange.contents,outputLen + 4,ctx)) != 0)
1114 return err;
1115
1116 keyExchange.contents.data[0] = SSL_HdskClientKeyExchange;
1117 SSLEncodeInt(keyExchange.contents.data+1,
1118 ctx->dhExchangePublic.length+2, 3);
1119
1120 SSLEncodeInt(keyExchange.contents.data+4,
1121 ctx->dhExchangePublic.length, 2);
1122 memcpy(keyExchange.contents.data+6, ctx->dhExchangePublic.data,
1123 ctx->dhExchangePublic.length);
1124
1125 dumpBuf("client pub key", ctx->dhExchangePublic);
1126 dumpBuf("client premaster", ctx->preMasterSecret);
1127 return noErr;
1128 }
1129
1130 #endif /* APPLE_DH */
1131
1132 #pragma mark -
1133 #pragma mark *** Public Functions ***
1134 OSStatus
1135 SSLEncodeServerKeyExchange(SSLRecord &keyExch, SSLContext *ctx)
1136 { OSStatus err;
1137
1138 switch (ctx->selectedCipherSpec->keyExchangeMethod)
1139 { case SSL_RSA:
1140 case SSL_RSA_EXPORT:
1141 #if APPLE_DH
1142 case SSL_DHE_RSA:
1143 case SSL_DHE_RSA_EXPORT:
1144 case SSL_DHE_DSS:
1145 case SSL_DHE_DSS_EXPORT:
1146 #endif /* APPLE_DH */
1147 if ((err = SSLEncodeSignedServerKeyExchange(keyExch, ctx)) != 0)
1148 return err;
1149 break;
1150 #if APPLE_DH
1151 case SSL_DH_anon:
1152 case SSL_DH_anon_EXPORT:
1153 if ((err = SSLEncodeDHanonServerKeyExchange(keyExch, ctx)) != 0)
1154 return err;
1155 break;
1156 #endif
1157 default:
1158 return unimpErr;
1159 }
1160
1161 return noErr;
1162 }
1163
1164 OSStatus
1165 SSLProcessServerKeyExchange(SSLBuffer message, SSLContext *ctx)
1166 {
1167 OSStatus err;
1168
1169 switch (ctx->selectedCipherSpec->keyExchangeMethod) {
1170 case SSL_RSA:
1171 case SSL_RSA_EXPORT:
1172 #if APPLE_DH
1173 case SSL_DHE_RSA:
1174 case SSL_DHE_RSA_EXPORT:
1175 case SSL_DHE_DSS:
1176 case SSL_DHE_DSS_EXPORT:
1177 #endif
1178 err = SSLDecodeSignedServerKeyExchange(message, ctx);
1179 break;
1180 #if APPLE_DH
1181 case SSL_DH_anon:
1182 case SSL_DH_anon_EXPORT:
1183 err = SSLDecodeDHanonServerKeyExchange(message, ctx);
1184 break;
1185 #endif
1186 default:
1187 err = unimpErr;
1188 break;
1189 }
1190
1191 return err;
1192 }
1193
1194 OSStatus
1195 SSLEncodeKeyExchange(SSLRecord &keyExchange, SSLContext *ctx)
1196 { OSStatus err;
1197
1198 assert(ctx->protocolSide == SSL_ClientSide);
1199
1200 switch (ctx->selectedCipherSpec->keyExchangeMethod) {
1201 case SSL_RSA:
1202 case SSL_RSA_EXPORT:
1203 err = SSLEncodeRSAKeyExchange(keyExchange, ctx);
1204 break;
1205 #if APPLE_DH
1206 case SSL_DHE_RSA:
1207 case SSL_DHE_RSA_EXPORT:
1208 case SSL_DHE_DSS:
1209 case SSL_DHE_DSS_EXPORT:
1210 case SSL_DH_anon:
1211 case SSL_DH_anon_EXPORT:
1212 err = SSLEncodeDHClientKeyExchange(keyExchange, ctx);
1213 break;
1214 #endif
1215 default:
1216 err = unimpErr;
1217 }
1218
1219 return err;
1220 }
1221
1222 OSStatus
1223 SSLProcessKeyExchange(SSLBuffer keyExchange, SSLContext *ctx)
1224 { OSStatus err;
1225
1226 switch (ctx->selectedCipherSpec->keyExchangeMethod)
1227 { case SSL_RSA:
1228 case SSL_RSA_EXPORT:
1229 if ((err = SSLDecodeRSAKeyExchange(keyExchange, ctx)) != 0)
1230 return err;
1231 break;
1232 #if APPLE_DH
1233 case SSL_DH_anon:
1234 case SSL_DHE_DSS:
1235 case SSL_DHE_DSS_EXPORT:
1236 case SSL_DHE_RSA:
1237 case SSL_DHE_RSA_EXPORT:
1238 case SSL_DH_anon_EXPORT:
1239 if ((err = SSLDecodeDHClientKeyExchange(keyExchange, ctx)) != 0)
1240 return err;
1241 break;
1242 #endif
1243 default:
1244 return unimpErr;
1245 }
1246
1247 return noErr;
1248 }
1249
1250 OSStatus
1251 SSLInitPendingCiphers(SSLContext *ctx)
1252 { OSStatus err;
1253 SSLBuffer key;
1254 UInt8 *keyDataProgress, *keyPtr, *ivPtr;
1255 int keyDataLen;
1256 CipherContext *serverPending, *clientPending;
1257
1258 key.data = 0;
1259
1260 ctx->readPending.macRef = ctx->selectedCipherSpec->macAlgorithm;
1261 ctx->writePending.macRef = ctx->selectedCipherSpec->macAlgorithm;
1262 ctx->readPending.symCipher = ctx->selectedCipherSpec->cipher;
1263 ctx->writePending.symCipher = ctx->selectedCipherSpec->cipher;
1264 ctx->readPending.sequenceNum.high = ctx->readPending.sequenceNum.low = 0;
1265 ctx->writePending.sequenceNum.high = ctx->writePending.sequenceNum.low = 0;
1266
1267 keyDataLen = ctx->selectedCipherSpec->macAlgorithm->hash->digestSize +
1268 ctx->selectedCipherSpec->cipher->secretKeySize;
1269 if (ctx->selectedCipherSpec->isExportable == NotExportable)
1270 keyDataLen += ctx->selectedCipherSpec->cipher->ivSize;
1271 keyDataLen *= 2; /* two of everything */
1272
1273 if ((err = SSLAllocBuffer(key, keyDataLen, ctx)) != 0)
1274 return err;
1275 assert(ctx->sslTslCalls != NULL);
1276 if ((err = ctx->sslTslCalls->generateKeyMaterial(key, ctx)) != 0)
1277 goto fail;
1278
1279 if (ctx->protocolSide == SSL_ServerSide)
1280 { serverPending = &ctx->writePending;
1281 clientPending = &ctx->readPending;
1282 }
1283 else
1284 { serverPending = &ctx->readPending;
1285 clientPending = &ctx->writePending;
1286 }
1287
1288 keyDataProgress = key.data;
1289 memcpy(clientPending->macSecret, keyDataProgress,
1290 ctx->selectedCipherSpec->macAlgorithm->hash->digestSize);
1291 keyDataProgress += ctx->selectedCipherSpec->macAlgorithm->hash->digestSize;
1292 memcpy(serverPending->macSecret, keyDataProgress,
1293 ctx->selectedCipherSpec->macAlgorithm->hash->digestSize);
1294 keyDataProgress += ctx->selectedCipherSpec->macAlgorithm->hash->digestSize;
1295
1296 /* init the reusable-per-record MAC contexts */
1297 err = ctx->sslTslCalls->initMac(clientPending, ctx);
1298 if(err) {
1299 goto fail;
1300 }
1301 err = ctx->sslTslCalls->initMac(serverPending, ctx);
1302 if(err) {
1303 goto fail;
1304 }
1305
1306 if (ctx->selectedCipherSpec->isExportable == NotExportable)
1307 { keyPtr = keyDataProgress;
1308 keyDataProgress += ctx->selectedCipherSpec->cipher->secretKeySize;
1309 /* Skip server write key to get to IV */
1310 ivPtr = keyDataProgress + ctx->selectedCipherSpec->cipher->secretKeySize;
1311 if ((err = ctx->selectedCipherSpec->cipher->initialize(keyPtr, ivPtr,
1312 clientPending, ctx)) != 0)
1313 goto fail;
1314 keyPtr = keyDataProgress;
1315 keyDataProgress += ctx->selectedCipherSpec->cipher->secretKeySize;
1316 /* Skip client write IV to get to server write IV */
1317 ivPtr = keyDataProgress + ctx->selectedCipherSpec->cipher->ivSize;
1318 if ((err = ctx->selectedCipherSpec->cipher->initialize(keyPtr, ivPtr,
1319 serverPending, ctx)) != 0)
1320 goto fail;
1321 }
1322 else {
1323 UInt8 clientExportKey[16], serverExportKey[16],
1324 clientExportIV[16], serverExportIV[16];
1325 SSLBuffer clientWrite, serverWrite;
1326 SSLBuffer finalClientWrite, finalServerWrite;
1327 SSLBuffer finalClientIV, finalServerIV;
1328
1329 assert(ctx->selectedCipherSpec->cipher->keySize <= 16);
1330 assert(ctx->selectedCipherSpec->cipher->ivSize <= 16);
1331
1332 /* Inputs to generateExportKeyAndIv are clientRandom, serverRandom,
1333 * clientWriteKey, serverWriteKey. The first two are already present
1334 * in ctx.
1335 * Outputs are a key and IV for each of {server, client}.
1336 */
1337 clientWrite.data = keyDataProgress;
1338 clientWrite.length = ctx->selectedCipherSpec->cipher->secretKeySize;
1339 serverWrite.data = keyDataProgress + clientWrite.length;
1340 serverWrite.length = ctx->selectedCipherSpec->cipher->secretKeySize;
1341 finalClientWrite.data = clientExportKey;
1342 finalServerWrite.data = serverExportKey;
1343 finalClientIV.data = clientExportIV;
1344 finalServerIV.data = serverExportIV;
1345 finalClientWrite.length = 16;
1346 finalServerWrite.length = 16;
1347 /* these can be zero */
1348 finalClientIV.length = ctx->selectedCipherSpec->cipher->ivSize;
1349 finalServerIV.length = ctx->selectedCipherSpec->cipher->ivSize;
1350
1351 assert(ctx->sslTslCalls != NULL);
1352 err = ctx->sslTslCalls->generateExportKeyAndIv(ctx, clientWrite, serverWrite,
1353 finalClientWrite, finalServerWrite, finalClientIV, finalServerIV);
1354 if(err) {
1355 goto fail;
1356 }
1357 if ((err = ctx->selectedCipherSpec->cipher->initialize(clientExportKey,
1358 clientExportIV, clientPending, ctx)) != 0)
1359 goto fail;
1360 if ((err = ctx->selectedCipherSpec->cipher->initialize(serverExportKey,
1361 serverExportIV, serverPending, ctx)) != 0)
1362 goto fail;
1363 }
1364
1365 /* Ciphers are ready for use */
1366 ctx->writePending.ready = 1;
1367 ctx->readPending.ready = 1;
1368
1369 /* Ciphers get swapped by sending or receiving a change cipher spec message */
1370
1371 err = noErr;
1372 fail:
1373 SSLFreeBuffer(key, ctx);
1374 return err;
1375 }
1376