diff options
Diffstat (limited to 'security/nss/lib/ssl/sslsock.c')
-rw-r--r-- | security/nss/lib/ssl/sslsock.c | 246 |
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; |