From c4fb4fa280826e1693d9a075a06522517ac78a7d Mon Sep 17 00:00:00 2001 From: "nelson%bolyard.com" Date: Thu, 13 Apr 2006 23:08:18 +0000 Subject: [PATCH] Implement TLS Hello extensions for ECC. Bug 236245. r=rrelyea. This patch has a known problem, choosing ephemeral ECDH curves according to the wrong (suboptimal, non-FIPS) criteria. Modified Files: ssl3con.c ssl3ecc.c sslimpl.h --- security/nss/lib/ssl/ssl3con.c | 71 ++++-- security/nss/lib/ssl/ssl3ecc.c | 395 ++++++++++++++++++++++++++++++--- security/nss/lib/ssl/sslimpl.h | 14 +- 3 files changed, 423 insertions(+), 57 deletions(-) diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 5a8402016f3e..5bda47c001a7 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -39,7 +39,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -/* $Id: ssl3con.c,v 1.85 2006/04/07 06:24:07 nelson%bolyard.com Exp $ */ +/* $Id: ssl3con.c,v 1.86 2006/04/13 23:08:18 nelson%bolyard.com Exp $ */ #include "nssrenam.h" #include "cert.h" @@ -5377,24 +5377,6 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto loser; /* malformed */ } - /* Handle TLS hello extensions, for SSL3 & TLS */ - if (length) { - /* Get length of hello extensions */ - PRInt32 extension_length; - extension_length = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); - if (extension_length < 0) { - goto loser; /* alert already sent */ - } - if (extension_length != length) { - ssl3_DecodeError(ss); /* send alert */ - goto loser; - } - rv = ssl3_HandleClientHelloExtensions(ss, &b, &length); - if (rv != SECSuccess) { - goto loser; /* malformed */ - } - } - desc = handshake_failure; if (sid != NULL) { @@ -5422,26 +5404,42 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ssl3_FilterECCipherSuitesByServerCerts(ss); #endif +#ifdef PARANOID /* Look for a matching cipher suite. */ j = ssl3_config_match_init(ss); if (j <= 0) { /* no ciphers are working/supported by PK11 */ errCode = PORT_GetError(); /* error code is already set. */ goto alert_loser; } +#endif + /* If we already have a session for this client, be sure to pick the ** same cipher suite we picked before. ** This is not a loop, despite appearances. */ if (sid) do { ssl3CipherSuiteCfg *suite = ss->cipherSuites; + /* Find the entry for the cipher suite used in the cached session. */ for (j = ssl_V3_SUITES_IMPLEMENTED; j > 0; --j, ++suite) { if (suite->cipher_suite == sid->u.ssl3.cipherSuite) break; } - if (!j) + PORT_Assert(j > 0); + if (j <= 0) break; +#ifdef PARANOID + /* Double check that the cached cipher suite is still enabled, + * implemented, and allowed by policy. Might have been disabled. + * The product policy won't change during the process lifetime. + * Implemented ("isPresent") shouldn't change for servers. + */ if (!config_match(suite, ss->ssl3.policy, PR_TRUE)) break; +#else + if (!suite->enabled) + break; +#endif + /* Double check that the cached cipher suite is in the client's list */ for (i = 0; i < suites.len; i += 2) { if ((suites.data[i] == MSB(suite->cipher_suite)) && (suites.data[i + 1] == LSB(suite->cipher_suite))) { @@ -5454,6 +5452,37 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } } while (0); + /* START A NEW SESSION */ + + /* Handle TLS hello extensions, for SSL3 & TLS, + * only if we're not restarting a previous session. + */ + if (length) { + /* Get length of hello extensions */ + PRInt32 extension_length; + extension_length = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); + if (extension_length < 0) { + goto loser; /* alert already sent */ + } + if (extension_length != length) { + ssl3_DecodeError(ss); /* send alert */ + goto loser; + } + rv = ssl3_HandleClientHelloExtensions(ss, &b, &length); + if (rv != SECSuccess) { + goto loser; /* malformed */ + } + } + +#ifndef PARANOID + /* Look for a matching cipher suite. */ + j = ssl3_config_match_init(ss); + if (j <= 0) { /* no ciphers are working/supported by PK11 */ + errCode = PORT_GetError(); /* error code is already set. */ + goto alert_loser; + } +#endif + /* Select a cipher suite. ** NOTE: This suite selection algorithm should be the same as the one in ** ssl3_HandleV2ClientHello(). @@ -7380,6 +7409,7 @@ xmit_loser: sid->u.ssl3.cipherSuite = ss->ssl3.hs.cipher_suite; sid->u.ssl3.compression = ss->ssl3.hs.compression; sid->u.ssl3.policy = ss->ssl3.policy; + sid->u.ssl3.negotiatedECCurves = ss->ssl3.hs.negotiatedECCurves; sid->u.ssl3.exchKeyType = effectiveExchKeyType; sid->version = ss->version; sid->authAlgorithm = ss->sec.authAlgorithm; @@ -8002,6 +8032,7 @@ ssl3_InitState(sslSocket *ss) ssl3_InitCipherSpec(ss, ss->ssl3.prSpec); ss->ssl3.hs.ws = (ss->sec.isServer) ? wait_client_hello : wait_server_hello; + ss->ssl3.hs.negotiatedECCurves = SSL3_SUPPORTED_CURVES_MASK; ssl_ReleaseSpecWriteLock(ss); /* diff --git a/security/nss/lib/ssl/ssl3ecc.c b/security/nss/lib/ssl/ssl3ecc.c index 312fcc0f651d..18bfac0a5ef8 100644 --- a/security/nss/lib/ssl/ssl3ecc.c +++ b/security/nss/lib/ssl/ssl3ecc.c @@ -40,9 +40,10 @@ * ***** END LICENSE BLOCK ***** */ /* ECC code moved here from ssl3con.c */ -/* $Id: ssl3ecc.c,v 1.6 2006/04/07 06:24:07 nelson%bolyard.com Exp $ */ +/* $Id: ssl3ecc.c,v 1.7 2006/04/13 23:08:18 nelson%bolyard.com Exp $ */ #include "nssrenam.h" +#include "nss.h" #include "cert.h" #include "ssl.h" #include "cryptohi.h" /* for DSAU_ stuff */ @@ -75,24 +76,41 @@ #endif /* Types and names of elliptic curves used in TLS */ -typedef enum { ec_type_explicitPrime = 1, - ec_type_explicitChar2Curve, +typedef enum { ec_type_explicitPrime = 1, + ec_type_explicitChar2Curve = 2, ec_type_named } ECType; -typedef enum { ec_noName = 0, - ec_sect163k1, ec_sect163r1, ec_sect163r2, - ec_sect193r1, ec_sect193r2, ec_sect233k1, - ec_sect233r1, ec_sect239k1, ec_sect283k1, - ec_sect283r1, ec_sect409k1, ec_sect409r1, - ec_sect571k1, ec_sect571r1, ec_secp160k1, - ec_secp160r1, ec_secp160r2, ec_secp192k1, - ec_secp192r1, ec_secp224k1, ec_secp224r1, - ec_secp256k1, ec_secp256r1, ec_secp384r1, - ec_secp521r1, +typedef enum { ec_noName = 0, + ec_sect163k1 = 1, + ec_sect163r1 = 2, + ec_sect163r2 = 3, + ec_sect193r1 = 4, + ec_sect193r2 = 5, + ec_sect233k1 = 6, + ec_sect233r1 = 7, + ec_sect239k1 = 8, + ec_sect283k1 = 9, + ec_sect283r1 = 10, + ec_sect409k1 = 11, + ec_sect409r1 = 12, + ec_sect571k1 = 13, + ec_sect571r1 = 14, + ec_secp160k1 = 15, + ec_secp160r1 = 16, + ec_secp160r2 = 17, + ec_secp192k1 = 18, + ec_secp192r1 = 19, + ec_secp224k1 = 20, + ec_secp224r1 = 21, + ec_secp256k1 = 22, + ec_secp256r1 = 23, + ec_secp384r1 = 24, + ec_secp521r1 = 25, ec_pastLastName } ECName; + #define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName)) /* Table containing OID tags for elliptic curves named in the @@ -127,6 +145,15 @@ static const SECOidTag ecName2OIDTag[] = { SEC_OID_SECG_EC_SECP521R1, /* 25 */ }; +typedef struct ECDHEKeyPairStr { + ssl3KeyPair * pair; + PRInt32 flag; + PRCallOnceType once; +} ECDHEKeyPair; + +/* arrays of ECDHE KeyPairs */ +static ECDHEKeyPair gECDHEKeyPairs[ec_pastLastName]; + static SECStatus ecName2params(PRArenaPool * arena, ECName curve, SECKEYECParams * params) { @@ -361,11 +388,79 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b, return SECSuccess; } +/* function to clear out the lists */ +static SECStatus +ssl3_ShutdownECDHECurves(void *appData, void *nssData) +{ + int i; + ECDHEKeyPair *keyPair = &gECDHEKeyPairs[0]; + + for (i=0; i < ec_pastLastName; i++, keyPair++) { + if (keyPair->pair) { + ssl3_FreeKeyPair(keyPair->pair); + } + } + memset(gECDHEKeyPairs, 0, sizeof gECDHEKeyPairs); + return SECSuccess; +} + +static PRStatus +ssl3_ECRegister(void) +{ + SECStatus rv; + rv = NSS_RegisterShutdown(ssl3_ShutdownECDHECurves, gECDHEKeyPairs); + return (PRStatus)rv; +} + +#define SSL_GET_SERVER_PUBLIC_KEY(sock, type) \ + (ss->serverCerts[type].serverKeyPair ? \ + ss->serverCerts[type].serverKeyPair->pubKey : NULL) + +#define SSL_IS_CURVE_NEGOTIATED(ss, curveName) \ + ((curveName > ec_noName) && \ + (curveName < ec_pastLastName) && \ + ((1UL << curveName) & ss->ssl3.hs.negotiatedECCurves) != 0) + +/* CallOnce function, called once for each named curve. */ +static PRStatus +ssl3_CreateECDHEphemeralKeyPair(void * arg) +{ + SECKEYPrivateKey * privKey = NULL; + SECKEYPublicKey * pubKey = NULL; + ssl3KeyPair * keyPair = NULL; + ECName ec_curve = (ECName)arg; + SECKEYECParams ecParams = { siBuffer, NULL, 0 }; + + PORT_Assert(gECDHEKeyPairs[ec_curve].pair == NULL); + + /* ok, no one has generated a global key for this curve yet, do so */ + if (ecName2params(NULL, ec_curve, &ecParams) != SECSuccess) { + return PR_FAILURE; + } + + privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL); + SECITEM_FreeItem(&ecParams, PR_FALSE); + + if (!privKey || !pubKey || !(keyPair = ssl3_NewKeyPair(privKey, pubKey))) { + if (privKey) { + SECKEY_DestroyPrivateKey(privKey); + } + if (pubKey) { + SECKEY_DestroyPublicKey(pubKey); + } + ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); + return PR_FAILURE; + } + + gECDHEKeyPairs[ec_curve].pair = keyPair; + return PR_SUCCESS; +} /* * Creates the ephemeral public and private ECDH keys used by * server in ECDHE_RSA and ECDHE_ECDSA handshakes. - * XXX For now, the elliptic curve is hardcoded to NIST P-256. + * For now, the elliptic curve is chosen to be the same + * strength as the signing certificate (ECC or RSA). * We need an API to specify the curve. This won't be a real * issue until we further develop server-side support for ECC * cipher suites. @@ -373,26 +468,73 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b, SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss) { - SECStatus rv = SECSuccess; - SECKEYPrivateKey * privKey; - SECKEYPublicKey * pubKey; - SECKEYECParams ecParams = { siBuffer, NULL, 0 }; + SECKEYPublicKey * svrPublicKey = NULL; + ssl3KeyPair * keyPair = NULL; + ECName ec_curve = ec_noName; - if (ss->ephemeralECDHKeyPair) - ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair); - ss->ephemeralECDHKeyPair = NULL; + /* find the appropriate curve */ + if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa) { + svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh); + if (svrPublicKey) + ec_curve = params2ecName(&svrPublicKey->u.ec.DEREncodedParams); + if (!SSL_IS_CURVE_NEGOTIATED(ss, ec_curve)) { + PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); + return SECFailure; + } + } else { + /* RSA is our signing cert */ + int serverKeyStrengthInBits = 3072; /* default it */ - if (ecName2params(NULL, ec_secp256r1, &ecParams) == SECFailure) - return SECFailure; - privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL); - if (!privKey || !pubKey || - !(ss->ephemeralECDHKeyPair = ssl3_NewKeyPair(privKey, pubKey))) { - ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); - rv = SECFailure; + svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_rsa); + if (!svrPublicKey) { + PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); + return SECFailure; + } + + /* currently strength in bytes */ + serverKeyStrengthInBits = svrPublicKey->u.rsa.modulus.len; + if (svrPublicKey->u.rsa.modulus.data[0] == 0) { + serverKeyStrengthInBits--; + } + /* convert to strength in bits */ + serverKeyStrengthInBits *= BPB; + + if (serverKeyStrengthInBits <= 1024) { + ec_curve = ec_secp160r2; + } else if (serverKeyStrengthInBits <= 2048) { + ec_curve = ec_secp224r1; + } else if (serverKeyStrengthInBits <= 3072) { + ec_curve = ec_secp256r1; + } else if (serverKeyStrengthInBits <= 7168) { + ec_curve = ec_secp384r1; + } else { + ec_curve = ec_secp521r1; + } } - PORT_Free(ecParams.data); - return rv; + /* if there's no global key for this curve, make one. */ + if (gECDHEKeyPairs[ec_curve].pair == NULL) { + PRStatus status; + + status = PR_CallOnce(&gECDHEKeyPairs[ec_noName].once, ssl3_ECRegister); + if (status != PR_SUCCESS) { + return SECFailure; + } + status = PR_CallOnceWithArg(&gECDHEKeyPairs[ec_curve].once, + ssl3_CreateECDHEphemeralKeyPair, + (void *)ec_curve); + if (status != PR_SUCCESS) { + return SECFailure; + } + } + + keyPair = gECDHEKeyPairs[ec_curve].pair; + PORT_Assert(keyPair != NULL); + if (!keyPair) + return SECFailure; + ss->ephemeralECDHKeyPair = ssl3_GetKeyPairRef(keyPair); + + return SECSuccess; } SECStatus @@ -418,8 +560,7 @@ ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) */ ec_params.len = 3; ec_params.data = paramBuf; - rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, - &b, &length); + rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length); if (rv != SECSuccess) { goto loser; /* malformed. */ } @@ -777,6 +918,182 @@ ssl3_FilterECCipherSuitesByServerCerts(sslSocket * ss) } } +/* Ask: is ANY ECC cipher suite enabled on this socket? */ +/* Order(N^2). Yuk. Also, this ignores export policy. */ +PRBool +ssl3_IsECCEnabled(sslSocket * ss) +{ + const ssl3CipherSuite * suite; + + for (suite = ecSuites; *suite; ++suite) { + PRBool enabled = PR_FALSE; + SECStatus rv = ssl3_CipherPrefGet(ss, *suite, &enabled); + + PORT_Assert(rv == SECSuccess); /* else is coding error */ + if (rv == SECSuccess && enabled) + return PR_TRUE; + } + return PR_FALSE; +} + +#define BE(n) 0, n + +/* Prefabricated TLS client hello extension, Elliptic Curves List, + * offers curves 1-25. + */ +static const PRUint8 EClist[55] = { + BE(10), /* Extension type */ + BE(51), /* octets that follow (25 pairs + 1 octet) */ + 50, /* octets that follow (25 pairs) */ + BE( 1), BE( 2), BE( 3), BE( 4), BE( 5), BE( 6), BE( 7), + BE( 8), BE( 9), BE(10), BE(11), BE(12), BE(13), BE(14), BE(15), + BE(16), BE(17), BE(18), BE(19), BE(20), BE(21), BE(22), BE(23), + BE(24), BE(25) +}; + +static const PRUint8 ECPtFmt[6] = { + BE(11), /* Extension type */ + BE( 2), /* octets that follow */ + 1, /* octets that follow */ + 0 /* uncompressed type only */ +}; + +/* Send our "canned" (precompiled) Supported Elliptic Curves extension, + * which says that we support all TLS-defined named curves. + */ +PRInt32 +ssl3_SendSupportedEllipticCurvesExtension( + sslSocket * ss, + PRBool append, + PRUint32 maxBytes) +{ + if (!ss || !ssl3_IsECCEnabled(ss)) + return 0; + if (append && maxBytes >= (sizeof EClist)) { + SECStatus rv = ssl3_AppendHandshake(ss, EClist, (sizeof EClist)); + } + return (sizeof EClist); +} + +/* Send our "canned" (precompiled) Supported Point Formats extension, + * which says that we only support uncompressed points. + */ +PRInt32 +ssl3_SendSupportedPointFormatsExtension( + sslSocket * ss, + PRBool append, + PRUint32 maxBytes) +{ + if (!ss || !ssl3_IsECCEnabled(ss)) + return 0; + if (append && maxBytes >= (sizeof ECPtFmt)) { + SECStatus rv = ssl3_AppendHandshake(ss, ECPtFmt, (sizeof ECPtFmt)); + } + return (sizeof ECPtFmt); +} + +/* Just make sure that the remote client supports uncompressed points, + * Since that is all we support. Disable ECC cipher suites if it doesn't. + */ +static SECStatus +ssl3_HandleSupportedPointFormatsExtension(sslSocket * ss, PRUint16 ex_type, + SECItem *data) +{ + int i; + + if (data->len < 2 || data->len > 255 || !data->data || + data->len != (unsigned int)data->data[0] + 1) { + /* malformed */ + goto loser; + } + for (i = data->len; --i > 0; ) { + if (data->data[i] == 0) { + /* indicate that we should send a reply */ + SECStatus rv; + rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type, + &ssl3_SendSupportedPointFormatsExtension); + return rv; + } + } +loser: + /* evil client doesn't support uncompressed */ + ssl3_DisableECCSuites(ss, ecSuites); + return SECFailure; +} + + +#define SSL3_GET_SERVER_PUBLICKEY(sock, type) \ + (ss->serverCerts[type].serverKeyPair ? \ + ss->serverCerts[type].serverKeyPair->pubKey : NULL) + +/* Extract the TLS curve name for the public key in our EC server cert. */ +ECName ssl3_GetSvrCertCurveName(sslSocket *ss) +{ + SECKEYPublicKey *srvPublicKey; + ECName ec_curve = ec_noName; + + srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh); + if (srvPublicKey) { + ec_curve = params2ecName(&srvPublicKey->u.ec.DEREncodedParams); + } + return ec_curve; +} + +/* Ensure that the curve in our server cert is one of the ones suppored + * by the remote client, and disable all ECC cipher suites if not. + */ +static SECStatus +ssl3_HandleSupportedEllipticCurvesExtension(sslSocket * ss, PRUint16 ex_type, + SECItem *data) +{ + PRInt32 list_len; + PRUint32 peerCurves = 0; + PRUint32 mutualCurves = 0; + PRUint16 svrCertCurveName; + + if (!data->data || data->len < 4 || data->len > 65535) + goto loser; + /* get the length of elliptic_curve_list */ + list_len = ssl3_ConsumeHandshakeNumber(ss, 1, &data->data, &data->len); + if (list_len < 0 || data->len != list_len || (data->len % 2) != 0) { + /* malformed */ + goto loser; + } + /* build bit vector of peer's supported curve names */ + while (data->len) { + PRInt32 curve_name = + ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); + if (curve_name > ec_noName && curve_name < ec_pastLastName) { + peerCurves |= (1U << curve_name); + } + } + /* What curves do we support in common? */ + mutualCurves = ss->ssl3.hs.negotiatedECCurves &= peerCurves; + if (!mutualCurves) { /* no mutually supported EC Curves */ + goto loser; + } + + /* if our ECC cert doesn't use one of these supported curves, + * disable ECC cipher suites that require an ECC cert. + */ + svrCertCurveName = ssl3_GetSvrCertCurveName(ss); + if (svrCertCurveName != ec_noName && + (mutualCurves & (1U << svrCertCurveName)) != 0) { + return SECSuccess; + } + /* Our EC cert doesn't contain a mutually supported curve. + * Disable all ECC cipher suites that require an EC cert + */ + ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites); + ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites); + return SECFailure; + +loser: + /* no common curve supported */ + ssl3_DisableECCSuites(ss, ecSuites); + return SECFailure; +} + #endif /* NSS_ENABLE_ECC */ /* Format an SNI extension, using the name from the socket's URL, @@ -835,7 +1152,10 @@ ssl3_HandleServerNameIndicationExtension(sslSocket * ss, PRUint16 ex_type, */ static const ssl3HelloExtensionHandler handlers[] = { { 0, &ssl3_HandleServerNameIndicationExtension }, - /* ECC handlers will be added here */ +#ifdef NSS_ENABLE_ECC + { 10, &ssl3_HandleSupportedEllipticCurvesExtension }, + { 11, &ssl3_HandleSupportedPointFormatsExtension }, +#endif { -1, NULL } }; @@ -847,14 +1167,18 @@ static const ssl3HelloExtensionHandler handlers[] = { static const ssl3HelloExtensionSender clientHelloSenders[MAX_EXTENSION_SENDERS] = { { 0, &ssl3_SendServerNameIndicationExtension }, - /* ECC senders will be added here */ +#ifdef NSS_ENABLE_ECC + { 10, &ssl3_SendSupportedEllipticCurvesExtension }, + { 11, &ssl3_SendSupportedPointFormatsExtension }, +#else { -1, NULL } +#endif }; /* go through hello extensions in buffer "b". * For each one, find the extension handler in the table above, and * if present, invoke that handler. - * ignore any externsions with unknown extensions types. + * ignore any extensions with unknown extension types. */ SECStatus ssl3_HandleClientHelloExtensions(sslSocket *ss, @@ -943,3 +1267,4 @@ ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, } return total_exten_len; } + diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index 65a7bf98b591..9a0d2f033741 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -39,7 +39,7 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -/* $Id: sslimpl.h,v 1.48 2006/04/07 06:24:07 nelson%bolyard.com Exp $ */ +/* $Id: sslimpl.h,v 1.49 2006/04/13 23:08:18 nelson%bolyard.com Exp $ */ #ifndef __sslimpl_h_ #define __sslimpl_h_ @@ -179,6 +179,9 @@ typedef enum { SSLAppOpRead = 0, #define NUM_MIXERS 9 +/* Mask of the 25 named curves we support. */ +#define SSL3_SUPPORTED_CURVES_MASK 0x3fffffe + #ifndef BPB #define BPB 8 /* Bits Per Byte */ #endif @@ -586,6 +589,9 @@ struct sslSessionIDStr { SSL3KEAType exchKeyType; /* key type used in exchange algorithm, * and to wrap the sym wrapping key. */ +#ifdef NSS_ENABLE_ECC + PRUint32 negotiatedECCurves; +#endif /* NSS_ENABLE_ECC */ /* The following values are NOT restored from the server's on-disk * session cache, but are restored from the client's cache. @@ -711,6 +717,9 @@ const ssl3CipherSuiteDef *suite_def; PRBool usedStepDownKey; /* we did a server key exchange. */ sslBuffer msgState; /* current state for handshake messages*/ /* protected by recvBufLock */ +#ifdef NSS_ENABLE_ECC + PRUint32 negotiatedECCurves; /* bit mask */ +#endif /* NSS_ENABLE_ECC */ } SSL3HandshakeState; @@ -1260,7 +1269,8 @@ extern SECStatus ssl3_CreateRSAStepDownKeys(sslSocket *ss); #ifdef NSS_ENABLE_ECC extern SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss); -extern void ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss); +extern void ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss); +extern PRBool ssl3_IsECCEnabled(sslSocket *ss); #endif /* NSS_ENABLE_ECC */ extern SECStatus ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool on);