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.
22 Contains: Support for key exchange and server key exchange
24 Written by: Doug Mitchell, based on Netscape SSLRef 3.0
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
29 /* *********************************************************************
32 SSLRef 3.0 Final -- 11/19/96
34 Copyright (c)1996 by Netscape Communications Corp.
36 By retrieving this software you are bound by the licensing terms
37 disclosed in the file "LICENSE.txt". Please read it, and if you don't
38 accept the terms, delete this software.
40 SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
41 View, California <http://home.netscape.com/> and Consensus Development
42 Corporation of Berkeley, California <http://www.consensus.com/>.
44 *********************************************************************
46 File: hdskkyex.c Support for key exchange and server key exchange
48 Encoding and decoding of key exchange and server key exchange
49 messages in both the Diffie-Hellman and RSA variants; also, includes
50 the necessary crypto library calls to support this negotiation.
52 ****************************************************************** */
74 #ifndef _APPLE_CDSA_H_
75 #include "appleCdsa.h"
86 * Client RSA Key Exchange msgs actually start with a two-byte
87 * length field, contrary to the first version of RFC 2246, dated
88 * January 1999. See RFC 2246, March 2002, section 7.4.7.1 for
89 * updated requirements.
91 #define RSA_CLIENT_KEY_ADD_LENGTH 1
93 typedef CSSM_KEY_PTR SSLRSAPrivateKey
;
95 static SSLErr
SSLEncodeRSAServerKeyExchange(SSLRecord
*keyExch
, SSLContext
*ctx
);
96 static SSLErr
SSLEncodeRSAKeyParams(SSLBuffer
*keyParams
, SSLRSAPrivateKey
*key
, SSLContext
*ctx
);
97 static SSLErr
SSLProcessRSAServerKeyExchange(SSLBuffer message
, SSLContext
*ctx
);
98 static SSLErr
SSLDecodeRSAKeyExchange(SSLBuffer keyExchange
, SSLContext
*ctx
);
99 static SSLErr
SSLEncodeRSAKeyExchange(SSLRecord
*keyExchange
, SSLContext
*ctx
);
101 static SSLErr
SSLEncodeDHanonServerKeyExchange(SSLRecord
*keyExch
, SSLContext
*ctx
);
102 static SSLErr
SSLEncodeDHanonKeyExchange(SSLRecord
*keyExchange
, SSLContext
*ctx
);
103 static SSLErr
SSLDecodeDHanonKeyExchange(SSLBuffer keyExchange
, SSLContext
*ctx
);
104 static SSLErr
SSLProcessDHanonServerKeyExchange(SSLBuffer message
, SSLContext
*ctx
);
108 SSLEncodeServerKeyExchange(SSLRecord
*keyExch
, SSLContext
*ctx
)
111 switch (ctx
->selectedCipherSpec
->keyExchangeMethod
)
114 if (ERR(err
= SSLEncodeRSAServerKeyExchange(keyExch
, ctx
)) != 0)
119 if (ERR(err
= SSLEncodeDHanonServerKeyExchange(keyExch
, ctx
)) != 0)
124 return ERR(SSLUnsupportedErr
);
131 SSLEncodeRSAServerKeyExchange(SSLRecord
*keyExch
, SSLContext
*ctx
)
135 UInt32 outputLen
, localKeyModulusLen
;
137 SSLBuffer exportKey
,clientRandom
,serverRandom
,hashCtx
, hash
;
142 /* we have a public key here... */
143 CASSERT(ctx
->encryptPubKey
!= NULL
);
144 CASSERT(ctx
->protocolSide
== SSL_ServerSide
);
146 if ((err
= SSLEncodeRSAKeyParams(&exportKey
, &ctx
->encryptPubKey
, ctx
)) != 0)
149 CASSERT(ctx
->signingPubKey
!= NULL
);
150 localKeyModulusLen
= sslKeyLengthInBytes(ctx
->signingPubKey
);
152 length
= exportKey
.length
+ 2 + localKeyModulusLen
; /* RSA ouputs a block as long as the modulus */
154 assert((ctx
->negProtocolVersion
== SSL_Version_3_0
) ||
155 (ctx
->negProtocolVersion
== TLS_Version_1_0
));
156 keyExch
->protocolVersion
= ctx
->negProtocolVersion
;
157 keyExch
->contentType
= SSL_handshake
;
158 if (ERR(err
= SSLAllocBuffer(&keyExch
->contents
, length
+4, &ctx
->sysCtx
)) != 0)
161 progress
= keyExch
->contents
.data
;
162 *progress
++ = SSL_server_key_exchange
;
163 progress
= SSLEncodeInt(progress
, length
, 3);
165 memcpy(progress
, exportKey
.data
, exportKey
.length
);
166 progress
+= exportKey
.length
;
168 clientRandom
.data
= ctx
->clientRandom
;
169 clientRandom
.length
= SSL_CLIENT_SRVR_RAND_SIZE
;
170 serverRandom
.data
= ctx
->serverRandom
;
171 serverRandom
.length
= SSL_CLIENT_SRVR_RAND_SIZE
;
173 hash
.data
= &hashes
[0];
175 if (ERR(err
= ReadyHash(&SSLHashMD5
, &hashCtx
, ctx
)) != 0)
177 if (ERR(err
= SSLHashMD5
.update(hashCtx
, clientRandom
)) != 0)
179 if (ERR(err
= SSLHashMD5
.update(hashCtx
, serverRandom
)) != 0)
181 if (ERR(err
= SSLHashMD5
.update(hashCtx
, exportKey
)) != 0)
183 if (ERR(err
= SSLHashMD5
.final(hashCtx
, hash
)) != 0)
185 if (ERR(err
= SSLFreeBuffer(&hashCtx
, &ctx
->sysCtx
)) != 0)
188 hash
.data
= &hashes
[16];
190 if (ERR(err
= ReadyHash(&SSLHashSHA1
, &hashCtx
, ctx
)) != 0)
192 if (ERR(err
= SSLHashSHA1
.update(hashCtx
, clientRandom
)) != 0)
194 if (ERR(err
= SSLHashSHA1
.update(hashCtx
, serverRandom
)) != 0)
196 if (ERR(err
= SSLHashSHA1
.update(hashCtx
, exportKey
)) != 0)
198 if (ERR(err
= SSLHashSHA1
.final(hashCtx
, hash
)) != 0)
200 if (ERR(err
= SSLFreeBuffer(&hashCtx
, &ctx
->sysCtx
)) != 0)
203 progress
= SSLEncodeInt(progress
, localKeyModulusLen
, 2);
204 err
= sslRsaRawSign(ctx
,
215 CASSERT(outputLen
== localKeyModulusLen
);
220 ERR(SSLFreeBuffer(&hashCtx
, &ctx
->sysCtx
));
221 ERR(SSLFreeBuffer(&exportKey
, &ctx
->sysCtx
));
227 SSLEncodeRSAKeyParams(SSLBuffer
*keyParams
, SSLRSAPrivateKey
*key
, SSLContext
*ctx
)
229 SSLBuffer modulus
, exponent
;
232 err
= sslGetPubKeyBits(ctx
,
238 SSLFreeBuffer(&modulus
, &ctx
->sysCtx
);
239 SSLFreeBuffer(&exponent
, &ctx
->sysCtx
);
243 if (ERR(err
= SSLAllocBuffer(keyParams
, modulus
.length
+ exponent
.length
+ 4, &ctx
->sysCtx
)) != 0)
245 progress
= keyParams
->data
;
246 progress
= SSLEncodeInt(progress
, modulus
.length
, 2);
247 memcpy(progress
, modulus
.data
, modulus
.length
);
248 progress
+= modulus
.length
;
249 progress
= SSLEncodeInt(progress
, exponent
.length
, 2);
250 memcpy(progress
, exponent
.data
, exponent
.length
);
252 /* these were mallocd by sslGetPubKeyBits() */
253 SSLFreeBuffer(&modulus
, &ctx
->sysCtx
);
254 SSLFreeBuffer(&exponent
, &ctx
->sysCtx
);
260 SSLEncodeDHanonServerKeyExchange(SSLRecord
*keyExch
, SSLContext
*ctx
)
268 length
= 6 + ctx
->dhAnonParams
.primeLen
+ ctx
->dhAnonParams
.generatorLen
+
269 ctx
->dhExchangePublic
.length
;
271 assert((ctx
->negProtocolVersion
== SSL_Version_3_0
) ||
272 (ctx
->negProtocolVersion
== TLS_Version_1_0
));
273 keyExch
->protocolVersion
= ctx
->negProtocolVersion
;
274 keyExch
->contentType
= SSL_handshake
;
275 if (ERR(err
= SSLAllocBuffer(&keyExch
->contents
, length
+4, &ctx
->sysCtx
)) != 0)
278 progress
= keyExch
->contents
.data
;
279 *progress
++ = SSL_server_key_exchange
;
280 progress
= SSLEncodeInt(progress
, length
, 3);
282 progress
= SSLEncodeInt(progress
, ctx
->dhAnonParams
.primeLen
, 2);
283 memcpy(progress
, ctx
->dhAnonParams
.prime
, ctx
->dhAnonParams
.primeLen
);
284 progress
+= ctx
->dhAnonParams
.primeLen
;
286 progress
= SSLEncodeInt(progress
, ctx
->dhAnonParams
.generatorLen
, 2);
287 memcpy(progress
, ctx
->dhAnonParams
.generator
, ctx
->dhAnonParams
.generatorLen
);
288 progress
+= ctx
->dhAnonParams
.generatorLen
;
290 if (ERR(err
= SSLAllocBuffer(&ctx
->dhExchangePublic
, ctx
->peerDHParams
.primeLen
, &ctx
->sysCtx
)) != 0)
292 if (ERR(err
= SSLAllocBuffer(&ctx
->dhPrivate
, ctx
->dhExchangePublic
.length
- 16, &ctx
->sysCtx
)) != 0)
295 if (ERR(err
= ReadyRandom(&random
, ctx
)) != 0)
298 if ((rsaErr
= R_SetupDHAgreement(ctx
->dhExchangePublic
.data
, ctx
->dhPrivate
.data
,
299 ctx
->dhPrivate
.length
, &ctx
->dhAnonParams
, &random
)) != 0)
300 { err
= SSLUnknownErr
;
304 progress
= SSLEncodeInt(progress
, ctx
->dhExchangePublic
.length
, 2);
305 memcpy(progress
, ctx
->dhExchangePublic
.data
, ctx
->dhExchangePublic
.length
);
306 progress
+= ctx
->dhExchangePublic
.length
;
309 { A_DH_KEY_AGREE_PARAMS
*params
;
310 unsigned int outputLen
;
312 if ((rsaErr
= B_GetAlgorithmInfo((POINTER
*)¶ms
, ctx
->dhAnonParams
, AI_DHKeyAgree
)) != 0)
313 return SSLUnknownErr
;
314 if (ERR(err
= ReadyRandom(&random
, ctx
)) != 0)
316 if (ERR(err
= SSLAllocBuffer(&ctx
->dhExchangePublic
, 128, &ctx
->sysCtx
)) != 0)
318 if ((rsaErr
= B_KeyAgreePhase1(ctx
->dhAnonParams
, ctx
->dhExchangePublic
.data
,
319 &outputLen
, 128, random
, NO_SURR
)) != 0)
320 { err
= SSLUnknownErr
;
323 ctx
->dhExchangePublic
.length
= outputLen
;
325 length
= 6 + params
->prime
.len
+ params
->base
.len
+ ctx
->dhExchangePublic
.length
;
327 assert((ctx
->negProtocolVersion
== SSL_Version_3_0
) ||
328 (ctx
->negProtocolVersion
== TLS_Version_1_0
));
329 keyExch
->protocolVersion
= ctx
->negProtocolVersion
;
330 keyExch
->contentType
= SSL_handshake
;
331 if (ERR(err
= SSLAllocBuffer(&keyExch
->contents
, length
+4, &ctx
->sysCtx
)) != 0)
334 progress
= keyExch
->contents
.data
;
335 *progress
++ = SSL_server_key_exchange
;
336 progress
= SSLEncodeInt(progress
, length
, 3);
338 progress
= SSLEncodeInt(progress
, params
->prime
.len
, 2);
339 memcpy(progress
, params
->prime
.data
, params
->prime
.len
);
340 progress
+= params
->prime
.len
;
342 progress
= SSLEncodeInt(progress
, params
->base
.len
, 2);
343 memcpy(progress
, params
->base
.data
, params
->base
.len
);
344 progress
+= params
->base
.len
;
346 progress
= SSLEncodeInt(progress
, ctx
->dhExchangePublic
.length
, 2);
347 memcpy(progress
, ctx
->dhExchangePublic
.data
, ctx
->dhExchangePublic
.length
);
348 progress
+= ctx
->dhExchangePublic
.length
;
350 #endif /* RSAREF / BSAFE */
352 ASSERT(progress
== keyExch
->contents
.data
+ keyExch
->contents
.length
);
357 #endif /* APPLE_DH */
360 SSLProcessServerKeyExchange(SSLBuffer message
, SSLContext
*ctx
)
363 switch (ctx
->selectedCipherSpec
->keyExchangeMethod
)
366 if (ERR(err
= SSLProcessRSAServerKeyExchange(message
, ctx
)) != 0)
371 if (ERR(err
= SSLProcessDHanonServerKeyExchange(message
, ctx
)) != 0)
376 return ERR(SSLUnsupportedErr
);
383 SSLProcessRSAServerKeyExchange(SSLBuffer message
, SSLContext
*ctx
)
386 SSLBuffer tempPubKey
, hashOut
, hashCtx
, clientRandom
, serverRandom
;
387 UInt16 modulusLen
, exponentLen
, signatureLen
;
388 UInt8
*progress
, *modulus
, *exponent
, *signature
;
390 SSLBuffer signedHashes
;
392 signedHashes
.data
= 0;
395 if (message
.length
< 2) {
396 errorLog0("SSLProcessRSAServerKeyExchange: msg len error 2\n");
397 return ERR(SSLProtocolErr
);
399 progress
= message
.data
;
400 modulusLen
= SSLDecodeInt(progress
, 2);
401 modulus
= progress
+ 2;
402 progress
+= 2+modulusLen
;
403 if (message
.length
< 4 + modulusLen
) {
404 errorLog0("SSLProcessRSAServerKeyExchange: msg len error 2\n");
405 return ERR(SSLProtocolErr
);
407 exponentLen
= SSLDecodeInt(progress
, 2);
408 exponent
= progress
+ 2;
409 progress
+= 2+exponentLen
;
410 if (message
.length
< 6 + modulusLen
+ exponentLen
) {
411 errorLog0("SSLProcessRSAServerKeyExchange: msg len error 2\n");
412 return ERR(SSLProtocolErr
);
414 signatureLen
= SSLDecodeInt(progress
, 2);
415 signature
= progress
+ 2;
416 if (message
.length
!= 6 + modulusLen
+ exponentLen
+ signatureLen
) {
417 errorLog0("SSLProcessRSAServerKeyExchange: msg len error 3\n");
418 return ERR(SSLProtocolErr
);
421 clientRandom
.data
= ctx
->clientRandom
;
422 clientRandom
.length
= SSL_CLIENT_SRVR_RAND_SIZE
;
423 serverRandom
.data
= ctx
->serverRandom
;
424 serverRandom
.length
= SSL_CLIENT_SRVR_RAND_SIZE
;
425 tempPubKey
.data
= message
.data
;
426 tempPubKey
.length
= modulusLen
+ exponentLen
+ 4;
430 if (ERR(err
= ReadyHash(&SSLHashMD5
, &hashCtx
, ctx
)) != 0)
432 if (ERR(err
= SSLHashMD5
.update(hashCtx
, clientRandom
)) != 0)
434 if (ERR(err
= SSLHashMD5
.update(hashCtx
, serverRandom
)) != 0)
436 if (ERR(err
= SSLHashMD5
.update(hashCtx
, tempPubKey
)) != 0)
438 if (ERR(err
= SSLHashMD5
.final(hashCtx
, hashOut
)) != 0)
442 * SHA hash goes right after the MD5 hash
444 hashOut
.data
= hash
+ 16;
446 if (ERR(err
= SSLFreeBuffer(&hashCtx
, &ctx
->sysCtx
)) != 0)
449 if (ERR(err
= ReadyHash(&SSLHashSHA1
, &hashCtx
, ctx
)) != 0)
451 if (ERR(err
= SSLHashSHA1
.update(hashCtx
, clientRandom
)) != 0)
453 if (ERR(err
= SSLHashSHA1
.update(hashCtx
, serverRandom
)) != 0)
455 if (ERR(err
= SSLHashSHA1
.update(hashCtx
, tempPubKey
)) != 0)
457 if (ERR(err
= SSLHashSHA1
.final(hashCtx
, hashOut
)) != 0)
460 err
= sslRsaRawVerify(ctx
,
463 hash
, /* plaintext */
464 36, /* plaintext length */
468 errorLog1("SSLProcessRSAServerKeyExchange: sslRsaRawVerify returned %d\n",
473 /* Signature matches; now replace server key with new key */
478 /* first free existing peerKey */
479 sslFreeKey(ctx
->peerPubKeyCsp
,
481 NULL
); /* no KCItem */
483 /* and cook up a new one from raw bits */
484 modBuf
.data
= modulus
;
485 modBuf
.length
= modulusLen
;
486 expBuf
.data
= exponent
;
487 expBuf
.length
= exponentLen
;
488 err
= sslGetPubKeyFromBits(ctx
,
492 &ctx
->peerPubKeyCsp
);
495 ERR(SSLFreeBuffer(&signedHashes
, &ctx
->sysCtx
));
496 ERR(SSLFreeBuffer(&hashCtx
, &ctx
->sysCtx
));
502 SSLProcessDHanonServerKeyExchange(SSLBuffer message
, SSLContext
*ctx
)
505 unsigned int totalLength
;
507 if (message
.length
< 6) {
508 errorLog1("SSLProcessDHanonServerKeyExchange error: msg len %d\n",
510 return ERR(SSLProtocolErr
);
512 progress
= message
.data
;
517 UInt8
*prime
, *generator
, *publicVal
;
519 ctx
->peerDHParams
.primeLen
= SSLDecodeInt(progress
, 2);
522 progress
+= ctx
->peerDHParams
.primeLen
;
523 totalLength
+= ctx
->peerDHParams
.primeLen
;
524 if (message
.length
< 6 + totalLength
)
525 return ERR(SSLProtocolErr
);
527 ctx
->peerDHParams
.generatorLen
= SSLDecodeInt(progress
, 2);
529 generator
= progress
;
530 progress
+= ctx
->peerDHParams
.generatorLen
;
531 totalLength
+= ctx
->peerDHParams
.generatorLen
;
532 if (message
.length
< 6 + totalLength
)
533 return ERR(SSLProtocolErr
);
535 ctx
->dhPeerPublic
.length
= SSLDecodeInt(progress
, 2);
537 publicVal
= progress
;
538 progress
+= ctx
->dhPeerPublic
.length
;
539 totalLength
+= ctx
->dhPeerPublic
.length
;
540 if (message
.length
!= 6 + totalLength
)
541 return ERR(SSLProtocolErr
);
543 ASSERT(progress
== message
.data
+ message
.length
);
545 if (ERR(err
= SSLAllocBuffer(&alloc
, ctx
->peerDHParams
.primeLen
+
546 ctx
->peerDHParams
.generatorLen
, &ctx
->sysCtx
)) != 0)
549 ctx
->peerDHParams
.prime
= alloc
.data
;
550 memcpy(ctx
->peerDHParams
.prime
, prime
, ctx
->peerDHParams
.primeLen
);
551 ctx
->peerDHParams
.generator
= alloc
.data
+ ctx
->peerDHParams
.primeLen
;
552 memcpy(ctx
->peerDHParams
.generator
, generator
, ctx
->peerDHParams
.generatorLen
);
554 if (ERR(err
= SSLAllocBuffer(&ctx
->dhPeerPublic
,
555 ctx
->dhPeerPublic
.length
, &ctx
->sysCtx
)) != 0)
558 memcpy(ctx
->dhPeerPublic
.data
, publicVal
, ctx
->dhPeerPublic
.length
);
562 unsigned char *publicVal
;
563 A_DH_KEY_AGREE_PARAMS params
;
564 B_ALGORITHM_METHOD
*chooser
[] = { &AM_DH_KEY_AGREE
, 0 };
566 params
.prime
.len
= SSLDecodeInt(progress
, 2);
568 params
.prime
.data
= progress
;
569 progress
+= params
.prime
.len
;
570 totalLength
+= params
.prime
.len
;
571 if (message
.length
< 6 + totalLength
)
572 return ERR(SSLProtocolErr
);
574 params
.base
.len
= SSLDecodeInt(progress
, 2);
576 params
.base
.data
= progress
;
577 progress
+= params
.base
.len
;
578 totalLength
+= params
.base
.len
;
579 if (message
.length
< 6 + totalLength
)
580 return ERR(SSLProtocolErr
);
582 ctx
->dhPeerPublic
.length
= SSLDecodeInt(progress
, 2);
583 if (ERR(err
= SSLAllocBuffer(&ctx
->dhPeerPublic
, ctx
->dhPeerPublic
.length
, &ctx
->sysCtx
)) != 0)
587 publicVal
= progress
;
588 progress
+= ctx
->dhPeerPublic
.length
;
589 totalLength
+= ctx
->dhPeerPublic
.length
;
590 memcpy(ctx
->dhPeerPublic
.data
, publicVal
, ctx
->dhPeerPublic
.length
);
591 if (message
.length
!= 6 + totalLength
)
592 return ERR(SSLProtocolErr
);
594 params
.exponentBits
= 8 * ctx
->dhPeerPublic
.length
- 1;
596 if ((rsaErr
= B_CreateAlgorithmObject(&ctx
->peerDHParams
)) != 0)
597 return SSLUnknownErr
;
598 if ((rsaErr
= B_SetAlgorithmInfo(ctx
->peerDHParams
, AI_DHKeyAgree
, (POINTER
)¶ms
)) != 0)
599 return SSLUnknownErr
;
600 if ((rsaErr
= B_KeyAgreeInit(ctx
->peerDHParams
, (B_KEY_OBJ
) 0, chooser
, NO_SURR
)) != 0)
601 return SSLUnknownErr
;
611 SSLProcessKeyExchange(SSLBuffer keyExchange
, SSLContext
*ctx
)
614 switch (ctx
->selectedCipherSpec
->keyExchangeMethod
)
617 if (ERR(err
= SSLDecodeRSAKeyExchange(keyExchange
, ctx
)) != 0)
622 if (ERR(err
= SSLDecodeDHanonKeyExchange(keyExchange
, ctx
)) != 0)
627 return ERR(SSLUnsupportedErr
);
634 SSLDecodeRSAKeyExchange(SSLBuffer keyExchange
, SSLContext
*ctx
)
637 UInt32 outputLen
, localKeyModulusLen
;
639 SSLProtocolVersion version
;
640 Boolean useEncryptKey
= false;
644 /* different key names, also need CSP handle */
645 CSSM_CSP_HANDLE cspHand
;
647 CASSERT(ctx
->protocolSide
== SSL_ServerSide
);
650 * FIXME - The original SSLRef looked at
651 * ctx->selectedCipherSpec->keyExchangeMethod to decide which
652 * key to use (exportKey or localKey). I really don't think we
653 * want to use that - it's constant. We need to look at
654 * whether the app specified encrypting certs, right?
656 #if SSL_SERVER_KEYEXCH_HACK
658 * the way we work with Netscape.
659 * FIXME - maybe we should *require* an encryptPrivKey in this
662 if((ctx
->selectedCipherSpec
->keyExchangeMethod
== SSL_RSA_EXPORT
) &&
663 (ctx
->encryptPrivKey
!= NULL
)) {
664 useEncryptKey
= true;
667 #else /* !SSL_SERVER_KEYEXCH_HACK */
668 /* The "correct" way, I think, which doesn't work with Netscape */
669 if (ctx
->encryptPrivKey
) {
670 useEncryptKey
= true;
672 #endif /* SSL_SERVER_KEYEXCH_HACK */
674 key
= &ctx
->encryptPrivKey
;
675 cspHand
= ctx
->encryptKeyCsp
;
678 key
= &ctx
->signingPrivKey
;
679 cspHand
= ctx
->signingKeyCsp
;
682 localKeyModulusLen
= sslKeyLengthInBytes(*key
);
685 * We have to tolerate incoming key exchange msgs with and without the
686 * two-byte "encrypted length" field.
688 if (keyExchange
.length
== localKeyModulusLen
) {
689 /* no length encoded */
690 src
= keyExchange
.data
;
692 else if((keyExchange
.length
== (localKeyModulusLen
+ 2)) &&
693 (ctx
->negProtocolVersion
>= TLS_Version_1_0
)) {
694 /* TLS only - skip the length bytes */
695 src
= keyExchange
.data
+ 2;
698 errorLog2("SSLDecodeRSAKeyExchange: length error (exp %u got %u)\n",
699 (unsigned)localKeyModulusLen
, (unsigned)keyExchange
.length
);
700 return ERR(SSLProtocolErr
);
702 err
= SSLAllocBuffer(&result
, localKeyModulusLen
, &ctx
->sysCtx
);
707 err
= sslRsaDecrypt(ctx
,
721 errorLog0("SSLDecodeRSAKeyExchange: outputLen error\n");
722 ERR(err
= SSLProtocolErr
);
725 result
.length
= outputLen
;
727 version
= (SSLProtocolVersion
)SSLDecodeInt(result
.data
, 2);
728 /* Modify this check to check against our maximum version with protocol revisions */
729 if (version
> ctx
->negProtocolVersion
&& version
< SSL_Version_3_0
) {
730 errorLog0("SSLDecodeRSAKeyExchange: version error\n");
731 ERR(err
= SSLProtocolErr
);
734 if (ERR(err
= SSLAllocBuffer(&ctx
->preMasterSecret
,
735 SSL_RSA_PREMASTER_SECRET_SIZE
, &ctx
->sysCtx
)) != 0)
737 memcpy(ctx
->preMasterSecret
.data
, result
.data
,
738 SSL_RSA_PREMASTER_SECRET_SIZE
);
742 ERR(SSLFreeBuffer(&result
, &ctx
->sysCtx
));
748 SSLDecodeDHanonKeyExchange(SSLBuffer keyExchange
, SSLContext
*ctx
)
750 unsigned int publicLen
;
753 publicLen
= SSLDecodeInt(keyExchange
.data
, 2);
756 if (keyExchange
.length
!= publicLen
+ 2 ||
757 publicLen
!= ctx
->dhAnonParams
.primeLen
)
758 return ERR(SSLProtocolErr
);
760 if (ERR(err
= SSLAllocBuffer(&ctx
->preMasterSecret
, ctx
->dhAnonParams
.primeLen
, &ctx
->sysCtx
)) != 0)
763 if ((rsaResult
= R_ComputeDHAgreedKey (ctx
->preMasterSecret
.data
, ctx
->dhPeerPublic
.data
,
764 ctx
->dhPrivate
.data
, ctx
->dhPrivate
.length
, &ctx
->dhAnonParams
)) != 0)
765 { err
= SSLUnknownErr
;
770 { unsigned int amount
;
771 if (keyExchange
.length
!= publicLen
+ 2)
772 return ERR(SSLProtocolErr
);
774 if (ERR(err
= SSLAllocBuffer(&ctx
->preMasterSecret
, 128, &ctx
->sysCtx
)) != 0)
777 if ((rsaResult
= B_KeyAgreePhase2(ctx
->dhAnonParams
, ctx
->preMasterSecret
.data
,
778 &amount
, 128, keyExchange
.data
+2, publicLen
, NO_SURR
)) != 0)
781 ctx
->preMasterSecret
.length
= amount
;
787 #endif /* APPLE_DH */
790 SSLEncodeKeyExchange(SSLRecord
*keyExchange
, SSLContext
*ctx
)
793 CASSERT(ctx
->protocolSide
== SSL_ClientSide
);
795 switch (ctx
->selectedCipherSpec
->keyExchangeMethod
)
798 if (ERR(err
= SSLEncodeRSAKeyExchange(keyExchange
, ctx
)) != 0)
803 if (ERR(err
= SSLEncodeDHanonKeyExchange(keyExchange
, ctx
)) != 0)
808 return ERR(SSLUnsupportedErr
);
815 SSLEncodeRSAKeyExchange(SSLRecord
*keyExchange
, SSLContext
*ctx
)
817 UInt32 outputLen
, peerKeyModulusLen
;
820 bool encodeLen
= false;
822 if (ERR(err
= SSLEncodeRSAPremasterSecret(ctx
)) != 0)
825 keyExchange
->contentType
= SSL_handshake
;
826 assert((ctx
->negProtocolVersion
== SSL_Version_3_0
) ||
827 (ctx
->negProtocolVersion
== TLS_Version_1_0
));
828 keyExchange
->protocolVersion
= ctx
->negProtocolVersion
;
830 peerKeyModulusLen
= sslKeyLengthInBytes(ctx
->peerPubKey
);
831 bufLen
= peerKeyModulusLen
+ 4;
832 #if RSA_CLIENT_KEY_ADD_LENGTH
833 if(ctx
->negProtocolVersion
>= TLS_Version_1_0
) {
838 if (ERR(err
= SSLAllocBuffer(&keyExchange
->contents
,
839 bufLen
,&ctx
->sysCtx
)) != 0)
843 dst
= keyExchange
->contents
.data
+ 4;
847 keyExchange
->contents
.data
[0] = SSL_client_key_exchange
;
849 /* this is the record payload length */
850 SSLEncodeInt(keyExchange
->contents
.data
+ 1, bufLen
- 4, 3);
852 /* the length of the encrypted pre_master_secret */
853 SSLEncodeInt(keyExchange
->contents
.data
+ 4,
854 peerKeyModulusLen
, 2);
856 err
= sslRsaEncrypt(ctx
,
858 /* FIXME - maybe this should be ctx->cspHand */
860 ctx
->preMasterSecret
.data
,
861 SSL_RSA_PREMASTER_SECRET_SIZE
,
869 CASSERT(outputLen
== encodeLen
?
870 keyExchange
->contents
.length
- 6 :
871 keyExchange
->contents
.length
- 4 );
878 SSLEncodeDHanonKeyExchange(SSLRecord
*keyExchange
, SSLContext
*ctx
)
880 unsigned int outputLen
;
882 if (ERR(err
= SSLEncodeDHPremasterSecret(ctx
)) != 0)
885 outputLen
= ctx
->dhExchangePublic
.length
+ 2;
887 keyExchange
->contentType
= SSL_handshake
;
888 assert((ctx
->negProtocolVersion
== SSL_Version_3_0
) ||
889 (ctx
->negProtocolVersion
== TLS_Version_1_0
));
890 keyExchange
->protocolVersion
= ctx
->negProtocolVersion
;
892 if (ERR(err
= SSLAllocBuffer(&keyExchange
->contents
,outputLen
+ 4,&ctx
->sysCtx
)) != 0)
895 keyExchange
->contents
.data
[0] = SSL_client_key_exchange
;
896 SSLEncodeInt(keyExchange
->contents
.data
+1, ctx
->dhExchangePublic
.length
+2, 3);
898 SSLEncodeInt(keyExchange
->contents
.data
+4, ctx
->dhExchangePublic
.length
, 2);
899 memcpy(keyExchange
->contents
.data
+6, ctx
->dhExchangePublic
.data
, ctx
->dhExchangePublic
.length
);