summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/sslsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/sslsock.c')
-rw-r--r--security/nss/lib/ssl/sslsock.c246
1 files changed, 235 insertions, 11 deletions
diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c
index ae904e29b..aa0e76e3c 100644
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -20,6 +20,7 @@
#include "pk11pqg.h"
#include "pk11pub.h"
#include "tls13esni.h"
+#include "tls13subcerts.h"
static const sslSocketOps ssl_default_ops = { /* No SSL. */
ssl_DefConnect,
@@ -75,18 +76,20 @@ static sslOptions ssl_defaults = {
.enableFalseStart = PR_FALSE,
.cbcRandomIV = PR_TRUE,
.enableOCSPStapling = PR_FALSE,
+ .enableDelegatedCredentials = PR_FALSE,
.enableALPN = PR_TRUE,
.reuseServerECDHEKey = PR_TRUE,
.enableFallbackSCSV = PR_FALSE,
.enableServerDhe = PR_TRUE,
- .enableExtendedMS = PR_FALSE,
+ .enableExtendedMS = PR_TRUE,
.enableSignedCertTimestamps = PR_FALSE,
.requireDHENamedGroups = PR_FALSE,
.enable0RttData = PR_FALSE,
.enableTls13CompatMode = PR_FALSE,
.enableDtlsShortHeader = PR_FALSE,
.enableHelloDowngradeCheck = PR_FALSE,
- .enableV2CompatibleHello = PR_FALSE
+ .enableV2CompatibleHello = PR_FALSE,
+ .enablePostHandshakeAuth = PR_FALSE
};
/*
@@ -94,7 +97,7 @@ static sslOptions ssl_defaults = {
*/
static SSLVersionRange versions_defaults_stream = {
SSL_LIBRARY_VERSION_TLS_1_0,
- SSL_LIBRARY_VERSION_TLS_1_2
+ SSL_LIBRARY_VERSION_TLS_1_3
};
static SSLVersionRange versions_defaults_datagram = {
@@ -276,6 +279,8 @@ ssl_DupSocket(sslSocket *os)
goto loser;
}
ss->vrange = os->vrange;
+ ss->now = os->now;
+ ss->nowArg = os->nowArg;
ss->peerID = !os->peerID ? NULL : PORT_Strdup(os->peerID);
ss->url = !os->url ? NULL : PORT_Strdup(os->url);
@@ -369,6 +374,13 @@ ssl_DupSocket(sslSocket *os)
goto loser;
}
}
+ if (os->antiReplay) {
+ ss->antiReplay = tls13_RefAntiReplayContext(os->antiReplay);
+ PORT_Assert(ss->antiReplay); /* Can't fail. */
+ if (!ss->antiReplay) {
+ goto loser;
+ }
+ }
/* Create security data */
rv = ssl_CopySecurityInfo(ss, os);
@@ -457,6 +469,7 @@ ssl_DestroySocketContents(sslSocket *ss)
ssl_ClearPRCList(&ss->ssl3.hs.dtlsRcvdHandshake, NULL);
tls13_DestroyESNIKeys(ss->esniKeys);
+ tls13_ReleaseAntiReplayContext(ss->antiReplay);
}
/*
@@ -782,6 +795,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRIntn val)
ss->opt.enableOCSPStapling = val;
break;
+ case SSL_ENABLE_DELEGATED_CREDENTIALS:
+ ss->opt.enableDelegatedCredentials = val;
+ break;
+
case SSL_ENABLE_NPN:
break;
@@ -842,6 +859,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRIntn val)
ss->opt.enableV2CompatibleHello = val;
break;
+ case SSL_ENABLE_POST_HANDSHAKE_AUTH:
+ ss->opt.enablePostHandshakeAuth = val;
+ break;
+
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
@@ -948,6 +969,9 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRIntn *pVal)
case SSL_ENABLE_OCSP_STAPLING:
val = ss->opt.enableOCSPStapling;
break;
+ case SSL_ENABLE_DELEGATED_CREDENTIALS:
+ val = ss->opt.enableDelegatedCredentials;
+ break;
case SSL_ENABLE_NPN:
val = PR_FALSE;
break;
@@ -990,6 +1014,9 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRIntn *pVal)
case SSL_ENABLE_V2_COMPATIBLE_HELLO:
val = ss->opt.enableV2CompatibleHello;
break;
+ case SSL_ENABLE_POST_HANDSHAKE_AUTH:
+ val = ss->opt.enablePostHandshakeAuth;
+ break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
@@ -1083,6 +1110,9 @@ SSL_OptionGetDefault(PRInt32 which, PRIntn *pVal)
case SSL_ENABLE_OCSP_STAPLING:
val = ssl_defaults.enableOCSPStapling;
break;
+ case SSL_ENABLE_DELEGATED_CREDENTIALS:
+ val = ssl_defaults.enableDelegatedCredentials;
+ break;
case SSL_ENABLE_NPN:
val = PR_FALSE;
break;
@@ -1122,6 +1152,9 @@ SSL_OptionGetDefault(PRInt32 which, PRIntn *pVal)
case SSL_ENABLE_V2_COMPATIBLE_HELLO:
val = ssl_defaults.enableV2CompatibleHello;
break;
+ case SSL_ENABLE_POST_HANDSHAKE_AUTH:
+ val = ssl_defaults.enablePostHandshakeAuth;
+ break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
@@ -1270,6 +1303,10 @@ SSL_OptionSetDefault(PRInt32 which, PRIntn val)
ssl_defaults.enableOCSPStapling = val;
break;
+ case SSL_ENABLE_DELEGATED_CREDENTIALS:
+ ssl_defaults.enableDelegatedCredentials = val;
+ break;
+
case SSL_ENABLE_NPN:
break;
@@ -1325,6 +1362,10 @@ SSL_OptionSetDefault(PRInt32 which, PRIntn val)
ssl_defaults.enableV2CompatibleHello = val;
break;
+ case SSL_ENABLE_POST_HANDSHAKE_AUTH:
+ ssl_defaults.enablePostHandshakeAuth = val;
+ break;
+
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@@ -1499,6 +1540,119 @@ SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
return rv;
}
+/* The client can call this function to be aware of the current
+ * CipherSuites order. */
+SECStatus
+SSLExp_CipherSuiteOrderGet(PRFileDesc *fd, PRUint16 *cipherOrder,
+ unsigned int *numCiphers)
+{
+ if (!fd) {
+ SSL_DBG(("%d: SSL: file descriptor in CipherSuiteOrderGet is null",
+ SSL_GETPID()));
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ if (!cipherOrder || !numCiphers) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ sslSocket *ss = ssl_FindSocket(fd);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in CipherSuiteOrderGet", SSL_GETPID(),
+ fd));
+ return SECFailure; /* Error code already set. */
+ }
+
+ unsigned int enabled = 0;
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+ for (unsigned int i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
+ const ssl3CipherSuiteCfg *suiteCfg = &ss->cipherSuites[i];
+ if (suiteCfg && suiteCfg->enabled &&
+ suiteCfg->policy != SSL_NOT_ALLOWED) {
+ cipherOrder[enabled++] = suiteCfg->cipher_suite;
+ }
+ }
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+ *numCiphers = enabled;
+ return SECSuccess;
+}
+
+/* This function permits reorder the CipherSuites List for the Handshake
+ * (Client Hello). */
+SECStatus
+SSLExp_CipherSuiteOrderSet(PRFileDesc *fd, const PRUint16 *cipherOrder,
+ unsigned int numCiphers)
+{
+ if (!fd) {
+ SSL_DBG(("%d: SSL: file descriptor in CipherSuiteOrderGet is null",
+ SSL_GETPID()));
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ if (!cipherOrder || !numCiphers || numCiphers > ssl_V3_SUITES_IMPLEMENTED) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ sslSocket *ss = ssl_FindSocket(fd);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in CipherSuiteOrderSet", SSL_GETPID(),
+ fd));
+ return SECFailure; /* Error code already set. */
+ }
+ ssl3CipherSuiteCfg tmpSuiteCfg[ssl_V3_SUITES_IMPLEMENTED];
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+ /* For each cipherSuite given as input, verify that it is
+ * known to NSS and only present in the list once. */
+ for (unsigned int i = 0; i < numCiphers; i++) {
+ const ssl3CipherSuiteCfg *suiteCfg =
+ ssl_LookupCipherSuiteCfg(cipherOrder[i], ss->cipherSuites);
+ if (!suiteCfg) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+ return SECFailure;
+ }
+ for (unsigned int j = i + 1; j < numCiphers; j++) {
+ /* This is a duplicate entry. */
+ if (cipherOrder[i] == cipherOrder[j]) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+ return SECFailure;
+ }
+ }
+ tmpSuiteCfg[i] = *suiteCfg;
+ tmpSuiteCfg[i].enabled = PR_TRUE;
+ }
+ /* Find all defined ciphersuites not present in the input list and append
+ * them after the preferred. This guarantees that the socket will always
+ * have a complete list of size ssl_V3_SUITES_IMPLEMENTED */
+ unsigned int cfgIdx = numCiphers;
+ for (unsigned int i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
+ PRBool received = PR_FALSE;
+ for (unsigned int j = 0; j < numCiphers; j++) {
+ if (ss->cipherSuites[i].cipher_suite ==
+ tmpSuiteCfg[j].cipher_suite) {
+ received = PR_TRUE;
+ break;
+ }
+ }
+ if (!received) {
+ tmpSuiteCfg[cfgIdx] = ss->cipherSuites[i];
+ tmpSuiteCfg[cfgIdx++].enabled = PR_FALSE;
+ }
+ }
+ PORT_Assert(cfgIdx == ssl_V3_SUITES_IMPLEMENTED);
+ /* now we can rewrite the socket with the desired order */
+ PORT_Memcpy(ss->cipherSuites, tmpSuiteCfg, sizeof(tmpSuiteCfg));
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+ return SECSuccess;
+}
+
SECStatus
NSS_SetDomesticPolicy(void)
{
@@ -2200,6 +2354,8 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
ss->opt = sm->opt;
ss->vrange = sm->vrange;
+ ss->now = sm->now;
+ ss->nowArg = sm->nowArg;
PORT_Memcpy(ss->cipherSuites, sm->cipherSuites, sizeof sm->cipherSuites);
PORT_Memcpy(ss->ssl3.dtlsSRTPCiphers, sm->ssl3.dtlsSRTPCiphers,
sizeof(PRUint16) * sm->ssl3.dtlsSRTPCipherCount);
@@ -2273,6 +2429,29 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
}
}
+ /* Copy ESNI. */
+ tls13_DestroyESNIKeys(ss->esniKeys);
+ ss->esniKeys = NULL;
+ if (sm->esniKeys) {
+ ss->esniKeys = tls13_CopyESNIKeys(sm->esniKeys);
+ if (!ss->esniKeys) {
+ return NULL;
+ }
+ }
+
+ /* Copy anti-replay context. */
+ if (ss->antiReplay) {
+ tls13_ReleaseAntiReplayContext(ss->antiReplay);
+ ss->antiReplay = NULL;
+ }
+ if (sm->antiReplay) {
+ ss->antiReplay = tls13_RefAntiReplayContext(sm->antiReplay);
+ PORT_Assert(ss->antiReplay);
+ if (!ss->antiReplay) {
+ return NULL;
+ }
+ }
+
if (sm->authCertificate)
ss->authCertificate = sm->authCertificate;
if (sm->authCertificateArg)
@@ -3644,6 +3823,7 @@ ssl_SetDefaultsFromEnvironment(void)
char *ev;
firsttime = 0;
#ifdef DEBUG
+ ssl_trace_iob = NULL;
ev = PR_GetEnvSecure("SSLDEBUGFILE");
if (ev && ev[0]) {
ssl_trace_iob = fopen(ev, "w");
@@ -3665,6 +3845,7 @@ ssl_SetDefaultsFromEnvironment(void)
}
#endif /* DEBUG */
#ifdef NSS_ALLOW_SSLKEYLOGFILE
+ ssl_keylog_iob = NULL;
ev = PR_GetEnvSecure("SSLKEYLOGFILE");
if (ev && ev[0]) {
ssl_keylog_iob = fopen(ev, "a");
@@ -3885,6 +4066,15 @@ ssl_FreeEphemeralKeyPairs(sslSocket *ss)
}
}
+PRTime
+ssl_Time(const sslSocket *ss)
+{
+ if (!ss->now) {
+ return PR_Now();
+ }
+ return ss->now(ss->nowArg);
+}
+
/*
** Create a newsocket structure for a file descriptor.
*/
@@ -3900,7 +4090,7 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
makeLocks = PR_TRUE;
/* Make a new socket and get it ready */
- ss = (sslSocket *)PORT_ZAlloc(sizeof(sslSocket));
+ ss = PORT_ZNew(sslSocket);
if (!ss) {
return NULL;
}
@@ -3958,6 +4148,7 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
dtls_InitTimers(ss);
ss->esniKeys = NULL;
+ ss->antiReplay = NULL;
if (makeLocks) {
rv = ssl_MakeLocks(ss);
@@ -4024,20 +4215,38 @@ struct {
void *function;
} ssl_experimental_functions[] = {
#ifndef SSL_DISABLE_EXPERIMENTAL_API
+ EXP(AeadDecrypt),
+ EXP(AeadEncrypt),
+ EXP(CipherSuiteOrderGet),
+ EXP(CipherSuiteOrderSet),
+ EXP(CreateAntiReplayContext),
+ EXP(DelegateCredential),
+ EXP(DestroyAead),
+ EXP(DestroyResumptionTokenInfo),
+ EXP(EnableESNI),
+ EXP(EncodeESNIKeys),
+ EXP(GetCurrentEpoch),
EXP(GetExtensionSupport),
+ EXP(GetResumptionTokenInfo),
EXP(HelloRetryRequestCallback),
EXP(InstallExtensionHooks),
+ EXP(HkdfExtract),
+ EXP(HkdfExpandLabel),
+ EXP(HkdfExpandLabelWithMech),
EXP(KeyUpdate),
+ EXP(MakeAead),
+ EXP(RecordLayerData),
+ EXP(RecordLayerWriteCallback),
+ EXP(ReleaseAntiReplayContext),
+ EXP(SecretCallback),
+ EXP(SendCertificateRequest),
EXP(SendSessionTicket),
+ EXP(SetAntiReplayContext),
+ EXP(SetESNIKeyPair),
EXP(SetMaxEarlyDataSize),
- EXP(SetupAntiReplay),
EXP(SetResumptionTokenCallback),
EXP(SetResumptionToken),
- EXP(GetResumptionTokenInfo),
- EXP(DestroyResumptionTokenInfo),
- EXP(SetESNIKeyPair),
- EXP(EncodeESNIKeys),
- EXP(EnableESNI),
+ EXP(SetTimeFunc),
#endif
{ "", NULL }
};
@@ -4073,6 +4282,21 @@ ssl_ClearPRCList(PRCList *list, void (*f)(void *))
}
}
+SECStatus
+SSLExp_SetTimeFunc(PRFileDesc *fd, SSLTimeFunc f, void *arg)
+{
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetTimeFunc",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
+ ss->now = f;
+ ss->nowArg = arg;
+ return SECSuccess;
+}
+
/* Experimental APIs for session cache handling. */
SECStatus
@@ -4156,7 +4380,7 @@ SSLExp_SetResumptionToken(PRFileDesc *fd, const PRUint8 *token,
/* Use the sid->cached as marker that this is from an external cache and
* we don't have to look up anything in the NSS internal cache. */
sid->cached = in_external_cache;
- sid->lastAccessTime = ssl_TimeSec();
+ sid->lastAccessTime = ssl_Time(ss);
ss->sec.ci.sid = sid;