ssl3ecc.c revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1/*
2 * SSL3 Protocol
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8/* ECC code moved here from ssl3con.c */
9/* $Id$ */
10
11#include "nss.h"
12#include "cert.h"
13#include "ssl.h"
14#include "cryptohi.h"	/* for DSAU_ stuff */
15#include "keyhi.h"
16#include "secder.h"
17#include "secitem.h"
18
19#include "sslimpl.h"
20#include "sslproto.h"
21#include "sslerr.h"
22#include "prtime.h"
23#include "prinrval.h"
24#include "prerror.h"
25#include "pratom.h"
26#include "prthread.h"
27#include "prinit.h"
28
29#include "pk11func.h"
30#include "secmod.h"
31
32#include <stdio.h>
33
34#ifdef NSS_ENABLE_ECC
35
36/*
37 * In NSS 3.13.2 the definition of the EC_POINT_FORM_UNCOMPRESSED macro
38 * was moved from the internal header ec.h to the public header blapit.h.
39 * Define the macro here when compiling against older system NSS headers.
40 */
41#ifndef EC_POINT_FORM_UNCOMPRESSED
42#define EC_POINT_FORM_UNCOMPRESSED 0x04
43#endif
44
45#ifndef PK11_SETATTRS
46#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
47		(x)->pValue=(v); (x)->ulValueLen = (l);
48#endif
49
50#define SSL_GET_SERVER_PUBLIC_KEY(sock, type) \
51    (ss->serverCerts[type].serverKeyPair ? \
52    ss->serverCerts[type].serverKeyPair->pubKey : NULL)
53
54#define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \
55    ((curveName > ec_noName) && \
56     (curveName < ec_pastLastName) && \
57     ((1UL << curveName) & curvemsk) != 0)
58
59
60
61static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve);
62
63#define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName))
64
65/* Table containing OID tags for elliptic curves named in the
66 * ECC-TLS IETF draft.
67 */
68static const SECOidTag ecName2OIDTag[] = {
69	0,
70	SEC_OID_SECG_EC_SECT163K1,  /*  1 */
71	SEC_OID_SECG_EC_SECT163R1,  /*  2 */
72	SEC_OID_SECG_EC_SECT163R2,  /*  3 */
73	SEC_OID_SECG_EC_SECT193R1,  /*  4 */
74	SEC_OID_SECG_EC_SECT193R2,  /*  5 */
75	SEC_OID_SECG_EC_SECT233K1,  /*  6 */
76	SEC_OID_SECG_EC_SECT233R1,  /*  7 */
77	SEC_OID_SECG_EC_SECT239K1,  /*  8 */
78	SEC_OID_SECG_EC_SECT283K1,  /*  9 */
79	SEC_OID_SECG_EC_SECT283R1,  /* 10 */
80	SEC_OID_SECG_EC_SECT409K1,  /* 11 */
81	SEC_OID_SECG_EC_SECT409R1,  /* 12 */
82	SEC_OID_SECG_EC_SECT571K1,  /* 13 */
83	SEC_OID_SECG_EC_SECT571R1,  /* 14 */
84	SEC_OID_SECG_EC_SECP160K1,  /* 15 */
85	SEC_OID_SECG_EC_SECP160R1,  /* 16 */
86	SEC_OID_SECG_EC_SECP160R2,  /* 17 */
87	SEC_OID_SECG_EC_SECP192K1,  /* 18 */
88	SEC_OID_SECG_EC_SECP192R1,  /* 19 */
89	SEC_OID_SECG_EC_SECP224K1,  /* 20 */
90	SEC_OID_SECG_EC_SECP224R1,  /* 21 */
91	SEC_OID_SECG_EC_SECP256K1,  /* 22 */
92	SEC_OID_SECG_EC_SECP256R1,  /* 23 */
93	SEC_OID_SECG_EC_SECP384R1,  /* 24 */
94	SEC_OID_SECG_EC_SECP521R1,  /* 25 */
95};
96
97static const PRUint16 curve2bits[] = {
98	  0, /*  ec_noName     = 0,   */
99	163, /*  ec_sect163k1  = 1,   */
100	163, /*  ec_sect163r1  = 2,   */
101	163, /*  ec_sect163r2  = 3,   */
102	193, /*  ec_sect193r1  = 4,   */
103	193, /*  ec_sect193r2  = 5,   */
104	233, /*  ec_sect233k1  = 6,   */
105	233, /*  ec_sect233r1  = 7,   */
106	239, /*  ec_sect239k1  = 8,   */
107	283, /*  ec_sect283k1  = 9,   */
108	283, /*  ec_sect283r1  = 10,  */
109	409, /*  ec_sect409k1  = 11,  */
110	409, /*  ec_sect409r1  = 12,  */
111	571, /*  ec_sect571k1  = 13,  */
112	571, /*  ec_sect571r1  = 14,  */
113	160, /*  ec_secp160k1  = 15,  */
114	160, /*  ec_secp160r1  = 16,  */
115	160, /*  ec_secp160r2  = 17,  */
116	192, /*  ec_secp192k1  = 18,  */
117	192, /*  ec_secp192r1  = 19,  */
118	224, /*  ec_secp224k1  = 20,  */
119	224, /*  ec_secp224r1  = 21,  */
120	256, /*  ec_secp256k1  = 22,  */
121	256, /*  ec_secp256r1  = 23,  */
122	384, /*  ec_secp384r1  = 24,  */
123	521, /*  ec_secp521r1  = 25,  */
124      65535  /*  ec_pastLastName      */
125};
126
127typedef struct Bits2CurveStr {
128    PRUint16    bits;
129    ECName      curve;
130} Bits2Curve;
131
132static const Bits2Curve bits2curve [] = {
133   {	192,     ec_secp192r1    /*  = 19,  fast */  },
134   {	160,     ec_secp160r2    /*  = 17,  fast */  },
135   {	160,     ec_secp160k1    /*  = 15,  */       },
136   {	160,     ec_secp160r1    /*  = 16,  */       },
137   {	163,     ec_sect163k1    /*  = 1,   */       },
138   {	163,     ec_sect163r1    /*  = 2,   */       },
139   {	163,     ec_sect163r2    /*  = 3,   */       },
140   {	192,     ec_secp192k1    /*  = 18,  */       },
141   {	193,     ec_sect193r1    /*  = 4,   */       },
142   {	193,     ec_sect193r2    /*  = 5,   */       },
143   {	224,     ec_secp224r1    /*  = 21,  fast */  },
144   {	224,     ec_secp224k1    /*  = 20,  */       },
145   {	233,     ec_sect233k1    /*  = 6,   */       },
146   {	233,     ec_sect233r1    /*  = 7,   */       },
147   {	239,     ec_sect239k1    /*  = 8,   */       },
148   {	256,     ec_secp256r1    /*  = 23,  fast */  },
149   {	256,     ec_secp256k1    /*  = 22,  */       },
150   {	283,     ec_sect283k1    /*  = 9,   */       },
151   {	283,     ec_sect283r1    /*  = 10,  */       },
152   {	384,     ec_secp384r1    /*  = 24,  fast */  },
153   {	409,     ec_sect409k1    /*  = 11,  */       },
154   {	409,     ec_sect409r1    /*  = 12,  */       },
155   {	521,     ec_secp521r1    /*  = 25,  fast */  },
156   {	571,     ec_sect571k1    /*  = 13,  */       },
157   {	571,     ec_sect571r1    /*  = 14,  */       },
158   {  65535,     ec_noName    }
159};
160
161typedef struct ECDHEKeyPairStr {
162    ssl3KeyPair *  pair;
163    int            error;  /* error code of the call-once function */
164    PRCallOnceType once;
165} ECDHEKeyPair;
166
167/* arrays of ECDHE KeyPairs */
168static ECDHEKeyPair gECDHEKeyPairs[ec_pastLastName];
169
170SECStatus
171ssl3_ECName2Params(PRArenaPool * arena, ECName curve, SECKEYECParams * params)
172{
173    SECOidData *oidData = NULL;
174
175    if ((curve <= ec_noName) || (curve >= ec_pastLastName) ||
176	((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) {
177        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
178	return SECFailure;
179    }
180
181    SECITEM_AllocItem(arena, params, (2 + oidData->oid.len));
182    /*
183     * params->data needs to contain the ASN encoding of an object ID (OID)
184     * representing the named curve. The actual OID is in
185     * oidData->oid.data so we simply prepend 0x06 and OID length
186     */
187    params->data[0] = SEC_ASN1_OBJECT_ID;
188    params->data[1] = oidData->oid.len;
189    memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
190
191    return SECSuccess;
192}
193
194static ECName
195params2ecName(SECKEYECParams * params)
196{
197    SECItem oid = { siBuffer, NULL, 0};
198    SECOidData *oidData = NULL;
199    ECName i;
200
201    /*
202     * params->data needs to contain the ASN encoding of an object ID (OID)
203     * representing a named curve. Here, we strip away everything
204     * before the actual OID and use the OID to look up a named curve.
205     */
206    if (params->data[0] != SEC_ASN1_OBJECT_ID) return ec_noName;
207    oid.len = params->len - 2;
208    oid.data = params->data + 2;
209    if ((oidData = SECOID_FindOID(&oid)) == NULL) return ec_noName;
210    for (i = ec_noName + 1; i < ec_pastLastName; i++) {
211	if (ecName2OIDTag[i] == oidData->offset)
212	    return i;
213    }
214
215    return ec_noName;
216}
217
218/* Caller must set hiLevel error code. */
219static SECStatus
220ssl3_ComputeECDHKeyHash(SECItem ec_params, SECItem server_ecpoint,
221			     SSL3Random *client_rand, SSL3Random *server_rand,
222			     SSL3Hashes *hashes, PRBool bypassPKCS11)
223{
224    PRUint8     * hashBuf;
225    PRUint8     * pBuf;
226    SECStatus     rv 		= SECSuccess;
227    unsigned int  bufLen;
228    /*
229     * XXX For now, we only support named curves (the appropriate
230     * checks are made before this method is called) so ec_params
231     * takes up only two bytes. ECPoint needs to fit in 256 bytes
232     * (because the spec says the length must fit in one byte)
233     */
234    PRUint8       buf[2*SSL3_RANDOM_LENGTH + 2 + 1 + 256];
235
236    bufLen = 2*SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len;
237    if (bufLen <= sizeof buf) {
238    	hashBuf = buf;
239    } else {
240    	hashBuf = PORT_Alloc(bufLen);
241	if (!hashBuf) {
242	    return SECFailure;
243	}
244    }
245
246    memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
247    	pBuf = hashBuf + SSL3_RANDOM_LENGTH;
248    memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
249    	pBuf += SSL3_RANDOM_LENGTH;
250    memcpy(pBuf, ec_params.data, ec_params.len);
251    	pBuf += ec_params.len;
252    pBuf[0] = (PRUint8)(server_ecpoint.len);
253    pBuf += 1;
254    memcpy(pBuf, server_ecpoint.data, server_ecpoint.len);
255    	pBuf += server_ecpoint.len;
256    PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
257
258    rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);
259
260    PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen));
261    PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result", hashes->md5, MD5_LENGTH));
262    PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH));
263
264    if (hashBuf != buf)
265    	PORT_Free(hashBuf);
266    return rv;
267}
268
269
270/* Called from ssl3_SendClientKeyExchange(). */
271SECStatus
272ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
273{
274    PK11SymKey *	pms 		= NULL;
275    SECStatus           rv    		= SECFailure;
276    PRBool              isTLS;
277    CK_MECHANISM_TYPE	target;
278    SECKEYPublicKey	*pubKey = NULL;		/* Ephemeral ECDH key */
279    SECKEYPrivateKey	*privKey = NULL;	/* Ephemeral ECDH key */
280
281    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
282    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
283
284    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
285
286    /* Generate ephemeral EC keypair */
287    if (svrPubKey->keyType != ecKey) {
288	PORT_SetError(SEC_ERROR_BAD_KEY);
289	goto loser;
290    }
291    /* XXX SHOULD CALL ssl3_CreateECDHEphemeralKeys here, instead! */
292    privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams,
293	                                &pubKey, ss->pkcs11PinArg);
294    if (!privKey || !pubKey) {
295	    ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
296	    rv = SECFailure;
297	    goto loser;
298    }
299    PRINT_BUF(50, (ss, "ECDH public value:",
300					pubKey->u.ec.publicValue.data,
301					pubKey->u.ec.publicValue.len));
302
303    if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
304    else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
305
306    /*  Determine the PMS */
307    pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL,
308			    CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
309			    CKD_NULL, NULL, NULL);
310
311    if (pms == NULL) {
312	SSL3AlertDescription desc  = illegal_parameter;
313	(void)SSL3_SendAlert(ss, alert_fatal, desc);
314	ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
315	goto loser;
316    }
317
318    SECKEY_DestroyPrivateKey(privKey);
319    privKey = NULL;
320
321    rv = ssl3_InitPendingCipherSpec(ss,  pms);
322    PK11_FreeSymKey(pms); pms = NULL;
323
324    if (rv != SECSuccess) {
325	ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
326	goto loser;
327    }
328
329    rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
330					pubKey->u.ec.publicValue.len + 1);
331    if (rv != SECSuccess) {
332        goto loser;	/* err set by ssl3_AppendHandshake* */
333    }
334
335    rv = ssl3_AppendHandshakeVariable(ss,
336					pubKey->u.ec.publicValue.data,
337					pubKey->u.ec.publicValue.len, 1);
338    SECKEY_DestroyPublicKey(pubKey);
339    pubKey = NULL;
340
341    if (rv != SECSuccess) {
342        goto loser;	/* err set by ssl3_AppendHandshake* */
343    }
344
345    rv = SECSuccess;
346
347loser:
348    if(pms) PK11_FreeSymKey(pms);
349    if(privKey) SECKEY_DestroyPrivateKey(privKey);
350    if(pubKey) SECKEY_DestroyPublicKey(pubKey);
351    return rv;
352}
353
354
355/*
356** Called from ssl3_HandleClientKeyExchange()
357*/
358SECStatus
359ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
360				     PRUint32 length,
361                                     SECKEYPublicKey *srvrPubKey,
362                                     SECKEYPrivateKey *srvrPrivKey)
363{
364    PK11SymKey *      pms;
365    SECStatus         rv;
366    SECKEYPublicKey   clntPubKey;
367    CK_MECHANISM_TYPE	target;
368    PRBool isTLS;
369
370    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
371    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
372
373    clntPubKey.keyType = ecKey;
374    clntPubKey.u.ec.DEREncodedParams.len =
375	srvrPubKey->u.ec.DEREncodedParams.len;
376    clntPubKey.u.ec.DEREncodedParams.data =
377	srvrPubKey->u.ec.DEREncodedParams.data;
378
379    rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue,
380	                               1, &b, &length);
381    if (rv != SECSuccess) {
382	SEND_ALERT
383	return SECFailure;	/* XXX Who sets the error code?? */
384    }
385
386    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
387
388    if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
389    else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
390
391    /*  Determine the PMS */
392    pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL,
393			    CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
394			    CKD_NULL, NULL, NULL);
395
396    if (pms == NULL) {
397	/* last gasp.  */
398	ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
399	return SECFailure;
400    }
401
402    rv = ssl3_InitPendingCipherSpec(ss,  pms);
403    PK11_FreeSymKey(pms);
404    if (rv != SECSuccess) {
405	SEND_ALERT
406	return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
407    }
408    return SECSuccess;
409}
410
411ECName
412ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits)
413{
414    int    i;
415
416    for ( i = 0; bits2curve[i].curve != ec_noName; i++) {
417	if (bits2curve[i].bits < requiredECCbits)
418	    continue;
419    	if (SSL_IS_CURVE_NEGOTIATED(curvemsk, bits2curve[i].curve)) {
420	    return bits2curve[i].curve;
421	}
422    }
423    PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
424    return ec_noName;
425}
426
427/* find the "weakest link".  Get strength of signature key and of sym key.
428 * choose curve for the weakest of those two.
429 */
430ECName
431ssl3_GetCurveNameForServerSocket(sslSocket *ss)
432{
433    SECKEYPublicKey * svrPublicKey = NULL;
434    ECName ec_curve = ec_noName;
435    int    signatureKeyStrength = 521;
436    int    requiredECCbits = ss->sec.secretKeyBits * 2;
437
438    if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa) {
439	svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh);
440	if (svrPublicKey)
441	    ec_curve = params2ecName(&svrPublicKey->u.ec.DEREncodedParams);
442	if (!SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, ec_curve)) {
443	    PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
444	    return ec_noName;
445	}
446	signatureKeyStrength = curve2bits[ ec_curve ];
447    } else {
448        /* RSA is our signing cert */
449        int serverKeyStrengthInBits;
450
451        svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_rsa);
452        if (!svrPublicKey) {
453            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
454            return ec_noName;
455        }
456
457        /* currently strength in bytes */
458        serverKeyStrengthInBits = svrPublicKey->u.rsa.modulus.len;
459        if (svrPublicKey->u.rsa.modulus.data[0] == 0) {
460            serverKeyStrengthInBits--;
461        }
462        /* convert to strength in bits */
463        serverKeyStrengthInBits *= BPB;
464
465        signatureKeyStrength =
466	    SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
467    }
468    if ( requiredECCbits > signatureKeyStrength )
469         requiredECCbits = signatureKeyStrength;
470
471    return ssl3_GetCurveWithECKeyStrength(ss->ssl3.hs.negotiatedECCurves,
472					  requiredECCbits);
473}
474
475/* function to clear out the lists */
476static SECStatus
477ssl3_ShutdownECDHECurves(void *appData, void *nssData)
478{
479    int i;
480    ECDHEKeyPair *keyPair = &gECDHEKeyPairs[0];
481
482    for (i=0; i < ec_pastLastName; i++, keyPair++) {
483	if (keyPair->pair) {
484	    ssl3_FreeKeyPair(keyPair->pair);
485	}
486    }
487    memset(gECDHEKeyPairs, 0, sizeof gECDHEKeyPairs);
488    return SECSuccess;
489}
490
491static PRStatus
492ssl3_ECRegister(void)
493{
494    SECStatus rv;
495    rv = NSS_RegisterShutdown(ssl3_ShutdownECDHECurves, gECDHEKeyPairs);
496    if (rv != SECSuccess) {
497	gECDHEKeyPairs[ec_noName].error = PORT_GetError();
498    }
499    return (PRStatus)rv;
500}
501
502/* CallOnce function, called once for each named curve. */
503static PRStatus
504ssl3_CreateECDHEphemeralKeyPair(void * arg)
505{
506    SECKEYPrivateKey *    privKey  = NULL;
507    SECKEYPublicKey *     pubKey   = NULL;
508    ssl3KeyPair *	  keyPair  = NULL;
509    ECName                ec_curve = (ECName)arg;
510    SECKEYECParams        ecParams = { siBuffer, NULL, 0 };
511
512    PORT_Assert(gECDHEKeyPairs[ec_curve].pair == NULL);
513
514    /* ok, no one has generated a global key for this curve yet, do so */
515    if (ssl3_ECName2Params(NULL, ec_curve, &ecParams) != SECSuccess) {
516	gECDHEKeyPairs[ec_curve].error = PORT_GetError();
517	return PR_FAILURE;
518    }
519
520    privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL);
521    SECITEM_FreeItem(&ecParams, PR_FALSE);
522
523    if (!privKey || !pubKey || !(keyPair = ssl3_NewKeyPair(privKey, pubKey))) {
524	if (privKey) {
525	    SECKEY_DestroyPrivateKey(privKey);
526	}
527	if (pubKey) {
528	    SECKEY_DestroyPublicKey(pubKey);
529	}
530	ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
531	gECDHEKeyPairs[ec_curve].error = PORT_GetError();
532	return PR_FAILURE;
533    }
534
535    gECDHEKeyPairs[ec_curve].pair = keyPair;
536    return PR_SUCCESS;
537}
538
539/*
540 * Creates the ephemeral public and private ECDH keys used by
541 * server in ECDHE_RSA and ECDHE_ECDSA handshakes.
542 * For now, the elliptic curve is chosen to be the same
543 * strength as the signing certificate (ECC or RSA).
544 * We need an API to specify the curve. This won't be a real
545 * issue until we further develop server-side support for ECC
546 * cipher suites.
547 */
548static SECStatus
549ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve)
550{
551    ssl3KeyPair *	  keyPair        = NULL;
552
553    /* if there's no global key for this curve, make one. */
554    if (gECDHEKeyPairs[ec_curve].pair == NULL) {
555	PRStatus status;
556
557	status = PR_CallOnce(&gECDHEKeyPairs[ec_noName].once, ssl3_ECRegister);
558        if (status != PR_SUCCESS) {
559	    PORT_SetError(gECDHEKeyPairs[ec_noName].error);
560	    return SECFailure;
561    	}
562	status = PR_CallOnceWithArg(&gECDHEKeyPairs[ec_curve].once,
563	                            ssl3_CreateECDHEphemeralKeyPair,
564				    (void *)ec_curve);
565        if (status != PR_SUCCESS) {
566	    PORT_SetError(gECDHEKeyPairs[ec_curve].error);
567	    return SECFailure;
568    	}
569    }
570
571    keyPair = gECDHEKeyPairs[ec_curve].pair;
572    PORT_Assert(keyPair != NULL);
573    if (!keyPair)
574    	return SECFailure;
575    ss->ephemeralECDHKeyPair = ssl3_GetKeyPairRef(keyPair);
576
577    return SECSuccess;
578}
579
580SECStatus
581ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
582{
583    PRArenaPool *    arena     = NULL;
584    SECKEYPublicKey *peerKey   = NULL;
585    PRBool           isTLS;
586    SECStatus        rv;
587    int              errCode   = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
588    SSL3AlertDescription desc  = illegal_parameter;
589    SSL3Hashes       hashes;
590    SECItem          signature = {siBuffer, NULL, 0};
591
592    SECItem          ec_params = {siBuffer, NULL, 0};
593    SECItem          ec_point  = {siBuffer, NULL, 0};
594    unsigned char    paramBuf[3]; /* only for curve_type == named_curve */
595
596    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
597
598    /* XXX This works only for named curves, revisit this when
599     * we support generic curves.
600     */
601    ec_params.len  = sizeof paramBuf;
602    ec_params.data = paramBuf;
603    rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length);
604    if (rv != SECSuccess) {
605	goto loser;		/* malformed. */
606    }
607
608    /* Fail if the curve is not a named curve */
609    if ((ec_params.data[0] != ec_type_named) ||
610	(ec_params.data[1] != 0) ||
611	!supportedCurve(ec_params.data[2])) {
612	    errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
613	    desc = handshake_failure;
614	    goto alert_loser;
615    }
616
617    rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);
618    if (rv != SECSuccess) {
619	goto loser;		/* malformed. */
620    }
621    /* Fail if the ec point uses compressed representation */
622    if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
623	    errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
624	    desc = handshake_failure;
625	    goto alert_loser;
626    }
627
628    rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
629    if (rv != SECSuccess) {
630	goto loser;		/* malformed. */
631    }
632
633    if (length != 0) {
634	if (isTLS)
635	    desc = decode_error;
636	goto alert_loser;		/* malformed. */
637    }
638
639    PRINT_BUF(60, (NULL, "Server EC params", ec_params.data,
640	ec_params.len));
641    PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));
642
643    /* failures after this point are not malformed handshakes. */
644    /* TLS: send decrypt_error if signature failed. */
645    desc = isTLS ? decrypt_error : handshake_failure;
646
647    /*
648     *  check to make sure the hash is signed by right guy
649     */
650    rv = ssl3_ComputeECDHKeyHash(ec_params, ec_point,
651				      &ss->ssl3.hs.client_random,
652				      &ss->ssl3.hs.server_random,
653				      &hashes, ss->opt.bypassPKCS11);
654
655    if (rv != SECSuccess) {
656	errCode =
657	    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
658	goto alert_loser;
659    }
660    rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
661				isTLS, ss->pkcs11PinArg);
662    if (rv != SECSuccess)  {
663	errCode =
664	    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
665	goto alert_loser;
666    }
667
668    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
669    if (arena == NULL) {
670	goto no_memory;
671    }
672
673    ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
674    if (peerKey == NULL) {
675	goto no_memory;
676    }
677
678    peerKey->arena                 = arena;
679    peerKey->keyType               = ecKey;
680
681    /* set up EC parameters in peerKey */
682    if (ssl3_ECName2Params(arena, ec_params.data[2],
683	    &peerKey->u.ec.DEREncodedParams) != SECSuccess) {
684	/* we should never get here since we already
685	 * checked that we are dealing with a supported curve
686	 */
687	errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
688	goto alert_loser;
689    }
690
691    /* copy publicValue in peerKey */
692    if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue,  &ec_point))
693    {
694	PORT_FreeArena(arena, PR_FALSE);
695	goto no_memory;
696    }
697    peerKey->pkcs11Slot         = NULL;
698    peerKey->pkcs11ID           = CK_INVALID_HANDLE;
699
700    ss->sec.peerKey = peerKey;
701    ss->ssl3.hs.ws = wait_cert_request;
702
703    return SECSuccess;
704
705alert_loser:
706    (void)SSL3_SendAlert(ss, alert_fatal, desc);
707loser:
708    PORT_SetError( errCode );
709    return SECFailure;
710
711no_memory:	/* no-memory error has already been set. */
712    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
713    return SECFailure;
714}
715
716SECStatus
717ssl3_SendECDHServerKeyExchange(sslSocket *ss)
718{
719const ssl3KEADef *     kea_def     = ss->ssl3.hs.kea_def;
720    SECStatus          rv          = SECFailure;
721    int                length;
722    PRBool             isTLS;
723    SECItem            signed_hash = {siBuffer, NULL, 0};
724    SSL3Hashes         hashes;
725
726    SECKEYPublicKey *  ecdhePub;
727    SECItem            ec_params = {siBuffer, NULL, 0};
728    unsigned char      paramBuf[3];
729    ECName             curve;
730    SSL3KEAType        certIndex;
731
732
733    /* Generate ephemeral ECDH key pair and send the public key */
734    curve = ssl3_GetCurveNameForServerSocket(ss);
735    if (curve == ec_noName) {
736    	goto loser;
737    }
738    rv = ssl3_CreateECDHEphemeralKeys(ss, curve);
739    if (rv != SECSuccess) {
740	goto loser; 	/* err set by AppendHandshake. */
741    }
742    ecdhePub = ss->ephemeralECDHKeyPair->pubKey;
743    PORT_Assert(ecdhePub != NULL);
744    if (!ecdhePub) {
745	PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
746	return SECFailure;
747    }
748
749    ec_params.len  = sizeof paramBuf;
750    ec_params.data = paramBuf;
751    curve = params2ecName(&ecdhePub->u.ec.DEREncodedParams);
752    if (curve != ec_noName) {
753	ec_params.data[0] = ec_type_named;
754	ec_params.data[1] = 0x00;
755	ec_params.data[2] = curve;
756    } else {
757	PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
758	goto loser;
759    }
760
761    rv = ssl3_ComputeECDHKeyHash(ec_params, ecdhePub->u.ec.publicValue,
762				      &ss->ssl3.hs.client_random,
763				      &ss->ssl3.hs.server_random,
764				      &hashes, ss->opt.bypassPKCS11);
765    if (rv != SECSuccess) {
766	ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
767	goto loser;
768    }
769
770    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
771
772    /* XXX SSLKEAType isn't really a good choice for
773     * indexing certificates but that's all we have
774     * for now.
775     */
776    if (kea_def->kea == kea_ecdhe_rsa)
777	certIndex = kt_rsa;
778    else /* kea_def->kea == kea_ecdhe_ecdsa */
779	certIndex = kt_ecdh;
780
781    rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY,
782			 &signed_hash, isTLS);
783    if (rv != SECSuccess) {
784	goto loser;		/* ssl3_SignHashes has set err. */
785    }
786    if (signed_hash.data == NULL) {
787	/* how can this happen and rv == SECSuccess ?? */
788	PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
789	goto loser;
790    }
791
792    length = ec_params.len +
793	     1 + ecdhePub->u.ec.publicValue.len +
794	     2 + signed_hash.len;
795
796    rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
797    if (rv != SECSuccess) {
798	goto loser; 	/* err set by AppendHandshake. */
799    }
800
801    rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len);
802    if (rv != SECSuccess) {
803	goto loser; 	/* err set by AppendHandshake. */
804    }
805
806    rv = ssl3_AppendHandshakeVariable(ss, ecdhePub->u.ec.publicValue.data,
807				      ecdhePub->u.ec.publicValue.len, 1);
808    if (rv != SECSuccess) {
809	goto loser; 	/* err set by AppendHandshake. */
810    }
811
812    rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
813				      signed_hash.len, 2);
814    if (rv != SECSuccess) {
815	goto loser; 	/* err set by AppendHandshake. */
816    }
817
818    PORT_Free(signed_hash.data);
819    return SECSuccess;
820
821loser:
822    if (signed_hash.data != NULL)
823    	PORT_Free(signed_hash.data);
824    return SECFailure;
825}
826
827/* Lists of ECC cipher suites for searching and disabling. */
828
829static const ssl3CipherSuite ecdh_suites[] = {
830    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
831    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
832    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
833    TLS_ECDH_ECDSA_WITH_NULL_SHA,
834    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
835    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
836    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
837    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
838    TLS_ECDH_RSA_WITH_NULL_SHA,
839    TLS_ECDH_RSA_WITH_RC4_128_SHA,
840    0 /* end of list marker */
841};
842
843static const ssl3CipherSuite ecdh_ecdsa_suites[] = {
844    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
845    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
846    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
847    TLS_ECDH_ECDSA_WITH_NULL_SHA,
848    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
849    0 /* end of list marker */
850};
851
852static const ssl3CipherSuite ecdh_rsa_suites[] = {
853    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
854    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
855    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
856    TLS_ECDH_RSA_WITH_NULL_SHA,
857    TLS_ECDH_RSA_WITH_RC4_128_SHA,
858    0 /* end of list marker */
859};
860
861static const ssl3CipherSuite ecdhe_ecdsa_suites[] = {
862    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
863    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
864    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
865    TLS_ECDHE_ECDSA_WITH_NULL_SHA,
866    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
867    0 /* end of list marker */
868};
869
870static const ssl3CipherSuite ecdhe_rsa_suites[] = {
871    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
872    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
873    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
874    TLS_ECDHE_RSA_WITH_NULL_SHA,
875    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
876    0 /* end of list marker */
877};
878
879/* List of all ECC cipher suites */
880static const ssl3CipherSuite ecSuites[] = {
881    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
882    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
883    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
884    TLS_ECDHE_ECDSA_WITH_NULL_SHA,
885    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
886    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
887    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
888    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
889    TLS_ECDHE_RSA_WITH_NULL_SHA,
890    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
891    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
892    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
893    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
894    TLS_ECDH_ECDSA_WITH_NULL_SHA,
895    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
896    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
897    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
898    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
899    TLS_ECDH_RSA_WITH_NULL_SHA,
900    TLS_ECDH_RSA_WITH_RC4_128_SHA,
901    0 /* end of list marker */
902};
903
904/* On this socket, Disable the ECC cipher suites in the argument's list */
905SECStatus
906ssl3_DisableECCSuites(sslSocket * ss, const ssl3CipherSuite * suite)
907{
908    if (!suite)
909    	suite = ecSuites;
910    for (; *suite; ++suite) {
911	SECStatus rv      = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
912
913	PORT_Assert(rv == SECSuccess); /* else is coding error */
914    }
915    return SECSuccess;
916}
917
918/* Look at the server certs configured on this socket, and disable any
919 * ECC cipher suites that are not supported by those certs.
920 */
921void
922ssl3_FilterECCipherSuitesByServerCerts(sslSocket * ss)
923{
924    CERTCertificate * svrCert;
925
926    svrCert = ss->serverCerts[kt_rsa].serverCert;
927    if (!svrCert) {
928	ssl3_DisableECCSuites(ss, ecdhe_rsa_suites);
929    }
930
931    svrCert = ss->serverCerts[kt_ecdh].serverCert;
932    if (!svrCert) {
933	ssl3_DisableECCSuites(ss, ecdh_suites);
934	ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
935    } else {
936	SECOidTag sigTag = SECOID_GetAlgorithmTag(&svrCert->signature);
937
938	switch (sigTag) {
939	case SEC_OID_PKCS1_RSA_ENCRYPTION:
940	case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
941	case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
942	case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
943	case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
944	case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
945	case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
946	case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
947	case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
948	    ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
949	    break;
950	case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
951	case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
952	case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
953	case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
954	case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
955	case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
956	case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
957	    ssl3_DisableECCSuites(ss, ecdh_rsa_suites);
958	    break;
959	default:
960	    ssl3_DisableECCSuites(ss, ecdh_suites);
961	    break;
962	}
963    }
964}
965
966/* Ask: is ANY ECC cipher suite enabled on this socket? */
967/* Order(N^2).  Yuk.  Also, this ignores export policy. */
968PRBool
969ssl3_IsECCEnabled(sslSocket * ss)
970{
971    const ssl3CipherSuite * suite;
972    PK11SlotInfo *slot;
973
974    /* make sure we can do ECC */
975    slot = PK11_GetBestSlot(CKM_ECDH1_DERIVE,  ss->pkcs11PinArg);
976    if (!slot) {
977	return PR_FALSE;
978    }
979    PK11_FreeSlot(slot);
980
981    /* make sure an ECC cipher is enabled */
982    for (suite = ecSuites; *suite; ++suite) {
983	PRBool    enabled = PR_FALSE;
984	SECStatus rv      = ssl3_CipherPrefGet(ss, *suite, &enabled);
985
986	PORT_Assert(rv == SECSuccess); /* else is coding error */
987	if (rv == SECSuccess && enabled)
988	    return PR_TRUE;
989    }
990    return PR_FALSE;
991}
992
993#define BE(n) 0, n
994
995/* Prefabricated TLS client hello extension, Elliptic Curves List,
996 * offers only 3 curves, the Suite B curves, 23-25
997 */
998static const PRUint8 suiteBECList[12] = {
999    BE(10),         /* Extension type */
1000    BE( 8),         /* octets that follow ( 3 pairs + 1 length pair) */
1001    BE( 6),         /* octets that follow ( 3 pairs) */
1002    BE(23), BE(24), BE(25)
1003};
1004
1005/* Prefabricated TLS client hello extension, Elliptic Curves List,
1006 * offers curves 1-25.
1007 */
1008static const PRUint8 tlsECList[56] = {
1009    BE(10),         /* Extension type */
1010    BE(52),         /* octets that follow (25 pairs + 1 length pair) */
1011    BE(50),         /* octets that follow (25 pairs) */
1012            BE( 1), BE( 2), BE( 3), BE( 4), BE( 5), BE( 6), BE( 7),
1013    BE( 8), BE( 9), BE(10), BE(11), BE(12), BE(13), BE(14), BE(15),
1014    BE(16), BE(17), BE(18), BE(19), BE(20), BE(21), BE(22), BE(23),
1015    BE(24), BE(25)
1016};
1017
1018static const PRUint8 ECPtFmt[6] = {
1019    BE(11),         /* Extension type */
1020    BE( 2),         /* octets that follow */
1021             1,     /* octets that follow */
1022                 0  /* uncompressed type only */
1023};
1024
1025/* This function already presumes we can do ECC, ssl_IsECCEnabled must be
1026 * called before this function. It looks to see if we have a token which
1027 * is capable of doing smaller than SuiteB curves. If the token can, we
1028 * presume the token can do the whole SSL suite of curves. If it can't we
1029 * presume the token that allowed ECC to be enabled can only do suite B
1030 * curves. */
1031static PRBool
1032ssl3_SuiteBOnly(sslSocket *ss)
1033{
1034#if 0
1035    /* look to see if we can handle certs less than 163 bits */
1036    PK11SlotInfo *slot =
1037	PK11_GetBestSlotWithAttributes(CKM_ECDH1_DERIVE, 0, 163,
1038					ss ? ss->pkcs11PinArg : NULL);
1039
1040    if (!slot) {
1041	/* nope, presume we can only do suite B */
1042	return PR_TRUE;
1043    }
1044    /* we can, presume we can do all curves */
1045    PK11_FreeSlot(slot);
1046    return PR_FALSE;
1047#else
1048    return PR_TRUE;
1049#endif
1050}
1051
1052/* Send our "canned" (precompiled) Supported Elliptic Curves extension,
1053 * which says that we support all TLS-defined named curves.
1054 */
1055PRInt32
1056ssl3_SendSupportedCurvesXtn(
1057			sslSocket * ss,
1058			PRBool      append,
1059			PRUint32    maxBytes)
1060{
1061    int ECListSize = 0;
1062    const PRUint8 *ECList = NULL;
1063
1064    if (!ss || !ssl3_IsECCEnabled(ss))
1065    	return 0;
1066
1067    if (ssl3_SuiteBOnly(ss)) {
1068	ECListSize = sizeof (suiteBECList);
1069	ECList = suiteBECList;
1070    } else {
1071	ECListSize = sizeof (tlsECList);
1072	ECList = tlsECList;
1073    }
1074
1075    if (append && maxBytes >= ECListSize) {
1076	SECStatus rv = ssl3_AppendHandshake(ss, ECList, ECListSize);
1077	if (rv != SECSuccess)
1078	    return -1;
1079	if (!ss->sec.isServer) {
1080	    TLSExtensionData *xtnData = &ss->xtnData;
1081	    xtnData->advertised[xtnData->numAdvertised++] =
1082		ssl_elliptic_curves_xtn;
1083	}
1084    }
1085    return ECListSize;
1086}
1087
1088PRInt32
1089ssl3_GetSupportedECCCurveMask(sslSocket *ss)
1090{
1091    if (ssl3_SuiteBOnly(ss)) {
1092	return SSL3_SUITE_B_SUPPORTED_CURVES_MASK;
1093    }
1094    return SSL3_ALL_SUPPORTED_CURVES_MASK;
1095}
1096
1097/* Send our "canned" (precompiled) Supported Point Formats extension,
1098 * which says that we only support uncompressed points.
1099 */
1100PRInt32
1101ssl3_SendSupportedPointFormatsXtn(
1102			sslSocket * ss,
1103			PRBool      append,
1104			PRUint32    maxBytes)
1105{
1106    if (!ss || !ssl3_IsECCEnabled(ss))
1107    	return 0;
1108    if (append && maxBytes >= (sizeof ECPtFmt)) {
1109	SECStatus rv = ssl3_AppendHandshake(ss, ECPtFmt, (sizeof ECPtFmt));
1110	if (rv != SECSuccess)
1111	    return -1;
1112	if (!ss->sec.isServer) {
1113	    TLSExtensionData *xtnData = &ss->xtnData;
1114	    xtnData->advertised[xtnData->numAdvertised++] =
1115		ssl_ec_point_formats_xtn;
1116	}
1117    }
1118    return (sizeof ECPtFmt);
1119}
1120
1121/* Just make sure that the remote client supports uncompressed points,
1122 * Since that is all we support.  Disable ECC cipher suites if it doesn't.
1123 */
1124SECStatus
1125ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type,
1126                                    SECItem *data)
1127{
1128    int i;
1129
1130    if (data->len < 2 || data->len > 255 || !data->data ||
1131        data->len != (unsigned int)data->data[0] + 1) {
1132    	/* malformed */
1133	goto loser;
1134    }
1135    for (i = data->len; --i > 0; ) {
1136    	if (data->data[i] == 0) {
1137	    /* indicate that we should send a reply */
1138	    SECStatus rv;
1139	    rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
1140			      &ssl3_SendSupportedPointFormatsXtn);
1141	    return rv;
1142	}
1143    }
1144loser:
1145    /* evil client doesn't support uncompressed */
1146    ssl3_DisableECCSuites(ss, ecSuites);
1147    return SECFailure;
1148}
1149
1150
1151#define SSL3_GET_SERVER_PUBLICKEY(sock, type) \
1152    (ss->serverCerts[type].serverKeyPair ? \
1153    ss->serverCerts[type].serverKeyPair->pubKey : NULL)
1154
1155/* Extract the TLS curve name for the public key in our EC server cert. */
1156ECName ssl3_GetSvrCertCurveName(sslSocket *ss)
1157{
1158    SECKEYPublicKey       *srvPublicKey;
1159    ECName		  ec_curve       = ec_noName;
1160
1161    srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh);
1162    if (srvPublicKey) {
1163	ec_curve = params2ecName(&srvPublicKey->u.ec.DEREncodedParams);
1164    }
1165    return ec_curve;
1166}
1167
1168/* Ensure that the curve in our server cert is one of the ones suppored
1169 * by the remote client, and disable all ECC cipher suites if not.
1170 */
1171SECStatus
1172ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
1173{
1174    PRInt32  list_len;
1175    PRUint32 peerCurves   = 0;
1176    PRUint32 mutualCurves = 0;
1177    PRUint16 svrCertCurveName;
1178
1179    if (!data->data || data->len < 4 || data->len > 65535)
1180    	goto loser;
1181    /* get the length of elliptic_curve_list */
1182    list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
1183    if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) {
1184    	/* malformed */
1185	goto loser;
1186    }
1187    /* build bit vector of peer's supported curve names */
1188    while (data->len) {
1189	PRInt32  curve_name =
1190		 ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
1191	if (curve_name > ec_noName && curve_name < ec_pastLastName) {
1192	    peerCurves |= (1U << curve_name);
1193	}
1194    }
1195    /* What curves do we support in common? */
1196    mutualCurves = ss->ssl3.hs.negotiatedECCurves &= peerCurves;
1197    if (!mutualCurves) { /* no mutually supported EC Curves */
1198    	goto loser;
1199    }
1200
1201    /* if our ECC cert doesn't use one of these supported curves,
1202     * disable ECC cipher suites that require an ECC cert.
1203     */
1204    svrCertCurveName = ssl3_GetSvrCertCurveName(ss);
1205    if (svrCertCurveName != ec_noName &&
1206        (mutualCurves & (1U << svrCertCurveName)) != 0) {
1207	return SECSuccess;
1208    }
1209    /* Our EC cert doesn't contain a mutually supported curve.
1210     * Disable all ECC cipher suites that require an EC cert
1211     */
1212    ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
1213    ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
1214    return SECFailure;
1215
1216loser:
1217    /* no common curve supported */
1218    ssl3_DisableECCSuites(ss, ecSuites);
1219    return SECFailure;
1220}
1221
1222#endif /* NSS_ENABLE_ECC */
1223