2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 File: sslKeyExchange.c
22 Contains: Support for key exchange and server key exchange
24 Written by: Doug Mitchell
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
30 #include "sslContext.h"
31 #include "sslHandshake.h"
32 #include "sslMemory.h"
35 #include "appleCdsa.h"
36 #include "sslDigests.h"
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.
47 #define RSA_CLIENT_KEY_ADD_LENGTH 1
49 typedef CSSM_KEY_PTR SSLRSAPrivateKey
;
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
);
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
);
64 SSLEncodeServerKeyExchange(SSLRecord
&keyExch
, SSLContext
*ctx
)
67 switch (ctx
->selectedCipherSpec
->keyExchangeMethod
)
70 if ((err
= SSLEncodeRSAServerKeyExchange(keyExch
, ctx
)) != 0)
75 if ((err
= SSLEncodeDHanonServerKeyExchange(keyExch
, ctx
)) != 0)
87 SSLEncodeRSAServerKeyExchange(SSLRecord
&keyExch
, SSLContext
*ctx
)
91 UInt32 outputLen
, localKeyModulusLen
;
93 SSLBuffer exportKey
,clientRandom
,serverRandom
,hashCtx
, hash
;
98 /* we have a public key here... */
99 assert(ctx
->encryptPubKey
!= NULL
);
100 assert(ctx
->protocolSide
== SSL_ServerSide
);
102 if ((err
= SSLEncodeRSAKeyParams(&exportKey
, &ctx
->encryptPubKey
, ctx
)) != 0)
105 assert(ctx
->signingPubKey
!= NULL
);
106 localKeyModulusLen
= sslKeyLengthInBytes(ctx
->signingPubKey
);
108 length
= exportKey
.length
+ 2 + localKeyModulusLen
;
109 /* RSA ouputs a block as long as the modulus */
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)
118 charPtr
= keyExch
.contents
.data
;
119 *charPtr
++ = SSL_HdskServerKeyExchange
;
120 charPtr
= SSLEncodeInt(charPtr
, length
, 3);
122 memcpy(charPtr
, exportKey
.data
, exportKey
.length
);
123 charPtr
+= exportKey
.length
;
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
;
130 hash
.data
= &hashes
[0];
132 if ((err
= ReadyHash(SSLHashMD5
, hashCtx
, ctx
)) != 0)
134 if ((err
= SSLHashMD5
.update(hashCtx
, clientRandom
)) != 0)
136 if ((err
= SSLHashMD5
.update(hashCtx
, serverRandom
)) != 0)
138 if ((err
= SSLHashMD5
.update(hashCtx
, exportKey
)) != 0)
140 if ((err
= SSLHashMD5
.final(hashCtx
, hash
)) != 0)
142 if ((err
= SSLFreeBuffer(hashCtx
, ctx
)) != 0)
145 hash
.data
= &hashes
[16];
147 if ((err
= ReadyHash(SSLHashSHA1
, hashCtx
, ctx
)) != 0)
149 if ((err
= SSLHashSHA1
.update(hashCtx
, clientRandom
)) != 0)
151 if ((err
= SSLHashSHA1
.update(hashCtx
, serverRandom
)) != 0)
153 if ((err
= SSLHashSHA1
.update(hashCtx
, exportKey
)) != 0)
155 if ((err
= SSLHashSHA1
.final(hashCtx
, hash
)) != 0)
157 if ((err
= SSLFreeBuffer(hashCtx
, ctx
)) != 0)
160 charPtr
= SSLEncodeInt(charPtr
, localKeyModulusLen
, 2);
161 err
= sslRsaRawSign(ctx
,
172 assert(outputLen
== localKeyModulusLen
);
177 SSLFreeBuffer(hashCtx
, ctx
);
178 SSLFreeBuffer(exportKey
, ctx
);
184 SSLEncodeRSAKeyParams(SSLBuffer
*keyParams
, SSLRSAPrivateKey
*key
, SSLContext
*ctx
)
186 SSLBuffer modulus
, exponent
;
189 err
= sslGetPubKeyBits(ctx
,
195 SSLFreeBuffer(modulus
, ctx
);
196 SSLFreeBuffer(exponent
, ctx
);
200 if ((err
= SSLAllocBuffer(*keyParams
, modulus
.length
+ exponent
.length
+ 4, ctx
)) != 0)
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
);
209 /* these were mallocd by sslGetPubKeyBits() */
210 SSLFreeBuffer(modulus
, ctx
);
211 SSLFreeBuffer(exponent
, ctx
);
217 SSLEncodeDHanonServerKeyExchange(SSLRecord
&keyExch
, SSLContext
*ctx
)
225 length
= 6 + ctx
->dhAnonParams
.primeLen
+ ctx
->dhAnonParams
.generatorLen
+
226 ctx
->dhExchangePublic
.length
;
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)
235 charPtr
= keyExch
.contents
.data
;
236 *charPtr
++ = SSL_HdskServerKeyExchange
;
237 charPtr
= SSLEncodeInt(charPtr
, length
, 3);
239 charPtr
= SSLEncodeInt(charPtr
, ctx
->dhAnonParams
.primeLen
, 2);
240 memcpy(charPtr
, ctx
->dhAnonParams
.prime
, ctx
->dhAnonParams
.primeLen
);
241 charPtr
+= ctx
->dhAnonParams
.primeLen
;
243 charPtr
= SSLEncodeInt(charPtr
, ctx
->dhAnonParams
.generatorLen
, 2);
244 memcpy(charPtr
, ctx
->dhAnonParams
.generator
, ctx
->dhAnonParams
.generatorLen
);
245 charPtr
+= ctx
->dhAnonParams
.generatorLen
;
247 if ((err
= SSLAllocBuffer(ctx
->dhExchangePublic
,
248 ctx
->peerDHParams
.primeLen
, ctx
)) != 0)
250 if ((err
= SSLAllocBuffer(ctx
->dhPrivate
,
251 ctx
->dhExchangePublic
.length
- 16, ctx
)) != 0)
254 if ((err
= ReadyRandom(&random
, ctx
)) != 0)
257 if ((rsaErr
= R_SetupDHAgreement(ctx
->dhExchangePublic
.data
, ctx
->dhPrivate
.data
,
258 ctx
->dhPrivate
.length
, &ctx
->dhAnonParams
, &random
)) != 0)
259 { err
= SSLUnknownErr
;
263 charPtr
= SSLEncodeInt(charPtr
, ctx
->dhExchangePublic
.length
, 2);
264 memcpy(charPtr
, ctx
->dhExchangePublic
.data
, ctx
->dhExchangePublic
.length
);
265 charPtr
+= ctx
->dhExchangePublic
.length
;
268 { A_DH_KEY_AGREE_PARAMS
*params
;
269 unsigned int outputLen
;
271 if ((rsaErr
= B_GetAlgorithmInfo((POINTER
*)¶ms
, ctx
->dhAnonParams
, AI_DHKeyAgree
)) != 0)
272 return SSLUnknownErr
;
273 if ((err
= ReadyRandom(&random
, ctx
)) != 0)
275 if ((err
= SSLAllocBuffer(ctx
->dhExchangePublic
, 128, ctx
)) != 0)
277 if ((rsaErr
= B_KeyAgreePhase1(ctx
->dhAnonParams
, ctx
->dhExchangePublic
.data
,
278 &outputLen
, 128, random
, NO_SURR
)) != 0)
279 { err
= SSLUnknownErr
;
282 ctx
->dhExchangePublic
.length
= outputLen
;
284 length
= 6 + params
->prime
.len
+ params
->base
.len
+ ctx
->dhExchangePublic
.length
;
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)
293 charPtr
= keyExch
.contents
.data
;
294 *charPtr
++ = SSL_HdskServerKeyExchange
;
295 charPtr
= SSLEncodeInt(charPtr
, length
, 3);
297 charPtr
= SSLEncodeInt(charPtr
, params
->prime
.len
, 2);
298 memcpy(charPtr
, params
->prime
.data
, params
->prime
.len
);
299 charPtr
+= params
->prime
.len
;
301 charPtr
= SSLEncodeInt(charPtr
, params
->base
.len
, 2);
302 memcpy(charPtr
, params
->base
.data
, params
->base
.len
);
303 charPtr
+= params
->base
.len
;
305 charPtr
= SSLEncodeInt(charPtr
, ctx
->dhExchangePublic
.length
, 2);
306 memcpy(charPtr
, ctx
->dhExchangePublic
.data
, ctx
->dhExchangePublic
.length
);
307 charPtr
+= ctx
->dhExchangePublic
.length
;
309 #endif /* RSAREF / BSAFE */
311 assert(charPtr
== keyExch
.contents
.data
+ keyExch
.contents
.length
);
316 #endif /* APPLE_DH */
319 SSLProcessServerKeyExchange(SSLBuffer message
, SSLContext
*ctx
)
322 switch (ctx
->selectedCipherSpec
->keyExchangeMethod
)
325 if ((err
= SSLProcessRSAServerKeyExchange(message
, ctx
)) != 0)
330 if ((err
= SSLProcessDHanonServerKeyExchange(message
, ctx
)) != 0)
342 SSLProcessRSAServerKeyExchange(SSLBuffer message
, SSLContext
*ctx
)
345 SSLBuffer tempPubKey
, hashOut
, hashCtx
, clientRandom
, serverRandom
;
346 UInt16 modulusLen
, exponentLen
, signatureLen
;
347 UInt8
*charPtr
, *modulus
, *exponent
, *signature
;
349 SSLBuffer signedHashes
;
351 signedHashes
.data
= 0;
354 if (message
.length
< 2) {
355 sslErrorLog("SSLProcessRSAServerKeyExchange: msg len error 2\n");
356 return errSSLProtocol
;
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
;
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
;
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
;
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;
389 if ((err
= ReadyHash(SSLHashMD5
, hashCtx
, ctx
)) != 0)
391 if ((err
= SSLHashMD5
.update(hashCtx
, clientRandom
)) != 0)
393 if ((err
= SSLHashMD5
.update(hashCtx
, serverRandom
)) != 0)
395 if ((err
= SSLHashMD5
.update(hashCtx
, tempPubKey
)) != 0)
397 if ((err
= SSLHashMD5
.final(hashCtx
, hashOut
)) != 0)
401 * SHA hash goes right after the MD5 hash
403 hashOut
.data
= hash
+ 16;
405 if ((err
= SSLFreeBuffer(hashCtx
, ctx
)) != 0)
408 if ((err
= ReadyHash(SSLHashSHA1
, hashCtx
, ctx
)) != 0)
410 if ((err
= SSLHashSHA1
.update(hashCtx
, clientRandom
)) != 0)
412 if ((err
= SSLHashSHA1
.update(hashCtx
, serverRandom
)) != 0)
414 if ((err
= SSLHashSHA1
.update(hashCtx
, tempPubKey
)) != 0)
416 if ((err
= SSLHashSHA1
.final(hashCtx
, hashOut
)) != 0)
419 err
= sslRsaRawVerify(ctx
,
422 hash
, /* plaintext */
423 36, /* plaintext length */
427 sslErrorLog("SSLProcessRSAServerKeyExchange: sslRsaRawVerify returned %d\n",
432 /* Signature matches; now replace server key with new key */
437 /* first free existing peerKey */
438 sslFreeKey(ctx
->peerPubKeyCsp
,
440 NULL
); /* no KCItem */
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
,
451 &ctx
->peerPubKeyCsp
);
454 SSLFreeBuffer(signedHashes
, ctx
);
455 SSLFreeBuffer(hashCtx
, ctx
);
461 SSLProcessDHanonServerKeyExchange(SSLBuffer message
, SSLContext
*ctx
)
464 unsigned int totalLength
;
466 if (message
.length
< 6) {
467 sslErrorLog("SSLProcessDHanonServerKeyExchange error: msg len %d\n",
469 return errSSLProtocol
;
471 charPtr
= message
.data
;
476 UInt8
*prime
, *generator
, *publicVal
;
478 ctx
->peerDHParams
.primeLen
= SSLDecodeInt(charPtr
, 2);
481 charPtr
+= ctx
->peerDHParams
.primeLen
;
482 totalLength
+= ctx
->peerDHParams
.primeLen
;
483 if (message
.length
< 6 + totalLength
)
484 return errSSLProtocol
;
486 ctx
->peerDHParams
.generatorLen
= SSLDecodeInt(charPtr
, 2);
489 charPtr
+= ctx
->peerDHParams
.generatorLen
;
490 totalLength
+= ctx
->peerDHParams
.generatorLen
;
491 if (message
.length
< 6 + totalLength
)
492 return errSSLProtocol
;
494 ctx
->dhPeerPublic
.length
= SSLDecodeInt(charPtr
, 2);
497 charPtr
+= ctx
->dhPeerPublic
.length
;
498 totalLength
+= ctx
->dhPeerPublic
.length
;
499 if (message
.length
!= 6 + totalLength
)
500 return errSSLProtocol
;
502 assert(charPtr
== message
.data
+ message
.length
);
504 if ((err
= SSLAllocBuffer(alloc
, ctx
->peerDHParams
.primeLen
+
505 ctx
->peerDHParams
.generatorLen
, ctx
)) != 0)
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
);
513 if ((err
= SSLAllocBuffer(ctx
->dhPeerPublic
,
514 ctx
->dhPeerPublic
.length
, ctx
)) != 0)
517 memcpy(ctx
->dhPeerPublic
.data
, publicVal
, ctx
->dhPeerPublic
.length
);
521 unsigned char *publicVal
;
522 A_DH_KEY_AGREE_PARAMS params
;
523 B_ALGORITHM_METHOD
*chooser
[] = { &AM_DH_KEY_AGREE
, 0 };
525 params
.prime
.len
= SSLDecodeInt(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
;
533 params
.base
.len
= SSLDecodeInt(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
;
541 ctx
->dhPeerPublic
.length
= SSLDecodeInt(charPtr
, 2);
542 if ((err
= SSLAllocBuffer(ctx
->dhPeerPublic
, ctx
->dhPeerPublic
.length
, ctx
)) != 0)
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
;
553 params
.exponentBits
= 8 * ctx
->dhPeerPublic
.length
- 1;
555 if ((rsaErr
= B_CreateAlgorithmObject(&ctx
->peerDHParams
)) != 0)
556 return SSLUnknownErr
;
557 if ((rsaErr
= B_SetAlgorithmInfo(ctx
->peerDHParams
, AI_DHKeyAgree
, (POINTER
)¶ms
)) != 0)
558 return SSLUnknownErr
;
559 if ((rsaErr
= B_KeyAgreeInit(ctx
->peerDHParams
, (B_KEY_OBJ
) 0, chooser
, NO_SURR
)) != 0)
560 return SSLUnknownErr
;
570 SSLProcessKeyExchange(SSLBuffer keyExchange
, SSLContext
*ctx
)
573 switch (ctx
->selectedCipherSpec
->keyExchangeMethod
)
576 if ((err
= SSLDecodeRSAKeyExchange(keyExchange
, ctx
)) != 0)
581 if ((err
= SSLDecodeDHanonKeyExchange(keyExchange
, ctx
)) != 0)
593 SSLDecodeRSAKeyExchange(SSLBuffer keyExchange
, SSLContext
*ctx
)
596 UInt32 outputLen
, localKeyModulusLen
;
598 SSLProtocolVersion version
;
599 Boolean useEncryptKey
= false;
603 /* different key names, also need CSP handle */
604 CSSM_CSP_HANDLE cspHand
;
606 assert(ctx
->protocolSide
== SSL_ServerSide
);
608 #if SSL_SERVER_KEYEXCH_HACK
610 * the way we work with Netscape.
611 * FIXME - maybe we should *require* an encryptPrivKey in this
614 if((ctx
->selectedCipherSpec
->keyExchangeMethod
== SSL_RSA_EXPORT
) &&
615 (ctx
->encryptPrivKey
!= NULL
)) {
616 useEncryptKey
= true;
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;
624 #endif /* SSL_SERVER_KEYEXCH_HACK */
626 key
= &ctx
->encryptPrivKey
;
627 cspHand
= ctx
->encryptKeyCsp
;
630 key
= &ctx
->signingPrivKey
;
631 cspHand
= ctx
->signingKeyCsp
;
634 localKeyModulusLen
= sslKeyLengthInBytes(*key
);
637 * We have to tolerate incoming key exchange msgs with and without the
638 * two-byte "encrypted length" field.
640 if (keyExchange
.length
== localKeyModulusLen
) {
641 /* no length encoded */
642 src
= keyExchange
.data
;
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;
650 sslErrorLog("SSLDecodeRSAKeyExchange: length error (exp %u got %u)\n",
651 (unsigned)localKeyModulusLen
, (unsigned)keyExchange
.length
);
652 return errSSLProtocol
;
654 err
= SSLAllocBuffer(result
, localKeyModulusLen
, ctx
);
659 err
= sslRsaDecrypt(ctx
,
673 sslErrorLog("SSLDecodeRSAKeyExchange: outputLen error\n");
674 err
= errSSLProtocol
;
677 result
.length
= outputLen
;
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
;
687 if ((err
= SSLAllocBuffer(ctx
->preMasterSecret
,
688 SSL_RSA_PREMASTER_SECRET_SIZE
, ctx
)) != 0)
690 memcpy(ctx
->preMasterSecret
.data
, result
.data
,
691 SSL_RSA_PREMASTER_SECRET_SIZE
);
695 SSLFreeBuffer(result
, ctx
);
701 SSLDecodeDHanonKeyExchange(SSLBuffer keyExchange
, SSLContext
*ctx
)
703 unsigned int publicLen
;
706 publicLen
= SSLDecodeInt(keyExchange
.data
, 2);
709 if (keyExchange
.length
!= publicLen
+ 2 ||
710 publicLen
!= ctx
->dhAnonParams
.primeLen
)
711 return errSSLProtocol
;
713 if ((err
= SSLAllocBuffer(ctx
->preMasterSecret
, ctx
->dhAnonParams
.primeLen
, ctx
)) != 0)
716 if ((rsaResult
= R_ComputeDHAgreedKey (ctx
->preMasterSecret
.data
, ctx
->dhPeerPublic
.data
,
717 ctx
->dhPrivate
.data
, ctx
->dhPrivate
.length
, &ctx
->dhAnonParams
)) != 0)
718 { err
= SSLUnknownErr
;
723 { unsigned int amount
;
724 if (keyExchange
.length
!= publicLen
+ 2)
725 return errSSLProtocol
;
727 if ((err
= SSLAllocBuffer(ctx
->preMasterSecret
, 128, ctx
)) != 0)
730 if ((rsaResult
= B_KeyAgreePhase2(ctx
->dhAnonParams
, ctx
->preMasterSecret
.data
,
731 &amount
, 128, keyExchange
.data
+2, publicLen
, NO_SURR
)) != 0)
734 ctx
->preMasterSecret
.length
= amount
;
740 #endif /* APPLE_DH */
743 SSLEncodeKeyExchange(SSLRecord
&keyExchange
, SSLContext
*ctx
)
746 assert(ctx
->protocolSide
== SSL_ClientSide
);
748 switch (ctx
->selectedCipherSpec
->keyExchangeMethod
)
751 if ((err
= SSLEncodeRSAKeyExchange(keyExchange
, ctx
)) != 0)
756 if ((err
= SSLEncodeDHanonKeyExchange(keyExchange
, ctx
)) != 0)
768 SSLEncodeRSAKeyExchange(SSLRecord
&keyExchange
, SSLContext
*ctx
)
770 UInt32 outputLen
, peerKeyModulusLen
;
773 bool encodeLen
= false;
775 if ((err
= SSLEncodeRSAPremasterSecret(ctx
)) != 0)
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
;
783 peerKeyModulusLen
= sslKeyLengthInBytes(ctx
->peerPubKey
);
784 bufLen
= peerKeyModulusLen
+ 4;
785 #if RSA_CLIENT_KEY_ADD_LENGTH
786 if(ctx
->negProtocolVersion
>= TLS_Version_1_0
) {
791 if ((err
= SSLAllocBuffer(keyExchange
.contents
,
796 dst
= keyExchange
.contents
.data
+ 4;
800 keyExchange
.contents
.data
[0] = SSL_HdskClientKeyExchange
;
802 /* this is the record payload length */
803 SSLEncodeInt(keyExchange
.contents
.data
+ 1, bufLen
- 4, 3);
805 /* the length of the encrypted pre_master_secret */
806 SSLEncodeInt(keyExchange
.contents
.data
+ 4,
807 peerKeyModulusLen
, 2);
809 err
= sslRsaEncrypt(ctx
,
811 /* FIXME - maybe this should be ctx->cspHand */
813 ctx
->preMasterSecret
.data
,
814 SSL_RSA_PREMASTER_SECRET_SIZE
,
822 assert(outputLen
== encodeLen
?
823 keyExchange
.contents
.length
- 6 :
824 keyExchange
.contents
.length
- 4 );
831 SSLEncodeDHanonKeyExchange(SSLRecord
&keyExchange
, SSLContext
*ctx
)
833 unsigned int outputLen
;
835 if ((err
= SSLEncodeDHPremasterSecret(ctx
)) != 0)
838 outputLen
= ctx
->dhExchangePublic
.length
+ 2;
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
;
845 if ((err
= SSLAllocBuffer(keyExchange
.contents
,outputLen
+ 4,ctx
)) != 0)
848 keyExchange
.contents
.data
[0] = SSL_HdskClientKeyExchange
;
849 SSLEncodeInt(keyExchange
.contents
.data
+1, ctx
->dhExchangePublic
.length
+2, 3);
851 SSLEncodeInt(keyExchange
.contents
.data
+4, ctx
->dhExchangePublic
.length
, 2);
852 memcpy(keyExchange
.contents
.data
+6, ctx
->dhExchangePublic
.data
, ctx
->dhExchangePublic
.length
);
859 SSLEncodeRSAPremasterSecret(SSLContext
*ctx
)
860 { SSLBuffer randData
;
863 if ((err
= SSLAllocBuffer(ctx
->preMasterSecret
,
864 SSL_RSA_PREMASTER_SECRET_SIZE
, ctx
)) != 0)
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)
880 SSLEncodeDHPremasterSecret(SSLContext
*ctx
)
888 SSLRandomCtx rsaRandom
;
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
896 if ((err
= ReadyRandom(&rsaRandom
, ctx
)) != 0)
900 { privateValue
.data
= 0;
902 if ((err
= SSLAllocBuffer(ctx
->dhExchangePublic
, ctx
->peerDHParams
.primeLen
, ctx
)) != 0)
904 if ((err
= SSLAllocBuffer(privateValue
, ctx
->dhExchangePublic
.length
- 16, ctx
)) != 0)
907 if ((rsaResult
= R_SetupDHAgreement(ctx
->dhExchangePublic
.data
, privateValue
.data
,
908 privateValue
.length
, &ctx
->peerDHParams
, &rsaRandom
)) != 0)
909 { err
= SSLUnknownErr
;
913 if ((err
= SSLAllocBuffer(ctx
->preMasterSecret
, ctx
->peerDHParams
.primeLen
, ctx
)) != 0)
916 if ((rsaResult
= R_ComputeDHAgreedKey (ctx
->preMasterSecret
.data
, ctx
->dhPeerPublic
.data
,
917 privateValue
.data
, privateValue
.length
, &ctx
->peerDHParams
)) != 0)
918 { err
= SSLUnknownErr
;
923 { unsigned int outputLen
;
925 if ((err
= SSLAllocBuffer(ctx
->dhExchangePublic
, 128, ctx
)) != 0)
927 if ((rsaResult
= B_KeyAgreePhase1(ctx
->peerDHParams
, ctx
->dhExchangePublic
.data
,
928 &outputLen
, 128, rsaRandom
, NO_SURR
)) != 0)
929 { err
= SSLUnknownErr
;
932 ctx
->dhExchangePublic
.length
= outputLen
;
933 if ((err
= SSLAllocBuffer(ctx
->preMasterSecret
, 128, ctx
)) != 0)
935 if ((rsaResult
= B_KeyAgreePhase2(ctx
->peerDHParams
, ctx
->preMasterSecret
.data
,
936 &outputLen
, 128, ctx
->dhPeerPublic
.data
, ctx
->dhPeerPublic
.length
,
938 { err
= SSLUnknownErr
;
941 ctx
->preMasterSecret
.length
= outputLen
;
948 SSLFreeBuffer(privateValue
, ctx
);
949 R_RandomFinal(&rsaRandom
);
951 B_DestroyAlgorithmObject(&rsaRandom
);
957 #endif /* APPLE_DH */
960 SSLInitPendingCiphers(SSLContext
*ctx
)
963 UInt8
*keyDataProgress
, *keyPtr
, *ivPtr
;
965 CipherContext
*serverPending
, *clientPending
;
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;
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 */
982 if ((err
= SSLAllocBuffer(key
, keyDataLen
, ctx
)) != 0)
984 assert(ctx
->sslTslCalls
!= NULL
);
985 if ((err
= ctx
->sslTslCalls
->generateKeyMaterial(key
, ctx
)) != 0)
988 if (ctx
->protocolSide
== SSL_ServerSide
)
989 { serverPending
= &ctx
->writePending
;
990 clientPending
= &ctx
->readPending
;
993 { serverPending
= &ctx
->readPending
;
994 clientPending
= &ctx
->writePending
;
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
;
1005 /* init the reusable-per-record MAC contexts */
1006 err
= ctx
->sslTslCalls
->initMac(clientPending
, ctx
);
1010 err
= ctx
->sslTslCalls
->initMac(serverPending
, ctx
);
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)
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)
1032 UInt8 clientExportKey
[16], serverExportKey
[16],
1033 clientExportIV
[16], serverExportIV
[16];
1034 SSLBuffer clientWrite
, serverWrite
;
1035 SSLBuffer finalClientWrite
, finalServerWrite
;
1036 SSLBuffer finalClientIV
, finalServerIV
;
1038 assert(ctx
->selectedCipherSpec
->cipher
->keySize
<= 16);
1039 assert(ctx
->selectedCipherSpec
->cipher
->ivSize
<= 16);
1041 /* Inputs to generateExportKeyAndIv are clientRandom, serverRandom,
1042 * clientWriteKey, serverWriteKey. The first two are already present
1044 * Outputs are a key and IV for each of {server, client}.
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
;
1060 assert(ctx
->sslTslCalls
!= NULL
);
1061 err
= ctx
->sslTslCalls
->generateExportKeyAndIv(ctx
, clientWrite
, serverWrite
,
1062 finalClientWrite
, finalServerWrite
, finalClientIV
, finalServerIV
);
1066 if ((err
= ctx
->selectedCipherSpec
->cipher
->initialize(clientExportKey
,
1067 clientExportIV
, clientPending
, ctx
)) != 0)
1069 if ((err
= ctx
->selectedCipherSpec
->cipher
->initialize(serverExportKey
,
1070 serverExportIV
, serverPending
, ctx
)) != 0)
1074 /* Ciphers are ready for use */
1075 ctx
->writePending
.ready
= 1;
1076 ctx
->readPending
.ready
= 1;
1078 /* Ciphers get swapped by sending or receiving a change cipher spec message */
1082 SSLFreeBuffer(key
, ctx
);