From acfe04a6dd445471bb36c931ef0aa6a226875a01 Mon Sep 17 00:00:00 2001 From: "nelson%bolyard.com" Date: Thu, 6 Apr 2006 04:40:49 +0000 Subject: [PATCH] Don't negotiate an ECDH_RSA cipher suite when the server's only ECDH cert has an ECDSA signature. bug 332350. r=vipul.gupta. --- security/nss/lib/ssl/ssl3con.c | 12 ++- security/nss/lib/ssl/ssl3ecc.c | 147 ++++++++++++++++++++++++++++++--- security/nss/lib/ssl/sslimpl.h | 3 +- 3 files changed, 148 insertions(+), 14 deletions(-) diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index afc66d6b3339..416d1bdb6fb0 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.83 2006/03/22 19:18:30 rrelyea%redhat.com Exp $ */ +/* $Id: ssl3con.c,v 1.84 2006/04/06 04:40:49 nelson%bolyard.com Exp $ */ #include "nssrenam.h" #include "cert.h" @@ -5358,6 +5358,11 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } } +#ifdef NSS_ENABLE_ECC + /* Disable any ECC cipher suites for which we have no cert. */ + ssl3_FilterECCipherSuitesByServerCerts(ss); +#endif + /* Look for a matching cipher suite. */ j = ssl3_config_match_init(ss); if (j <= 0) { /* no ciphers are working/supported by PK11 */ @@ -5718,7 +5723,10 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) PRINT_BUF(60, (ss, "client random:", &ss->ssl3.hs.client_random.rand[0], SSL3_RANDOM_LENGTH)); - +#ifdef NSS_ENABLE_ECC + /* Disable any ECC cipher suites for which we have no cert. */ + ssl3_FilterECCipherSuitesByServerCerts(ss); +#endif i = ssl3_config_match_init(ss); if (i <= 0) { errCode = PORT_GetError(); /* error code is already set. */ diff --git a/security/nss/lib/ssl/ssl3ecc.c b/security/nss/lib/ssl/ssl3ecc.c index 5217c7651894..1150db906b20 100644 --- a/security/nss/lib/ssl/ssl3ecc.c +++ b/security/nss/lib/ssl/ssl3ecc.c @@ -40,7 +40,7 @@ * ***** END LICENSE BLOCK ***** */ /* ECC code moved here from ssl3con.c */ -/* $Id: ssl3ecc.c,v 1.4 2005/12/14 01:49:39 wtchang%redhat.com Exp $ */ +/* $Id: ssl3ecc.c,v 1.5 2006/04/06 04:40:49 nelson%bolyard.com Exp $ */ #ifdef NSS_ENABLE_ECC @@ -69,14 +69,6 @@ #include -/* - line 297: implicit function declaration: ssl3_InitPendingCipherSpec - line 305: implicit function declaration: ssl3_AppendHandshakeHeader - line 311: implicit function declaration: ssl3_AppendHandshakeVariable - line 356: implicit function declaration: ssl3_ConsumeHandshakeVariable -*/ - - #ifndef PK11_SETATTRS #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \ (x)->pValue=(v); (x)->ulValueLen = (l); @@ -229,7 +221,6 @@ ssl3_ComputeECDHKeyHash(SECItem ec_params, SECItem server_ecpoint, PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result", hashes->md5, MD5_LENGTH)); PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH)); -done: if (hashBuf != buf && hashBuf != NULL) PORT_Free(hashBuf); return rv; @@ -650,6 +641,140 @@ loser: return SECFailure; } +/* Lists of ECC cipher suites for searching and disabling. */ + +static const ssl3CipherSuite ecdh_suites[] = { + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_ECDSA_WITH_NULL_SHA, + TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_RSA_WITH_NULL_SHA, + TLS_ECDH_RSA_WITH_RC4_128_SHA, + 0 /* end of list marker */ +}; + +static const ssl3CipherSuite ecdh_ecdsa_suites[] = { + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_ECDSA_WITH_NULL_SHA, + TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + 0 /* end of list marker */ +}; + +static const ssl3CipherSuite ecdh_rsa_suites[] = { + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_RSA_WITH_NULL_SHA, + TLS_ECDH_RSA_WITH_RC4_128_SHA, + 0 /* end of list marker */ +}; + +static const ssl3CipherSuite ecdhe_ecdsa_suites[] = { + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_NULL_SHA, + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + 0 /* end of list marker */ +}; + +static const ssl3CipherSuite ecdhe_rsa_suites[] = { + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_RSA_WITH_NULL_SHA, + TLS_ECDHE_RSA_WITH_RC4_128_SHA, + 0 /* end of list marker */ +}; + +/* List of all ECC cipher suites */ +static const ssl3CipherSuite ecSuites[] = { + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_ECDSA_WITH_NULL_SHA, + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDHE_RSA_WITH_NULL_SHA, + TLS_ECDHE_RSA_WITH_RC4_128_SHA, + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_ECDSA_WITH_NULL_SHA, + TLS_ECDH_ECDSA_WITH_RC4_128_SHA, + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + TLS_ECDH_RSA_WITH_NULL_SHA, + TLS_ECDH_RSA_WITH_RC4_128_SHA, + 0 /* end of list marker */ +}; + +/* On this socket, Disable the ECC cipher suites in the argument's list */ +SECStatus +ssl3_DisableECCSuites(sslSocket * ss, const ssl3CipherSuite * suite) +{ + for (; *suite; ++suite) { + SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE); + + PORT_Assert(rv == SECSuccess); /* else is coding error */ + } + return SECSuccess; +} + +/* Look at the server certs configured on this socket, and disable any + * ECC cipher suites that are not supported by those certs. + */ +void +ssl3_FilterECCipherSuitesByServerCerts(sslSocket * ss) +{ + CERTCertificate * svrCert; + + svrCert = ss->serverCerts[kt_rsa].serverCert; + if (!svrCert) { + ssl3_DisableECCSuites(ss, ecdhe_rsa_suites); + } + + svrCert = ss->serverCerts[kt_ecdh].serverCert; + if (!svrCert) { + ssl3_DisableECCSuites(ss, ecdh_suites); + ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites); + } else { + SECOidTag sigTag = SECOID_GetAlgorithmTag(&svrCert->signature); + + switch (sigTag) { + case SEC_OID_PKCS1_RSA_ENCRYPTION: + case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: + ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites); + break; + case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: + case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE: + case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE: + case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE: + case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE: + case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST: + case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST: + ssl3_DisableECCSuites(ss, ecdh_rsa_suites); + break; + default: + ssl3_DisableECCSuites(ss, ecdh_suites); + break; + } + } +} #endif /* NSS_ENABLE_ECC */ - diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index 17dd6f770ec3..f4b1308c0f69 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.46 2006/03/22 19:18:30 rrelyea%redhat.com Exp $ */ +/* $Id: sslimpl.h,v 1.47 2006/04/06 04:40:49 nelson%bolyard.com Exp $ */ #ifndef __sslimpl_h_ #define __sslimpl_h_ @@ -1223,6 +1223,7 @@ extern SECStatus ssl3_CreateRSAStepDownKeys(sslSocket *ss); #ifdef NSS_ENABLE_ECC extern SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss); +extern void ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss); #endif /* NSS_ENABLE_ECC */ extern SECStatus ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool on);