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