Back to index

lightning-sunbird  0.9+nobinonly
ssl3ecc.c
Go to the documentation of this file.
00001 /*
00002  * SSL3 Protocol
00003  *
00004  * ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is the Netscape security libraries.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   Dr Vipul Gupta <vipul.gupta@sun.com> and
00026  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
00027  *
00028  * Alternatively, the contents of this file may be used under the terms of
00029  * either the GNU General Public License Version 2 or later (the "GPL"), or
00030  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00031  * in which case the provisions of the GPL or the LGPL are applicable instead
00032  * of those above. If you wish to allow use of your version of this file only
00033  * under the terms of either the GPL or the LGPL, and not to allow others to
00034  * use your version of this file under the terms of the MPL, indicate your
00035  * decision by deleting the provisions above and replace them with the notice
00036  * and other provisions required by the GPL or the LGPL. If you do not delete
00037  * the provisions above, a recipient may use your version of this file under
00038  * the terms of any one of the MPL, the GPL or the LGPL.
00039  *
00040  * ***** END LICENSE BLOCK ***** */
00041 
00042 /* ECC code moved here from ssl3con.c */
00043 /* $Id: ssl3ecc.c,v 1.3.2.12 2007/06/23 01:33:33 neil.williams%sun.com Exp $ */
00044 
00045 #include "nssrenam.h"
00046 #include "nss.h"
00047 #include "cert.h"
00048 #include "ssl.h"
00049 #include "cryptohi.h"       /* for DSAU_ stuff */
00050 #include "keyhi.h"
00051 #include "secder.h"
00052 #include "secitem.h"
00053 
00054 #include "sslimpl.h"
00055 #include "sslproto.h"
00056 #include "sslerr.h"
00057 #include "prtime.h"
00058 #include "prinrval.h"
00059 #include "prerror.h"
00060 #include "pratom.h"
00061 #include "prthread.h"
00062 #include "prinit.h"
00063 
00064 #include "pk11func.h"
00065 #include "secmod.h"
00066 #include "nsslocks.h"
00067 #include "ec.h"
00068 #include "blapi.h"
00069 
00070 #include <stdio.h>
00071 
00072 #ifdef NSS_ENABLE_ECC
00073 
00074 #ifndef PK11_SETATTRS
00075 #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
00076               (x)->pValue=(v); (x)->ulValueLen = (l);
00077 #endif
00078 
00079 #define SSL_GET_SERVER_PUBLIC_KEY(sock, type) \
00080     (ss->serverCerts[type].serverKeyPair ? \
00081     ss->serverCerts[type].serverKeyPair->pubKey : NULL)
00082 
00083 #define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \
00084     ((curveName > ec_noName) && \
00085      (curveName < ec_pastLastName) && \
00086      ((1UL << curveName) & curvemsk) != 0)
00087 
00088 
00089 
00090 static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve);
00091 
00092 #define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName))
00093 
00094 /* Table containing OID tags for elliptic curves named in the
00095  * ECC-TLS IETF draft.
00096  */
00097 static const SECOidTag ecName2OIDTag[] = {
00098        0,  
00099        SEC_OID_SECG_EC_SECT163K1,  /*  1 */
00100        SEC_OID_SECG_EC_SECT163R1,  /*  2 */
00101        SEC_OID_SECG_EC_SECT163R2,  /*  3 */
00102        SEC_OID_SECG_EC_SECT193R1,  /*  4 */
00103        SEC_OID_SECG_EC_SECT193R2,  /*  5 */
00104        SEC_OID_SECG_EC_SECT233K1,  /*  6 */
00105        SEC_OID_SECG_EC_SECT233R1,  /*  7 */
00106        SEC_OID_SECG_EC_SECT239K1,  /*  8 */
00107        SEC_OID_SECG_EC_SECT283K1,  /*  9 */
00108        SEC_OID_SECG_EC_SECT283R1,  /* 10 */
00109        SEC_OID_SECG_EC_SECT409K1,  /* 11 */
00110        SEC_OID_SECG_EC_SECT409R1,  /* 12 */
00111        SEC_OID_SECG_EC_SECT571K1,  /* 13 */
00112        SEC_OID_SECG_EC_SECT571R1,  /* 14 */
00113        SEC_OID_SECG_EC_SECP160K1,  /* 15 */
00114        SEC_OID_SECG_EC_SECP160R1,  /* 16 */
00115        SEC_OID_SECG_EC_SECP160R2,  /* 17 */
00116        SEC_OID_SECG_EC_SECP192K1,  /* 18 */
00117        SEC_OID_SECG_EC_SECP192R1,  /* 19 */
00118        SEC_OID_SECG_EC_SECP224K1,  /* 20 */
00119        SEC_OID_SECG_EC_SECP224R1,  /* 21 */
00120        SEC_OID_SECG_EC_SECP256K1,  /* 22 */
00121        SEC_OID_SECG_EC_SECP256R1,  /* 23 */
00122        SEC_OID_SECG_EC_SECP384R1,  /* 24 */
00123        SEC_OID_SECG_EC_SECP521R1,  /* 25 */
00124 };
00125 
00126 static const PRUint16 curve2bits[] = {
00127          0, /*  ec_noName     = 0,   */
00128        163, /*  ec_sect163k1  = 1,   */
00129        163, /*  ec_sect163r1  = 2,   */
00130        163, /*  ec_sect163r2  = 3,   */
00131        193, /*  ec_sect193r1  = 4,   */
00132        193, /*  ec_sect193r2  = 5,   */
00133        233, /*  ec_sect233k1  = 6,   */
00134        233, /*  ec_sect233r1  = 7,   */
00135        239, /*  ec_sect239k1  = 8,   */
00136        283, /*  ec_sect283k1  = 9,   */
00137        283, /*  ec_sect283r1  = 10,  */
00138        409, /*  ec_sect409k1  = 11,  */
00139        409, /*  ec_sect409r1  = 12,  */
00140        571, /*  ec_sect571k1  = 13,  */
00141        571, /*  ec_sect571r1  = 14,  */
00142        160, /*  ec_secp160k1  = 15,  */
00143        160, /*  ec_secp160r1  = 16,  */
00144        160, /*  ec_secp160r2  = 17,  */
00145        192, /*  ec_secp192k1  = 18,  */
00146        192, /*  ec_secp192r1  = 19,  */
00147        224, /*  ec_secp224k1  = 20,  */
00148        224, /*  ec_secp224r1  = 21,  */
00149        256, /*  ec_secp256k1  = 22,  */
00150        256, /*  ec_secp256r1  = 23,  */
00151        384, /*  ec_secp384r1  = 24,  */
00152        521, /*  ec_secp521r1  = 25,  */
00153       65535  /*  ec_pastLastName      */
00154 };
00155 
00156 typedef struct Bits2CurveStr {
00157     PRUint16    bits;
00158     ECName      curve;
00159 } Bits2Curve;
00160 
00161 static const Bits2Curve bits2curve [] = {
00162    {   192,     ec_secp192r1    /*  = 19,  fast */  },
00163    {   160,     ec_secp160r2    /*  = 17,  fast */  },
00164    {   160,     ec_secp160k1    /*  = 15,  */       },
00165    {   160,     ec_secp160r1    /*  = 16,  */       },
00166    {   163,     ec_sect163k1    /*  = 1,   */       },
00167    {   163,     ec_sect163r1    /*  = 2,   */       },
00168    {   163,     ec_sect163r2    /*  = 3,   */       },
00169    {   192,     ec_secp192k1    /*  = 18,  */       },
00170    {   193,     ec_sect193r1    /*  = 4,   */       },
00171    {   193,     ec_sect193r2    /*  = 5,   */       },
00172    {   224,     ec_secp224r1    /*  = 21,  fast */  },
00173    {   224,     ec_secp224k1    /*  = 20,  */       },
00174    {   233,     ec_sect233k1    /*  = 6,   */       },
00175    {   233,     ec_sect233r1    /*  = 7,   */       },
00176    {   239,     ec_sect239k1    /*  = 8,   */       },
00177    {   256,     ec_secp256r1    /*  = 23,  fast */  },
00178    {   256,     ec_secp256k1    /*  = 22,  */       },
00179    {   283,     ec_sect283k1    /*  = 9,   */       },
00180    {   283,     ec_sect283r1    /*  = 10,  */       },
00181    {   384,     ec_secp384r1    /*  = 24,  fast */  },
00182    {   409,     ec_sect409k1    /*  = 11,  */       },
00183    {   409,     ec_sect409r1    /*  = 12,  */       },
00184    {   521,     ec_secp521r1    /*  = 25,  fast */  },
00185    {   571,     ec_sect571k1    /*  = 13,  */       },
00186    {   571,     ec_sect571r1    /*  = 14,  */       },
00187    {  65535,     ec_noName    }
00188 };
00189 
00190 typedef struct ECDHEKeyPairStr {
00191     ssl3KeyPair *  pair;
00192     int            error;  /* error code of the call-once function */
00193     PRCallOnceType once;
00194 } ECDHEKeyPair;
00195 
00196 /* arrays of ECDHE KeyPairs */
00197 static ECDHEKeyPair gECDHEKeyPairs[ec_pastLastName];
00198 
00199 SECStatus 
00200 ssl3_ECName2Params(PRArenaPool * arena, ECName curve, SECKEYECParams * params)
00201 {
00202     SECOidData *oidData = NULL;
00203 
00204     if ((curve <= ec_noName) || (curve >= ec_pastLastName) ||
00205        ((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) {
00206         PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
00207        return SECFailure;
00208     }
00209 
00210     SECITEM_AllocItem(arena, params, (2 + oidData->oid.len));
00211     /* 
00212      * params->data needs to contain the ASN encoding of an object ID (OID)
00213      * representing the named curve. The actual OID is in 
00214      * oidData->oid.data so we simply prepend 0x06 and OID length
00215      */
00216     params->data[0] = SEC_ASN1_OBJECT_ID;
00217     params->data[1] = oidData->oid.len;
00218     memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
00219 
00220     return SECSuccess;
00221 }
00222 
00223 static ECName 
00224 params2ecName(SECKEYECParams * params)
00225 {
00226     SECItem oid = { siBuffer, NULL, 0};
00227     SECOidData *oidData = NULL;
00228     ECName i;
00229 
00230     /* 
00231      * params->data needs to contain the ASN encoding of an object ID (OID)
00232      * representing a named curve. Here, we strip away everything
00233      * before the actual OID and use the OID to look up a named curve.
00234      */
00235     if (params->data[0] != SEC_ASN1_OBJECT_ID) return ec_noName;
00236     oid.len = params->len - 2;
00237     oid.data = params->data + 2;
00238     if ((oidData = SECOID_FindOID(&oid)) == NULL) return ec_noName;
00239     for (i = ec_noName + 1; i < ec_pastLastName; i++) {
00240        if (ecName2OIDTag[i] == oidData->offset)
00241            return i;
00242     }
00243 
00244     return ec_noName;
00245 }
00246 
00247 /* Caller must set hiLevel error code. */
00248 static SECStatus
00249 ssl3_ComputeECDHKeyHash(SECItem ec_params, SECItem server_ecpoint,
00250                           SSL3Random *client_rand, SSL3Random *server_rand,
00251                           SSL3Hashes *hashes, PRBool bypassPKCS11)
00252 {
00253     PRUint8     * hashBuf;
00254     PRUint8     * pBuf;
00255     SECStatus     rv               = SECSuccess;
00256     unsigned int  bufLen;
00257     /*
00258      * XXX For now, we only support named curves (the appropriate
00259      * checks are made before this method is called) so ec_params
00260      * takes up only two bytes. ECPoint needs to fit in 256 bytes
00261      * (because the spec says the length must fit in one byte)
00262      */
00263     PRUint8       buf[2*SSL3_RANDOM_LENGTH + 2 + 1 + 256];
00264 
00265     bufLen = 2*SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len;
00266     if (bufLen <= sizeof buf) {
00267        hashBuf = buf;
00268     } else {
00269        hashBuf = PORT_Alloc(bufLen);
00270        if (!hashBuf) {
00271            return SECFailure;
00272        }
00273     }
00274 
00275     memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); 
00276        pBuf = hashBuf + SSL3_RANDOM_LENGTH;
00277     memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
00278        pBuf += SSL3_RANDOM_LENGTH;
00279     memcpy(pBuf, ec_params.data, ec_params.len);
00280        pBuf += ec_params.len;
00281     pBuf[0] = (PRUint8)(server_ecpoint.len);
00282     pBuf += 1;
00283     memcpy(pBuf, server_ecpoint.data, server_ecpoint.len);
00284        pBuf += server_ecpoint.len;
00285     PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
00286 
00287     rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11);
00288 
00289     PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen));
00290     PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result", hashes->md5, MD5_LENGTH));
00291     PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH));
00292 
00293     if (hashBuf != buf && hashBuf != NULL)
00294        PORT_Free(hashBuf);
00295     return rv;
00296 }
00297 
00298 
00299 /* Called from ssl3_SendClientKeyExchange(). */
00300 SECStatus
00301 ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
00302 {
00303     PK11SymKey *     pms           = NULL;
00304     SECStatus           rv                = SECFailure;
00305     PRBool              isTLS;
00306     CK_MECHANISM_TYPE       target;
00307     SECKEYPublicKey  *pubKey = NULL;             /* Ephemeral ECDH key */
00308     SECKEYPrivateKey *privKey = NULL;     /* Ephemeral ECDH key */
00309 
00310     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
00311     PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
00312 
00313     isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
00314 
00315     /* Generate ephemeral EC keypair */
00316     if (svrPubKey->keyType != ecKey) {
00317        PORT_SetError(SEC_ERROR_BAD_KEY);
00318        goto loser;
00319     }
00320     /* XXX SHOULD CALL ssl3_CreateECDHEphemeralKeys here, instead! */
00321     privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams, 
00322                                        &pubKey, NULL);
00323     if (!privKey || !pubKey) {
00324            ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
00325            rv = SECFailure;
00326            goto loser;
00327     }
00328     PRINT_BUF(50, (ss, "ECDH public value:",
00329                                    pubKey->u.ec.publicValue.data,
00330                                    pubKey->u.ec.publicValue.len));
00331 
00332     if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
00333     else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
00334 
00335     /*  Determine the PMS */
00336     pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL,
00337                          CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
00338                          CKD_NULL, NULL, NULL);
00339 
00340     if (pms == NULL) {
00341        SSL3AlertDescription desc  = illegal_parameter;
00342        (void)SSL3_SendAlert(ss, alert_fatal, desc);
00343        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
00344        goto loser;
00345     }
00346 
00347     SECKEY_DestroyPrivateKey(privKey);
00348     privKey = NULL;
00349 
00350     rv = ssl3_InitPendingCipherSpec(ss,  pms);
00351     PK11_FreeSymKey(pms); pms = NULL;
00352 
00353     if (rv != SECSuccess) {
00354        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
00355        goto loser;
00356     }
00357 
00358     rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, 
00359                                    pubKey->u.ec.publicValue.len + 1);
00360     if (rv != SECSuccess) {
00361         goto loser;  /* err set by ssl3_AppendHandshake* */
00362     }
00363 
00364     rv = ssl3_AppendHandshakeVariable(ss, 
00365                                    pubKey->u.ec.publicValue.data,
00366                                    pubKey->u.ec.publicValue.len, 1);
00367     SECKEY_DestroyPublicKey(pubKey);
00368     pubKey = NULL;
00369 
00370     if (rv != SECSuccess) {
00371         goto loser;  /* err set by ssl3_AppendHandshake* */
00372     }
00373 
00374     rv = SECSuccess;
00375 
00376 loser:
00377     if(pms) PK11_FreeSymKey(pms);
00378     if(privKey) SECKEY_DestroyPrivateKey(privKey);
00379     if(pubKey) SECKEY_DestroyPublicKey(pubKey);
00380     return rv;
00381 }
00382 
00383 
00384 /*
00385 ** Called from ssl3_HandleClientKeyExchange()
00386 */
00387 SECStatus
00388 ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
00389                                  PRUint32 length,
00390                                      SECKEYPublicKey *srvrPubKey,
00391                                      SECKEYPrivateKey *srvrPrivKey)
00392 {
00393     PK11SymKey *      pms;
00394     SECStatus         rv;
00395     SECKEYPublicKey   clntPubKey;
00396     CK_MECHANISM_TYPE       target;
00397     PRBool isTLS;
00398 
00399     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
00400     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
00401 
00402     clntPubKey.keyType = ecKey;
00403     clntPubKey.u.ec.DEREncodedParams.len = 
00404        srvrPubKey->u.ec.DEREncodedParams.len;
00405     clntPubKey.u.ec.DEREncodedParams.data = 
00406        srvrPubKey->u.ec.DEREncodedParams.data;
00407 
00408     rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue, 
00409                                       1, &b, &length);
00410     if (rv != SECSuccess) {
00411        SEND_ALERT
00412        return SECFailure;   /* XXX Who sets the error code?? */
00413     }
00414 
00415     isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
00416 
00417     if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
00418     else target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
00419 
00420     /*  Determine the PMS */
00421     pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL,
00422                          CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
00423                          CKD_NULL, NULL, NULL);
00424 
00425     if (pms == NULL) {
00426        /* last gasp.  */
00427        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
00428        return SECFailure;
00429     }
00430 
00431     rv = ssl3_InitPendingCipherSpec(ss,  pms);
00432     PK11_FreeSymKey(pms);
00433     if (rv != SECSuccess) {
00434        SEND_ALERT
00435        return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
00436     }
00437     return SECSuccess;
00438 }
00439 
00440 ECName
00441 ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits)
00442 {
00443     int    i;
00444     
00445     for ( i = 0; bits2curve[i].curve != ec_noName; i++) {
00446        if (bits2curve[i].bits < requiredECCbits)
00447            continue;
00448        if (SSL_IS_CURVE_NEGOTIATED(curvemsk, bits2curve[i].curve)) {
00449            return bits2curve[i].curve;
00450        }
00451     }
00452     PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
00453     return ec_noName;
00454 }
00455 
00456 /* find the "weakest link".  Get strength of signature key and of sym key.
00457  * choose curve for the weakest of those two.
00458  */
00459 ECName
00460 ssl3_GetCurveNameForServerSocket(sslSocket *ss)
00461 {
00462     SECKEYPublicKey * svrPublicKey = NULL;
00463     ECName ec_curve = ec_noName;
00464     int    signatureKeyStrength = 521;
00465     int    requiredECCbits = ss->sec.secretKeyBits * 2;
00466     int    i;
00467 
00468     if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa) {
00469        svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh);
00470        if (svrPublicKey)
00471            ec_curve = params2ecName(&svrPublicKey->u.ec.DEREncodedParams);
00472        if (!SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, ec_curve)) {
00473            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
00474            return ec_noName;
00475        }
00476        signatureKeyStrength = curve2bits[ ec_curve ];
00477     } else {
00478         /* RSA is our signing cert */
00479         int serverKeyStrengthInBits;
00480  
00481         svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_rsa);
00482         if (!svrPublicKey) {
00483             PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
00484             return ec_noName;
00485         }
00486  
00487         /* currently strength in bytes */
00488         serverKeyStrengthInBits = svrPublicKey->u.rsa.modulus.len;
00489         if (svrPublicKey->u.rsa.modulus.data[0] == 0) {
00490             serverKeyStrengthInBits--;
00491         }
00492         /* convert to strength in bits */
00493         serverKeyStrengthInBits *= BPB;
00494  
00495         signatureKeyStrength =
00496            SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
00497     }
00498     if ( requiredECCbits > signatureKeyStrength ) 
00499          requiredECCbits = signatureKeyStrength;
00500 
00501     return ssl3_GetCurveWithECKeyStrength(ss->ssl3.hs.negotiatedECCurves,
00502                                      requiredECCbits);
00503 }
00504 
00505 /* function to clear out the lists */
00506 static SECStatus 
00507 ssl3_ShutdownECDHECurves(void *appData, void *nssData)
00508 {
00509     int i;
00510     ECDHEKeyPair *keyPair = &gECDHEKeyPairs[0];
00511 
00512     for (i=0; i < ec_pastLastName; i++, keyPair++) {
00513        if (keyPair->pair) {
00514            ssl3_FreeKeyPair(keyPair->pair);
00515        }
00516     }
00517     memset(gECDHEKeyPairs, 0, sizeof gECDHEKeyPairs);
00518     return SECSuccess;
00519 }
00520 
00521 static PRStatus
00522 ssl3_ECRegister(void)
00523 {
00524     SECStatus rv;
00525     rv = NSS_RegisterShutdown(ssl3_ShutdownECDHECurves, gECDHEKeyPairs);
00526     if (rv != SECSuccess) {
00527        gECDHEKeyPairs[ec_noName].error = PORT_GetError();
00528     }
00529     return (PRStatus)rv;
00530 }
00531 
00532 /* CallOnce function, called once for each named curve. */
00533 static PRStatus 
00534 ssl3_CreateECDHEphemeralKeyPair(void * arg)
00535 {
00536     SECKEYPrivateKey *    privKey  = NULL;
00537     SECKEYPublicKey *     pubKey   = NULL;
00538     ssl3KeyPair *      keyPair  = NULL;
00539     ECName                ec_curve = (ECName)arg;
00540     SECKEYECParams        ecParams = { siBuffer, NULL, 0 };
00541 
00542     PORT_Assert(gECDHEKeyPairs[ec_curve].pair == NULL);
00543 
00544     /* ok, no one has generated a global key for this curve yet, do so */
00545     if (ssl3_ECName2Params(NULL, ec_curve, &ecParams) != SECSuccess) {
00546        gECDHEKeyPairs[ec_curve].error = PORT_GetError();
00547        return PR_FAILURE;
00548     }
00549 
00550     privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL);    
00551     SECITEM_FreeItem(&ecParams, PR_FALSE);
00552 
00553     if (!privKey || !pubKey || !(keyPair = ssl3_NewKeyPair(privKey, pubKey))) {
00554        if (privKey) {
00555            SECKEY_DestroyPrivateKey(privKey);
00556        }
00557        if (pubKey) {
00558            SECKEY_DestroyPublicKey(pubKey);
00559        }
00560        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
00561        gECDHEKeyPairs[ec_curve].error = PORT_GetError();
00562        return PR_FAILURE;
00563     }
00564 
00565     gECDHEKeyPairs[ec_curve].pair = keyPair;
00566     return PR_SUCCESS;
00567 }
00568 
00569 /*
00570  * Creates the ephemeral public and private ECDH keys used by
00571  * server in ECDHE_RSA and ECDHE_ECDSA handshakes.
00572  * For now, the elliptic curve is chosen to be the same
00573  * strength as the signing certificate (ECC or RSA).
00574  * We need an API to specify the curve. This won't be a real
00575  * issue until we further develop server-side support for ECC
00576  * cipher suites.
00577  */
00578 static SECStatus
00579 ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve)
00580 {
00581     ssl3KeyPair *      keyPair        = NULL;
00582 
00583     /* if there's no global key for this curve, make one. */
00584     if (gECDHEKeyPairs[ec_curve].pair == NULL) {
00585        PRStatus status;
00586 
00587        status = PR_CallOnce(&gECDHEKeyPairs[ec_noName].once, ssl3_ECRegister);
00588         if (status != PR_SUCCESS) {
00589            PORT_SetError(gECDHEKeyPairs[ec_noName].error);
00590            return SECFailure;
00591        }
00592        status = PR_CallOnceWithArg(&gECDHEKeyPairs[ec_curve].once,
00593                                    ssl3_CreateECDHEphemeralKeyPair,
00594                                 (void *)ec_curve);
00595         if (status != PR_SUCCESS) {
00596            PORT_SetError(gECDHEKeyPairs[ec_curve].error);
00597            return SECFailure;
00598        }
00599     }
00600 
00601     keyPair = gECDHEKeyPairs[ec_curve].pair;
00602     PORT_Assert(keyPair != NULL);
00603     if (!keyPair) 
00604        return SECFailure;
00605     ss->ephemeralECDHKeyPair = ssl3_GetKeyPairRef(keyPair);
00606 
00607     return SECSuccess;
00608 }
00609 
00610 SECStatus
00611 ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
00612 {
00613     PRArenaPool *    arena     = NULL;
00614     SECKEYPublicKey *peerKey   = NULL;
00615     PRBool           isTLS;
00616     SECStatus        rv;
00617     int              errCode   = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
00618     SSL3AlertDescription desc  = illegal_parameter;
00619     SSL3Hashes       hashes;
00620     SECItem          signature = {siBuffer, NULL, 0};
00621 
00622     SECItem          ec_params = {siBuffer, NULL, 0};
00623     SECItem          ec_point  = {siBuffer, NULL, 0};
00624     unsigned char    paramBuf[3]; /* only for curve_type == named_curve */
00625 
00626     isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
00627 
00628     /* XXX This works only for named curves, revisit this when
00629      * we support generic curves.
00630      */
00631     ec_params.len  = sizeof paramBuf;
00632     ec_params.data = paramBuf;
00633     rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length);
00634     if (rv != SECSuccess) {
00635        goto loser;          /* malformed. */
00636     }
00637 
00638     /* Fail if the curve is not a named curve */
00639     if ((ec_params.data[0] != ec_type_named) || 
00640        (ec_params.data[1] != 0) ||
00641        !supportedCurve(ec_params.data[2])) {
00642            errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
00643            desc = handshake_failure;
00644            goto alert_loser;
00645     }
00646 
00647     rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);
00648     if (rv != SECSuccess) {
00649        goto loser;          /* malformed. */
00650     }
00651     /* Fail if the ec point uses compressed representation */
00652     if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
00653            errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
00654            desc = handshake_failure;
00655            goto alert_loser;
00656     }
00657 
00658     rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
00659     if (rv != SECSuccess) {
00660        goto loser;          /* malformed. */
00661     }
00662 
00663     if (length != 0) {
00664        if (isTLS)
00665            desc = decode_error;
00666        goto alert_loser;           /* malformed. */
00667     }
00668 
00669     PRINT_BUF(60, (NULL, "Server EC params", ec_params.data, 
00670        ec_params.len));
00671     PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));
00672 
00673     /* failures after this point are not malformed handshakes. */
00674     /* TLS: send decrypt_error if signature failed. */
00675     desc = isTLS ? decrypt_error : handshake_failure;
00676 
00677     /*
00678      *  check to make sure the hash is signed by right guy
00679      */
00680     rv = ssl3_ComputeECDHKeyHash(ec_params, ec_point,
00681                                   &ss->ssl3.hs.client_random,
00682                                   &ss->ssl3.hs.server_random, 
00683                                   &hashes, ss->opt.bypassPKCS11);
00684 
00685     if (rv != SECSuccess) {
00686        errCode =
00687            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
00688        goto alert_loser;
00689     }
00690     rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
00691                             isTLS, ss->pkcs11PinArg);
00692     if (rv != SECSuccess)  {
00693        errCode =
00694            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
00695        goto alert_loser;
00696     }
00697 
00698     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00699     if (arena == NULL) {
00700        goto no_memory;
00701     }
00702 
00703     ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
00704     if (peerKey == NULL) {
00705        goto no_memory;
00706     }
00707 
00708     peerKey->arena                 = arena;
00709     peerKey->keyType               = ecKey;
00710 
00711     /* set up EC parameters in peerKey */
00712     if (ssl3_ECName2Params(arena, ec_params.data[2], 
00713            &peerKey->u.ec.DEREncodedParams) != SECSuccess) {
00714        /* we should never get here since we already 
00715         * checked that we are dealing with a supported curve
00716         */
00717        errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
00718        goto alert_loser;
00719     }
00720 
00721     /* copy publicValue in peerKey */
00722     if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue,  &ec_point))
00723     {
00724        PORT_FreeArena(arena, PR_FALSE);
00725        goto no_memory;
00726     }
00727     peerKey->pkcs11Slot         = NULL;
00728     peerKey->pkcs11ID           = CK_INVALID_HANDLE;
00729 
00730     ss->sec.peerKey = peerKey;
00731     ss->ssl3.hs.ws = wait_cert_request;
00732 
00733     return SECSuccess;
00734 
00735 alert_loser:
00736     (void)SSL3_SendAlert(ss, alert_fatal, desc);
00737 loser:
00738     PORT_SetError( errCode );
00739     return SECFailure;
00740 
00741 no_memory:    /* no-memory error has already been set. */
00742     ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
00743     return SECFailure;
00744 }
00745 
00746 SECStatus
00747 ssl3_SendECDHServerKeyExchange(sslSocket *ss)
00748 {
00749 const ssl3KEADef *     kea_def     = ss->ssl3.hs.kea_def;
00750     SECStatus          rv          = SECFailure;
00751     int                length;
00752     PRBool             isTLS;
00753     SECItem            signed_hash = {siBuffer, NULL, 0};
00754     SSL3Hashes         hashes;
00755 
00756     SECKEYPublicKey *  ecdhePub;
00757     SECItem            ec_params = {siBuffer, NULL, 0};
00758     unsigned char      paramBuf[3];
00759     ECName             curve;
00760     SSL3KEAType        certIndex;
00761 
00762 
00763     /* Generate ephemeral ECDH key pair and send the public key */
00764     curve = ssl3_GetCurveNameForServerSocket(ss);
00765     if (curve == ec_noName) {
00766        goto loser;
00767     }
00768     rv = ssl3_CreateECDHEphemeralKeys(ss, curve);
00769     if (rv != SECSuccess) {
00770        goto loser;   /* err set by AppendHandshake. */
00771     }      
00772     ecdhePub = ss->ephemeralECDHKeyPair->pubKey;
00773     PORT_Assert(ecdhePub != NULL);
00774     if (!ecdhePub) {
00775        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
00776        return SECFailure;
00777     }  
00778     
00779     ec_params.len  = sizeof paramBuf;
00780     ec_params.data = paramBuf;
00781     curve = params2ecName(&ecdhePub->u.ec.DEREncodedParams);
00782     if (curve != ec_noName) {
00783        ec_params.data[0] = ec_type_named;
00784        ec_params.data[1] = 0x00;
00785        ec_params.data[2] = curve;
00786     } else {
00787        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
00788        goto loser;
00789     }         
00790 
00791     rv = ssl3_ComputeECDHKeyHash(ec_params, ecdhePub->u.ec.publicValue,
00792                                   &ss->ssl3.hs.client_random,
00793                                   &ss->ssl3.hs.server_random,
00794                                   &hashes, ss->opt.bypassPKCS11);
00795     if (rv != SECSuccess) {
00796        ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
00797        goto loser;
00798     }
00799 
00800     isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
00801 
00802     /* XXX SSLKEAType isn't really a good choice for 
00803      * indexing certificates but that's all we have
00804      * for now.
00805      */
00806     if (kea_def->kea == kea_ecdhe_rsa)
00807        certIndex = kt_rsa;
00808     else /* kea_def->kea == kea_ecdhe_ecdsa */
00809        certIndex = kt_ecdh;
00810 
00811     rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY, 
00812                       &signed_hash, isTLS);
00813     if (rv != SECSuccess) {
00814        goto loser;          /* ssl3_SignHashes has set err. */
00815     }
00816     if (signed_hash.data == NULL) {
00817        /* how can this happen and rv == SECSuccess ?? */
00818        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
00819        goto loser;
00820     }
00821 
00822     length = ec_params.len + 
00823             1 + ecdhePub->u.ec.publicValue.len + 
00824             2 + signed_hash.len;
00825 
00826     rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
00827     if (rv != SECSuccess) {
00828        goto loser;   /* err set by AppendHandshake. */
00829     }
00830 
00831     rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len);
00832     if (rv != SECSuccess) {
00833        goto loser;   /* err set by AppendHandshake. */
00834     }
00835 
00836     rv = ssl3_AppendHandshakeVariable(ss, ecdhePub->u.ec.publicValue.data,
00837                                   ecdhePub->u.ec.publicValue.len, 1);
00838     if (rv != SECSuccess) {
00839        goto loser;   /* err set by AppendHandshake. */
00840     }
00841 
00842     rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
00843                                   signed_hash.len, 2);
00844     if (rv != SECSuccess) {
00845        goto loser;   /* err set by AppendHandshake. */
00846     }
00847 
00848     PORT_Free(signed_hash.data);
00849     return SECSuccess;
00850 
00851 loser:
00852     if (signed_hash.data != NULL) 
00853        PORT_Free(signed_hash.data);
00854     return SECFailure;
00855 }
00856 
00857 /* Lists of ECC cipher suites for searching and disabling. */
00858 
00859 static const ssl3CipherSuite ecdh_suites[] = {
00860     TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
00861     TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
00862     TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
00863     TLS_ECDH_ECDSA_WITH_NULL_SHA,
00864     TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
00865     TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
00866     TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
00867     TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
00868     TLS_ECDH_RSA_WITH_NULL_SHA,
00869     TLS_ECDH_RSA_WITH_RC4_128_SHA,
00870     0 /* end of list marker */
00871 };
00872 
00873 static const ssl3CipherSuite ecdh_ecdsa_suites[] = {
00874     TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
00875     TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
00876     TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
00877     TLS_ECDH_ECDSA_WITH_NULL_SHA,
00878     TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
00879     0 /* end of list marker */
00880 };
00881 
00882 static const ssl3CipherSuite ecdh_rsa_suites[] = {
00883     TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
00884     TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
00885     TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
00886     TLS_ECDH_RSA_WITH_NULL_SHA,
00887     TLS_ECDH_RSA_WITH_RC4_128_SHA,
00888     0 /* end of list marker */
00889 };
00890 
00891 static const ssl3CipherSuite ecdhe_ecdsa_suites[] = {
00892     TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
00893     TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
00894     TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
00895     TLS_ECDHE_ECDSA_WITH_NULL_SHA,
00896     TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
00897     0 /* end of list marker */
00898 };
00899 
00900 static const ssl3CipherSuite ecdhe_rsa_suites[] = {
00901     TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
00902     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
00903     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
00904     TLS_ECDHE_RSA_WITH_NULL_SHA,
00905     TLS_ECDHE_RSA_WITH_RC4_128_SHA,
00906     0 /* end of list marker */
00907 };
00908 
00909 /* List of all ECC cipher suites */
00910 static const ssl3CipherSuite ecSuites[] = {
00911     TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
00912     TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
00913     TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
00914     TLS_ECDHE_ECDSA_WITH_NULL_SHA,
00915     TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
00916     TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
00917     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
00918     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
00919     TLS_ECDHE_RSA_WITH_NULL_SHA,
00920     TLS_ECDHE_RSA_WITH_RC4_128_SHA,
00921     TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
00922     TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
00923     TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
00924     TLS_ECDH_ECDSA_WITH_NULL_SHA,
00925     TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
00926     TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
00927     TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
00928     TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
00929     TLS_ECDH_RSA_WITH_NULL_SHA,
00930     TLS_ECDH_RSA_WITH_RC4_128_SHA,
00931     0 /* end of list marker */
00932 };
00933 
00934 /* On this socket, Disable the ECC cipher suites in the argument's list */
00935 SECStatus
00936 ssl3_DisableECCSuites(sslSocket * ss, const ssl3CipherSuite * suite)
00937 {
00938     if (!suite)
00939        suite = ecSuites;
00940     for (; *suite; ++suite) {
00941        SECStatus rv      = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
00942 
00943        PORT_Assert(rv == SECSuccess); /* else is coding error */
00944     }
00945     return SECSuccess;
00946 }
00947 
00948 /* Look at the server certs configured on this socket, and disable any
00949  * ECC cipher suites that are not supported by those certs.
00950  */
00951 void
00952 ssl3_FilterECCipherSuitesByServerCerts(sslSocket * ss)
00953 {
00954     CERTCertificate * svrCert;
00955 
00956     svrCert = ss->serverCerts[kt_rsa].serverCert;
00957     if (!svrCert) {
00958        ssl3_DisableECCSuites(ss, ecdhe_rsa_suites);
00959     }
00960 
00961     svrCert = ss->serverCerts[kt_ecdh].serverCert;
00962     if (!svrCert) {
00963        ssl3_DisableECCSuites(ss, ecdh_suites);
00964        ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
00965     } else {
00966        SECOidTag sigTag = SECOID_GetAlgorithmTag(&svrCert->signature);
00967 
00968        switch (sigTag) {
00969        case SEC_OID_PKCS1_RSA_ENCRYPTION:
00970        case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
00971        case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
00972        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
00973        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
00974        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
00975        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
00976        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
00977            ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
00978            break;
00979        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
00980        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
00981        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
00982        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
00983        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
00984        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
00985        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
00986            ssl3_DisableECCSuites(ss, ecdh_rsa_suites);
00987            break;
00988        default:
00989            ssl3_DisableECCSuites(ss, ecdh_suites);
00990            break;
00991        }
00992     }
00993 }
00994 
00995 /* Ask: is ANY ECC cipher suite enabled on this socket? */
00996 /* Order(N^2).  Yuk.  Also, this ignores export policy. */
00997 PRBool
00998 ssl3_IsECCEnabled(sslSocket * ss)
00999 {
01000     const ssl3CipherSuite * suite;
01001 
01002     for (suite = ecSuites; *suite; ++suite) {
01003        PRBool    enabled = PR_FALSE;
01004        SECStatus rv      = ssl3_CipherPrefGet(ss, *suite, &enabled);
01005 
01006        PORT_Assert(rv == SECSuccess); /* else is coding error */
01007        if (rv == SECSuccess && enabled)
01008            return PR_TRUE;
01009     }
01010     return PR_FALSE;
01011 }
01012 
01013 #define BE(n) 0, n
01014 
01015 #ifndef NSS_ECC_MORE_THAN_SUITE_B
01016 /* Prefabricated TLS client hello extension, Elliptic Curves List,
01017  * offers only 3 curves, the Suite B curves, 23-25 
01018  */
01019 static const PRUint8 EClist[12] = {
01020     BE(10),         /* Extension type */
01021     BE( 8),         /* octets that follow ( 3 pairs + 1 length pair) */
01022     BE( 6),         /* octets that follow ( 3 pairs) */
01023     BE(23), BE(24), BE(25)
01024 };
01025 #else
01026 /* Prefabricated TLS client hello extension, Elliptic Curves List,
01027  * offers curves 1-25.
01028  */
01029 static const PRUint8 EClist[56] = {
01030     BE(10),         /* Extension type */
01031     BE(52),         /* octets that follow (25 pairs + 1 length pair) */
01032     BE(50),         /* octets that follow (25 pairs) */
01033             BE( 1), BE( 2), BE( 3), BE( 4), BE( 5), BE( 6), BE( 7), 
01034     BE( 8), BE( 9), BE(10), BE(11), BE(12), BE(13), BE(14), BE(15), 
01035     BE(16), BE(17), BE(18), BE(19), BE(20), BE(21), BE(22), BE(23), 
01036     BE(24), BE(25)
01037 };
01038 #endif
01039 
01040 static const PRUint8 ECPtFmt[6] = {
01041     BE(11),         /* Extension type */
01042     BE( 2),         /* octets that follow */
01043              1,     /* octets that follow */
01044                  0  /* uncompressed type only */
01045 };
01046 
01047 /* Send our "canned" (precompiled) Supported Elliptic Curves extension,
01048  * which says that we support all TLS-defined named curves.
01049  */
01050 PRInt32
01051 ssl3_SendSupportedEllipticCurvesExtension(
01052                      sslSocket * ss,
01053                      PRBool      append,
01054                      PRUint32    maxBytes)
01055 {
01056     if (!ss || !ssl3_IsECCEnabled(ss))
01057        return 0;
01058     if (append && maxBytes >= (sizeof EClist)) {
01059        SECStatus rv = ssl3_AppendHandshake(ss, EClist, (sizeof EClist));
01060     }
01061     return (sizeof EClist);
01062 }
01063 
01064 /* Send our "canned" (precompiled) Supported Point Formats extension,
01065  * which says that we only support uncompressed points.
01066  */
01067 PRInt32
01068 ssl3_SendSupportedPointFormatsExtension(
01069                      sslSocket * ss,
01070                      PRBool      append,
01071                      PRUint32    maxBytes)
01072 {
01073     if (!ss || !ssl3_IsECCEnabled(ss))
01074        return 0;
01075     if (append && maxBytes >= (sizeof ECPtFmt)) {
01076        SECStatus rv = ssl3_AppendHandshake(ss, ECPtFmt, (sizeof ECPtFmt));
01077     }
01078     return (sizeof ECPtFmt);
01079 }
01080 
01081 /* Just make sure that the remote client supports uncompressed points,
01082  * Since that is all we support.  Disable ECC cipher suites if it doesn't.
01083  */
01084 static SECStatus
01085 ssl3_HandleSupportedPointFormatsExtension(sslSocket * ss, PRUint16 ex_type, 
01086                                           SECItem *data)
01087 {
01088     int i;
01089 
01090     if (data->len < 2 || data->len > 255 || !data->data ||
01091         data->len != (unsigned int)data->data[0] + 1) {
01092        /* malformed */
01093        goto loser;
01094     }
01095     for (i = data->len; --i > 0; ) {
01096        if (data->data[i] == 0) {
01097            /* indicate that we should send a reply */
01098            SECStatus rv;
01099            rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
01100                            &ssl3_SendSupportedPointFormatsExtension);
01101            return rv;
01102        }
01103     }
01104 loser:
01105     /* evil client doesn't support uncompressed */
01106     ssl3_DisableECCSuites(ss, ecSuites);
01107     return SECFailure;
01108 }
01109 
01110 
01111 #define SSL3_GET_SERVER_PUBLICKEY(sock, type) \
01112     (ss->serverCerts[type].serverKeyPair ? \
01113     ss->serverCerts[type].serverKeyPair->pubKey : NULL)
01114 
01115 /* Extract the TLS curve name for the public key in our EC server cert. */
01116 ECName ssl3_GetSvrCertCurveName(sslSocket *ss) 
01117 {
01118     SECKEYPublicKey       *srvPublicKey; 
01119     ECName             ec_curve       = ec_noName;
01120 
01121     srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh);
01122     if (srvPublicKey) {
01123        ec_curve = params2ecName(&srvPublicKey->u.ec.DEREncodedParams);
01124     }
01125     return ec_curve;
01126 }
01127 
01128 /* Ensure that the curve in our server cert is one of the ones suppored
01129  * by the remote client, and disable all ECC cipher suites if not.
01130  */
01131 static SECStatus
01132 ssl3_HandleSupportedEllipticCurvesExtension(sslSocket * ss, PRUint16 ex_type, 
01133                                             SECItem *data)
01134 {
01135     PRInt32  list_len;
01136     PRUint32 peerCurves   = 0;
01137     PRUint32 mutualCurves = 0;
01138     PRUint16 svrCertCurveName;
01139 
01140     if (!data->data || data->len < 4 || data->len > 65535)
01141        goto loser;
01142     /* get the length of elliptic_curve_list */
01143     list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
01144     if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) {
01145        /* malformed */
01146        goto loser;
01147     }
01148     /* build bit vector of peer's supported curve names */
01149     while (data->len) {
01150        PRInt32  curve_name = 
01151                ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
01152        if (curve_name > ec_noName && curve_name < ec_pastLastName) {
01153            peerCurves |= (1U << curve_name);
01154        }
01155     }
01156     /* What curves do we support in common? */
01157     mutualCurves = ss->ssl3.hs.negotiatedECCurves &= peerCurves;
01158     if (!mutualCurves) { /* no mutually supported EC Curves */
01159        goto loser;
01160     }
01161 
01162     /* if our ECC cert doesn't use one of these supported curves, 
01163      * disable ECC cipher suites that require an ECC cert. 
01164      */
01165     svrCertCurveName = ssl3_GetSvrCertCurveName(ss);
01166     if (svrCertCurveName != ec_noName &&
01167         (mutualCurves & (1U << svrCertCurveName)) != 0) {
01168        return SECSuccess;
01169     }
01170     /* Our EC cert doesn't contain a mutually supported curve.
01171      * Disable all ECC cipher suites that require an EC cert 
01172      */
01173     ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
01174     ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
01175     return SECFailure;
01176 
01177 loser:
01178     /* no common curve supported */
01179     ssl3_DisableECCSuites(ss, ecSuites);
01180     return SECFailure;
01181 }
01182 
01183 #endif /* NSS_ENABLE_ECC */
01184 
01185 /* Format an SNI extension, using the name from the socket's URL,
01186  * unless that name is a dotted decimal string.
01187  */
01188 PRInt32 
01189 ssl3_SendServerNameIndicationExtension(
01190                      sslSocket * ss,
01191                      PRBool      append,
01192                      PRUint32    maxBytes)
01193 {
01194     PRUint32 len, span;
01195     /* must have a hostname */
01196     if (!ss || !ss->url || !ss->url[0])
01197        return 0;
01198     /* must have at lest one character other than [0-9\.] */
01199     len  = PORT_Strlen(ss->url);
01200     span = strspn(ss->url, "0123456789.");
01201     if (len == span) {
01202        /* is a dotted decimal IP address */
01203        return 0;
01204     }
01205     if (append && maxBytes >= len + 9) {
01206        SECStatus rv;
01207        /* extension_type */
01208        rv = ssl3_AppendHandshakeNumber(ss,       0, 2); 
01209        if (rv != SECSuccess) return 0;
01210        /* length of extension_data */
01211        rv = ssl3_AppendHandshakeNumber(ss, len + 5, 2); 
01212        if (rv != SECSuccess) return 0;
01213        /* length of server_name_list */
01214        rv = ssl3_AppendHandshakeNumber(ss, len + 3, 2);
01215        if (rv != SECSuccess) return 0;
01216        /* Name Type (host_name) */
01217        rv = ssl3_AppendHandshake(ss,       "\0",    1);
01218        if (rv != SECSuccess) return 0;
01219        /* HostName (length and value) */
01220        rv = ssl3_AppendHandshakeVariable(ss, ss->url, len, 2);
01221        if (rv != SECSuccess) return 0;
01222     }
01223     return len + 9;
01224 }
01225 
01226 /* handle an incoming SNI extension, by ignoring it. */
01227 SECStatus
01228 ssl3_HandleServerNameIndicationExtension(sslSocket * ss, PRUint16 ex_type, 
01229                                          SECItem *data)
01230 {
01231     /* For now, we ignore this, as if we didn't understand it. :-)  */
01232     return SECSuccess;
01233 }
01234 
01235 /* Table of handlers for received TLS hello extensions, one per extension.
01236  * In the second generation, this table will be dynamic, and functions
01237  * will be registered here.
01238  */
01239 static const ssl3HelloExtensionHandler handlers[] = {
01240     {  0, &ssl3_HandleServerNameIndicationExtension    },
01241 #ifdef NSS_ENABLE_ECC
01242     { 10, &ssl3_HandleSupportedEllipticCurvesExtension },
01243     { 11, &ssl3_HandleSupportedPointFormatsExtension   },
01244 #endif
01245     { -1, NULL }
01246 };
01247 
01248 /* Table of functions to format TLS hello extensions, one per extension.
01249  * This static table is for the formatting of client hello extensions.
01250  * The server's table of hello senders is dynamic, in the socket struct,
01251  * and sender functions are registered there.
01252  */
01253 static const 
01254 ssl3HelloExtensionSender clientHelloSenders[MAX_EXTENSION_SENDERS] = {
01255     {  0, &ssl3_SendServerNameIndicationExtension    },
01256 #ifdef NSS_ENABLE_ECC
01257     { 10, &ssl3_SendSupportedEllipticCurvesExtension },
01258     { 11, &ssl3_SendSupportedPointFormatsExtension   },
01259 #else
01260     { -1, NULL }
01261 #endif
01262 };
01263 
01264 /* go through hello extensions in buffer "b".
01265  * For each one, find the extension handler in the table above, and 
01266  * if present, invoke that handler.  
01267  * ignore any extensions with unknown extension types.
01268  */
01269 SECStatus 
01270 ssl3_HandleClientHelloExtensions(sslSocket *ss, 
01271                                  SSL3Opaque **b, 
01272                              PRUint32 *length)
01273 {
01274     while (*length) {
01275        const ssl3HelloExtensionHandler * handler;
01276        SECStatus rv;
01277        PRInt32   extension_type;
01278        SECItem   extension_data;
01279 
01280        /* Get the extension's type field */
01281        extension_type = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
01282        if (extension_type < 0)  /* failure to decode extension_type */
01283            return SECFailure;   /* alert already sent */
01284 
01285        /* get the data for this extension, so we can pass it or skip it. */
01286        rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length);
01287        if (rv != SECSuccess)
01288            return rv;
01289 
01290        /* find extension_type in table of Client Hello Extension Handlers */
01291        for (handler = handlers; handler->ex_type >= 0; handler++) {
01292            if (handler->ex_type == extension_type)
01293                break;
01294        }
01295 
01296        /* if found,  Call this handler */
01297        if (handler->ex_type == extension_type) {
01298            rv = (*handler->ex_handler)(ss, (PRUint16)extension_type, 
01299                                                     &extension_data);
01300            /* Ignore this result */
01301            /* Essentially, treat all bad extensions as unrecognized types. */
01302        }
01303     }
01304     return SECSuccess;
01305 }
01306 
01307 /* Add a callback function to the table of senders of server hello extensions.
01308  */
01309 SECStatus 
01310 ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
01311                                     ssl3HelloExtensionSenderFunc cb)
01312 {
01313     int i;
01314     ssl3HelloExtensionSender *sender = &ss->serverExtensionSenders[0];
01315 
01316     for (i = 0; i < MAX_EXTENSION_SENDERS; ++i, ++sender) {
01317         if (!sender->ex_sender) {
01318            sender->ex_type   = ex_type;
01319            sender->ex_sender = cb;
01320            return SECSuccess;
01321        }
01322        /* detect duplicate senders */
01323        PORT_Assert(sender->ex_type != ex_type);
01324        if (sender->ex_type == ex_type) {
01325            /* duplicate */
01326            break;
01327        }
01328     }
01329     PORT_Assert(i < MAX_EXTENSION_SENDERS); /* table needs to grow */
01330     PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
01331     return SECFailure;
01332 }
01333 
01334 /* call each of the extension senders and return the accumulated length */
01335 PRInt32
01336 ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
01337                                const ssl3HelloExtensionSender *sender)
01338 {
01339     PRInt32 total_exten_len = 0;
01340     int i;
01341 
01342     if (!sender)
01343        sender = &clientHelloSenders[0];
01344 
01345     for (i = 0; i < MAX_EXTENSION_SENDERS; ++i, ++sender) {
01346        if (sender->ex_sender) {
01347            PRInt32 extLen = (*sender->ex_sender)(ss, append, maxBytes);
01348            if (extLen < 0)
01349               return -1;
01350            maxBytes        -= extLen;
01351            total_exten_len += extLen;
01352        }
01353     }
01354     return total_exten_len;
01355 }
01356