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