Index: net/third_party/nss/ssl/sslsock.c |
diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c |
index 09a0fb514b293c68d1887ba32c23183e0d447cc7..0a8fbf0fdcd600761a6785024d602527ecd4a117 100644 |
--- a/net/third_party/nss/ssl/sslsock.c |
+++ b/net/third_party/nss/ssl/sslsock.c |
@@ -19,6 +19,7 @@ |
#endif |
#include "pk11pub.h" |
#include "nss.h" |
+#include "pk11pqg.h" |
/* This is a bodge to allow this code to be compiled against older NSS headers |
* that don't contain the TLS 1.2 changes. */ |
@@ -90,6 +91,8 @@ static sslOptions ssl_defaults = { |
PR_FALSE, /* enableALPN */ |
PR_TRUE, /* reuseServerECDHEKey */ |
PR_FALSE, /* enableFallbackSCSV */ |
+ PR_TRUE, /* enableServerDhe */ |
+ PR_FALSE, /* enableExtendedMS */ |
PR_FALSE, /* enableSignedCertTimestamps */ |
}; |
@@ -232,6 +235,24 @@ ssl_DupSocket(sslSocket *os) |
PORT_Memcpy(ss->ssl3.dtlsSRTPCiphers, os->ssl3.dtlsSRTPCiphers, |
sizeof(PRUint16) * os->ssl3.dtlsSRTPCipherCount); |
ss->ssl3.dtlsSRTPCipherCount = os->ssl3.dtlsSRTPCipherCount; |
+ PORT_Memcpy(ss->ssl3.signatureAlgorithms, os->ssl3.signatureAlgorithms, |
+ sizeof(ss->ssl3.signatureAlgorithms[0]) * |
+ os->ssl3.signatureAlgorithmCount); |
+ ss->ssl3.signatureAlgorithmCount = os->ssl3.signatureAlgorithmCount; |
+ |
+ ss->ssl3.dheWeakGroupEnabled = os->ssl3.dheWeakGroupEnabled; |
+ ss->ssl3.numDHEGroups = os->ssl3.numDHEGroups; |
+ if (os->ssl3.dheGroups) { |
+ ss->ssl3.dheGroups = PORT_NewArray(SSLDHEGroupType, |
+ os->ssl3.numDHEGroups); |
+ if (!ss->ssl3.dheGroups) { |
+ goto loser; |
+ } |
+ PORT_Memcpy(ss->ssl3.dheGroups, os->ssl3.dheGroups, |
+ sizeof(SSLDHEGroupType) * os->ssl3.numDHEGroups); |
+ } else { |
+ ss->ssl3.dheGroups = NULL; |
+ } |
if (os->cipherSpecs) { |
ss->cipherSpecs = (unsigned char*)PORT_Alloc(os->sizeCipherSpecs); |
@@ -275,6 +296,10 @@ ssl_DupSocket(sslSocket *os) |
ssl3_GetKeyPairRef(os->stepDownKeyPair); |
ss->ephemeralECDHKeyPair = !os->ephemeralECDHKeyPair ? NULL : |
ssl3_GetKeyPairRef(os->ephemeralECDHKeyPair); |
+ ss->dheKeyPair = !os->dheKeyPair ? NULL : |
+ ssl3_GetKeyPairRef(os->dheKeyPair); |
+ ss->dheParams = os->dheParams; |
+ |
/* |
* XXX the preceding CERT_ and SECKEY_ functions can fail and return NULL. |
* XXX We should detect this, and not just march on with NULL pointers. |
@@ -398,8 +423,11 @@ ssl_DestroySocketContents(sslSocket *ss) |
ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair); |
ss->ephemeralECDHKeyPair = NULL; |
} |
+ if (ss->dheKeyPair) { |
+ ssl3_FreeKeyPair(ss->dheKeyPair); |
+ ss->dheKeyPair = NULL; |
+ } |
SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE); |
- PORT_Assert(!ss->xtnData.sniNameArr); |
if (ss->xtnData.sniNameArr) { |
PORT_Free(ss->xtnData.sniNameArr); |
ss->xtnData.sniNameArr = NULL; |
@@ -808,6 +836,14 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) |
ss->opt.enableFallbackSCSV = on; |
break; |
+ case SSL_ENABLE_SERVER_DHE: |
+ ss->opt.enableServerDhe = on; |
+ break; |
+ |
+ case SSL_ENABLE_EXTENDED_MASTER_SECRET: |
+ ss->opt.enableExtendedMS = on; |
+ break; |
+ |
case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: |
ss->opt.enableSignedCertTimestamps = on; |
break; |
@@ -887,6 +923,9 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) |
case SSL_REUSE_SERVER_ECDHE_KEY: |
on = ss->opt.reuseServerECDHEKey; break; |
case SSL_ENABLE_FALLBACK_SCSV: on = ss->opt.enableFallbackSCSV; break; |
+ case SSL_ENABLE_SERVER_DHE: on = ss->opt.enableServerDhe; break; |
+ case SSL_ENABLE_EXTENDED_MASTER_SECRET: |
+ on = ss->opt.enableExtendedMS; break; |
case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: |
on = ss->opt.enableSignedCertTimestamps; |
break; |
@@ -959,6 +998,12 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) |
case SSL_ENABLE_FALLBACK_SCSV: |
on = ssl_defaults.enableFallbackSCSV; |
break; |
+ case SSL_ENABLE_SERVER_DHE: |
+ on = ssl_defaults.enableServerDhe; |
+ break; |
+ case SSL_ENABLE_EXTENDED_MASTER_SECRET: |
+ on = ssl_defaults.enableExtendedMS; |
+ break; |
case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: |
on = ssl_defaults.enableSignedCertTimestamps; |
break; |
@@ -1145,6 +1190,14 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) |
ssl_defaults.enableFallbackSCSV = on; |
break; |
+ case SSL_ENABLE_SERVER_DHE: |
+ ssl_defaults.enableServerDhe = on; |
+ break; |
+ |
+ case SSL_ENABLE_EXTENDED_MASTER_SECRET: |
+ ssl_defaults.enableExtendedMS = on; |
+ break; |
+ |
case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: |
ssl_defaults.enableSignedCertTimestamps = on; |
break; |
@@ -1381,6 +1434,148 @@ NSS_SetFrancePolicy(void) |
} |
SECStatus |
+SSL_DHEGroupPrefSet(PRFileDesc *fd, |
+ SSLDHEGroupType *groups, |
+ PRUint16 num_groups) |
+{ |
+ sslSocket *ss; |
+ |
+ if ((num_groups && !groups) || (!num_groups && groups)) { |
+ PORT_SetError(SEC_ERROR_INVALID_ARGS); |
+ return SECFailure; |
+ } |
+ |
+ ss = ssl_FindSocket(fd); |
+ if (!ss) { |
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_DHEGroupPrefSet", SSL_GETPID(), fd)); |
+ return SECFailure; |
+ } |
+ |
+ if (ss->ssl3.dheGroups) { |
+ PORT_Free(ss->ssl3.dheGroups); |
+ ss->ssl3.dheGroups = NULL; |
+ ss->ssl3.numDHEGroups = 0; |
+ } |
+ |
+ if (groups) { |
+ ss->ssl3.dheGroups = PORT_NewArray(SSLDHEGroupType, num_groups); |
+ if (!ss->ssl3.dheGroups) { |
+ PORT_SetError(SEC_ERROR_NO_MEMORY); |
+ return SECFailure; |
+ } |
+ PORT_Memcpy(ss->ssl3.dheGroups, groups, |
+ sizeof(SSLDHEGroupType) * num_groups); |
+ } |
+ return SECSuccess; |
+} |
+ |
+ |
+PRCallOnceType gWeakDHParamsRegisterOnce; |
+int gWeakDHParamsRegisterError; |
+ |
+PRCallOnceType gWeakDHParamsOnce; |
+int gWeakDHParamsError; |
+/* As our code allocates type PQGParams, we'll keep it around, |
+ * even though we only make use of it's parameters through gWeakDHParam. */ |
+static PQGParams *gWeakParamsPQG; |
+static ssl3DHParams *gWeakDHParams; |
+ |
+static PRStatus |
+ssl3_CreateWeakDHParams(void) |
+{ |
+ PQGVerify *vfy; |
+ SECStatus rv, passed; |
+ |
+ PORT_Assert(!gWeakDHParams && !gWeakParamsPQG); |
+ |
+ rv = PK11_PQG_ParamGenV2(1024, 160, 64 /*maximum seed that will work*/, |
+ &gWeakParamsPQG, &vfy); |
+ if (rv != SECSuccess) { |
+ gWeakDHParamsError = PORT_GetError(); |
+ return PR_FAILURE; |
+ } |
+ |
+ rv = PK11_PQG_VerifyParams(gWeakParamsPQG, vfy, &passed); |
+ if (rv != SECSuccess || passed != SECSuccess) { |
+ SSL_DBG(("%d: PK11_PQG_VerifyParams failed in ssl3_CreateWeakDHParams", |
+ SSL_GETPID())); |
+ gWeakDHParamsError = PORT_GetError(); |
+ return PR_FAILURE; |
+ } |
+ |
+ gWeakDHParams = PORT_ArenaNew(gWeakParamsPQG->arena, ssl3DHParams); |
+ if (!gWeakDHParams) { |
+ gWeakDHParamsError = PORT_GetError(); |
+ return PR_FAILURE; |
+ } |
+ |
+ gWeakDHParams->prime.data = gWeakParamsPQG->prime.data; |
+ gWeakDHParams->prime.len = gWeakParamsPQG->prime.len; |
+ gWeakDHParams->base.data = gWeakParamsPQG->base.data; |
+ gWeakDHParams->base.len = gWeakParamsPQG->base.len; |
+ |
+ PK11_PQG_DestroyVerify(vfy); |
+ return PR_SUCCESS; |
+} |
+ |
+static SECStatus |
+ssl3_WeakDHParamsShutdown(void *appData, void *nssData) |
+{ |
+ if (gWeakParamsPQG) { |
+ PK11_PQG_DestroyParams(gWeakParamsPQG); |
+ gWeakParamsPQG = NULL; |
+ gWeakDHParams = NULL; |
+ } |
+ return SECSuccess; |
+} |
+ |
+static PRStatus |
+ssl3_WeakDHParamsRegisterShutdown(void) |
+{ |
+ SECStatus rv; |
+ rv = NSS_RegisterShutdown(ssl3_WeakDHParamsShutdown, NULL); |
+ if (rv != SECSuccess) { |
+ gWeakDHParamsRegisterError = PORT_GetError(); |
+ } |
+ return (PRStatus)rv; |
+} |
+ |
+/* global init strategy inspired by ssl3_CreateECDHEphemeralKeys */ |
+SECStatus |
+SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled) |
+{ |
+ sslSocket *ss; |
+ PRStatus status; |
+ |
+ if (enabled) { |
+ status = PR_CallOnce(&gWeakDHParamsRegisterOnce, |
+ ssl3_WeakDHParamsRegisterShutdown); |
+ if (status != PR_SUCCESS) { |
+ PORT_SetError(gWeakDHParamsRegisterError); |
+ return SECFailure; |
+ } |
+ |
+ status = PR_CallOnce(&gWeakDHParamsOnce, ssl3_CreateWeakDHParams); |
+ if (status != PR_SUCCESS) { |
+ PORT_SetError(gWeakDHParamsError); |
+ return SECFailure; |
+ } |
+ } |
+ |
+ if (!fd) |
+ return SECSuccess; |
+ |
+ ss = ssl_FindSocket(fd); |
+ if (!ss) { |
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_DHEGroupPrefSet", SSL_GETPID(), fd)); |
+ return SECFailure; |
+ } |
+ |
+ ss->ssl3.dheWeakGroupEnabled = enabled; |
+ return SECSuccess; |
+} |
+ |
+SECStatus |
SSL_GetChannelBinding(PRFileDesc *fd, |
SSLChannelBindingType binding_type, |
unsigned char *out, |
@@ -1402,6 +1597,62 @@ SSL_GetChannelBinding(PRFileDesc *fd, |
return ssl3_GetTLSUniqueChannelBinding(ss, out, outLen, outLenMax); |
} |
+#include "dhe-param.c" |
+ |
+static const SSLDHEGroupType ssl_default_dhe_groups[] = { |
+ ssl_ff_dhe_2048_group |
+}; |
+ |
+/* Keep this array synchronized with the index definitions in SSLDHEGroupType */ |
+static const ssl3DHParams *all_ssl3DHParams[] = { |
+ NULL, /* ssl_dhe_group_none */ |
+ &ff_dhe_2048, |
+ &ff_dhe_3072, |
+ &ff_dhe_4096, |
+ &ff_dhe_6144, |
+ &ff_dhe_8192, |
+}; |
+ |
+static SSLDHEGroupType |
+selectDHEGroup(sslSocket *ss, const SSLDHEGroupType *groups, PRUint16 num_groups) |
+{ |
+ if (!groups || !num_groups) |
+ return ssl_dhe_group_none; |
+ |
+ /* We don't have automatic group parameter selection yet |
+ * (potentially) based on socket parameters, e.g. key sizes. |
+ * For now, we return the first available group from the allowed list. */ |
+ return groups[0]; |
+} |
+ |
+/* Ensure DH parameters have been selected */ |
+SECStatus |
+ssl3_SelectDHParams(sslSocket *ss) |
+{ |
+ SSLDHEGroupType selectedGroup = ssl_dhe_group_none; |
+ |
+ if (ss->ssl3.dheWeakGroupEnabled) { |
+ ss->dheParams = gWeakDHParams; |
+ } else { |
+ if (ss->ssl3.dheGroups) { |
+ selectedGroup = selectDHEGroup(ss, ss->ssl3.dheGroups, |
+ ss->ssl3.numDHEGroups); |
+ } else { |
+ size_t number_of_default_groups = PR_ARRAY_SIZE(ssl_default_dhe_groups); |
+ selectedGroup = selectDHEGroup(ss, ssl_default_dhe_groups, |
+ number_of_default_groups); |
+ } |
+ |
+ if (selectedGroup == ssl_dhe_group_none || |
+ selectedGroup >= ssl_dhe_group_max) { |
+ return SECFailure; |
+ } |
+ |
+ ss->dheParams = all_ssl3DHParams[selectedGroup]; |
+ } |
+ |
+ return SECSuccess; |
+} |
/* LOCKS ??? XXX */ |
static PRFileDesc * |
@@ -1699,6 +1950,10 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd) |
PORT_Memcpy(ss->ssl3.dtlsSRTPCiphers, sm->ssl3.dtlsSRTPCiphers, |
sizeof(PRUint16) * sm->ssl3.dtlsSRTPCipherCount); |
ss->ssl3.dtlsSRTPCipherCount = sm->ssl3.dtlsSRTPCipherCount; |
+ PORT_Memcpy(ss->ssl3.signatureAlgorithms, sm->ssl3.signatureAlgorithms, |
+ sizeof(ss->ssl3.signatureAlgorithms[0]) * |
+ sm->ssl3.signatureAlgorithmCount); |
+ ss->ssl3.signatureAlgorithmCount = sm->ssl3.signatureAlgorithmCount; |
if (!ss->opt.useSecurity) { |
PORT_SetError(SEC_ERROR_INVALID_ARGS); |
@@ -3122,6 +3377,10 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant) |
} |
ss->requestedCertTypes = NULL; |
ss->stepDownKeyPair = NULL; |
+ |
+ ss->dheParams = NULL; |
+ ss->dheKeyPair = NULL; |
+ |
ss->dbHandle = CERT_GetDefaultCertDB(); |
/* Provide default implementation of hooks */ |