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