4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is the Netscape security libraries.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1994-2000
22 * the Initial Developer. All Rights Reserved.
25 * Dr Vipul Gupta <vipul.gupta@sun.com> and
26 * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
28 * Alternatively, the contents of this file may be used under the terms of
29 * either the GNU General Public License Version 2 or later (the "GPL"), or
30 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 * in which case the provisions of the GPL or the LGPL are applicable instead
32 * of those above. If you wish to allow use of your version of this file only
33 * under the terms of either the GPL or the LGPL, and not to allow others to
34 * use your version of this file under the terms of the MPL, indicate your
35 * decision by deleting the provisions above and replace them with the notice
36 * and other provisions required by the GPL or the LGPL. If you do not delete
37 * the provisions above, a recipient may use your version of this file under
38 * the terms of any one of the MPL, the GPL or the LGPL.
40 * ***** END LICENSE BLOCK ***** */
42 /* ECC code moved here from ssl3con.c */
43 /* $Id: ssl3ecc.c,v 1.22 2008/03/10 00:01:28 wtc%google.com Exp $ */
48 #include "cryptohi.h" /* for DSAU_ stuff */
73 #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
74 (x)->pValue=(v); (x)->ulValueLen = (l);
77 #define SSL_GET_SERVER_PUBLIC_KEY(sock, type) \
78 (ss->serverCerts[type].serverKeyPair ? \
79 ss->serverCerts[type].serverKeyPair->pubKey : NULL)
81 #define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \
82 ((curveName > ec_noName) && \
83 (curveName < ec_pastLastName) && \
84 ((1UL << curveName) & curvemsk) != 0)
88 static SECStatus
ssl3_CreateECDHEphemeralKeys(sslSocket
*ss
, ECName ec_curve
);
90 #define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName))
92 /* Table containing OID tags for elliptic curves named in the
95 static const SECOidTag ecName2OIDTag
[] = {
97 SEC_OID_SECG_EC_SECT163K1
, /* 1 */
98 SEC_OID_SECG_EC_SECT163R1
, /* 2 */
99 SEC_OID_SECG_EC_SECT163R2
, /* 3 */
100 SEC_OID_SECG_EC_SECT193R1
, /* 4 */
101 SEC_OID_SECG_EC_SECT193R2
, /* 5 */
102 SEC_OID_SECG_EC_SECT233K1
, /* 6 */
103 SEC_OID_SECG_EC_SECT233R1
, /* 7 */
104 SEC_OID_SECG_EC_SECT239K1
, /* 8 */
105 SEC_OID_SECG_EC_SECT283K1
, /* 9 */
106 SEC_OID_SECG_EC_SECT283R1
, /* 10 */
107 SEC_OID_SECG_EC_SECT409K1
, /* 11 */
108 SEC_OID_SECG_EC_SECT409R1
, /* 12 */
109 SEC_OID_SECG_EC_SECT571K1
, /* 13 */
110 SEC_OID_SECG_EC_SECT571R1
, /* 14 */
111 SEC_OID_SECG_EC_SECP160K1
, /* 15 */
112 SEC_OID_SECG_EC_SECP160R1
, /* 16 */
113 SEC_OID_SECG_EC_SECP160R2
, /* 17 */
114 SEC_OID_SECG_EC_SECP192K1
, /* 18 */
115 SEC_OID_SECG_EC_SECP192R1
, /* 19 */
116 SEC_OID_SECG_EC_SECP224K1
, /* 20 */
117 SEC_OID_SECG_EC_SECP224R1
, /* 21 */
118 SEC_OID_SECG_EC_SECP256K1
, /* 22 */
119 SEC_OID_SECG_EC_SECP256R1
, /* 23 */
120 SEC_OID_SECG_EC_SECP384R1
, /* 24 */
121 SEC_OID_SECG_EC_SECP521R1
, /* 25 */
124 static const PRUint16 curve2bits
[] = {
125 0, /* ec_noName = 0, */
126 163, /* ec_sect163k1 = 1, */
127 163, /* ec_sect163r1 = 2, */
128 163, /* ec_sect163r2 = 3, */
129 193, /* ec_sect193r1 = 4, */
130 193, /* ec_sect193r2 = 5, */
131 233, /* ec_sect233k1 = 6, */
132 233, /* ec_sect233r1 = 7, */
133 239, /* ec_sect239k1 = 8, */
134 283, /* ec_sect283k1 = 9, */
135 283, /* ec_sect283r1 = 10, */
136 409, /* ec_sect409k1 = 11, */
137 409, /* ec_sect409r1 = 12, */
138 571, /* ec_sect571k1 = 13, */
139 571, /* ec_sect571r1 = 14, */
140 160, /* ec_secp160k1 = 15, */
141 160, /* ec_secp160r1 = 16, */
142 160, /* ec_secp160r2 = 17, */
143 192, /* ec_secp192k1 = 18, */
144 192, /* ec_secp192r1 = 19, */
145 224, /* ec_secp224k1 = 20, */
146 224, /* ec_secp224r1 = 21, */
147 256, /* ec_secp256k1 = 22, */
148 256, /* ec_secp256r1 = 23, */
149 384, /* ec_secp384r1 = 24, */
150 521, /* ec_secp521r1 = 25, */
151 65535 /* ec_pastLastName */
154 typedef struct Bits2CurveStr
{
159 static const Bits2Curve bits2curve
[] = {
160 { 192, ec_secp192r1
/* = 19, fast */ },
161 { 160, ec_secp160r2
/* = 17, fast */ },
162 { 160, ec_secp160k1
/* = 15, */ },
163 { 160, ec_secp160r1
/* = 16, */ },
164 { 163, ec_sect163k1
/* = 1, */ },
165 { 163, ec_sect163r1
/* = 2, */ },
166 { 163, ec_sect163r2
/* = 3, */ },
167 { 192, ec_secp192k1
/* = 18, */ },
168 { 193, ec_sect193r1
/* = 4, */ },
169 { 193, ec_sect193r2
/* = 5, */ },
170 { 224, ec_secp224r1
/* = 21, fast */ },
171 { 224, ec_secp224k1
/* = 20, */ },
172 { 233, ec_sect233k1
/* = 6, */ },
173 { 233, ec_sect233r1
/* = 7, */ },
174 { 239, ec_sect239k1
/* = 8, */ },
175 { 256, ec_secp256r1
/* = 23, fast */ },
176 { 256, ec_secp256k1
/* = 22, */ },
177 { 283, ec_sect283k1
/* = 9, */ },
178 { 283, ec_sect283r1
/* = 10, */ },
179 { 384, ec_secp384r1
/* = 24, fast */ },
180 { 409, ec_sect409k1
/* = 11, */ },
181 { 409, ec_sect409r1
/* = 12, */ },
182 { 521, ec_secp521r1
/* = 25, fast */ },
183 { 571, ec_sect571k1
/* = 13, */ },
184 { 571, ec_sect571r1
/* = 14, */ },
188 typedef struct ECDHEKeyPairStr
{
190 int error
; /* error code of the call-once function */
194 /* arrays of ECDHE KeyPairs */
195 static ECDHEKeyPair gECDHEKeyPairs
[ec_pastLastName
];
198 ssl3_ECName2Params(PRArenaPool
* arena
, ECName curve
, SECKEYECParams
* params
)
200 SECOidData
*oidData
= NULL
;
202 if ((curve
<= ec_noName
) || (curve
>= ec_pastLastName
) ||
203 ((oidData
= SECOID_FindOIDByTag(ecName2OIDTag
[curve
])) == NULL
)) {
204 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE
);
208 SECITEM_AllocItem(arena
, params
, (2 + oidData
->oid
.len
));
210 * params->data needs to contain the ASN encoding of an object ID (OID)
211 * representing the named curve. The actual OID is in
212 * oidData->oid.data so we simply prepend 0x06 and OID length
214 params
->data
[0] = SEC_ASN1_OBJECT_ID
;
215 params
->data
[1] = oidData
->oid
.len
;
216 memcpy(params
->data
+ 2, oidData
->oid
.data
, oidData
->oid
.len
);
222 params2ecName(SECKEYECParams
* params
)
224 SECItem oid
= { siBuffer
, NULL
, 0};
225 SECOidData
*oidData
= NULL
;
229 * params->data needs to contain the ASN encoding of an object ID (OID)
230 * representing a named curve. Here, we strip away everything
231 * before the actual OID and use the OID to look up a named curve.
233 if (params
->data
[0] != SEC_ASN1_OBJECT_ID
) return ec_noName
;
234 oid
.len
= params
->len
- 2;
235 oid
.data
= params
->data
+ 2;
236 if ((oidData
= SECOID_FindOID(&oid
)) == NULL
) return ec_noName
;
237 for (i
= ec_noName
+ 1; i
< ec_pastLastName
; i
++) {
238 if (ecName2OIDTag
[i
] == oidData
->offset
)
245 /* Caller must set hiLevel error code. */
247 ssl3_ComputeECDHKeyHash(SECItem ec_params
, SECItem server_ecpoint
,
248 SSL3Random
*client_rand
, SSL3Random
*server_rand
,
249 SSL3Hashes
*hashes
, PRBool bypassPKCS11
)
253 SECStatus rv
= SECSuccess
;
256 * XXX For now, we only support named curves (the appropriate
257 * checks are made before this method is called) so ec_params
258 * takes up only two bytes. ECPoint needs to fit in 256 bytes
259 * (because the spec says the length must fit in one byte)
261 PRUint8 buf
[2*SSL3_RANDOM_LENGTH
+ 2 + 1 + 256];
263 bufLen
= 2*SSL3_RANDOM_LENGTH
+ ec_params
.len
+ 1 + server_ecpoint
.len
;
264 if (bufLen
<= sizeof buf
) {
267 hashBuf
= PORT_Alloc(bufLen
);
273 memcpy(hashBuf
, client_rand
, SSL3_RANDOM_LENGTH
);
274 pBuf
= hashBuf
+ SSL3_RANDOM_LENGTH
;
275 memcpy(pBuf
, server_rand
, SSL3_RANDOM_LENGTH
);
276 pBuf
+= SSL3_RANDOM_LENGTH
;
277 memcpy(pBuf
, ec_params
.data
, ec_params
.len
);
278 pBuf
+= ec_params
.len
;
279 pBuf
[0] = (PRUint8
)(server_ecpoint
.len
);
281 memcpy(pBuf
, server_ecpoint
.data
, server_ecpoint
.len
);
282 pBuf
+= server_ecpoint
.len
;
283 PORT_Assert((unsigned int)(pBuf
- hashBuf
) == bufLen
);
285 rv
= ssl3_ComputeCommonKeyHash(hashBuf
, bufLen
, hashes
, bypassPKCS11
);
287 PRINT_BUF(95, (NULL
, "ECDHkey hash: ", hashBuf
, bufLen
));
288 PRINT_BUF(95, (NULL
, "ECDHkey hash: MD5 result", hashes
->md5
, MD5_LENGTH
));
289 PRINT_BUF(95, (NULL
, "ECDHkey hash: SHA1 result", hashes
->sha
, SHA1_LENGTH
));
291 if (hashBuf
!= buf
&& hashBuf
!= NULL
)
297 /* Called from ssl3_SendClientKeyExchange(). */
299 ssl3_SendECDHClientKeyExchange(sslSocket
* ss
, SECKEYPublicKey
* svrPubKey
)
301 PK11SymKey
* pms
= NULL
;
302 SECStatus rv
= SECFailure
;
304 CK_MECHANISM_TYPE target
;
305 SECKEYPublicKey
*pubKey
= NULL
; /* Ephemeral ECDH key */
306 SECKEYPrivateKey
*privKey
= NULL
; /* Ephemeral ECDH key */
308 PORT_Assert( ss
->opt
.noLocks
|| ssl_HaveSSL3HandshakeLock(ss
) );
309 PORT_Assert( ss
->opt
.noLocks
|| ssl_HaveXmitBufLock(ss
));
311 isTLS
= (PRBool
)(ss
->ssl3
.pwSpec
->version
> SSL_LIBRARY_VERSION_3_0
);
313 /* Generate ephemeral EC keypair */
314 if (svrPubKey
->keyType
!= ecKey
) {
315 PORT_SetError(SEC_ERROR_BAD_KEY
);
318 /* XXX SHOULD CALL ssl3_CreateECDHEphemeralKeys here, instead! */
319 privKey
= SECKEY_CreateECPrivateKey(&svrPubKey
->u
.ec
.DEREncodedParams
,
321 if (!privKey
|| !pubKey
) {
322 ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL
);
326 PRINT_BUF(50, (ss
, "ECDH public value:",
327 pubKey
->u
.ec
.publicValue
.data
,
328 pubKey
->u
.ec
.publicValue
.len
));
330 if (isTLS
) target
= CKM_TLS_MASTER_KEY_DERIVE_DH
;
331 else target
= CKM_SSL3_MASTER_KEY_DERIVE_DH
;
333 /* Determine the PMS */
334 pms
= PK11_PubDeriveWithKDF(privKey
, svrPubKey
, PR_FALSE
, NULL
, NULL
,
335 CKM_ECDH1_DERIVE
, target
, CKA_DERIVE
, 0,
336 CKD_NULL
, NULL
, NULL
);
339 SSL3AlertDescription desc
= illegal_parameter
;
340 (void)SSL3_SendAlert(ss
, alert_fatal
, desc
);
341 ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE
);
345 SECKEY_DestroyPrivateKey(privKey
);
348 rv
= ssl3_InitPendingCipherSpec(ss
, pms
);
349 PK11_FreeSymKey(pms
); pms
= NULL
;
351 if (rv
!= SECSuccess
) {
352 ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE
);
356 rv
= ssl3_AppendHandshakeHeader(ss
, client_key_exchange
,
357 pubKey
->u
.ec
.publicValue
.len
+ 1);
358 if (rv
!= SECSuccess
) {
359 goto loser
; /* err set by ssl3_AppendHandshake* */
362 rv
= ssl3_AppendHandshakeVariable(ss
,
363 pubKey
->u
.ec
.publicValue
.data
,
364 pubKey
->u
.ec
.publicValue
.len
, 1);
365 SECKEY_DestroyPublicKey(pubKey
);
368 if (rv
!= SECSuccess
) {
369 goto loser
; /* err set by ssl3_AppendHandshake* */
375 if(pms
) PK11_FreeSymKey(pms
);
376 if(privKey
) SECKEY_DestroyPrivateKey(privKey
);
377 if(pubKey
) SECKEY_DestroyPublicKey(pubKey
);
383 ** Called from ssl3_HandleClientKeyExchange()
386 ssl3_HandleECDHClientKeyExchange(sslSocket
*ss
, SSL3Opaque
*b
,
388 SECKEYPublicKey
*srvrPubKey
,
389 SECKEYPrivateKey
*srvrPrivKey
)
393 SECKEYPublicKey clntPubKey
;
394 CK_MECHANISM_TYPE target
;
397 PORT_Assert( ss
->opt
.noLocks
|| ssl_HaveRecvBufLock(ss
) );
398 PORT_Assert( ss
->opt
.noLocks
|| ssl_HaveSSL3HandshakeLock(ss
) );
400 clntPubKey
.keyType
= ecKey
;
401 clntPubKey
.u
.ec
.DEREncodedParams
.len
=
402 srvrPubKey
->u
.ec
.DEREncodedParams
.len
;
403 clntPubKey
.u
.ec
.DEREncodedParams
.data
=
404 srvrPubKey
->u
.ec
.DEREncodedParams
.data
;
406 rv
= ssl3_ConsumeHandshakeVariable(ss
, &clntPubKey
.u
.ec
.publicValue
,
408 if (rv
!= SECSuccess
) {
410 return SECFailure
; /* XXX Who sets the error code?? */
413 isTLS
= (PRBool
)(ss
->ssl3
.prSpec
->version
> SSL_LIBRARY_VERSION_3_0
);
415 if (isTLS
) target
= CKM_TLS_MASTER_KEY_DERIVE_DH
;
416 else target
= CKM_SSL3_MASTER_KEY_DERIVE_DH
;
418 /* Determine the PMS */
419 pms
= PK11_PubDeriveWithKDF(srvrPrivKey
, &clntPubKey
, PR_FALSE
, NULL
, NULL
,
420 CKM_ECDH1_DERIVE
, target
, CKA_DERIVE
, 0,
421 CKD_NULL
, NULL
, NULL
);
425 ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE
);
429 rv
= ssl3_InitPendingCipherSpec(ss
, pms
);
430 PK11_FreeSymKey(pms
);
431 if (rv
!= SECSuccess
) {
433 return SECFailure
; /* error code set by ssl3_InitPendingCipherSpec */
439 ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk
, int requiredECCbits
)
443 for ( i
= 0; bits2curve
[i
].curve
!= ec_noName
; i
++) {
444 if (bits2curve
[i
].bits
< requiredECCbits
)
446 if (SSL_IS_CURVE_NEGOTIATED(curvemsk
, bits2curve
[i
].curve
)) {
447 return bits2curve
[i
].curve
;
450 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP
);
454 /* find the "weakest link". Get strength of signature key and of sym key.
455 * choose curve for the weakest of those two.
458 ssl3_GetCurveNameForServerSocket(sslSocket
*ss
)
460 SECKEYPublicKey
* svrPublicKey
= NULL
;
461 ECName ec_curve
= ec_noName
;
462 int signatureKeyStrength
= 521;
463 int requiredECCbits
= ss
->sec
.secretKeyBits
* 2;
465 if (ss
->ssl3
.hs
.kea_def
->kea
== kea_ecdhe_ecdsa
) {
466 svrPublicKey
= SSL_GET_SERVER_PUBLIC_KEY(ss
, kt_ecdh
);
468 ec_curve
= params2ecName(&svrPublicKey
->u
.ec
.DEREncodedParams
);
469 if (!SSL_IS_CURVE_NEGOTIATED(ss
->ssl3
.hs
.negotiatedECCurves
, ec_curve
)) {
470 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP
);
473 signatureKeyStrength
= curve2bits
[ ec_curve
];
475 /* RSA is our signing cert */
476 int serverKeyStrengthInBits
;
478 svrPublicKey
= SSL_GET_SERVER_PUBLIC_KEY(ss
, kt_rsa
);
480 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP
);
484 /* currently strength in bytes */
485 serverKeyStrengthInBits
= svrPublicKey
->u
.rsa
.modulus
.len
;
486 if (svrPublicKey
->u
.rsa
.modulus
.data
[0] == 0) {
487 serverKeyStrengthInBits
--;
489 /* convert to strength in bits */
490 serverKeyStrengthInBits
*= BPB
;
492 signatureKeyStrength
=
493 SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits
);
495 if ( requiredECCbits
> signatureKeyStrength
)
496 requiredECCbits
= signatureKeyStrength
;
498 return ssl3_GetCurveWithECKeyStrength(ss
->ssl3
.hs
.negotiatedECCurves
,
502 /* function to clear out the lists */
504 ssl3_ShutdownECDHECurves(void *appData
, void *nssData
)
507 ECDHEKeyPair
*keyPair
= &gECDHEKeyPairs
[0];
509 for (i
=0; i
< ec_pastLastName
; i
++, keyPair
++) {
511 ssl3_FreeKeyPair(keyPair
->pair
);
514 memset(gECDHEKeyPairs
, 0, sizeof gECDHEKeyPairs
);
519 ssl3_ECRegister(void)
522 rv
= NSS_RegisterShutdown(ssl3_ShutdownECDHECurves
, gECDHEKeyPairs
);
523 if (rv
!= SECSuccess
) {
524 gECDHEKeyPairs
[ec_noName
].error
= PORT_GetError();
529 /* CallOnce function, called once for each named curve. */
531 ssl3_CreateECDHEphemeralKeyPair(void * arg
)
533 SECKEYPrivateKey
* privKey
= NULL
;
534 SECKEYPublicKey
* pubKey
= NULL
;
535 ssl3KeyPair
* keyPair
= NULL
;
536 ECName ec_curve
= (ECName
)arg
;
537 SECKEYECParams ecParams
= { siBuffer
, NULL
, 0 };
539 PORT_Assert(gECDHEKeyPairs
[ec_curve
].pair
== NULL
);
541 /* ok, no one has generated a global key for this curve yet, do so */
542 if (ssl3_ECName2Params(NULL
, ec_curve
, &ecParams
) != SECSuccess
) {
543 gECDHEKeyPairs
[ec_curve
].error
= PORT_GetError();
547 privKey
= SECKEY_CreateECPrivateKey(&ecParams
, &pubKey
, NULL
);
548 SECITEM_FreeItem(&ecParams
, PR_FALSE
);
550 if (!privKey
|| !pubKey
|| !(keyPair
= ssl3_NewKeyPair(privKey
, pubKey
))) {
552 SECKEY_DestroyPrivateKey(privKey
);
555 SECKEY_DestroyPublicKey(pubKey
);
557 ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL
);
558 gECDHEKeyPairs
[ec_curve
].error
= PORT_GetError();
562 gECDHEKeyPairs
[ec_curve
].pair
= keyPair
;
567 * Creates the ephemeral public and private ECDH keys used by
568 * server in ECDHE_RSA and ECDHE_ECDSA handshakes.
569 * For now, the elliptic curve is chosen to be the same
570 * strength as the signing certificate (ECC or RSA).
571 * We need an API to specify the curve. This won't be a real
572 * issue until we further develop server-side support for ECC
576 ssl3_CreateECDHEphemeralKeys(sslSocket
*ss
, ECName ec_curve
)
578 ssl3KeyPair
* keyPair
= NULL
;
580 /* if there's no global key for this curve, make one. */
581 if (gECDHEKeyPairs
[ec_curve
].pair
== NULL
) {
584 status
= PR_CallOnce(&gECDHEKeyPairs
[ec_noName
].once
, ssl3_ECRegister
);
585 if (status
!= PR_SUCCESS
) {
586 PORT_SetError(gECDHEKeyPairs
[ec_noName
].error
);
589 status
= PR_CallOnceWithArg(&gECDHEKeyPairs
[ec_curve
].once
,
590 ssl3_CreateECDHEphemeralKeyPair
,
592 if (status
!= PR_SUCCESS
) {
593 PORT_SetError(gECDHEKeyPairs
[ec_curve
].error
);
598 keyPair
= gECDHEKeyPairs
[ec_curve
].pair
;
599 PORT_Assert(keyPair
!= NULL
);
602 ss
->ephemeralECDHKeyPair
= ssl3_GetKeyPairRef(keyPair
);
608 ssl3_HandleECDHServerKeyExchange(sslSocket
*ss
, SSL3Opaque
*b
, PRUint32 length
)
610 PRArenaPool
* arena
= NULL
;
611 SECKEYPublicKey
*peerKey
= NULL
;
614 int errCode
= SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH
;
615 SSL3AlertDescription desc
= illegal_parameter
;
617 SECItem signature
= {siBuffer
, NULL
, 0};
619 SECItem ec_params
= {siBuffer
, NULL
, 0};
620 SECItem ec_point
= {siBuffer
, NULL
, 0};
621 unsigned char paramBuf
[3]; /* only for curve_type == named_curve */
623 isTLS
= (PRBool
)(ss
->ssl3
.prSpec
->version
> SSL_LIBRARY_VERSION_3_0
);
625 /* XXX This works only for named curves, revisit this when
626 * we support generic curves.
628 ec_params
.len
= sizeof paramBuf
;
629 ec_params
.data
= paramBuf
;
630 rv
= ssl3_ConsumeHandshake(ss
, ec_params
.data
, ec_params
.len
, &b
, &length
);
631 if (rv
!= SECSuccess
) {
632 goto loser
; /* malformed. */
635 /* Fail if the curve is not a named curve */
636 if ((ec_params
.data
[0] != ec_type_named
) ||
637 (ec_params
.data
[1] != 0) ||
638 !supportedCurve(ec_params
.data
[2])) {
639 errCode
= SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE
;
640 desc
= handshake_failure
;
644 rv
= ssl3_ConsumeHandshakeVariable(ss
, &ec_point
, 1, &b
, &length
);
645 if (rv
!= SECSuccess
) {
646 goto loser
; /* malformed. */
648 /* Fail if the ec point uses compressed representation */
649 if (ec_point
.data
[0] != EC_POINT_FORM_UNCOMPRESSED
) {
650 errCode
= SEC_ERROR_UNSUPPORTED_EC_POINT_FORM
;
651 desc
= handshake_failure
;
655 rv
= ssl3_ConsumeHandshakeVariable(ss
, &signature
, 2, &b
, &length
);
656 if (rv
!= SECSuccess
) {
657 goto loser
; /* malformed. */
663 goto alert_loser
; /* malformed. */
666 PRINT_BUF(60, (NULL
, "Server EC params", ec_params
.data
,
668 PRINT_BUF(60, (NULL
, "Server EC point", ec_point
.data
, ec_point
.len
));
670 /* failures after this point are not malformed handshakes. */
671 /* TLS: send decrypt_error if signature failed. */
672 desc
= isTLS
? decrypt_error
: handshake_failure
;
675 * check to make sure the hash is signed by right guy
677 rv
= ssl3_ComputeECDHKeyHash(ec_params
, ec_point
,
678 &ss
->ssl3
.hs
.client_random
,
679 &ss
->ssl3
.hs
.server_random
,
680 &hashes
, ss
->opt
.bypassPKCS11
);
682 if (rv
!= SECSuccess
) {
684 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE
);
687 rv
= ssl3_VerifySignedHashes(&hashes
, ss
->sec
.peerCert
, &signature
,
688 isTLS
, ss
->pkcs11PinArg
);
689 if (rv
!= SECSuccess
) {
691 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE
);
695 arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
700 ss
->sec
.peerKey
= peerKey
= PORT_ArenaZNew(arena
, SECKEYPublicKey
);
701 if (peerKey
== NULL
) {
705 peerKey
->arena
= arena
;
706 peerKey
->keyType
= ecKey
;
708 /* set up EC parameters in peerKey */
709 if (ssl3_ECName2Params(arena
, ec_params
.data
[2],
710 &peerKey
->u
.ec
.DEREncodedParams
) != SECSuccess
) {
711 /* we should never get here since we already
712 * checked that we are dealing with a supported curve
714 errCode
= SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE
;
718 /* copy publicValue in peerKey */
719 if (SECITEM_CopyItem(arena
, &peerKey
->u
.ec
.publicValue
, &ec_point
))
721 PORT_FreeArena(arena
, PR_FALSE
);
724 peerKey
->pkcs11Slot
= NULL
;
725 peerKey
->pkcs11ID
= CK_INVALID_HANDLE
;
727 ss
->sec
.peerKey
= peerKey
;
728 ss
->ssl3
.hs
.ws
= wait_cert_request
;
733 (void)SSL3_SendAlert(ss
, alert_fatal
, desc
);
735 PORT_SetError( errCode
);
738 no_memory
: /* no-memory error has already been set. */
739 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE
);
744 ssl3_SendECDHServerKeyExchange(sslSocket
*ss
)
746 const ssl3KEADef
* kea_def
= ss
->ssl3
.hs
.kea_def
;
747 SECStatus rv
= SECFailure
;
750 SECItem signed_hash
= {siBuffer
, NULL
, 0};
753 SECKEYPublicKey
* ecdhePub
;
754 SECItem ec_params
= {siBuffer
, NULL
, 0};
755 unsigned char paramBuf
[3];
757 SSL3KEAType certIndex
;
760 /* Generate ephemeral ECDH key pair and send the public key */
761 curve
= ssl3_GetCurveNameForServerSocket(ss
);
762 if (curve
== ec_noName
) {
765 rv
= ssl3_CreateECDHEphemeralKeys(ss
, curve
);
766 if (rv
!= SECSuccess
) {
767 goto loser
; /* err set by AppendHandshake. */
769 ecdhePub
= ss
->ephemeralECDHKeyPair
->pubKey
;
770 PORT_Assert(ecdhePub
!= NULL
);
772 PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE
);
776 ec_params
.len
= sizeof paramBuf
;
777 ec_params
.data
= paramBuf
;
778 curve
= params2ecName(&ecdhePub
->u
.ec
.DEREncodedParams
);
779 if (curve
!= ec_noName
) {
780 ec_params
.data
[0] = ec_type_named
;
781 ec_params
.data
[1] = 0x00;
782 ec_params
.data
[2] = curve
;
784 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE
);
788 rv
= ssl3_ComputeECDHKeyHash(ec_params
, ecdhePub
->u
.ec
.publicValue
,
789 &ss
->ssl3
.hs
.client_random
,
790 &ss
->ssl3
.hs
.server_random
,
791 &hashes
, ss
->opt
.bypassPKCS11
);
792 if (rv
!= SECSuccess
) {
793 ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE
);
797 isTLS
= (PRBool
)(ss
->ssl3
.pwSpec
->version
> SSL_LIBRARY_VERSION_3_0
);
799 /* XXX SSLKEAType isn't really a good choice for
800 * indexing certificates but that's all we have
803 if (kea_def
->kea
== kea_ecdhe_rsa
)
805 else /* kea_def->kea == kea_ecdhe_ecdsa */
808 rv
= ssl3_SignHashes(&hashes
, ss
->serverCerts
[certIndex
].SERVERKEY
,
809 &signed_hash
, isTLS
);
810 if (rv
!= SECSuccess
) {
811 goto loser
; /* ssl3_SignHashes has set err. */
813 if (signed_hash
.data
== NULL
) {
814 /* how can this happen and rv == SECSuccess ?? */
815 PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE
);
819 length
= ec_params
.len
+
820 1 + ecdhePub
->u
.ec
.publicValue
.len
+
823 rv
= ssl3_AppendHandshakeHeader(ss
, server_key_exchange
, length
);
824 if (rv
!= SECSuccess
) {
825 goto loser
; /* err set by AppendHandshake. */
828 rv
= ssl3_AppendHandshake(ss
, ec_params
.data
, ec_params
.len
);
829 if (rv
!= SECSuccess
) {
830 goto loser
; /* err set by AppendHandshake. */
833 rv
= ssl3_AppendHandshakeVariable(ss
, ecdhePub
->u
.ec
.publicValue
.data
,
834 ecdhePub
->u
.ec
.publicValue
.len
, 1);
835 if (rv
!= SECSuccess
) {
836 goto loser
; /* err set by AppendHandshake. */
839 rv
= ssl3_AppendHandshakeVariable(ss
, signed_hash
.data
,
841 if (rv
!= SECSuccess
) {
842 goto loser
; /* err set by AppendHandshake. */
845 PORT_Free(signed_hash
.data
);
849 if (signed_hash
.data
!= NULL
)
850 PORT_Free(signed_hash
.data
);
854 /* Lists of ECC cipher suites for searching and disabling. */
856 static const ssl3CipherSuite ecdh_suites
[] = {
857 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
,
858 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
,
859 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
,
860 TLS_ECDH_ECDSA_WITH_NULL_SHA
,
861 TLS_ECDH_ECDSA_WITH_RC4_128_SHA
,
862 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
,
863 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
,
864 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
,
865 TLS_ECDH_RSA_WITH_NULL_SHA
,
866 TLS_ECDH_RSA_WITH_RC4_128_SHA
,
867 0 /* end of list marker */
870 static const ssl3CipherSuite ecdh_ecdsa_suites
[] = {
871 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
,
872 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
,
873 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
,
874 TLS_ECDH_ECDSA_WITH_NULL_SHA
,
875 TLS_ECDH_ECDSA_WITH_RC4_128_SHA
,
876 0 /* end of list marker */
879 static const ssl3CipherSuite ecdh_rsa_suites
[] = {
880 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
,
881 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
,
882 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
,
883 TLS_ECDH_RSA_WITH_NULL_SHA
,
884 TLS_ECDH_RSA_WITH_RC4_128_SHA
,
885 0 /* end of list marker */
888 static const ssl3CipherSuite ecdhe_ecdsa_suites
[] = {
889 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
,
890 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
,
891 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
,
892 TLS_ECDHE_ECDSA_WITH_NULL_SHA
,
893 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
,
894 0 /* end of list marker */
897 static const ssl3CipherSuite ecdhe_rsa_suites
[] = {
898 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
,
899 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
,
900 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
,
901 TLS_ECDHE_RSA_WITH_NULL_SHA
,
902 TLS_ECDHE_RSA_WITH_RC4_128_SHA
,
903 0 /* end of list marker */
906 /* List of all ECC cipher suites */
907 static const ssl3CipherSuite ecSuites
[] = {
908 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
,
909 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
,
910 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
,
911 TLS_ECDHE_ECDSA_WITH_NULL_SHA
,
912 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
,
913 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
,
914 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
,
915 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
,
916 TLS_ECDHE_RSA_WITH_NULL_SHA
,
917 TLS_ECDHE_RSA_WITH_RC4_128_SHA
,
918 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
,
919 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
,
920 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
,
921 TLS_ECDH_ECDSA_WITH_NULL_SHA
,
922 TLS_ECDH_ECDSA_WITH_RC4_128_SHA
,
923 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
,
924 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
,
925 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
,
926 TLS_ECDH_RSA_WITH_NULL_SHA
,
927 TLS_ECDH_RSA_WITH_RC4_128_SHA
,
928 0 /* end of list marker */
931 /* On this socket, Disable the ECC cipher suites in the argument's list */
933 ssl3_DisableECCSuites(sslSocket
* ss
, const ssl3CipherSuite
* suite
)
937 for (; *suite
; ++suite
) {
938 SECStatus rv
= ssl3_CipherPrefSet(ss
, *suite
, PR_FALSE
);
940 PORT_Assert(rv
== SECSuccess
); /* else is coding error */
945 /* Look at the server certs configured on this socket, and disable any
946 * ECC cipher suites that are not supported by those certs.
949 ssl3_FilterECCipherSuitesByServerCerts(sslSocket
* ss
)
951 CERTCertificate
* svrCert
;
953 svrCert
= ss
->serverCerts
[kt_rsa
].serverCert
;
955 ssl3_DisableECCSuites(ss
, ecdhe_rsa_suites
);
958 svrCert
= ss
->serverCerts
[kt_ecdh
].serverCert
;
960 ssl3_DisableECCSuites(ss
, ecdh_suites
);
961 ssl3_DisableECCSuites(ss
, ecdhe_ecdsa_suites
);
963 SECOidTag sigTag
= SECOID_GetAlgorithmTag(&svrCert
->signature
);
966 case SEC_OID_PKCS1_RSA_ENCRYPTION
:
967 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION
:
968 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION
:
969 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION
:
970 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION
:
971 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION
:
972 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION
:
973 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION
:
974 ssl3_DisableECCSuites(ss
, ecdh_ecdsa_suites
);
976 case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE
:
977 case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE
:
978 case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE
:
979 case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE
:
980 case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE
:
981 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST
:
982 case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST
:
983 ssl3_DisableECCSuites(ss
, ecdh_rsa_suites
);
986 ssl3_DisableECCSuites(ss
, ecdh_suites
);
992 /* Ask: is ANY ECC cipher suite enabled on this socket? */
993 /* Order(N^2). Yuk. Also, this ignores export policy. */
995 ssl3_IsECCEnabled(sslSocket
* ss
)
997 const ssl3CipherSuite
* suite
;
999 for (suite
= ecSuites
; *suite
; ++suite
) {
1000 PRBool enabled
= PR_FALSE
;
1001 SECStatus rv
= ssl3_CipherPrefGet(ss
, *suite
, &enabled
);
1003 PORT_Assert(rv
== SECSuccess
); /* else is coding error */
1004 if (rv
== SECSuccess
&& enabled
)
1012 #ifndef NSS_ECC_MORE_THAN_SUITE_B
1013 /* Prefabricated TLS client hello extension, Elliptic Curves List,
1014 * offers only 3 curves, the Suite B curves, 23-25
1016 static const PRUint8 EClist
[12] = {
1017 BE(10), /* Extension type */
1018 BE( 8), /* octets that follow ( 3 pairs + 1 length pair) */
1019 BE( 6), /* octets that follow ( 3 pairs) */
1020 BE(23), BE(24), BE(25)
1023 /* Prefabricated TLS client hello extension, Elliptic Curves List,
1024 * offers curves 1-25.
1026 static const PRUint8 EClist
[56] = {
1027 BE(10), /* Extension type */
1028 BE(52), /* octets that follow (25 pairs + 1 length pair) */
1029 BE(50), /* octets that follow (25 pairs) */
1030 BE( 1), BE( 2), BE( 3), BE( 4), BE( 5), BE( 6), BE( 7),
1031 BE( 8), BE( 9), BE(10), BE(11), BE(12), BE(13), BE(14), BE(15),
1032 BE(16), BE(17), BE(18), BE(19), BE(20), BE(21), BE(22), BE(23),
1037 static const PRUint8 ECPtFmt
[6] = {
1038 BE(11), /* Extension type */
1039 BE( 2), /* octets that follow */
1040 1, /* octets that follow */
1041 0 /* uncompressed type only */
1044 /* Send our "canned" (precompiled) Supported Elliptic Curves extension,
1045 * which says that we support all TLS-defined named curves.
1048 ssl3_SendSupportedCurvesXtn(
1053 if (!ss
|| !ssl3_IsECCEnabled(ss
))
1055 if (append
&& maxBytes
>= (sizeof EClist
)) {
1056 SECStatus rv
= ssl3_AppendHandshake(ss
, EClist
, (sizeof EClist
));
1057 if (rv
!= SECSuccess
)
1059 if (!ss
->sec
.isServer
) {
1060 TLSExtensionData
*xtnData
= &ss
->xtnData
;
1061 xtnData
->advertised
[xtnData
->numAdvertised
++] =
1062 elliptic_curves_xtn
;
1065 return (sizeof EClist
);
1068 /* Send our "canned" (precompiled) Supported Point Formats extension,
1069 * which says that we only support uncompressed points.
1072 ssl3_SendSupportedPointFormatsXtn(
1077 if (!ss
|| !ssl3_IsECCEnabled(ss
))
1079 if (append
&& maxBytes
>= (sizeof ECPtFmt
)) {
1080 SECStatus rv
= ssl3_AppendHandshake(ss
, ECPtFmt
, (sizeof ECPtFmt
));
1081 if (rv
!= SECSuccess
)
1083 if (!ss
->sec
.isServer
) {
1084 TLSExtensionData
*xtnData
= &ss
->xtnData
;
1085 xtnData
->advertised
[xtnData
->numAdvertised
++] =
1086 ec_point_formats_xtn
;
1089 return (sizeof ECPtFmt
);
1092 /* Just make sure that the remote client supports uncompressed points,
1093 * Since that is all we support. Disable ECC cipher suites if it doesn't.
1096 ssl3_HandleSupportedPointFormatsXtn(sslSocket
*ss
, PRUint16 ex_type
,
1101 if (data
->len
< 2 || data
->len
> 255 || !data
->data
||
1102 data
->len
!= (unsigned int)data
->data
[0] + 1) {
1106 for (i
= data
->len
; --i
> 0; ) {
1107 if (data
->data
[i
] == 0) {
1108 /* indicate that we should send a reply */
1110 rv
= ssl3_RegisterServerHelloExtensionSender(ss
, ex_type
,
1111 &ssl3_SendSupportedPointFormatsXtn
);
1116 /* evil client doesn't support uncompressed */
1117 ssl3_DisableECCSuites(ss
, ecSuites
);
1122 #define SSL3_GET_SERVER_PUBLICKEY(sock, type) \
1123 (ss->serverCerts[type].serverKeyPair ? \
1124 ss->serverCerts[type].serverKeyPair->pubKey : NULL)
1126 /* Extract the TLS curve name for the public key in our EC server cert. */
1127 ECName
ssl3_GetSvrCertCurveName(sslSocket
*ss
)
1129 SECKEYPublicKey
*srvPublicKey
;
1130 ECName ec_curve
= ec_noName
;
1132 srvPublicKey
= SSL3_GET_SERVER_PUBLICKEY(ss
, kt_ecdh
);
1134 ec_curve
= params2ecName(&srvPublicKey
->u
.ec
.DEREncodedParams
);
1139 /* Ensure that the curve in our server cert is one of the ones suppored
1140 * by the remote client, and disable all ECC cipher suites if not.
1143 ssl3_HandleSupportedCurvesXtn(sslSocket
*ss
, PRUint16 ex_type
, SECItem
*data
)
1146 PRUint32 peerCurves
= 0;
1147 PRUint32 mutualCurves
= 0;
1148 PRUint16 svrCertCurveName
;
1150 if (!data
->data
|| data
->len
< 4 || data
->len
> 65535)
1152 /* get the length of elliptic_curve_list */
1153 list_len
= ssl3_ConsumeHandshakeNumber(ss
, 2, &data
->data
, &data
->len
);
1154 if (list_len
< 0 || data
->len
!= list_len
|| (data
->len
% 2) != 0) {
1158 /* build bit vector of peer's supported curve names */
1160 PRInt32 curve_name
=
1161 ssl3_ConsumeHandshakeNumber(ss
, 2, &data
->data
, &data
->len
);
1162 if (curve_name
> ec_noName
&& curve_name
< ec_pastLastName
) {
1163 peerCurves
|= (1U << curve_name
);
1166 /* What curves do we support in common? */
1167 mutualCurves
= ss
->ssl3
.hs
.negotiatedECCurves
&= peerCurves
;
1168 if (!mutualCurves
) { /* no mutually supported EC Curves */
1172 /* if our ECC cert doesn't use one of these supported curves,
1173 * disable ECC cipher suites that require an ECC cert.
1175 svrCertCurveName
= ssl3_GetSvrCertCurveName(ss
);
1176 if (svrCertCurveName
!= ec_noName
&&
1177 (mutualCurves
& (1U << svrCertCurveName
)) != 0) {
1180 /* Our EC cert doesn't contain a mutually supported curve.
1181 * Disable all ECC cipher suites that require an EC cert
1183 ssl3_DisableECCSuites(ss
, ecdh_ecdsa_suites
);
1184 ssl3_DisableECCSuites(ss
, ecdhe_ecdsa_suites
);
1188 /* no common curve supported */
1189 ssl3_DisableECCSuites(ss
, ecSuites
);
1193 #endif /* NSS_ENABLE_ECC */