security/nss/lib/ssl/ssl3ecc.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial