PageRenderTime 80ms CodeModel.GetById 12ms app.highlight 58ms RepoModel.GetById 2ms app.codeStats 0ms

/security/nss/lib/ssl/ssl3ecc.c

http://github.com/zpao/v8monkey
C | 1194 lines | 892 code | 149 blank | 153 comment | 185 complexity | 38834139a6ba69e68c44cd32c0334d78 MD5 | raw file
   1/*
   2 * SSL3 Protocol
   3 *
   4 * ***** BEGIN LICENSE BLOCK *****
   5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
   6 *
   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/
  11 *
  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
  15 * License.
  16 *
  17 * The Original Code is the Netscape security libraries.
  18 *
  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.
  23 *
  24 * Contributor(s):
  25 *   Dr Vipul Gupta <vipul.gupta@sun.com> and
  26 *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  27 *
  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.
  39 *
  40 * ***** END LICENSE BLOCK ***** */
  41
  42/* ECC code moved here from ssl3con.c */
  43/* $Id: ssl3ecc.c,v 1.26 2012/02/13 17:19:40 kaie%kuix.de Exp $ */
  44
  45#include "nss.h"
  46#include "cert.h"
  47#include "ssl.h"
  48#include "cryptohi.h"	/* for DSAU_ stuff */
  49#include "keyhi.h"
  50#include "secder.h"
  51#include "secitem.h"
  52
  53#include "sslimpl.h"
  54#include "sslproto.h"
  55#include "sslerr.h"
  56#include "prtime.h"
  57#include "prinrval.h"
  58#include "prerror.h"
  59#include "pratom.h"
  60#include "prthread.h"
  61#include "prinit.h"
  62
  63#include "pk11func.h"
  64#include "secmod.h"
  65#include "ec.h"
  66#include "blapi.h"
  67
  68#include <stdio.h>
  69
  70#ifdef NSS_ENABLE_ECC
  71
  72#ifndef PK11_SETATTRS
  73#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
  74		(x)->pValue=(v); (x)->ulValueLen = (l);
  75#endif
  76
  77#define SSL_GET_SERVER_PUBLIC_KEY(sock, type) \
  78    (ss->serverCerts[type].serverKeyPair ? \
  79    ss->serverCerts[type].serverKeyPair->pubKey : NULL)
  80
  81#define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \
  82    ((curveName > ec_noName) && \
  83     (curveName < ec_pastLastName) && \
  84     ((1UL << curveName) & curvemsk) != 0)
  85
  86
  87
  88static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve);
  89
  90#define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName))
  91
  92/* Table containing OID tags for elliptic curves named in the
  93 * ECC-TLS IETF draft.
  94 */
  95static const SECOidTag ecName2OIDTag[] = {
  96	0,  
  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 */
 122};
 123
 124static 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      */
 152};
 153
 154typedef struct Bits2CurveStr {
 155    PRUint16    bits;
 156    ECName      curve;
 157} Bits2Curve;
 158
 159static 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,  */       },
 185   {  65535,     ec_noName    }
 186};
 187
 188typedef struct ECDHEKeyPairStr {
 189    ssl3KeyPair *  pair;
 190    int            error;  /* error code of the call-once function */
 191    PRCallOnceType once;
 192} ECDHEKeyPair;
 193
 194/* arrays of ECDHE KeyPairs */
 195static ECDHEKeyPair gECDHEKeyPairs[ec_pastLastName];
 196
 197SECStatus 
 198ssl3_ECName2Params(PRArenaPool * arena, ECName curve, SECKEYECParams * params)
 199{
 200    SECOidData *oidData = NULL;
 201
 202    if ((curve <= ec_noName) || (curve >= ec_pastLastName) ||
 203	((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) {
 204        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
 205	return SECFailure;
 206    }
 207
 208    SECITEM_AllocItem(arena, params, (2 + oidData->oid.len));
 209    /* 
 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
 213     */
 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);
 217
 218    return SECSuccess;
 219}
 220
 221static ECName 
 222params2ecName(SECKEYECParams * params)
 223{
 224    SECItem oid = { siBuffer, NULL, 0};
 225    SECOidData *oidData = NULL;
 226    ECName i;
 227
 228    /* 
 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.
 232     */
 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)
 239	    return i;
 240    }
 241
 242    return ec_noName;
 243}
 244
 245/* Caller must set hiLevel error code. */
 246static SECStatus
 247ssl3_ComputeECDHKeyHash(SECItem ec_params, SECItem server_ecpoint,
 248			     SSL3Random *client_rand, SSL3Random *server_rand,
 249			     SSL3Hashes *hashes, PRBool bypassPKCS11)
 250{
 251    PRUint8     * hashBuf;
 252    PRUint8     * pBuf;
 253    SECStatus     rv 		= SECSuccess;
 254    unsigned int  bufLen;
 255    /*
 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)
 260     */
 261    PRUint8       buf[2*SSL3_RANDOM_LENGTH + 2 + 1 + 256];
 262
 263    bufLen = 2*SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len;
 264    if (bufLen <= sizeof buf) {
 265    	hashBuf = buf;
 266    } else {
 267    	hashBuf = PORT_Alloc(bufLen);
 268	if (!hashBuf) {
 269	    return SECFailure;
 270	}
 271    }
 272
 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);
 280    pBuf += 1;
 281    memcpy(pBuf, server_ecpoint.data, server_ecpoint.len);
 282    	pBuf += server_ecpoint.len;
 283    PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
 284
 285    rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);
 286
 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));
 290
 291    if (hashBuf != buf)
 292    	PORT_Free(hashBuf);
 293    return rv;
 294}
 295
 296
 297/* Called from ssl3_SendClientKeyExchange(). */
 298SECStatus
 299ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
 300{
 301    PK11SymKey *	pms 		= NULL;
 302    SECStatus           rv    		= SECFailure;
 303    PRBool              isTLS;
 304    CK_MECHANISM_TYPE	target;
 305    SECKEYPublicKey	*pubKey = NULL;		/* Ephemeral ECDH key */
 306    SECKEYPrivateKey	*privKey = NULL;	/* Ephemeral ECDH key */
 307
 308    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
 309    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
 310
 311    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
 312
 313    /* Generate ephemeral EC keypair */
 314    if (svrPubKey->keyType != ecKey) {
 315	PORT_SetError(SEC_ERROR_BAD_KEY);
 316	goto loser;
 317    }
 318    /* XXX SHOULD CALL ssl3_CreateECDHEphemeralKeys here, instead! */
 319    privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams, 
 320	                                &pubKey, ss->pkcs11PinArg);
 321    if (!privKey || !pubKey) {
 322	    ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
 323	    rv = SECFailure;
 324	    goto loser;
 325    }
 326    PRINT_BUF(50, (ss, "ECDH public value:",
 327					pubKey->u.ec.publicValue.data,
 328					pubKey->u.ec.publicValue.len));
 329
 330    if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
 331    else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
 332
 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);
 337
 338    if (pms == NULL) {
 339	SSL3AlertDescription desc  = illegal_parameter;
 340	(void)SSL3_SendAlert(ss, alert_fatal, desc);
 341	ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
 342	goto loser;
 343    }
 344
 345    SECKEY_DestroyPrivateKey(privKey);
 346    privKey = NULL;
 347
 348    rv = ssl3_InitPendingCipherSpec(ss,  pms);
 349    PK11_FreeSymKey(pms); pms = NULL;
 350
 351    if (rv != SECSuccess) {
 352	ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
 353	goto loser;
 354    }
 355
 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* */
 360    }
 361
 362    rv = ssl3_AppendHandshakeVariable(ss, 
 363					pubKey->u.ec.publicValue.data,
 364					pubKey->u.ec.publicValue.len, 1);
 365    SECKEY_DestroyPublicKey(pubKey);
 366    pubKey = NULL;
 367
 368    if (rv != SECSuccess) {
 369        goto loser;	/* err set by ssl3_AppendHandshake* */
 370    }
 371
 372    rv = SECSuccess;
 373
 374loser:
 375    if(pms) PK11_FreeSymKey(pms);
 376    if(privKey) SECKEY_DestroyPrivateKey(privKey);
 377    if(pubKey) SECKEY_DestroyPublicKey(pubKey);
 378    return rv;
 379}
 380
 381
 382/*
 383** Called from ssl3_HandleClientKeyExchange()
 384*/
 385SECStatus
 386ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
 387				     PRUint32 length,
 388                                     SECKEYPublicKey *srvrPubKey,
 389                                     SECKEYPrivateKey *srvrPrivKey)
 390{
 391    PK11SymKey *      pms;
 392    SECStatus         rv;
 393    SECKEYPublicKey   clntPubKey;
 394    CK_MECHANISM_TYPE	target;
 395    PRBool isTLS;
 396
 397    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
 398    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
 399
 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;
 405
 406    rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue, 
 407	                               1, &b, &length);
 408    if (rv != SECSuccess) {
 409	SEND_ALERT
 410	return SECFailure;	/* XXX Who sets the error code?? */
 411    }
 412
 413    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
 414
 415    if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
 416    else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
 417
 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);
 422
 423    if (pms == NULL) {
 424	/* last gasp.  */
 425	ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
 426	return SECFailure;
 427    }
 428
 429    rv = ssl3_InitPendingCipherSpec(ss,  pms);
 430    PK11_FreeSymKey(pms);
 431    if (rv != SECSuccess) {
 432	SEND_ALERT
 433	return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
 434    }
 435    return SECSuccess;
 436}
 437
 438ECName
 439ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits)
 440{
 441    int    i;
 442    
 443    for ( i = 0; bits2curve[i].curve != ec_noName; i++) {
 444	if (bits2curve[i].bits < requiredECCbits)
 445	    continue;
 446    	if (SSL_IS_CURVE_NEGOTIATED(curvemsk, bits2curve[i].curve)) {
 447	    return bits2curve[i].curve;
 448	}
 449    }
 450    PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
 451    return ec_noName;
 452}
 453
 454/* find the "weakest link".  Get strength of signature key and of sym key.
 455 * choose curve for the weakest of those two.
 456 */
 457ECName
 458ssl3_GetCurveNameForServerSocket(sslSocket *ss)
 459{
 460    SECKEYPublicKey * svrPublicKey = NULL;
 461    ECName ec_curve = ec_noName;
 462    int    signatureKeyStrength = 521;
 463    int    requiredECCbits = ss->sec.secretKeyBits * 2;
 464
 465    if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa) {
 466	svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh);
 467	if (svrPublicKey)
 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);
 471	    return ec_noName;
 472	}
 473	signatureKeyStrength = curve2bits[ ec_curve ];
 474    } else {
 475        /* RSA is our signing cert */
 476        int serverKeyStrengthInBits;
 477 
 478        svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_rsa);
 479        if (!svrPublicKey) {
 480            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
 481            return ec_noName;
 482        }
 483 
 484        /* currently strength in bytes */
 485        serverKeyStrengthInBits = svrPublicKey->u.rsa.modulus.len;
 486        if (svrPublicKey->u.rsa.modulus.data[0] == 0) {
 487            serverKeyStrengthInBits--;
 488        }
 489        /* convert to strength in bits */
 490        serverKeyStrengthInBits *= BPB;
 491 
 492        signatureKeyStrength =
 493	    SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
 494    }
 495    if ( requiredECCbits > signatureKeyStrength ) 
 496         requiredECCbits = signatureKeyStrength;
 497
 498    return ssl3_GetCurveWithECKeyStrength(ss->ssl3.hs.negotiatedECCurves,
 499					  requiredECCbits);
 500}
 501
 502/* function to clear out the lists */
 503static SECStatus 
 504ssl3_ShutdownECDHECurves(void *appData, void *nssData)
 505{
 506    int i;
 507    ECDHEKeyPair *keyPair = &gECDHEKeyPairs[0];
 508
 509    for (i=0; i < ec_pastLastName; i++, keyPair++) {
 510	if (keyPair->pair) {
 511	    ssl3_FreeKeyPair(keyPair->pair);
 512	}
 513    }
 514    memset(gECDHEKeyPairs, 0, sizeof gECDHEKeyPairs);
 515    return SECSuccess;
 516}
 517
 518static PRStatus
 519ssl3_ECRegister(void)
 520{
 521    SECStatus rv;
 522    rv = NSS_RegisterShutdown(ssl3_ShutdownECDHECurves, gECDHEKeyPairs);
 523    if (rv != SECSuccess) {
 524	gECDHEKeyPairs[ec_noName].error = PORT_GetError();
 525    }
 526    return (PRStatus)rv;
 527}
 528
 529/* CallOnce function, called once for each named curve. */
 530static PRStatus 
 531ssl3_CreateECDHEphemeralKeyPair(void * arg)
 532{
 533    SECKEYPrivateKey *    privKey  = NULL;
 534    SECKEYPublicKey *     pubKey   = NULL;
 535    ssl3KeyPair *	  keyPair  = NULL;
 536    ECName                ec_curve = (ECName)arg;
 537    SECKEYECParams        ecParams = { siBuffer, NULL, 0 };
 538
 539    PORT_Assert(gECDHEKeyPairs[ec_curve].pair == NULL);
 540
 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();
 544	return PR_FAILURE;
 545    }
 546
 547    privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL);    
 548    SECITEM_FreeItem(&ecParams, PR_FALSE);
 549
 550    if (!privKey || !pubKey || !(keyPair = ssl3_NewKeyPair(privKey, pubKey))) {
 551	if (privKey) {
 552	    SECKEY_DestroyPrivateKey(privKey);
 553	}
 554	if (pubKey) {
 555	    SECKEY_DestroyPublicKey(pubKey);
 556	}
 557	ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
 558	gECDHEKeyPairs[ec_curve].error = PORT_GetError();
 559	return PR_FAILURE;
 560    }
 561
 562    gECDHEKeyPairs[ec_curve].pair = keyPair;
 563    return PR_SUCCESS;
 564}
 565
 566/*
 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
 573 * cipher suites.
 574 */
 575static SECStatus
 576ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve)
 577{
 578    ssl3KeyPair *	  keyPair        = NULL;
 579
 580    /* if there's no global key for this curve, make one. */
 581    if (gECDHEKeyPairs[ec_curve].pair == NULL) {
 582	PRStatus status;
 583
 584	status = PR_CallOnce(&gECDHEKeyPairs[ec_noName].once, ssl3_ECRegister);
 585        if (status != PR_SUCCESS) {
 586	    PORT_SetError(gECDHEKeyPairs[ec_noName].error);
 587	    return SECFailure;
 588    	}
 589	status = PR_CallOnceWithArg(&gECDHEKeyPairs[ec_curve].once,
 590	                            ssl3_CreateECDHEphemeralKeyPair,
 591				    (void *)ec_curve);
 592        if (status != PR_SUCCESS) {
 593	    PORT_SetError(gECDHEKeyPairs[ec_curve].error);
 594	    return SECFailure;
 595    	}
 596    }
 597
 598    keyPair = gECDHEKeyPairs[ec_curve].pair;
 599    PORT_Assert(keyPair != NULL);
 600    if (!keyPair) 
 601    	return SECFailure;
 602    ss->ephemeralECDHKeyPair = ssl3_GetKeyPairRef(keyPair);
 603
 604    return SECSuccess;
 605}
 606
 607SECStatus
 608ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 609{
 610    PRArenaPool *    arena     = NULL;
 611    SECKEYPublicKey *peerKey   = NULL;
 612    PRBool           isTLS;
 613    SECStatus        rv;
 614    int              errCode   = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
 615    SSL3AlertDescription desc  = illegal_parameter;
 616    SSL3Hashes       hashes;
 617    SECItem          signature = {siBuffer, NULL, 0};
 618
 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 */
 622
 623    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
 624
 625    /* XXX This works only for named curves, revisit this when
 626     * we support generic curves.
 627     */
 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. */
 633    }
 634
 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;
 641	    goto alert_loser;
 642    }
 643
 644    rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);
 645    if (rv != SECSuccess) {
 646	goto loser;		/* malformed. */
 647    }
 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;
 652	    goto alert_loser;
 653    }
 654
 655    rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
 656    if (rv != SECSuccess) {
 657	goto loser;		/* malformed. */
 658    }
 659
 660    if (length != 0) {
 661	if (isTLS)
 662	    desc = decode_error;
 663	goto alert_loser;		/* malformed. */
 664    }
 665
 666    PRINT_BUF(60, (NULL, "Server EC params", ec_params.data, 
 667	ec_params.len));
 668    PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));
 669
 670    /* failures after this point are not malformed handshakes. */
 671    /* TLS: send decrypt_error if signature failed. */
 672    desc = isTLS ? decrypt_error : handshake_failure;
 673
 674    /*
 675     *  check to make sure the hash is signed by right guy
 676     */
 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);
 681
 682    if (rv != SECSuccess) {
 683	errCode =
 684	    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
 685	goto alert_loser;
 686    }
 687    rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
 688				isTLS, ss->pkcs11PinArg);
 689    if (rv != SECSuccess)  {
 690	errCode =
 691	    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
 692	goto alert_loser;
 693    }
 694
 695    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
 696    if (arena == NULL) {
 697	goto no_memory;
 698    }
 699
 700    ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
 701    if (peerKey == NULL) {
 702	goto no_memory;
 703    }
 704
 705    peerKey->arena                 = arena;
 706    peerKey->keyType               = ecKey;
 707
 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
 713	 */
 714	errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
 715	goto alert_loser;
 716    }
 717
 718    /* copy publicValue in peerKey */
 719    if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue,  &ec_point))
 720    {
 721	PORT_FreeArena(arena, PR_FALSE);
 722	goto no_memory;
 723    }
 724    peerKey->pkcs11Slot         = NULL;
 725    peerKey->pkcs11ID           = CK_INVALID_HANDLE;
 726
 727    ss->sec.peerKey = peerKey;
 728    ss->ssl3.hs.ws = wait_cert_request;
 729
 730    return SECSuccess;
 731
 732alert_loser:
 733    (void)SSL3_SendAlert(ss, alert_fatal, desc);
 734loser:
 735    PORT_SetError( errCode );
 736    return SECFailure;
 737
 738no_memory:	/* no-memory error has already been set. */
 739    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
 740    return SECFailure;
 741}
 742
 743SECStatus
 744ssl3_SendECDHServerKeyExchange(sslSocket *ss)
 745{
 746const ssl3KEADef *     kea_def     = ss->ssl3.hs.kea_def;
 747    SECStatus          rv          = SECFailure;
 748    int                length;
 749    PRBool             isTLS;
 750    SECItem            signed_hash = {siBuffer, NULL, 0};
 751    SSL3Hashes         hashes;
 752
 753    SECKEYPublicKey *  ecdhePub;
 754    SECItem            ec_params = {siBuffer, NULL, 0};
 755    unsigned char      paramBuf[3];
 756    ECName             curve;
 757    SSL3KEAType        certIndex;
 758
 759
 760    /* Generate ephemeral ECDH key pair and send the public key */
 761    curve = ssl3_GetCurveNameForServerSocket(ss);
 762    if (curve == ec_noName) {
 763    	goto loser;
 764    }
 765    rv = ssl3_CreateECDHEphemeralKeys(ss, curve);
 766    if (rv != SECSuccess) {
 767	goto loser; 	/* err set by AppendHandshake. */
 768    }	    
 769    ecdhePub = ss->ephemeralECDHKeyPair->pubKey;
 770    PORT_Assert(ecdhePub != NULL);
 771    if (!ecdhePub) {
 772	PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
 773	return SECFailure;
 774    }	
 775    
 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;
 783    } else {
 784	PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
 785	goto loser;
 786    }		
 787
 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);
 794	goto loser;
 795    }
 796
 797    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
 798
 799    /* XXX SSLKEAType isn't really a good choice for 
 800     * indexing certificates but that's all we have
 801     * for now.
 802     */
 803    if (kea_def->kea == kea_ecdhe_rsa)
 804	certIndex = kt_rsa;
 805    else /* kea_def->kea == kea_ecdhe_ecdsa */
 806	certIndex = kt_ecdh;
 807
 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. */
 812    }
 813    if (signed_hash.data == NULL) {
 814	/* how can this happen and rv == SECSuccess ?? */
 815	PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
 816	goto loser;
 817    }
 818
 819    length = ec_params.len + 
 820	     1 + ecdhePub->u.ec.publicValue.len + 
 821	     2 + signed_hash.len;
 822
 823    rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
 824    if (rv != SECSuccess) {
 825	goto loser; 	/* err set by AppendHandshake. */
 826    }
 827
 828    rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len);
 829    if (rv != SECSuccess) {
 830	goto loser; 	/* err set by AppendHandshake. */
 831    }
 832
 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. */
 837    }
 838
 839    rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
 840				      signed_hash.len, 2);
 841    if (rv != SECSuccess) {
 842	goto loser; 	/* err set by AppendHandshake. */
 843    }
 844
 845    PORT_Free(signed_hash.data);
 846    return SECSuccess;
 847
 848loser:
 849    if (signed_hash.data != NULL) 
 850    	PORT_Free(signed_hash.data);
 851    return SECFailure;
 852}
 853
 854/* Lists of ECC cipher suites for searching and disabling. */
 855
 856static 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 */
 868};
 869
 870static 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 */
 877};
 878
 879static 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 */
 886};
 887
 888static 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 */
 895};
 896
 897static 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 */
 904};
 905
 906/* List of all ECC cipher suites */
 907static 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 */
 929};
 930
 931/* On this socket, Disable the ECC cipher suites in the argument's list */
 932SECStatus
 933ssl3_DisableECCSuites(sslSocket * ss, const ssl3CipherSuite * suite)
 934{
 935    if (!suite)
 936    	suite = ecSuites;
 937    for (; *suite; ++suite) {
 938	SECStatus rv      = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
 939
 940	PORT_Assert(rv == SECSuccess); /* else is coding error */
 941    }
 942    return SECSuccess;
 943}
 944
 945/* Look at the server certs configured on this socket, and disable any
 946 * ECC cipher suites that are not supported by those certs.
 947 */
 948void
 949ssl3_FilterECCipherSuitesByServerCerts(sslSocket * ss)
 950{
 951    CERTCertificate * svrCert;
 952
 953    svrCert = ss->serverCerts[kt_rsa].serverCert;
 954    if (!svrCert) {
 955	ssl3_DisableECCSuites(ss, ecdhe_rsa_suites);
 956    }
 957
 958    svrCert = ss->serverCerts[kt_ecdh].serverCert;
 959    if (!svrCert) {
 960	ssl3_DisableECCSuites(ss, ecdh_suites);
 961	ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
 962    } else {
 963	SECOidTag sigTag = SECOID_GetAlgorithmTag(&svrCert->signature);
 964
 965	switch (sigTag) {
 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_SHA224_WITH_RSA_ENCRYPTION:
 972	case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
 973	case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
 974	case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
 975	    ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
 976	    break;
 977	case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
 978	case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
 979	case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
 980	case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
 981	case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
 982	case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
 983	case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
 984	    ssl3_DisableECCSuites(ss, ecdh_rsa_suites);
 985	    break;
 986	default:
 987	    ssl3_DisableECCSuites(ss, ecdh_suites);
 988	    break;
 989	}
 990    }
 991}
 992
 993/* Ask: is ANY ECC cipher suite enabled on this socket? */
 994/* Order(N^2).  Yuk.  Also, this ignores export policy. */
 995PRBool
 996ssl3_IsECCEnabled(sslSocket * ss)
 997{
 998    const ssl3CipherSuite * suite;
 999
1000    for (suite = ecSuites; *suite; ++suite) {
1001	PRBool    enabled = PR_FALSE;
1002	SECStatus rv      = ssl3_CipherPrefGet(ss, *suite, &enabled);
1003
1004	PORT_Assert(rv == SECSuccess); /* else is coding error */
1005	if (rv == SECSuccess && enabled)
1006	    return PR_TRUE;
1007    }
1008    return PR_FALSE;
1009}
1010
1011#define BE(n) 0, n
1012
1013#ifndef NSS_ECC_MORE_THAN_SUITE_B
1014/* Prefabricated TLS client hello extension, Elliptic Curves List,
1015 * offers only 3 curves, the Suite B curves, 23-25 
1016 */
1017static const PRUint8 EClist[12] = {
1018    BE(10),         /* Extension type */
1019    BE( 8),         /* octets that follow ( 3 pairs + 1 length pair) */
1020    BE( 6),         /* octets that follow ( 3 pairs) */
1021    BE(23), BE(24), BE(25)
1022};
1023#else
1024/* Prefabricated TLS client hello extension, Elliptic Curves List,
1025 * offers curves 1-25.
1026 */
1027static const PRUint8 EClist[56] = {
1028    BE(10),         /* Extension type */
1029    BE(52),         /* octets that follow (25 pairs + 1 length pair) */
1030    BE(50),         /* octets that follow (25 pairs) */
1031            BE( 1), BE( 2), BE( 3), BE( 4), BE( 5), BE( 6), BE( 7), 
1032    BE( 8), BE( 9), BE(10), BE(11), BE(12), BE(13), BE(14), BE(15), 
1033    BE(16), BE(17), BE(18), BE(19), BE(20), BE(21), BE(22), BE(23), 
1034    BE(24), BE(25)
1035};
1036#endif
1037
1038static const PRUint8 ECPtFmt[6] = {
1039    BE(11),         /* Extension type */
1040    BE( 2),         /* octets that follow */
1041             1,     /* octets that follow */
1042                 0  /* uncompressed type only */
1043};
1044
1045/* Send our "canned" (precompiled) Supported Elliptic Curves extension,
1046 * which says that we support all TLS-defined named curves.
1047 */
1048PRInt32
1049ssl3_SendSupportedCurvesXtn(
1050			sslSocket * ss,
1051			PRBool      append,
1052			PRUint32    maxBytes)
1053{
1054    if (!ss || !ssl3_IsECCEnabled(ss))
1055    	return 0;
1056    if (append && maxBytes >= (sizeof EClist)) {
1057	SECStatus rv = ssl3_AppendHandshake(ss, EClist, (sizeof EClist));
1058	if (rv != SECSuccess)
1059	    return -1;
1060	if (!ss->sec.isServer) {
1061	    TLSExtensionData *xtnData = &ss->xtnData;
1062	    xtnData->advertised[xtnData->numAdvertised++] =
1063		ssl_elliptic_curves_xtn;
1064	}
1065    }
1066    return (sizeof EClist);
1067}
1068
1069/* Send our "canned" (precompiled) Supported Point Formats extension,
1070 * which says that we only support uncompressed points.
1071 */
1072PRInt32
1073ssl3_SendSupportedPointFormatsXtn(
1074			sslSocket * ss,
1075			PRBool      append,
1076			PRUint32    maxBytes)
1077{
1078    if (!ss || !ssl3_IsECCEnabled(ss))
1079    	return 0;
1080    if (append && maxBytes >= (sizeof ECPtFmt)) {
1081	SECStatus rv = ssl3_AppendHandshake(ss, ECPtFmt, (sizeof ECPtFmt));
1082	if (rv != SECSuccess)
1083	    return -1;
1084	if (!ss->sec.isServer) {
1085	    TLSExtensionData *xtnData = &ss->xtnData;
1086	    xtnData->advertised[xtnData->numAdvertised++] =
1087		ssl_ec_point_formats_xtn;
1088	}
1089    }
1090    return (sizeof ECPtFmt);
1091}
1092
1093/* Just make sure that the remote client supports uncompressed points,
1094 * Since that is all we support.  Disable ECC cipher suites if it doesn't.
1095 */
1096SECStatus
1097ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type,
1098                                    SECItem *data)
1099{
1100    int i;
1101
1102    if (data->len < 2 || data->len > 255 || !data->data ||
1103        data->len != (unsigned int)data->data[0] + 1) {
1104    	/* malformed */
1105	goto loser;
1106    }
1107    for (i = data->len; --i > 0; ) {
1108    	if (data->data[i] == 0) {
1109	    /* indicate that we should send a reply */
1110	    SECStatus rv;
1111	    rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
1112			      &ssl3_SendSupportedPointFormatsXtn);
1113	    return rv;
1114	}
1115    }
1116loser:
1117    /* evil client doesn't support uncompressed */
1118    ssl3_DisableECCSuites(ss, ecSuites);
1119    return SECFailure;
1120}
1121
1122
1123#define SSL3_GET_SERVER_PUBLICKEY(sock, type) \
1124    (ss->serverCerts[type].serverKeyPair ? \
1125    ss->serverCerts[type].serverKeyPair->pubKey : NULL)
1126
1127/* Extract the TLS curve name for the public key in our EC server cert. */
1128ECName ssl3_GetSvrCertCurveName(sslSocket *ss) 
1129{
1130    SECKEYPublicKey       *srvPublicKey; 
1131    ECName		  ec_curve       = ec_noName;
1132
1133    srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh);
1134    if (srvPublicKey) {
1135	ec_curve = params2ecName(&srvPublicKey->u.ec.DEREncodedParams);
1136    }
1137    return ec_curve;
1138}
1139
1140/* Ensure that the curve in our server cert is one of the ones suppored
1141 * by the remote client, and disable all ECC cipher suites if not.
1142 */
1143SECStatus
1144ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
1145{
1146    PRInt32  list_len;
1147    PRUint32 peerCurves   = 0;
1148    PRUint32 mutualCurves = 0;
1149    PRUint16 svrCertCurveName;
1150
1151    if (!data->data || data->len < 4 || data->len > 65535)
1152    	goto loser;
1153    /* get the length of elliptic_curve_list */
1154    list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
1155    if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) {
1156    	/* malformed */
1157	goto loser;
1158    }
1159    /* build bit vector of peer's supported curve names */
1160    while (data->len) {
1161	PRInt32  curve_name = 
1162		 ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
1163	if (curve_name > ec_noName && curve_name < ec_pastLastName) {
1164	    peerCurves |= (1U << curve_name);
1165	}
1166    }
1167    /* What curves do we support in common? */
1168    mutualCurves = ss->ssl3.hs.negotiatedECCurves &= peerCurves;
1169    if (!mutualCurves) { /* no mutually supported EC Curves */
1170    	goto loser;
1171    }
1172
1173    /* if our ECC cert doesn't use one of these supported curves, 
1174     * disable ECC cipher suites that require an ECC cert. 
1175     */
1176    svrCertCurveName = ssl3_GetSvrCertCurveName(ss);
1177    if (svrCertCurveName != ec_noName &&
1178        (mutualCurves & (1U << svrCertCurveName)) != 0) {
1179	return SECSuccess;
1180    }
1181    /* Our EC cert doesn't contain a mutually supported curve.
1182     * Disable all ECC cipher suites that require an EC cert 
1183     */
1184    ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
1185    ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
1186    return SECFailure;
1187
1188loser:
1189    /* no common curve supported */
1190    ssl3_DisableECCSuites(ss, ecSuites);
1191    return SECFailure;
1192}
1193
1194#endif /* NSS_ENABLE_ECC */