security/nss/lib/ssl/ssl3ecc.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/ssl/ssl3ecc.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1261 @@
     1.4 +/*
     1.5 + * SSL3 Protocol
     1.6 + *
     1.7 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    1.10 +
    1.11 +/* ECC code moved here from ssl3con.c */
    1.12 +
    1.13 +#include "nss.h"
    1.14 +#include "cert.h"
    1.15 +#include "ssl.h"
    1.16 +#include "cryptohi.h"   /* for DSAU_ stuff */
    1.17 +#include "keyhi.h"
    1.18 +#include "secder.h"
    1.19 +#include "secitem.h"
    1.20 +
    1.21 +#include "sslimpl.h"
    1.22 +#include "sslproto.h"
    1.23 +#include "sslerr.h"
    1.24 +#include "prtime.h"
    1.25 +#include "prinrval.h"
    1.26 +#include "prerror.h"
    1.27 +#include "pratom.h"
    1.28 +#include "prthread.h"
    1.29 +#include "prinit.h"
    1.30 +
    1.31 +#include "pk11func.h"
    1.32 +#include "secmod.h"
    1.33 +
    1.34 +#include <stdio.h>
    1.35 +
    1.36 +#ifndef NSS_DISABLE_ECC
    1.37 +
    1.38 +#ifndef PK11_SETATTRS
    1.39 +#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
    1.40 +                (x)->pValue=(v); (x)->ulValueLen = (l);
    1.41 +#endif
    1.42 +
    1.43 +#define SSL_GET_SERVER_PUBLIC_KEY(sock, type) \
    1.44 +    (ss->serverCerts[type].serverKeyPair ? \
    1.45 +    ss->serverCerts[type].serverKeyPair->pubKey : NULL)
    1.46 +
    1.47 +#define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \
    1.48 +    ((curveName > ec_noName) && \
    1.49 +     (curveName < ec_pastLastName) && \
    1.50 +     ((1UL << curveName) & curvemsk) != 0)
    1.51 +
    1.52 +
    1.53 +
    1.54 +static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve);
    1.55 +
    1.56 +#define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName))
    1.57 +
    1.58 +/* Table containing OID tags for elliptic curves named in the
    1.59 + * ECC-TLS IETF draft.
    1.60 + */
    1.61 +static const SECOidTag ecName2OIDTag[] = {
    1.62 +        0,
    1.63 +        SEC_OID_SECG_EC_SECT163K1,  /*  1 */
    1.64 +        SEC_OID_SECG_EC_SECT163R1,  /*  2 */
    1.65 +        SEC_OID_SECG_EC_SECT163R2,  /*  3 */
    1.66 +        SEC_OID_SECG_EC_SECT193R1,  /*  4 */
    1.67 +        SEC_OID_SECG_EC_SECT193R2,  /*  5 */
    1.68 +        SEC_OID_SECG_EC_SECT233K1,  /*  6 */
    1.69 +        SEC_OID_SECG_EC_SECT233R1,  /*  7 */
    1.70 +        SEC_OID_SECG_EC_SECT239K1,  /*  8 */
    1.71 +        SEC_OID_SECG_EC_SECT283K1,  /*  9 */
    1.72 +        SEC_OID_SECG_EC_SECT283R1,  /* 10 */
    1.73 +        SEC_OID_SECG_EC_SECT409K1,  /* 11 */
    1.74 +        SEC_OID_SECG_EC_SECT409R1,  /* 12 */
    1.75 +        SEC_OID_SECG_EC_SECT571K1,  /* 13 */
    1.76 +        SEC_OID_SECG_EC_SECT571R1,  /* 14 */
    1.77 +        SEC_OID_SECG_EC_SECP160K1,  /* 15 */
    1.78 +        SEC_OID_SECG_EC_SECP160R1,  /* 16 */
    1.79 +        SEC_OID_SECG_EC_SECP160R2,  /* 17 */
    1.80 +        SEC_OID_SECG_EC_SECP192K1,  /* 18 */
    1.81 +        SEC_OID_SECG_EC_SECP192R1,  /* 19 */
    1.82 +        SEC_OID_SECG_EC_SECP224K1,  /* 20 */
    1.83 +        SEC_OID_SECG_EC_SECP224R1,  /* 21 */
    1.84 +        SEC_OID_SECG_EC_SECP256K1,  /* 22 */
    1.85 +        SEC_OID_SECG_EC_SECP256R1,  /* 23 */
    1.86 +        SEC_OID_SECG_EC_SECP384R1,  /* 24 */
    1.87 +        SEC_OID_SECG_EC_SECP521R1,  /* 25 */
    1.88 +};
    1.89 +
    1.90 +static const PRUint16 curve2bits[] = {
    1.91 +          0, /*  ec_noName     = 0,   */
    1.92 +        163, /*  ec_sect163k1  = 1,   */
    1.93 +        163, /*  ec_sect163r1  = 2,   */
    1.94 +        163, /*  ec_sect163r2  = 3,   */
    1.95 +        193, /*  ec_sect193r1  = 4,   */
    1.96 +        193, /*  ec_sect193r2  = 5,   */
    1.97 +        233, /*  ec_sect233k1  = 6,   */
    1.98 +        233, /*  ec_sect233r1  = 7,   */
    1.99 +        239, /*  ec_sect239k1  = 8,   */
   1.100 +        283, /*  ec_sect283k1  = 9,   */
   1.101 +        283, /*  ec_sect283r1  = 10,  */
   1.102 +        409, /*  ec_sect409k1  = 11,  */
   1.103 +        409, /*  ec_sect409r1  = 12,  */
   1.104 +        571, /*  ec_sect571k1  = 13,  */
   1.105 +        571, /*  ec_sect571r1  = 14,  */
   1.106 +        160, /*  ec_secp160k1  = 15,  */
   1.107 +        160, /*  ec_secp160r1  = 16,  */
   1.108 +        160, /*  ec_secp160r2  = 17,  */
   1.109 +        192, /*  ec_secp192k1  = 18,  */
   1.110 +        192, /*  ec_secp192r1  = 19,  */
   1.111 +        224, /*  ec_secp224k1  = 20,  */
   1.112 +        224, /*  ec_secp224r1  = 21,  */
   1.113 +        256, /*  ec_secp256k1  = 22,  */
   1.114 +        256, /*  ec_secp256r1  = 23,  */
   1.115 +        384, /*  ec_secp384r1  = 24,  */
   1.116 +        521, /*  ec_secp521r1  = 25,  */
   1.117 +      65535  /*  ec_pastLastName      */
   1.118 +};
   1.119 +
   1.120 +typedef struct Bits2CurveStr {
   1.121 +    PRUint16    bits;
   1.122 +    ECName      curve;
   1.123 +} Bits2Curve;
   1.124 +
   1.125 +static const Bits2Curve bits2curve [] = {
   1.126 +   {    192,     ec_secp192r1    /*  = 19,  fast */  },
   1.127 +   {    160,     ec_secp160r2    /*  = 17,  fast */  },
   1.128 +   {    160,     ec_secp160k1    /*  = 15,  */       },
   1.129 +   {    160,     ec_secp160r1    /*  = 16,  */       },
   1.130 +   {    163,     ec_sect163k1    /*  = 1,   */       },
   1.131 +   {    163,     ec_sect163r1    /*  = 2,   */       },
   1.132 +   {    163,     ec_sect163r2    /*  = 3,   */       },
   1.133 +   {    192,     ec_secp192k1    /*  = 18,  */       },
   1.134 +   {    193,     ec_sect193r1    /*  = 4,   */       },
   1.135 +   {    193,     ec_sect193r2    /*  = 5,   */       },
   1.136 +   {    224,     ec_secp224r1    /*  = 21,  fast */  },
   1.137 +   {    224,     ec_secp224k1    /*  = 20,  */       },
   1.138 +   {    233,     ec_sect233k1    /*  = 6,   */       },
   1.139 +   {    233,     ec_sect233r1    /*  = 7,   */       },
   1.140 +   {    239,     ec_sect239k1    /*  = 8,   */       },
   1.141 +   {    256,     ec_secp256r1    /*  = 23,  fast */  },
   1.142 +   {    256,     ec_secp256k1    /*  = 22,  */       },
   1.143 +   {    283,     ec_sect283k1    /*  = 9,   */       },
   1.144 +   {    283,     ec_sect283r1    /*  = 10,  */       },
   1.145 +   {    384,     ec_secp384r1    /*  = 24,  fast */  },
   1.146 +   {    409,     ec_sect409k1    /*  = 11,  */       },
   1.147 +   {    409,     ec_sect409r1    /*  = 12,  */       },
   1.148 +   {    521,     ec_secp521r1    /*  = 25,  fast */  },
   1.149 +   {    571,     ec_sect571k1    /*  = 13,  */       },
   1.150 +   {    571,     ec_sect571r1    /*  = 14,  */       },
   1.151 +   {  65535,     ec_noName    }
   1.152 +};
   1.153 +
   1.154 +typedef struct ECDHEKeyPairStr {
   1.155 +    ssl3KeyPair *  pair;
   1.156 +    int            error;  /* error code of the call-once function */
   1.157 +    PRCallOnceType once;
   1.158 +} ECDHEKeyPair;
   1.159 +
   1.160 +/* arrays of ECDHE KeyPairs */
   1.161 +static ECDHEKeyPair gECDHEKeyPairs[ec_pastLastName];
   1.162 +
   1.163 +SECStatus
   1.164 +ssl3_ECName2Params(PLArenaPool * arena, ECName curve, SECKEYECParams * params)
   1.165 +{
   1.166 +    SECOidData *oidData = NULL;
   1.167 +
   1.168 +    if ((curve <= ec_noName) || (curve >= ec_pastLastName) ||
   1.169 +        ((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) {
   1.170 +        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
   1.171 +        return SECFailure;
   1.172 +    }
   1.173 +
   1.174 +    SECITEM_AllocItem(arena, params, (2 + oidData->oid.len));
   1.175 +    /*
   1.176 +     * params->data needs to contain the ASN encoding of an object ID (OID)
   1.177 +     * representing the named curve. The actual OID is in
   1.178 +     * oidData->oid.data so we simply prepend 0x06 and OID length
   1.179 +     */
   1.180 +    params->data[0] = SEC_ASN1_OBJECT_ID;
   1.181 +    params->data[1] = oidData->oid.len;
   1.182 +    memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
   1.183 +
   1.184 +    return SECSuccess;
   1.185 +}
   1.186 +
   1.187 +static ECName
   1.188 +params2ecName(SECKEYECParams * params)
   1.189 +{
   1.190 +    SECItem oid = { siBuffer, NULL, 0};
   1.191 +    SECOidData *oidData = NULL;
   1.192 +    ECName i;
   1.193 +
   1.194 +    /*
   1.195 +     * params->data needs to contain the ASN encoding of an object ID (OID)
   1.196 +     * representing a named curve. Here, we strip away everything
   1.197 +     * before the actual OID and use the OID to look up a named curve.
   1.198 +     */
   1.199 +    if (params->data[0] != SEC_ASN1_OBJECT_ID) return ec_noName;
   1.200 +    oid.len = params->len - 2;
   1.201 +    oid.data = params->data + 2;
   1.202 +    if ((oidData = SECOID_FindOID(&oid)) == NULL) return ec_noName;
   1.203 +    for (i = ec_noName + 1; i < ec_pastLastName; i++) {
   1.204 +        if (ecName2OIDTag[i] == oidData->offset)
   1.205 +            return i;
   1.206 +    }
   1.207 +
   1.208 +    return ec_noName;
   1.209 +}
   1.210 +
   1.211 +/* Caller must set hiLevel error code. */
   1.212 +static SECStatus
   1.213 +ssl3_ComputeECDHKeyHash(SECOidTag hashAlg,
   1.214 +                        SECItem ec_params, SECItem server_ecpoint,
   1.215 +                        SSL3Random *client_rand, SSL3Random *server_rand,
   1.216 +                        SSL3Hashes *hashes, PRBool bypassPKCS11)
   1.217 +{
   1.218 +    PRUint8     * hashBuf;
   1.219 +    PRUint8     * pBuf;
   1.220 +    SECStatus     rv            = SECSuccess;
   1.221 +    unsigned int  bufLen;
   1.222 +    /*
   1.223 +     * XXX For now, we only support named curves (the appropriate
   1.224 +     * checks are made before this method is called) so ec_params
   1.225 +     * takes up only two bytes. ECPoint needs to fit in 256 bytes
   1.226 +     * (because the spec says the length must fit in one byte)
   1.227 +     */
   1.228 +    PRUint8       buf[2*SSL3_RANDOM_LENGTH + 2 + 1 + 256];
   1.229 +
   1.230 +    bufLen = 2*SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len;
   1.231 +    if (bufLen <= sizeof buf) {
   1.232 +        hashBuf = buf;
   1.233 +    } else {
   1.234 +        hashBuf = PORT_Alloc(bufLen);
   1.235 +        if (!hashBuf) {
   1.236 +            return SECFailure;
   1.237 +        }
   1.238 +    }
   1.239 +
   1.240 +    memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH);
   1.241 +        pBuf = hashBuf + SSL3_RANDOM_LENGTH;
   1.242 +    memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH);
   1.243 +        pBuf += SSL3_RANDOM_LENGTH;
   1.244 +    memcpy(pBuf, ec_params.data, ec_params.len);
   1.245 +        pBuf += ec_params.len;
   1.246 +    pBuf[0] = (PRUint8)(server_ecpoint.len);
   1.247 +    pBuf += 1;
   1.248 +    memcpy(pBuf, server_ecpoint.data, server_ecpoint.len);
   1.249 +        pBuf += server_ecpoint.len;
   1.250 +    PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen);
   1.251 +
   1.252 +    rv = ssl3_ComputeCommonKeyHash(hashAlg, hashBuf, bufLen, hashes,
   1.253 +                                   bypassPKCS11);
   1.254 +
   1.255 +    PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen));
   1.256 +    PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result",
   1.257 +              hashes->u.s.md5, MD5_LENGTH));
   1.258 +    PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result",
   1.259 +              hashes->u.s.sha, SHA1_LENGTH));
   1.260 +
   1.261 +    if (hashBuf != buf)
   1.262 +        PORT_Free(hashBuf);
   1.263 +    return rv;
   1.264 +}
   1.265 +
   1.266 +
   1.267 +/* Called from ssl3_SendClientKeyExchange(). */
   1.268 +SECStatus
   1.269 +ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
   1.270 +{
   1.271 +    PK11SymKey *        pms             = NULL;
   1.272 +    SECStatus           rv              = SECFailure;
   1.273 +    PRBool              isTLS, isTLS12;
   1.274 +    CK_MECHANISM_TYPE   target;
   1.275 +    SECKEYPublicKey     *pubKey = NULL;         /* Ephemeral ECDH key */
   1.276 +    SECKEYPrivateKey    *privKey = NULL;        /* Ephemeral ECDH key */
   1.277 +
   1.278 +    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
   1.279 +    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
   1.280 +
   1.281 +    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
   1.282 +    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
   1.283 +
   1.284 +    /* Generate ephemeral EC keypair */
   1.285 +    if (svrPubKey->keyType != ecKey) {
   1.286 +        PORT_SetError(SEC_ERROR_BAD_KEY);
   1.287 +        goto loser;
   1.288 +    }
   1.289 +    /* XXX SHOULD CALL ssl3_CreateECDHEphemeralKeys here, instead! */
   1.290 +    privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams,
   1.291 +                                        &pubKey, ss->pkcs11PinArg);
   1.292 +    if (!privKey || !pubKey) {
   1.293 +            ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
   1.294 +            rv = SECFailure;
   1.295 +            goto loser;
   1.296 +    }
   1.297 +    PRINT_BUF(50, (ss, "ECDH public value:",
   1.298 +                                        pubKey->u.ec.publicValue.data,
   1.299 +                                        pubKey->u.ec.publicValue.len));
   1.300 +
   1.301 +    if (isTLS12) {
   1.302 +        target = CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256;
   1.303 +    } else if (isTLS) {
   1.304 +        target = CKM_TLS_MASTER_KEY_DERIVE_DH;
   1.305 +    } else {
   1.306 +        target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
   1.307 +    }
   1.308 +
   1.309 +    /*  Determine the PMS */
   1.310 +    pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL,
   1.311 +                            CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
   1.312 +                            CKD_NULL, NULL, NULL);
   1.313 +
   1.314 +    if (pms == NULL) {
   1.315 +        SSL3AlertDescription desc  = illegal_parameter;
   1.316 +        (void)SSL3_SendAlert(ss, alert_fatal, desc);
   1.317 +        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
   1.318 +        goto loser;
   1.319 +    }
   1.320 +
   1.321 +    SECKEY_DestroyPrivateKey(privKey);
   1.322 +    privKey = NULL;
   1.323 +
   1.324 +    rv = ssl3_InitPendingCipherSpec(ss,  pms);
   1.325 +    PK11_FreeSymKey(pms); pms = NULL;
   1.326 +
   1.327 +    if (rv != SECSuccess) {
   1.328 +        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
   1.329 +        goto loser;
   1.330 +    }
   1.331 +
   1.332 +    rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange,
   1.333 +                                        pubKey->u.ec.publicValue.len + 1);
   1.334 +    if (rv != SECSuccess) {
   1.335 +        goto loser;     /* err set by ssl3_AppendHandshake* */
   1.336 +    }
   1.337 +
   1.338 +    rv = ssl3_AppendHandshakeVariable(ss,
   1.339 +                                        pubKey->u.ec.publicValue.data,
   1.340 +                                        pubKey->u.ec.publicValue.len, 1);
   1.341 +    SECKEY_DestroyPublicKey(pubKey);
   1.342 +    pubKey = NULL;
   1.343 +
   1.344 +    if (rv != SECSuccess) {
   1.345 +        goto loser;     /* err set by ssl3_AppendHandshake* */
   1.346 +    }
   1.347 +
   1.348 +    rv = SECSuccess;
   1.349 +
   1.350 +loser:
   1.351 +    if(pms) PK11_FreeSymKey(pms);
   1.352 +    if(privKey) SECKEY_DestroyPrivateKey(privKey);
   1.353 +    if(pubKey) SECKEY_DestroyPublicKey(pubKey);
   1.354 +    return rv;
   1.355 +}
   1.356 +
   1.357 +
   1.358 +/*
   1.359 +** Called from ssl3_HandleClientKeyExchange()
   1.360 +*/
   1.361 +SECStatus
   1.362 +ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
   1.363 +                                     PRUint32 length,
   1.364 +                                     SECKEYPublicKey *srvrPubKey,
   1.365 +                                     SECKEYPrivateKey *srvrPrivKey)
   1.366 +{
   1.367 +    PK11SymKey *      pms;
   1.368 +    SECStatus         rv;
   1.369 +    SECKEYPublicKey   clntPubKey;
   1.370 +    CK_MECHANISM_TYPE   target;
   1.371 +    PRBool isTLS, isTLS12;
   1.372 +
   1.373 +    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
   1.374 +    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
   1.375 +
   1.376 +    clntPubKey.keyType = ecKey;
   1.377 +    clntPubKey.u.ec.DEREncodedParams.len =
   1.378 +        srvrPubKey->u.ec.DEREncodedParams.len;
   1.379 +    clntPubKey.u.ec.DEREncodedParams.data =
   1.380 +        srvrPubKey->u.ec.DEREncodedParams.data;
   1.381 +
   1.382 +    rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue,
   1.383 +                                       1, &b, &length);
   1.384 +    if (rv != SECSuccess) {
   1.385 +        SEND_ALERT
   1.386 +        return SECFailure;      /* XXX Who sets the error code?? */
   1.387 +    }
   1.388 +
   1.389 +    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
   1.390 +    isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
   1.391 +
   1.392 +    if (isTLS12) {
   1.393 +        target = CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256;
   1.394 +    } else if (isTLS) {
   1.395 +        target = CKM_TLS_MASTER_KEY_DERIVE_DH;
   1.396 +    } else {
   1.397 +        target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
   1.398 +    }
   1.399 +
   1.400 +    /*  Determine the PMS */
   1.401 +    pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL,
   1.402 +                            CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
   1.403 +                            CKD_NULL, NULL, NULL);
   1.404 +
   1.405 +    if (pms == NULL) {
   1.406 +        /* last gasp.  */
   1.407 +        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
   1.408 +        return SECFailure;
   1.409 +    }
   1.410 +
   1.411 +    rv = ssl3_InitPendingCipherSpec(ss,  pms);
   1.412 +    PK11_FreeSymKey(pms);
   1.413 +    if (rv != SECSuccess) {
   1.414 +        SEND_ALERT
   1.415 +        return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
   1.416 +    }
   1.417 +    return SECSuccess;
   1.418 +}
   1.419 +
   1.420 +ECName
   1.421 +ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits)
   1.422 +{
   1.423 +    int    i;
   1.424 +
   1.425 +    for ( i = 0; bits2curve[i].curve != ec_noName; i++) {
   1.426 +        if (bits2curve[i].bits < requiredECCbits)
   1.427 +            continue;
   1.428 +        if (SSL_IS_CURVE_NEGOTIATED(curvemsk, bits2curve[i].curve)) {
   1.429 +            return bits2curve[i].curve;
   1.430 +        }
   1.431 +    }
   1.432 +    PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
   1.433 +    return ec_noName;
   1.434 +}
   1.435 +
   1.436 +/* find the "weakest link".  Get strength of signature key and of sym key.
   1.437 + * choose curve for the weakest of those two.
   1.438 + */
   1.439 +ECName
   1.440 +ssl3_GetCurveNameForServerSocket(sslSocket *ss)
   1.441 +{
   1.442 +    SECKEYPublicKey * svrPublicKey = NULL;
   1.443 +    ECName ec_curve = ec_noName;
   1.444 +    int    signatureKeyStrength = 521;
   1.445 +    int    requiredECCbits = ss->sec.secretKeyBits * 2;
   1.446 +
   1.447 +    if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa) {
   1.448 +        svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh);
   1.449 +        if (svrPublicKey)
   1.450 +            ec_curve = params2ecName(&svrPublicKey->u.ec.DEREncodedParams);
   1.451 +        if (!SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, ec_curve)) {
   1.452 +            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
   1.453 +            return ec_noName;
   1.454 +        }
   1.455 +        signatureKeyStrength = curve2bits[ ec_curve ];
   1.456 +    } else {
   1.457 +        /* RSA is our signing cert */
   1.458 +        int serverKeyStrengthInBits;
   1.459 +
   1.460 +        svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_rsa);
   1.461 +        if (!svrPublicKey) {
   1.462 +            PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
   1.463 +            return ec_noName;
   1.464 +        }
   1.465 +
   1.466 +        /* currently strength in bytes */
   1.467 +        serverKeyStrengthInBits = svrPublicKey->u.rsa.modulus.len;
   1.468 +        if (svrPublicKey->u.rsa.modulus.data[0] == 0) {
   1.469 +            serverKeyStrengthInBits--;
   1.470 +        }
   1.471 +        /* convert to strength in bits */
   1.472 +        serverKeyStrengthInBits *= BPB;
   1.473 +
   1.474 +        signatureKeyStrength =
   1.475 +            SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);
   1.476 +    }
   1.477 +    if ( requiredECCbits > signatureKeyStrength )
   1.478 +         requiredECCbits = signatureKeyStrength;
   1.479 +
   1.480 +    return ssl3_GetCurveWithECKeyStrength(ss->ssl3.hs.negotiatedECCurves,
   1.481 +                                          requiredECCbits);
   1.482 +}
   1.483 +
   1.484 +/* function to clear out the lists */
   1.485 +static SECStatus
   1.486 +ssl3_ShutdownECDHECurves(void *appData, void *nssData)
   1.487 +{
   1.488 +    int i;
   1.489 +    ECDHEKeyPair *keyPair = &gECDHEKeyPairs[0];
   1.490 +
   1.491 +    for (i=0; i < ec_pastLastName; i++, keyPair++) {
   1.492 +        if (keyPair->pair) {
   1.493 +            ssl3_FreeKeyPair(keyPair->pair);
   1.494 +        }
   1.495 +    }
   1.496 +    memset(gECDHEKeyPairs, 0, sizeof gECDHEKeyPairs);
   1.497 +    return SECSuccess;
   1.498 +}
   1.499 +
   1.500 +static PRStatus
   1.501 +ssl3_ECRegister(void)
   1.502 +{
   1.503 +    SECStatus rv;
   1.504 +    rv = NSS_RegisterShutdown(ssl3_ShutdownECDHECurves, gECDHEKeyPairs);
   1.505 +    if (rv != SECSuccess) {
   1.506 +        gECDHEKeyPairs[ec_noName].error = PORT_GetError();
   1.507 +    }
   1.508 +    return (PRStatus)rv;
   1.509 +}
   1.510 +
   1.511 +/* CallOnce function, called once for each named curve. */
   1.512 +static PRStatus
   1.513 +ssl3_CreateECDHEphemeralKeyPair(void * arg)
   1.514 +{
   1.515 +    SECKEYPrivateKey *    privKey  = NULL;
   1.516 +    SECKEYPublicKey *     pubKey   = NULL;
   1.517 +    ssl3KeyPair *         keyPair  = NULL;
   1.518 +    ECName                ec_curve = (ECName)arg;
   1.519 +    SECKEYECParams        ecParams = { siBuffer, NULL, 0 };
   1.520 +
   1.521 +    PORT_Assert(gECDHEKeyPairs[ec_curve].pair == NULL);
   1.522 +
   1.523 +    /* ok, no one has generated a global key for this curve yet, do so */
   1.524 +    if (ssl3_ECName2Params(NULL, ec_curve, &ecParams) != SECSuccess) {
   1.525 +        gECDHEKeyPairs[ec_curve].error = PORT_GetError();
   1.526 +        return PR_FAILURE;
   1.527 +    }
   1.528 +
   1.529 +    privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL);
   1.530 +    SECITEM_FreeItem(&ecParams, PR_FALSE);
   1.531 +
   1.532 +    if (!privKey || !pubKey || !(keyPair = ssl3_NewKeyPair(privKey, pubKey))) {
   1.533 +        if (privKey) {
   1.534 +            SECKEY_DestroyPrivateKey(privKey);
   1.535 +        }
   1.536 +        if (pubKey) {
   1.537 +            SECKEY_DestroyPublicKey(pubKey);
   1.538 +        }
   1.539 +        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
   1.540 +        gECDHEKeyPairs[ec_curve].error = PORT_GetError();
   1.541 +        return PR_FAILURE;
   1.542 +    }
   1.543 +
   1.544 +    gECDHEKeyPairs[ec_curve].pair = keyPair;
   1.545 +    return PR_SUCCESS;
   1.546 +}
   1.547 +
   1.548 +/*
   1.549 + * Creates the ephemeral public and private ECDH keys used by
   1.550 + * server in ECDHE_RSA and ECDHE_ECDSA handshakes.
   1.551 + * For now, the elliptic curve is chosen to be the same
   1.552 + * strength as the signing certificate (ECC or RSA).
   1.553 + * We need an API to specify the curve. This won't be a real
   1.554 + * issue until we further develop server-side support for ECC
   1.555 + * cipher suites.
   1.556 + */
   1.557 +static SECStatus
   1.558 +ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve)
   1.559 +{
   1.560 +    ssl3KeyPair *         keyPair        = NULL;
   1.561 +
   1.562 +    /* if there's no global key for this curve, make one. */
   1.563 +    if (gECDHEKeyPairs[ec_curve].pair == NULL) {
   1.564 +        PRStatus status;
   1.565 +
   1.566 +        status = PR_CallOnce(&gECDHEKeyPairs[ec_noName].once, ssl3_ECRegister);
   1.567 +        if (status != PR_SUCCESS) {
   1.568 +            PORT_SetError(gECDHEKeyPairs[ec_noName].error);
   1.569 +            return SECFailure;
   1.570 +        }
   1.571 +        status = PR_CallOnceWithArg(&gECDHEKeyPairs[ec_curve].once,
   1.572 +                                    ssl3_CreateECDHEphemeralKeyPair,
   1.573 +                                    (void *)ec_curve);
   1.574 +        if (status != PR_SUCCESS) {
   1.575 +            PORT_SetError(gECDHEKeyPairs[ec_curve].error);
   1.576 +            return SECFailure;
   1.577 +        }
   1.578 +    }
   1.579 +
   1.580 +    keyPair = gECDHEKeyPairs[ec_curve].pair;
   1.581 +    PORT_Assert(keyPair != NULL);
   1.582 +    if (!keyPair)
   1.583 +        return SECFailure;
   1.584 +    ss->ephemeralECDHKeyPair = ssl3_GetKeyPairRef(keyPair);
   1.585 +
   1.586 +    return SECSuccess;
   1.587 +}
   1.588 +
   1.589 +SECStatus
   1.590 +ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
   1.591 +{
   1.592 +    PLArenaPool *    arena     = NULL;
   1.593 +    SECKEYPublicKey *peerKey   = NULL;
   1.594 +    PRBool           isTLS, isTLS12;
   1.595 +    SECStatus        rv;
   1.596 +    int              errCode   = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH;
   1.597 +    SSL3AlertDescription desc  = illegal_parameter;
   1.598 +    SSL3Hashes       hashes;
   1.599 +    SECItem          signature = {siBuffer, NULL, 0};
   1.600 +
   1.601 +    SECItem          ec_params = {siBuffer, NULL, 0};
   1.602 +    SECItem          ec_point  = {siBuffer, NULL, 0};
   1.603 +    unsigned char    paramBuf[3]; /* only for curve_type == named_curve */
   1.604 +    SSL3SignatureAndHashAlgorithm sigAndHash;
   1.605 +
   1.606 +    sigAndHash.hashAlg = SEC_OID_UNKNOWN;
   1.607 +
   1.608 +    isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
   1.609 +    isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
   1.610 +
   1.611 +    /* XXX This works only for named curves, revisit this when
   1.612 +     * we support generic curves.
   1.613 +     */
   1.614 +    ec_params.len  = sizeof paramBuf;
   1.615 +    ec_params.data = paramBuf;
   1.616 +    rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length);
   1.617 +    if (rv != SECSuccess) {
   1.618 +        goto loser;             /* malformed. */
   1.619 +    }
   1.620 +
   1.621 +    /* Fail if the curve is not a named curve */
   1.622 +    if ((ec_params.data[0] != ec_type_named) ||
   1.623 +        (ec_params.data[1] != 0) ||
   1.624 +        !supportedCurve(ec_params.data[2])) {
   1.625 +            errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
   1.626 +            desc = handshake_failure;
   1.627 +            goto alert_loser;
   1.628 +    }
   1.629 +
   1.630 +    rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length);
   1.631 +    if (rv != SECSuccess) {
   1.632 +        goto loser;             /* malformed. */
   1.633 +    }
   1.634 +    /* Fail if the ec point uses compressed representation */
   1.635 +    if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) {
   1.636 +            errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM;
   1.637 +            desc = handshake_failure;
   1.638 +            goto alert_loser;
   1.639 +    }
   1.640 +
   1.641 +    if (isTLS12) {
   1.642 +        rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
   1.643 +                                                   &sigAndHash);
   1.644 +        if (rv != SECSuccess) {
   1.645 +            goto loser;         /* malformed or unsupported. */
   1.646 +        }
   1.647 +        rv = ssl3_CheckSignatureAndHashAlgorithmConsistency(
   1.648 +                &sigAndHash, ss->sec.peerCert);
   1.649 +        if (rv != SECSuccess) {
   1.650 +            goto loser;
   1.651 +        }
   1.652 +    }
   1.653 +
   1.654 +    rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length);
   1.655 +    if (rv != SECSuccess) {
   1.656 +        goto loser;             /* malformed. */
   1.657 +    }
   1.658 +
   1.659 +    if (length != 0) {
   1.660 +        if (isTLS)
   1.661 +            desc = decode_error;
   1.662 +        goto alert_loser;               /* malformed. */
   1.663 +    }
   1.664 +
   1.665 +    PRINT_BUF(60, (NULL, "Server EC params", ec_params.data,
   1.666 +        ec_params.len));
   1.667 +    PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len));
   1.668 +
   1.669 +    /* failures after this point are not malformed handshakes. */
   1.670 +    /* TLS: send decrypt_error if signature failed. */
   1.671 +    desc = isTLS ? decrypt_error : handshake_failure;
   1.672 +
   1.673 +    /*
   1.674 +     *  check to make sure the hash is signed by right guy
   1.675 +     */
   1.676 +    rv = ssl3_ComputeECDHKeyHash(sigAndHash.hashAlg, ec_params, ec_point,
   1.677 +                                 &ss->ssl3.hs.client_random,
   1.678 +                                 &ss->ssl3.hs.server_random,
   1.679 +                                 &hashes, ss->opt.bypassPKCS11);
   1.680 +
   1.681 +    if (rv != SECSuccess) {
   1.682 +        errCode =
   1.683 +            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
   1.684 +        goto alert_loser;
   1.685 +    }
   1.686 +    rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature,
   1.687 +                                isTLS, ss->pkcs11PinArg);
   1.688 +    if (rv != SECSuccess)  {
   1.689 +        errCode =
   1.690 +            ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
   1.691 +        goto alert_loser;
   1.692 +    }
   1.693 +
   1.694 +    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1.695 +    if (arena == NULL) {
   1.696 +        goto no_memory;
   1.697 +    }
   1.698 +
   1.699 +    ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey);
   1.700 +    if (peerKey == NULL) {
   1.701 +        goto no_memory;
   1.702 +    }
   1.703 +
   1.704 +    peerKey->arena                 = arena;
   1.705 +    peerKey->keyType               = ecKey;
   1.706 +
   1.707 +    /* set up EC parameters in peerKey */
   1.708 +    if (ssl3_ECName2Params(arena, ec_params.data[2],
   1.709 +            &peerKey->u.ec.DEREncodedParams) != SECSuccess) {
   1.710 +        /* we should never get here since we already
   1.711 +         * checked that we are dealing with a supported curve
   1.712 +         */
   1.713 +        errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE;
   1.714 +        goto alert_loser;
   1.715 +    }
   1.716 +
   1.717 +    /* copy publicValue in peerKey */
   1.718 +    if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue,  &ec_point))
   1.719 +    {
   1.720 +        PORT_FreeArena(arena, PR_FALSE);
   1.721 +        goto no_memory;
   1.722 +    }
   1.723 +    peerKey->pkcs11Slot         = NULL;
   1.724 +    peerKey->pkcs11ID           = CK_INVALID_HANDLE;
   1.725 +
   1.726 +    ss->sec.peerKey = peerKey;
   1.727 +    ss->ssl3.hs.ws = wait_cert_request;
   1.728 +
   1.729 +    return SECSuccess;
   1.730 +
   1.731 +alert_loser:
   1.732 +    (void)SSL3_SendAlert(ss, alert_fatal, desc);
   1.733 +loser:
   1.734 +    PORT_SetError( errCode );
   1.735 +    return SECFailure;
   1.736 +
   1.737 +no_memory:      /* no-memory error has already been set. */
   1.738 +    ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
   1.739 +    return SECFailure;
   1.740 +}
   1.741 +
   1.742 +SECStatus
   1.743 +ssl3_SendECDHServerKeyExchange(
   1.744 +    sslSocket *ss,
   1.745 +    const SSL3SignatureAndHashAlgorithm *sigAndHash)
   1.746 +{
   1.747 +    const ssl3KEADef * kea_def     = ss->ssl3.hs.kea_def;
   1.748 +    SECStatus          rv          = SECFailure;
   1.749 +    int                length;
   1.750 +    PRBool             isTLS, isTLS12;
   1.751 +    SECItem            signed_hash = {siBuffer, NULL, 0};
   1.752 +    SSL3Hashes         hashes;
   1.753 +
   1.754 +    SECKEYPublicKey *  ecdhePub;
   1.755 +    SECItem            ec_params = {siBuffer, NULL, 0};
   1.756 +    unsigned char      paramBuf[3];
   1.757 +    ECName             curve;
   1.758 +    SSL3KEAType        certIndex;
   1.759 +
   1.760 +    /* Generate ephemeral ECDH key pair and send the public key */
   1.761 +    curve = ssl3_GetCurveNameForServerSocket(ss);
   1.762 +    if (curve == ec_noName) {
   1.763 +        goto loser;
   1.764 +    }
   1.765 +    rv = ssl3_CreateECDHEphemeralKeys(ss, curve);
   1.766 +    if (rv != SECSuccess) {
   1.767 +        goto loser;     /* err set by AppendHandshake. */
   1.768 +    }
   1.769 +    ecdhePub = ss->ephemeralECDHKeyPair->pubKey;
   1.770 +    PORT_Assert(ecdhePub != NULL);
   1.771 +    if (!ecdhePub) {
   1.772 +        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
   1.773 +        return SECFailure;
   1.774 +    }
   1.775 +
   1.776 +    ec_params.len  = sizeof paramBuf;
   1.777 +    ec_params.data = paramBuf;
   1.778 +    curve = params2ecName(&ecdhePub->u.ec.DEREncodedParams);
   1.779 +    if (curve != ec_noName) {
   1.780 +        ec_params.data[0] = ec_type_named;
   1.781 +        ec_params.data[1] = 0x00;
   1.782 +        ec_params.data[2] = curve;
   1.783 +    } else {
   1.784 +        PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
   1.785 +        goto loser;
   1.786 +    }
   1.787 +
   1.788 +    rv = ssl3_ComputeECDHKeyHash(sigAndHash->hashAlg,
   1.789 +                                 ec_params,
   1.790 +                                 ecdhePub->u.ec.publicValue,
   1.791 +                                 &ss->ssl3.hs.client_random,
   1.792 +                                 &ss->ssl3.hs.server_random,
   1.793 +                                 &hashes, ss->opt.bypassPKCS11);
   1.794 +    if (rv != SECSuccess) {
   1.795 +        ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
   1.796 +        goto loser;
   1.797 +    }
   1.798 +
   1.799 +    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
   1.800 +    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);
   1.801 +
   1.802 +    /* XXX SSLKEAType isn't really a good choice for
   1.803 +     * indexing certificates but that's all we have
   1.804 +     * for now.
   1.805 +     */
   1.806 +    if (kea_def->kea == kea_ecdhe_rsa)
   1.807 +        certIndex = kt_rsa;
   1.808 +    else /* kea_def->kea == kea_ecdhe_ecdsa */
   1.809 +        certIndex = kt_ecdh;
   1.810 +
   1.811 +    rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY,
   1.812 +                         &signed_hash, isTLS);
   1.813 +    if (rv != SECSuccess) {
   1.814 +        goto loser;             /* ssl3_SignHashes has set err. */
   1.815 +    }
   1.816 +    if (signed_hash.data == NULL) {
   1.817 +        /* how can this happen and rv == SECSuccess ?? */
   1.818 +        PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE);
   1.819 +        goto loser;
   1.820 +    }
   1.821 +
   1.822 +    length = ec_params.len +
   1.823 +             1 + ecdhePub->u.ec.publicValue.len +
   1.824 +             (isTLS12 ? 2 : 0) + 2 + signed_hash.len;
   1.825 +
   1.826 +    rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length);
   1.827 +    if (rv != SECSuccess) {
   1.828 +        goto loser;     /* err set by AppendHandshake. */
   1.829 +    }
   1.830 +
   1.831 +    rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len);
   1.832 +    if (rv != SECSuccess) {
   1.833 +        goto loser;     /* err set by AppendHandshake. */
   1.834 +    }
   1.835 +
   1.836 +    rv = ssl3_AppendHandshakeVariable(ss, ecdhePub->u.ec.publicValue.data,
   1.837 +                                      ecdhePub->u.ec.publicValue.len, 1);
   1.838 +    if (rv != SECSuccess) {
   1.839 +        goto loser;     /* err set by AppendHandshake. */
   1.840 +    }
   1.841 +
   1.842 +    if (isTLS12) {
   1.843 +        rv = ssl3_AppendSignatureAndHashAlgorithm(ss, sigAndHash);
   1.844 +        if (rv != SECSuccess) {
   1.845 +            goto loser;         /* err set by AppendHandshake. */
   1.846 +        }
   1.847 +    }
   1.848 +
   1.849 +    rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data,
   1.850 +                                      signed_hash.len, 2);
   1.851 +    if (rv != SECSuccess) {
   1.852 +        goto loser;     /* err set by AppendHandshake. */
   1.853 +    }
   1.854 +
   1.855 +    PORT_Free(signed_hash.data);
   1.856 +    return SECSuccess;
   1.857 +
   1.858 +loser:
   1.859 +    if (signed_hash.data != NULL)
   1.860 +        PORT_Free(signed_hash.data);
   1.861 +    return SECFailure;
   1.862 +}
   1.863 +
   1.864 +/* Lists of ECC cipher suites for searching and disabling. */
   1.865 +
   1.866 +static const ssl3CipherSuite ecdh_suites[] = {
   1.867 +    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
   1.868 +    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
   1.869 +    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
   1.870 +    TLS_ECDH_ECDSA_WITH_NULL_SHA,
   1.871 +    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
   1.872 +    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
   1.873 +    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
   1.874 +    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
   1.875 +    TLS_ECDH_RSA_WITH_NULL_SHA,
   1.876 +    TLS_ECDH_RSA_WITH_RC4_128_SHA,
   1.877 +    0 /* end of list marker */
   1.878 +};
   1.879 +
   1.880 +static const ssl3CipherSuite ecdh_ecdsa_suites[] = {
   1.881 +    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
   1.882 +    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
   1.883 +    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
   1.884 +    TLS_ECDH_ECDSA_WITH_NULL_SHA,
   1.885 +    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
   1.886 +    0 /* end of list marker */
   1.887 +};
   1.888 +
   1.889 +static const ssl3CipherSuite ecdh_rsa_suites[] = {
   1.890 +    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
   1.891 +    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
   1.892 +    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
   1.893 +    TLS_ECDH_RSA_WITH_NULL_SHA,
   1.894 +    TLS_ECDH_RSA_WITH_RC4_128_SHA,
   1.895 +    0 /* end of list marker */
   1.896 +};
   1.897 +
   1.898 +static const ssl3CipherSuite ecdhe_ecdsa_suites[] = {
   1.899 +    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
   1.900 +    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
   1.901 +    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
   1.902 +    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   1.903 +    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
   1.904 +    TLS_ECDHE_ECDSA_WITH_NULL_SHA,
   1.905 +    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
   1.906 +    0 /* end of list marker */
   1.907 +};
   1.908 +
   1.909 +static const ssl3CipherSuite ecdhe_rsa_suites[] = {
   1.910 +    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
   1.911 +    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
   1.912 +    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
   1.913 +    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   1.914 +    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
   1.915 +    TLS_ECDHE_RSA_WITH_NULL_SHA,
   1.916 +    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
   1.917 +    0 /* end of list marker */
   1.918 +};
   1.919 +
   1.920 +/* List of all ECC cipher suites */
   1.921 +static const ssl3CipherSuite ecSuites[] = {
   1.922 +    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
   1.923 +    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
   1.924 +    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
   1.925 +    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   1.926 +    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
   1.927 +    TLS_ECDHE_ECDSA_WITH_NULL_SHA,
   1.928 +    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
   1.929 +    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
   1.930 +    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
   1.931 +    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
   1.932 +    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   1.933 +    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
   1.934 +    TLS_ECDHE_RSA_WITH_NULL_SHA,
   1.935 +    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
   1.936 +    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
   1.937 +    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
   1.938 +    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
   1.939 +    TLS_ECDH_ECDSA_WITH_NULL_SHA,
   1.940 +    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
   1.941 +    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
   1.942 +    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
   1.943 +    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
   1.944 +    TLS_ECDH_RSA_WITH_NULL_SHA,
   1.945 +    TLS_ECDH_RSA_WITH_RC4_128_SHA,
   1.946 +    0 /* end of list marker */
   1.947 +};
   1.948 +
   1.949 +/* On this socket, Disable the ECC cipher suites in the argument's list */
   1.950 +SECStatus
   1.951 +ssl3_DisableECCSuites(sslSocket * ss, const ssl3CipherSuite * suite)
   1.952 +{
   1.953 +    if (!suite)
   1.954 +        suite = ecSuites;
   1.955 +    for (; *suite; ++suite) {
   1.956 +        SECStatus rv      = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
   1.957 +
   1.958 +        PORT_Assert(rv == SECSuccess); /* else is coding error */
   1.959 +    }
   1.960 +    return SECSuccess;
   1.961 +}
   1.962 +
   1.963 +/* Look at the server certs configured on this socket, and disable any
   1.964 + * ECC cipher suites that are not supported by those certs.
   1.965 + */
   1.966 +void
   1.967 +ssl3_FilterECCipherSuitesByServerCerts(sslSocket * ss)
   1.968 +{
   1.969 +    CERTCertificate * svrCert;
   1.970 +
   1.971 +    svrCert = ss->serverCerts[kt_rsa].serverCert;
   1.972 +    if (!svrCert) {
   1.973 +        ssl3_DisableECCSuites(ss, ecdhe_rsa_suites);
   1.974 +    }
   1.975 +
   1.976 +    svrCert = ss->serverCerts[kt_ecdh].serverCert;
   1.977 +    if (!svrCert) {
   1.978 +        ssl3_DisableECCSuites(ss, ecdh_suites);
   1.979 +        ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
   1.980 +    } else {
   1.981 +        SECOidTag sigTag = SECOID_GetAlgorithmTag(&svrCert->signature);
   1.982 +
   1.983 +        switch (sigTag) {
   1.984 +        case SEC_OID_PKCS1_RSA_ENCRYPTION:
   1.985 +        case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
   1.986 +        case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
   1.987 +        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
   1.988 +        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
   1.989 +        case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
   1.990 +        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
   1.991 +        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
   1.992 +        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
   1.993 +            ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
   1.994 +            break;
   1.995 +        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
   1.996 +        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
   1.997 +        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
   1.998 +        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
   1.999 +        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
  1.1000 +        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
  1.1001 +        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
  1.1002 +            ssl3_DisableECCSuites(ss, ecdh_rsa_suites);
  1.1003 +            break;
  1.1004 +        default:
  1.1005 +            ssl3_DisableECCSuites(ss, ecdh_suites);
  1.1006 +            break;
  1.1007 +        }
  1.1008 +    }
  1.1009 +}
  1.1010 +
  1.1011 +/* Ask: is ANY ECC cipher suite enabled on this socket? */
  1.1012 +/* Order(N^2).  Yuk.  Also, this ignores export policy. */
  1.1013 +PRBool
  1.1014 +ssl3_IsECCEnabled(sslSocket * ss)
  1.1015 +{
  1.1016 +    const ssl3CipherSuite * suite;
  1.1017 +    PK11SlotInfo *slot;
  1.1018 +
  1.1019 +    /* make sure we can do ECC */
  1.1020 +    slot = PK11_GetBestSlot(CKM_ECDH1_DERIVE,  ss->pkcs11PinArg);
  1.1021 +    if (!slot) {
  1.1022 +        return PR_FALSE;
  1.1023 +    }
  1.1024 +    PK11_FreeSlot(slot);
  1.1025 +
  1.1026 +    /* make sure an ECC cipher is enabled */
  1.1027 +    for (suite = ecSuites; *suite; ++suite) {
  1.1028 +        PRBool    enabled = PR_FALSE;
  1.1029 +        SECStatus rv      = ssl3_CipherPrefGet(ss, *suite, &enabled);
  1.1030 +
  1.1031 +        PORT_Assert(rv == SECSuccess); /* else is coding error */
  1.1032 +        if (rv == SECSuccess && enabled)
  1.1033 +            return PR_TRUE;
  1.1034 +    }
  1.1035 +    return PR_FALSE;
  1.1036 +}
  1.1037 +
  1.1038 +#define BE(n) 0, n
  1.1039 +
  1.1040 +/* Prefabricated TLS client hello extension, Elliptic Curves List,
  1.1041 + * offers only 3 curves, the Suite B curves, 23-25
  1.1042 + */
  1.1043 +static const PRUint8 suiteBECList[12] = {
  1.1044 +    BE(10),         /* Extension type */
  1.1045 +    BE( 8),         /* octets that follow ( 3 pairs + 1 length pair) */
  1.1046 +    BE( 6),         /* octets that follow ( 3 pairs) */
  1.1047 +    BE(23), BE(24), BE(25)
  1.1048 +};
  1.1049 +
  1.1050 +/* Prefabricated TLS client hello extension, Elliptic Curves List,
  1.1051 + * offers curves 1-25.
  1.1052 + */
  1.1053 +static const PRUint8 tlsECList[56] = {
  1.1054 +    BE(10),         /* Extension type */
  1.1055 +    BE(52),         /* octets that follow (25 pairs + 1 length pair) */
  1.1056 +    BE(50),         /* octets that follow (25 pairs) */
  1.1057 +            BE( 1), BE( 2), BE( 3), BE( 4), BE( 5), BE( 6), BE( 7),
  1.1058 +    BE( 8), BE( 9), BE(10), BE(11), BE(12), BE(13), BE(14), BE(15),
  1.1059 +    BE(16), BE(17), BE(18), BE(19), BE(20), BE(21), BE(22), BE(23),
  1.1060 +    BE(24), BE(25)
  1.1061 +};
  1.1062 +
  1.1063 +static const PRUint8 ecPtFmt[6] = {
  1.1064 +    BE(11),         /* Extension type */
  1.1065 +    BE( 2),         /* octets that follow */
  1.1066 +             1,     /* octets that follow */
  1.1067 +                 0  /* uncompressed type only */
  1.1068 +};
  1.1069 +
  1.1070 +/* This function already presumes we can do ECC, ssl3_IsECCEnabled must be
  1.1071 + * called before this function. It looks to see if we have a token which
  1.1072 + * is capable of doing smaller than SuiteB curves. If the token can, we
  1.1073 + * presume the token can do the whole SSL suite of curves. If it can't we
  1.1074 + * presume the token that allowed ECC to be enabled can only do suite B
  1.1075 + * curves. */
  1.1076 +static PRBool
  1.1077 +ssl3_SuiteBOnly(sslSocket *ss)
  1.1078 +{
  1.1079 +    /* See if we can support small curves (like 163). If not, assume we can
  1.1080 +     * only support Suite-B curves (P-256, P-384, P-521). */
  1.1081 +    PK11SlotInfo *slot =
  1.1082 +        PK11_GetBestSlotWithAttributes(CKM_ECDH1_DERIVE, 0, 163,
  1.1083 +                                       ss ? ss->pkcs11PinArg : NULL);
  1.1084 +
  1.1085 +    if (!slot) {
  1.1086 +        /* nope, presume we can only do suite B */
  1.1087 +        return PR_TRUE;
  1.1088 +    }
  1.1089 +    /* we can, presume we can do all curves */
  1.1090 +    PK11_FreeSlot(slot);
  1.1091 +    return PR_FALSE;
  1.1092 +}
  1.1093 +
  1.1094 +/* Send our "canned" (precompiled) Supported Elliptic Curves extension,
  1.1095 + * which says that we support all TLS-defined named curves.
  1.1096 + */
  1.1097 +PRInt32
  1.1098 +ssl3_SendSupportedCurvesXtn(
  1.1099 +                        sslSocket * ss,
  1.1100 +                        PRBool      append,
  1.1101 +                        PRUint32    maxBytes)
  1.1102 +{
  1.1103 +    PRInt32 ecListSize = 0;
  1.1104 +    const PRUint8 *ecList = NULL;
  1.1105 +
  1.1106 +    if (!ss || !ssl3_IsECCEnabled(ss))
  1.1107 +        return 0;
  1.1108 +
  1.1109 +    if (ssl3_SuiteBOnly(ss)) {
  1.1110 +        ecListSize = sizeof suiteBECList;
  1.1111 +        ecList = suiteBECList;
  1.1112 +    } else {
  1.1113 +        ecListSize = sizeof tlsECList;
  1.1114 +        ecList = tlsECList;
  1.1115 +    }
  1.1116 +
  1.1117 +    if (append && maxBytes >= ecListSize) {
  1.1118 +        SECStatus rv = ssl3_AppendHandshake(ss, ecList, ecListSize);
  1.1119 +        if (rv != SECSuccess)
  1.1120 +            return -1;
  1.1121 +        if (!ss->sec.isServer) {
  1.1122 +            TLSExtensionData *xtnData = &ss->xtnData;
  1.1123 +            xtnData->advertised[xtnData->numAdvertised++] =
  1.1124 +                ssl_elliptic_curves_xtn;
  1.1125 +        }
  1.1126 +    }
  1.1127 +    return ecListSize;
  1.1128 +}
  1.1129 +
  1.1130 +PRUint32
  1.1131 +ssl3_GetSupportedECCurveMask(sslSocket *ss)
  1.1132 +{
  1.1133 +    if (ssl3_SuiteBOnly(ss)) {
  1.1134 +        return SSL3_SUITE_B_SUPPORTED_CURVES_MASK;
  1.1135 +    }
  1.1136 +    return SSL3_ALL_SUPPORTED_CURVES_MASK;
  1.1137 +}
  1.1138 +
  1.1139 +/* Send our "canned" (precompiled) Supported Point Formats extension,
  1.1140 + * which says that we only support uncompressed points.
  1.1141 + */
  1.1142 +PRInt32
  1.1143 +ssl3_SendSupportedPointFormatsXtn(
  1.1144 +                        sslSocket * ss,
  1.1145 +                        PRBool      append,
  1.1146 +                        PRUint32    maxBytes)
  1.1147 +{
  1.1148 +    if (!ss || !ssl3_IsECCEnabled(ss))
  1.1149 +        return 0;
  1.1150 +    if (append && maxBytes >= (sizeof ecPtFmt)) {
  1.1151 +        SECStatus rv = ssl3_AppendHandshake(ss, ecPtFmt, (sizeof ecPtFmt));
  1.1152 +        if (rv != SECSuccess)
  1.1153 +            return -1;
  1.1154 +        if (!ss->sec.isServer) {
  1.1155 +            TLSExtensionData *xtnData = &ss->xtnData;
  1.1156 +            xtnData->advertised[xtnData->numAdvertised++] =
  1.1157 +                ssl_ec_point_formats_xtn;
  1.1158 +        }
  1.1159 +    }
  1.1160 +    return (sizeof ecPtFmt);
  1.1161 +}
  1.1162 +
  1.1163 +/* Just make sure that the remote client supports uncompressed points,
  1.1164 + * Since that is all we support.  Disable ECC cipher suites if it doesn't.
  1.1165 + */
  1.1166 +SECStatus
  1.1167 +ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type,
  1.1168 +                                    SECItem *data)
  1.1169 +{
  1.1170 +    int i;
  1.1171 +
  1.1172 +    if (data->len < 2 || data->len > 255 || !data->data ||
  1.1173 +        data->len != (unsigned int)data->data[0] + 1) {
  1.1174 +        /* malformed */
  1.1175 +        goto loser;
  1.1176 +    }
  1.1177 +    for (i = data->len; --i > 0; ) {
  1.1178 +        if (data->data[i] == 0) {
  1.1179 +            /* indicate that we should send a reply */
  1.1180 +            SECStatus rv;
  1.1181 +            rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
  1.1182 +                              &ssl3_SendSupportedPointFormatsXtn);
  1.1183 +            return rv;
  1.1184 +        }
  1.1185 +    }
  1.1186 +loser:
  1.1187 +    /* evil client doesn't support uncompressed */
  1.1188 +    ssl3_DisableECCSuites(ss, ecSuites);
  1.1189 +    return SECFailure;
  1.1190 +}
  1.1191 +
  1.1192 +
  1.1193 +#define SSL3_GET_SERVER_PUBLICKEY(sock, type) \
  1.1194 +    (ss->serverCerts[type].serverKeyPair ? \
  1.1195 +    ss->serverCerts[type].serverKeyPair->pubKey : NULL)
  1.1196 +
  1.1197 +/* Extract the TLS curve name for the public key in our EC server cert. */
  1.1198 +ECName ssl3_GetSvrCertCurveName(sslSocket *ss)
  1.1199 +{
  1.1200 +    SECKEYPublicKey       *srvPublicKey;
  1.1201 +    ECName                ec_curve       = ec_noName;
  1.1202 +
  1.1203 +    srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh);
  1.1204 +    if (srvPublicKey) {
  1.1205 +        ec_curve = params2ecName(&srvPublicKey->u.ec.DEREncodedParams);
  1.1206 +    }
  1.1207 +    return ec_curve;
  1.1208 +}
  1.1209 +
  1.1210 +/* Ensure that the curve in our server cert is one of the ones suppored
  1.1211 + * by the remote client, and disable all ECC cipher suites if not.
  1.1212 + */
  1.1213 +SECStatus
  1.1214 +ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
  1.1215 +{
  1.1216 +    PRInt32  list_len;
  1.1217 +    PRUint32 peerCurves   = 0;
  1.1218 +    PRUint32 mutualCurves = 0;
  1.1219 +    PRUint16 svrCertCurveName;
  1.1220 +
  1.1221 +    if (!data->data || data->len < 4 || data->len > 65535)
  1.1222 +        goto loser;
  1.1223 +    /* get the length of elliptic_curve_list */
  1.1224 +    list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
  1.1225 +    if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) {
  1.1226 +        /* malformed */
  1.1227 +        goto loser;
  1.1228 +    }
  1.1229 +    /* build bit vector of peer's supported curve names */
  1.1230 +    while (data->len) {
  1.1231 +        PRInt32  curve_name =
  1.1232 +                 ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
  1.1233 +        if (curve_name > ec_noName && curve_name < ec_pastLastName) {
  1.1234 +            peerCurves |= (1U << curve_name);
  1.1235 +        }
  1.1236 +    }
  1.1237 +    /* What curves do we support in common? */
  1.1238 +    mutualCurves = ss->ssl3.hs.negotiatedECCurves &= peerCurves;
  1.1239 +    if (!mutualCurves) { /* no mutually supported EC Curves */
  1.1240 +        goto loser;
  1.1241 +    }
  1.1242 +
  1.1243 +    /* if our ECC cert doesn't use one of these supported curves,
  1.1244 +     * disable ECC cipher suites that require an ECC cert.
  1.1245 +     */
  1.1246 +    svrCertCurveName = ssl3_GetSvrCertCurveName(ss);
  1.1247 +    if (svrCertCurveName != ec_noName &&
  1.1248 +        (mutualCurves & (1U << svrCertCurveName)) != 0) {
  1.1249 +        return SECSuccess;
  1.1250 +    }
  1.1251 +    /* Our EC cert doesn't contain a mutually supported curve.
  1.1252 +     * Disable all ECC cipher suites that require an EC cert
  1.1253 +     */
  1.1254 +    ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites);
  1.1255 +    ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites);
  1.1256 +    return SECFailure;
  1.1257 +
  1.1258 +loser:
  1.1259 +    /* no common curve supported */
  1.1260 +    ssl3_DisableECCSuites(ss, ecSuites);
  1.1261 +    return SECFailure;
  1.1262 +}
  1.1263 +
  1.1264 +#endif /* NSS_DISABLE_ECC */

mercurial