diff options
Diffstat (limited to 'nss/lib/ssl/sslsock.c')
-rw-r--r-- | nss/lib/ssl/sslsock.c | 2947 |
1 files changed, 1713 insertions, 1234 deletions
diff --git a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c index f735009..626f4a9 100644 --- a/nss/lib/ssl/sslsock.c +++ b/nss/lib/ssl/sslsock.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * vtables (and methods that call through them) for the 4 types of * SSLSockets supported. Only one type is still supported. @@ -14,42 +15,37 @@ #include "sslproto.h" #include "nspr.h" #include "private/pprio.h" -#ifndef NO_PKCS11_BYPASS -#include "blapi.h" -#endif #include "nss.h" #include "pk11pqg.h" -#define SET_ERROR_CODE /* reminder */ - -static const sslSocketOps ssl_default_ops = { /* No SSL. */ - ssl_DefConnect, - NULL, - ssl_DefBind, - ssl_DefListen, - ssl_DefShutdown, - ssl_DefClose, - ssl_DefRecv, - ssl_DefSend, - ssl_DefRead, - ssl_DefWrite, - ssl_DefGetpeername, - ssl_DefGetsockname +static const sslSocketOps ssl_default_ops = { /* No SSL. */ + ssl_DefConnect, + NULL, + ssl_DefBind, + ssl_DefListen, + ssl_DefShutdown, + ssl_DefClose, + ssl_DefRecv, + ssl_DefSend, + ssl_DefRead, + ssl_DefWrite, + ssl_DefGetpeername, + ssl_DefGetsockname }; -static const sslSocketOps ssl_secure_ops = { /* SSL. */ - ssl_SecureConnect, - NULL, - ssl_DefBind, - ssl_DefListen, - ssl_SecureShutdown, - ssl_SecureClose, - ssl_SecureRecv, - ssl_SecureSend, - ssl_SecureRead, - ssl_SecureWrite, - ssl_DefGetpeername, - ssl_DefGetsockname +static const sslSocketOps ssl_secure_ops = { /* SSL. */ + ssl_SecureConnect, + NULL, + ssl_DefBind, + ssl_DefListen, + ssl_SecureShutdown, + ssl_SecureClose, + ssl_SecureRecv, + ssl_SecureSend, + ssl_SecureRead, + ssl_SecureWrite, + ssl_DefGetpeername, + ssl_DefGetsockname }; /* @@ -57,35 +53,37 @@ static const sslSocketOps ssl_secure_ops = { /* SSL. */ */ static sslOptions ssl_defaults = { { siBuffer, NULL, 0 }, /* nextProtoNego */ - PR_TRUE, /* useSecurity */ - PR_FALSE, /* useSocks */ - PR_FALSE, /* requestCertificate */ - 2, /* requireCertificate */ - PR_FALSE, /* handshakeAsClient */ - PR_FALSE, /* handshakeAsServer */ - PR_FALSE, /* enableSSL2 */ /* now defaults to off in NSS 3.13 */ - PR_FALSE, /* unusedBit9 */ - PR_FALSE, /* unusedBit10 */ - PR_FALSE, /* noCache */ - PR_FALSE, /* fdx */ - PR_FALSE, /* v2CompatibleHello */ /* now defaults to off in NSS 3.13 */ - PR_TRUE, /* detectRollBack */ - PR_FALSE, /* noStepDown */ - PR_FALSE, /* bypassPKCS11 */ - PR_FALSE, /* noLocks */ - PR_FALSE, /* enableSessionTickets */ - PR_FALSE, /* enableDeflate */ - 2, /* enableRenegotiation (default: requires extension) */ - PR_FALSE, /* requireSafeNegotiation */ - PR_FALSE, /* enableFalseStart */ - PR_TRUE, /* cbcRandomIV */ - PR_FALSE, /* enableOCSPStapling */ - PR_TRUE, /* enableNPN */ - PR_FALSE, /* enableALPN */ - PR_TRUE, /* reuseServerECDHEKey */ - PR_FALSE, /* enableFallbackSCSV */ - PR_TRUE, /* enableServerDhe */ - PR_FALSE /* enableExtendedMS */ + PR_TRUE, /* useSecurity */ + PR_FALSE, /* useSocks */ + PR_FALSE, /* requestCertificate */ + 2, /* requireCertificate */ + PR_FALSE, /* handshakeAsClient */ + PR_FALSE, /* handshakeAsServer */ + PR_FALSE, /* noCache */ + PR_FALSE, /* fdx */ + PR_TRUE, /* detectRollBack */ + PR_FALSE, /* noLocks */ + PR_FALSE, /* enableSessionTickets */ + PR_FALSE, /* enableDeflate */ + 2, /* enableRenegotiation (default: requires extension) */ + PR_FALSE, /* requireSafeNegotiation */ + PR_FALSE, /* enableFalseStart */ + PR_TRUE, /* cbcRandomIV */ + PR_FALSE, /* enableOCSPStapling */ + PR_FALSE, /* enableNPN */ + PR_TRUE, /* enableALPN */ + PR_TRUE, /* reuseServerECDHEKey */ + PR_FALSE, /* enableFallbackSCSV */ + PR_TRUE, /* enableServerDhe */ + PR_FALSE, /* enableExtendedMS */ + PR_FALSE, /* enableSignedCertTimestamps */ + PR_FALSE, /* requireDHENamedGroups */ + PR_FALSE, /* enable0RttData */ +#ifdef NSS_ENABLE_TLS13_SHORT_HEADERS + PR_TRUE /* enableShortHeaders */ +#else + PR_FALSE /* enableShortHeaders */ +#endif }; /* @@ -102,23 +100,30 @@ static SSLVersionRange versions_defaults_datagram = { }; #define VERSIONS_DEFAULTS(variant) \ - (variant == ssl_variant_stream ? &versions_defaults_stream : \ - &versions_defaults_datagram) - -sslSessionIDLookupFunc ssl_sid_lookup; -sslSessionIDCacheFunc ssl_sid_cache; + (variant == ssl_variant_stream ? &versions_defaults_stream : &versions_defaults_datagram) +#define VERSIONS_POLICY_MIN(variant) \ + (variant == ssl_variant_stream ? NSS_TLS_VERSION_MIN_POLICY : NSS_DTLS_VERSION_MIN_POLICY) +#define VERSIONS_POLICY_MAX(variant) \ + (variant == ssl_variant_stream ? NSS_TLS_VERSION_MAX_POLICY : NSS_DTLS_VERSION_MAX_POLICY) + +sslSessionIDLookupFunc ssl_sid_lookup; +sslSessionIDCacheFunc ssl_sid_cache; sslSessionIDUncacheFunc ssl_sid_uncache; static PRBool ssl_inited = PR_FALSE; static PRDescIdentity ssl_layer_id; -PRBool locksEverDisabled; /* implicitly PR_FALSE */ -PRBool ssl_force_locks; /* implicitly PR_FALSE */ -int ssl_lock_readers = 1; /* default true. */ -char ssl_debug; -char ssl_trace; -FILE * ssl_trace_iob; -FILE * ssl_keylog_iob; +PRBool locksEverDisabled; /* implicitly PR_FALSE */ +PRBool ssl_force_locks; /* implicitly PR_FALSE */ +int ssl_lock_readers = 1; /* default true. */ +char ssl_debug; +char ssl_trace; +FILE *ssl_trace_iob; + +#ifdef NSS_ALLOW_SSLKEYLOGFILE +FILE *ssl_keylog_iob; +#endif + char lockStatus[] = "Locks are ENABLED. "; #define LOCKSTATUS_OFFSET 10 /* offset of ENABLED */ @@ -129,12 +134,66 @@ static const PRUint16 srtpCiphers[] = { 0 }; +/* This list is in preference order. Note that while some smaller groups appear + * early in the list, smaller groups are generally ignored when iterating + * through this list. ffdhe_custom must not appear in this list. */ +#define ECGROUP(name, size, oid, assumeSupported) \ + { \ + ssl_grp_ec_##name, size, ssl_kea_ecdh, \ + SEC_OID_SECG_EC_##oid, assumeSupported \ + } +#define FFGROUP(size) \ + { \ + ssl_grp_ffdhe_##size, size, ssl_kea_dh, \ + SEC_OID_TLS_FFDHE_##size, PR_TRUE \ + } + +const sslNamedGroupDef ssl_named_groups[] = { + /* Note that 256 for 25519 is a lie, but we only use it for checking bit + * security and expect 256 bits there (not 255). */ + { ssl_grp_ec_curve25519, 256, ssl_kea_ecdh, SEC_OID_CURVE25519, PR_TRUE }, + ECGROUP(secp256r1, 256, SECP256R1, PR_TRUE), + ECGROUP(secp384r1, 384, SECP384R1, PR_TRUE), + ECGROUP(secp521r1, 521, SECP521R1, PR_TRUE), + FFGROUP(2048), + FFGROUP(3072), + FFGROUP(4096), + FFGROUP(6144), + FFGROUP(8192), + ECGROUP(secp192r1, 192, SECP192R1, PR_FALSE), + ECGROUP(secp160r2, 160, SECP160R2, PR_FALSE), + ECGROUP(secp160k1, 160, SECP160K1, PR_FALSE), + ECGROUP(secp160r1, 160, SECP160R1, PR_FALSE), + ECGROUP(sect163k1, 163, SECT163K1, PR_FALSE), + ECGROUP(sect163r1, 163, SECT163R1, PR_FALSE), + ECGROUP(sect163r2, 163, SECT163R2, PR_FALSE), + ECGROUP(secp192k1, 192, SECP192K1, PR_FALSE), + ECGROUP(sect193r1, 193, SECT193R1, PR_FALSE), + ECGROUP(sect193r2, 193, SECT193R2, PR_FALSE), + ECGROUP(secp224r1, 224, SECP224R1, PR_FALSE), + ECGROUP(secp224k1, 224, SECP224K1, PR_FALSE), + ECGROUP(sect233k1, 233, SECT233K1, PR_FALSE), + ECGROUP(sect233r1, 233, SECT233R1, PR_FALSE), + ECGROUP(sect239k1, 239, SECT239K1, PR_FALSE), + ECGROUP(secp256k1, 256, SECP256K1, PR_FALSE), + ECGROUP(sect283k1, 283, SECT283K1, PR_FALSE), + ECGROUP(sect283r1, 283, SECT283R1, PR_FALSE), + ECGROUP(sect409k1, 409, SECT409K1, PR_FALSE), + ECGROUP(sect409r1, 409, SECT409R1, PR_FALSE), + ECGROUP(sect571k1, 571, SECT571K1, PR_FALSE), + ECGROUP(sect571r1, 571, SECT571R1, PR_FALSE), +}; +PR_STATIC_ASSERT(SSL_NAMED_GROUP_COUNT == PR_ARRAY_SIZE(ssl_named_groups)); + +#undef ECGROUP +#undef FFGROUP + /* forward declarations. */ static sslSocket *ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant variant); -static SECStatus ssl_MakeLocks(sslSocket *ss); -static void ssl_SetDefaultsFromEnvironment(void); -static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, - PRDescIdentity id); +static SECStatus ssl_MakeLocks(sslSocket *ss); +static void ssl_SetDefaultsFromEnvironment(void); +static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, + PRDescIdentity id); /************************************************************************/ @@ -205,116 +264,90 @@ ssl_DupSocket(sslSocket *os) SECStatus rv; ss = ssl_NewSocket((PRBool)(!os->opt.noLocks), os->protocolVariant); - if (ss) { - ss->opt = os->opt; - ss->opt.useSocks = PR_FALSE; - ss->vrange = os->vrange; - - ss->peerID = !os->peerID ? NULL : PORT_Strdup(os->peerID); - ss->url = !os->url ? NULL : PORT_Strdup(os->url); - - ss->ops = os->ops; - ss->rTimeout = os->rTimeout; - ss->wTimeout = os->wTimeout; - ss->cTimeout = os->cTimeout; - ss->dbHandle = os->dbHandle; - - /* copy ssl2&3 policy & prefs, even if it's not selected (yet) */ - ss->allowedByPolicy = os->allowedByPolicy; - ss->maybeAllowedByPolicy= os->maybeAllowedByPolicy; - ss->chosenPreference = os->chosenPreference; - PORT_Memcpy(ss->cipherSuites, os->cipherSuites, sizeof os->cipherSuites); - 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) { + if (!ss) { + return NULL; + } + + ss->opt = os->opt; + ss->opt.useSocks = PR_FALSE; + rv = SECITEM_CopyItem(NULL, &ss->opt.nextProtoNego, &os->opt.nextProtoNego); + if (rv != SECSuccess) { + goto loser; + } + ss->vrange = os->vrange; + + ss->peerID = !os->peerID ? NULL : PORT_Strdup(os->peerID); + ss->url = !os->url ? NULL : PORT_Strdup(os->url); + + ss->ops = os->ops; + ss->rTimeout = os->rTimeout; + ss->wTimeout = os->wTimeout; + ss->cTimeout = os->cTimeout; + ss->dbHandle = os->dbHandle; + + /* copy ssl2&3 policy & prefs, even if it's not selected (yet) */ + PORT_Memcpy(ss->cipherSuites, os->cipherSuites, sizeof os->cipherSuites); + PORT_Memcpy(ss->ssl3.dtlsSRTPCiphers, os->ssl3.dtlsSRTPCiphers, + sizeof(PRUint16) * os->ssl3.dtlsSRTPCipherCount); + ss->ssl3.dtlsSRTPCipherCount = os->ssl3.dtlsSRTPCipherCount; + PORT_Memcpy(ss->ssl3.signatureSchemes, os->ssl3.signatureSchemes, + sizeof(ss->ssl3.signatureSchemes[0]) * + os->ssl3.signatureSchemeCount); + ss->ssl3.signatureSchemeCount = os->ssl3.signatureSchemeCount; + ss->ssl3.downgradeCheckVersion = os->ssl3.downgradeCheckVersion; + + ss->ssl3.dheWeakGroupEnabled = os->ssl3.dheWeakGroupEnabled; + + if (ss->opt.useSecurity) { + PRCList *cursor; + for (cursor = PR_NEXT_LINK(&os->serverCerts); + cursor != &os->serverCerts; + cursor = PR_NEXT_LINK(cursor)) { + sslServerCert *sc = ssl_CopyServerCert((sslServerCert *)cursor); + if (!sc) goto loser; - } - PORT_Memcpy(ss->ssl3.dheGroups, os->ssl3.dheGroups, - sizeof(SSLDHEGroupType) * os->ssl3.numDHEGroups); - } else { - ss->ssl3.dheGroups = NULL; + PR_APPEND_LINK(&sc->link, &ss->serverCerts); } - if (os->cipherSpecs) { - ss->cipherSpecs = (unsigned char*)PORT_Alloc(os->sizeCipherSpecs); - if (ss->cipherSpecs) - PORT_Memcpy(ss->cipherSpecs, os->cipherSpecs, - os->sizeCipherSpecs); - ss->sizeCipherSpecs = os->sizeCipherSpecs; - ss->preferredCipher = os->preferredCipher; - } else { - ss->cipherSpecs = NULL; /* produced lazily */ - ss->sizeCipherSpecs = 0; - ss->preferredCipher = NULL; + PR_INIT_CLIST(&ss->ephemeralKeyPairs); + for (cursor = PR_NEXT_LINK(&os->ephemeralKeyPairs); + cursor != &os->ephemeralKeyPairs; + cursor = PR_NEXT_LINK(cursor)) { + sslEphemeralKeyPair *okp = (sslEphemeralKeyPair *)cursor; + sslEphemeralKeyPair *skp = ssl_CopyEphemeralKeyPair(okp); + if (!skp) + goto loser; + PR_APPEND_LINK(&skp->link, &ss->ephemeralKeyPairs); } - if (ss->opt.useSecurity) { - /* This int should be SSLKEAType, but CC on Irix complains, - * during the for loop. - */ - int i; - sslServerCerts * oc = os->serverCerts; - sslServerCerts * sc = ss->serverCerts; - - for (i=kt_null; i < kt_kea_size; i++, oc++, sc++) { - if (oc->serverCert && oc->serverCertChain) { - sc->serverCert = CERT_DupCertificate(oc->serverCert); - sc->serverCertChain = CERT_DupCertList(oc->serverCertChain); - if (!sc->serverCertChain) - goto loser; - } else { - sc->serverCert = NULL; - sc->serverCertChain = NULL; - } - sc->serverKeyPair = oc->serverKeyPair ? - ssl3_GetKeyPairRef(oc->serverKeyPair) : NULL; - if (oc->serverKeyPair && !sc->serverKeyPair) - goto loser; - sc->serverKeyBits = oc->serverKeyBits; - ss->certStatusArray[i] = !os->certStatusArray[i] ? NULL : - SECITEM_DupArray(NULL, os->certStatusArray[i]); - } - ss->stepDownKeyPair = !os->stepDownKeyPair ? NULL : - 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. - */ - ss->authCertificate = os->authCertificate; - ss->authCertificateArg = os->authCertificateArg; - ss->getClientAuthData = os->getClientAuthData; - ss->getClientAuthDataArg = os->getClientAuthDataArg; - ss->sniSocketConfig = os->sniSocketConfig; - ss->sniSocketConfigArg = os->sniSocketConfigArg; - ss->handleBadCert = os->handleBadCert; - ss->badCertArg = os->badCertArg; - ss->handshakeCallback = os->handshakeCallback; - ss->handshakeCallbackData = os->handshakeCallbackData; - ss->canFalseStartCallback = os->canFalseStartCallback; - ss->canFalseStartCallbackData = os->canFalseStartCallbackData; - ss->pkcs11PinArg = os->pkcs11PinArg; - - /* Create security data */ - rv = ssl_CopySecurityInfo(ss, os); - if (rv != SECSuccess) { - goto loser; - } + /* + * 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. + */ + ss->authCertificate = os->authCertificate; + ss->authCertificateArg = os->authCertificateArg; + ss->getClientAuthData = os->getClientAuthData; + ss->getClientAuthDataArg = os->getClientAuthDataArg; + ss->sniSocketConfig = os->sniSocketConfig; + ss->sniSocketConfigArg = os->sniSocketConfigArg; + ss->handleBadCert = os->handleBadCert; + ss->badCertArg = os->badCertArg; + ss->handshakeCallback = os->handshakeCallback; + ss->handshakeCallbackData = os->handshakeCallbackData; + ss->canFalseStartCallback = os->canFalseStartCallback; + ss->canFalseStartCallbackData = os->canFalseStartCallbackData; + ss->pkcs11PinArg = os->pkcs11PinArg; + ss->nextProtoCallback = os->nextProtoCallback; + ss->nextProtoArg = os->nextProtoArg; + PORT_Memcpy((void *)ss->namedGroupPreferences, + os->namedGroupPreferences, + sizeof(ss->namedGroupPreferences)); + ss->additionalShares = os->additionalShares; + + /* Create security data */ + rv = ssl_CopySecurityInfo(ss, os); + if (rv != SECSuccess) { + goto loser; } } return ss; @@ -363,10 +396,7 @@ ssl_DestroyLocks(sslSocket *ss) static void ssl_DestroySocketContents(sslSocket *ss) { - /* "i" should be of type SSLKEAType, but CC on IRIX complains during - * the for loop. - */ - int i; + PRCList *cursor; /* Free up socket */ ssl_DestroySecurityInfo(&ss->sec); @@ -375,49 +405,22 @@ ssl_DestroySocketContents(sslSocket *ss) PORT_Free(ss->saveBuf.buf); PORT_Free(ss->pendingBuf.buf); - ssl_DestroyGather(&ss->gs); + ssl3_DestroyGather(&ss->gs); if (ss->peerID != NULL) PORT_Free(ss->peerID); if (ss->url != NULL) - PORT_Free((void *)ss->url); /* CONST */ - if (ss->cipherSpecs) { - PORT_Free(ss->cipherSpecs); - ss->cipherSpecs = NULL; - ss->sizeCipherSpecs = 0; - } - - /* Clean up server configuration */ - for (i=kt_null; i < kt_kea_size; i++) { - sslServerCerts * sc = ss->serverCerts + i; - if (sc->serverCert != NULL) - CERT_DestroyCertificate(sc->serverCert); - if (sc->serverCertChain != NULL) - CERT_DestroyCertificateList(sc->serverCertChain); - if (sc->serverKeyPair != NULL) - ssl3_FreeKeyPair(sc->serverKeyPair); - if (ss->certStatusArray[i] != NULL) { - SECITEM_FreeArray(ss->certStatusArray[i], PR_TRUE); - ss->certStatusArray[i] = NULL; - } - } - if (ss->stepDownKeyPair) { - ssl3_FreeKeyPair(ss->stepDownKeyPair); - ss->stepDownKeyPair = NULL; - } - if (ss->ephemeralECDHKeyPair) { - ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair); - ss->ephemeralECDHKeyPair = NULL; - } - if (ss->dheKeyPair) { - ssl3_FreeKeyPair(ss->dheKeyPair); - ss->dheKeyPair = NULL; + PORT_Free((void *)ss->url); /* CONST */ + + /* Clean up server certificates and sundries. */ + while (!PR_CLIST_IS_EMPTY(&ss->serverCerts)) { + cursor = PR_LIST_TAIL(&ss->serverCerts); + PR_REMOVE_LINK(cursor); + ssl_FreeServerCert((sslServerCert *)cursor); } + ssl_FreeEphemeralKeyPairs(ss); SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE); - if (ss->xtnData.sniNameArr) { - PORT_Free(ss->xtnData.sniNameArr); - ss->xtnData.sniNameArr = NULL; - } + ssl3_FreeSniNameArray(&ss->xtnData); } /* @@ -426,11 +429,11 @@ ssl_DestroySocketContents(sslSocket *ss) void ssl_FreeSocket(sslSocket *ss) { -/* Get every lock you can imagine! -** Caller already holds these: -** SSL_LOCK_READER(ss); -** SSL_LOCK_WRITER(ss); -*/ + /* Get every lock you can imagine! + ** Caller already holds these: + ** SSL_LOCK_READER(ss); + ** SSL_LOCK_WRITER(ss); + */ ssl_Get1stHandshakeLock(ss); ssl_GetRecvBufLock(ss); ssl_GetSSL3HandshakeLock(ss); @@ -461,15 +464,15 @@ ssl_FreeSocket(sslSocket *ss) SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled) { - PRFileDesc * osfd = ss->fd->lower; - SECStatus rv = SECFailure; + PRFileDesc *osfd = ss->fd->lower; + SECStatus rv = SECFailure; PRSocketOptionData opt; - opt.option = PR_SockOpt_NoDelay; + opt.option = PR_SockOpt_NoDelay; opt.value.no_delay = (PRBool)!enabled; if (osfd->methods->setsocketoption) { - rv = (SECStatus) osfd->methods->setsocketoption(osfd, &opt); + rv = (SECStatus)osfd->methods->setsocketoption(osfd, &opt); } else { PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); } @@ -487,7 +490,7 @@ ssl_ChooseOps(sslSocket *ss) static SECStatus PrepareSocket(sslSocket *ss) { - SECStatus rv = SECSuccess; + SECStatus rv = SECSuccess; ssl_ChooseOps(ss); return rv; @@ -499,35 +502,8 @@ SSL_Enable(PRFileDesc *fd, int which, PRBool on) return SSL_OptionSet(fd, which, on); } -#ifndef NO_PKCS11_BYPASS -static const PRCallOnceType pristineCallOnce; -static PRCallOnceType setupBypassOnce; - -static SECStatus SSL_BypassShutdown(void* appData, void* nssData) -{ - /* unload freeBL shared library from memory */ - BL_Unload(); - setupBypassOnce = pristineCallOnce; - return SECSuccess; -} - -static PRStatus SSL_BypassRegisterShutdown(void) -{ - SECStatus rv = NSS_RegisterShutdown(SSL_BypassShutdown, NULL); - PORT_Assert(SECSuccess == rv); - return SECSuccess == rv ? PR_SUCCESS : PR_FAILURE; -} -#endif - -static PRStatus SSL_BypassSetup(void) -{ -#ifdef NO_PKCS11_BYPASS - /* Guarantee binary compatibility */ - return PR_SUCCESS; -#else - return PR_CallOnce(&setupBypassOnce, &SSL_BypassRegisterShutdown); -#endif -} +static PRBool ssl_VersionIsSupportedByPolicy( + SSLProtocolVariant protocolVariant, SSL3ProtocolVersion version); /* Implements the semantics for SSL_OptionSet(SSL_ENABLE_TLS, on) described in * ssl.h in the section "SSL version range setting API". @@ -535,7 +511,14 @@ static PRStatus SSL_BypassSetup(void) static void ssl_EnableTLS(SSLVersionRange *vrange, PRBool on) { - if (SSL3_ALL_VERSIONS_DISABLED(vrange)) { + if (on) { + /* don't turn it on if tls1.0 disallowed by by policy */ + if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream, + SSL_LIBRARY_VERSION_TLS_1_0)) { + return; + } + } + if (SSL_ALL_VERSIONS_DISABLED(vrange)) { if (on) { vrange->min = SSL_LIBRARY_VERSION_TLS_1_0; vrange->max = SSL_LIBRARY_VERSION_TLS_1_0; @@ -565,7 +548,14 @@ ssl_EnableTLS(SSLVersionRange *vrange, PRBool on) static void ssl_EnableSSL3(SSLVersionRange *vrange, PRBool on) { - if (SSL3_ALL_VERSIONS_DISABLED(vrange)) { + if (on) { + /* don't turn it on if ssl3 disallowed by by policy */ + if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream, + SSL_LIBRARY_VERSION_3_0)) { + return; + } + } + if (SSL_ALL_VERSIONS_DISABLED(vrange)) { if (on) { vrange->min = SSL_LIBRARY_VERSION_3_0; vrange->max = SSL_LIBRARY_VERSION_3_0; @@ -573,13 +563,13 @@ ssl_EnableSSL3(SSLVersionRange *vrange, PRBool on) return; } - if (on) { + if (on) { /* Expand the range of enabled versions to include SSL 3.0. We know * SSL 3.0 or some version of TLS is already enabled at this point, so * we don't need to change vrange->max. */ vrange->min = SSL_LIBRARY_VERSION_3_0; - } else { + } else { /* Disable SSL 3.0, leaving TLS unaffected. */ if (vrange->max > SSL_LIBRARY_VERSION_3_0) { vrange->min = PR_MAX(vrange->min, SSL_LIBRARY_VERSION_TLS_1_0); @@ -595,8 +585,8 @@ SECStatus SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) { sslSocket *ss = ssl_FindSocket(fd); - SECStatus rv = SECSuccess; - PRBool holdingLocks; + SECStatus rv = SECSuccess; + PRBool holdingLocks; if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in Enable", SSL_GETPID(), fd)); @@ -608,231 +598,192 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) ssl_GetSSL3HandshakeLock(ss); switch (which) { - case SSL_SOCKS: - ss->opt.useSocks = PR_FALSE; - rv = PrepareSocket(ss); - if (on) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; - } - break; - - case SSL_SECURITY: - ss->opt.useSecurity = on; - rv = PrepareSocket(ss); - break; - - case SSL_REQUEST_CERTIFICATE: - ss->opt.requestCertificate = on; - break; + case SSL_SOCKS: + ss->opt.useSocks = PR_FALSE; + rv = PrepareSocket(ss); + if (on) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; + } + break; - case SSL_REQUIRE_CERTIFICATE: - ss->opt.requireCertificate = on; - break; + case SSL_SECURITY: + ss->opt.useSecurity = on; + rv = PrepareSocket(ss); + break; - case SSL_HANDSHAKE_AS_CLIENT: - if ( ss->opt.handshakeAsServer && on ) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; + case SSL_REQUEST_CERTIFICATE: + ss->opt.requestCertificate = on; break; - } - ss->opt.handshakeAsClient = on; - break; - case SSL_HANDSHAKE_AS_SERVER: - if ( ss->opt.handshakeAsClient && on ) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; + case SSL_REQUIRE_CERTIFICATE: + ss->opt.requireCertificate = on; break; - } - ss->opt.handshakeAsServer = on; - break; - case SSL_ENABLE_TLS: - if (IS_DTLS(ss)) { - if (on) { + case SSL_HANDSHAKE_AS_CLIENT: + if (ss->opt.handshakeAsServer && on) { PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; /* not allowed */ + rv = SECFailure; + break; } + ss->opt.handshakeAsClient = on; break; - } - ssl_EnableTLS(&ss->vrange, on); - ss->preferredCipher = NULL; - if (ss->cipherSpecs) { - PORT_Free(ss->cipherSpecs); - ss->cipherSpecs = NULL; - ss->sizeCipherSpecs = 0; - } - break; - case SSL_ENABLE_SSL3: - if (IS_DTLS(ss)) { - if (on) { + case SSL_HANDSHAKE_AS_SERVER: + if (ss->opt.handshakeAsClient && on) { PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; /* not allowed */ + rv = SECFailure; + break; } + ss->opt.handshakeAsServer = on; break; - } - ssl_EnableSSL3(&ss->vrange, on); - ss->preferredCipher = NULL; - if (ss->cipherSpecs) { - PORT_Free(ss->cipherSpecs); - ss->cipherSpecs = NULL; - ss->sizeCipherSpecs = 0; - } - break; - case SSL_ENABLE_SSL2: - if (IS_DTLS(ss)) { + case SSL_ENABLE_TLS: + if (IS_DTLS(ss)) { + if (on) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; /* not allowed */ + } + break; + } + ssl_EnableTLS(&ss->vrange, on); + break; + + case SSL_ENABLE_SSL3: + if (IS_DTLS(ss)) { + if (on) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; /* not allowed */ + } + break; + } + ssl_EnableSSL3(&ss->vrange, on); + break; + + case SSL_ENABLE_SSL2: + case SSL_V2_COMPATIBLE_HELLO: + /* We no longer support SSL v2. + * However, if an old application requests to disable SSL v2, + * we shouldn't fail. + */ if (on) { PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; /* not allowed */ + rv = SECFailure; } break; - } - ss->opt.enableSSL2 = on; - if (on) { - ss->opt.v2CompatibleHello = on; - } - ss->preferredCipher = NULL; - if (ss->cipherSpecs) { - PORT_Free(ss->cipherSpecs); - ss->cipherSpecs = NULL; - ss->sizeCipherSpecs = 0; - } - break; - case SSL_NO_CACHE: - ss->opt.noCache = on; - break; - - case SSL_ENABLE_FDX: - if (on && ss->opt.noLocks) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; - } - ss->opt.fdx = on; - break; + case SSL_NO_CACHE: + ss->opt.noCache = on; + break; - case SSL_V2_COMPATIBLE_HELLO: - if (IS_DTLS(ss)) { - if (on) { + case SSL_ENABLE_FDX: + if (on && ss->opt.noLocks) { PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; /* not allowed */ + rv = SECFailure; } + ss->opt.fdx = on; break; - } - ss->opt.v2CompatibleHello = on; - if (!on) { - ss->opt.enableSSL2 = on; - } - break; - case SSL_ROLLBACK_DETECTION: - ss->opt.detectRollBack = on; - break; + case SSL_ROLLBACK_DETECTION: + ss->opt.detectRollBack = on; + break; - case SSL_NO_STEP_DOWN: - ss->opt.noStepDown = on; - if (on) - SSL_DisableExportCipherSuites(fd); - break; + case SSL_NO_STEP_DOWN: + break; - case SSL_BYPASS_PKCS11: - if (ss->handshakeBegun) { - PORT_SetError(PR_INVALID_STATE_ERROR); - rv = SECFailure; - } else { - if (PR_FALSE != on) { - if (PR_SUCCESS == SSL_BypassSetup() ) { -#ifdef NO_PKCS11_BYPASS - ss->opt.bypassPKCS11 = PR_FALSE; -#else - ss->opt.bypassPKCS11 = on; -#endif - } else { - rv = SECFailure; + case SSL_BYPASS_PKCS11: + break; + + case SSL_NO_LOCKS: + if (on && ss->opt.fdx) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; + } + if (on && ssl_force_locks) + on = PR_FALSE; /* silent override */ + ss->opt.noLocks = on; + if (on) { + locksEverDisabled = PR_TRUE; + strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED."); + } else if (!holdingLocks) { + rv = ssl_MakeLocks(ss); + if (rv != SECSuccess) { + ss->opt.noLocks = PR_TRUE; } - } else { - ss->opt.bypassPKCS11 = PR_FALSE; } - } - break; + break; - case SSL_NO_LOCKS: - if (on && ss->opt.fdx) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; - } - if (on && ssl_force_locks) - on = PR_FALSE; /* silent override */ - ss->opt.noLocks = on; - if (on) { - locksEverDisabled = PR_TRUE; - strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED."); - } else if (!holdingLocks) { - rv = ssl_MakeLocks(ss); - if (rv != SECSuccess) { - ss->opt.noLocks = PR_TRUE; + case SSL_ENABLE_SESSION_TICKETS: + ss->opt.enableSessionTickets = on; + break; + + case SSL_ENABLE_DEFLATE: + ss->opt.enableDeflate = on; + break; + + case SSL_ENABLE_RENEGOTIATION: + if (IS_DTLS(ss) && on != SSL_RENEGOTIATE_NEVER) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; + break; } - } - break; + ss->opt.enableRenegotiation = on; + break; - case SSL_ENABLE_SESSION_TICKETS: - ss->opt.enableSessionTickets = on; - break; + case SSL_REQUIRE_SAFE_NEGOTIATION: + ss->opt.requireSafeNegotiation = on; + break; - case SSL_ENABLE_DEFLATE: - ss->opt.enableDeflate = on; - break; + case SSL_ENABLE_FALSE_START: + ss->opt.enableFalseStart = on; + break; - case SSL_ENABLE_RENEGOTIATION: - ss->opt.enableRenegotiation = on; - break; + case SSL_CBC_RANDOM_IV: + ss->opt.cbcRandomIV = on; + break; - case SSL_REQUIRE_SAFE_NEGOTIATION: - ss->opt.requireSafeNegotiation = on; - break; + case SSL_ENABLE_OCSP_STAPLING: + ss->opt.enableOCSPStapling = on; + break; - case SSL_ENABLE_FALSE_START: - ss->opt.enableFalseStart = on; - break; + case SSL_ENABLE_NPN: + break; - case SSL_CBC_RANDOM_IV: - ss->opt.cbcRandomIV = on; - break; + case SSL_ENABLE_ALPN: + ss->opt.enableALPN = on; + break; - case SSL_ENABLE_OCSP_STAPLING: - ss->opt.enableOCSPStapling = on; - break; + case SSL_REUSE_SERVER_ECDHE_KEY: + ss->opt.reuseServerECDHEKey = on; + break; - case SSL_ENABLE_NPN: - ss->opt.enableNPN = on; - break; + case SSL_ENABLE_FALLBACK_SCSV: + ss->opt.enableFallbackSCSV = on; + break; - case SSL_ENABLE_ALPN: - ss->opt.enableALPN = on; - break; + case SSL_ENABLE_SERVER_DHE: + ss->opt.enableServerDhe = on; + break; - case SSL_REUSE_SERVER_ECDHE_KEY: - ss->opt.reuseServerECDHEKey = on; - break; + case SSL_ENABLE_EXTENDED_MASTER_SECRET: + ss->opt.enableExtendedMS = on; + break; - case SSL_ENABLE_FALLBACK_SCSV: - ss->opt.enableFallbackSCSV = on; - break; + case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: + ss->opt.enableSignedCertTimestamps = on; + break; - case SSL_ENABLE_SERVER_DHE: - ss->opt.enableServerDhe = on; - break; + case SSL_REQUIRE_DH_NAMED_GROUPS: + ss->opt.requireDHENamedGroups = on; + break; - case SSL_ENABLE_EXTENDED_MASTER_SECRET: - ss->opt.enableExtendedMS = on; - break; + case SSL_ENABLE_0RTT_DATA: + ss->opt.enable0RttData = on; + break; - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; } /* We can't use the macros for releasing the locks here, @@ -852,8 +803,8 @@ SECStatus SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) { sslSocket *ss = ssl_FindSocket(fd); - SECStatus rv = SECSuccess; - PRBool on = PR_FALSE; + SECStatus rv = SECSuccess; + PRBool on = PR_FALSE; if (!pOn) { PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -869,49 +820,103 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) ssl_GetSSL3HandshakeLock(ss); switch (which) { - case SSL_SOCKS: on = PR_FALSE; break; - case SSL_SECURITY: on = ss->opt.useSecurity; break; - case SSL_REQUEST_CERTIFICATE: on = ss->opt.requestCertificate; break; - case SSL_REQUIRE_CERTIFICATE: on = ss->opt.requireCertificate; break; - case SSL_HANDSHAKE_AS_CLIENT: on = ss->opt.handshakeAsClient; break; - case SSL_HANDSHAKE_AS_SERVER: on = ss->opt.handshakeAsServer; break; - case SSL_ENABLE_TLS: - on = ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_0; - break; - case SSL_ENABLE_SSL3: - on = ss->vrange.min == SSL_LIBRARY_VERSION_3_0; - break; - case SSL_ENABLE_SSL2: on = ss->opt.enableSSL2; break; - case SSL_NO_CACHE: on = ss->opt.noCache; break; - case SSL_ENABLE_FDX: on = ss->opt.fdx; break; - case SSL_V2_COMPATIBLE_HELLO: on = ss->opt.v2CompatibleHello; break; - case SSL_ROLLBACK_DETECTION: on = ss->opt.detectRollBack; break; - case SSL_NO_STEP_DOWN: on = ss->opt.noStepDown; break; - case SSL_BYPASS_PKCS11: on = ss->opt.bypassPKCS11; break; - case SSL_NO_LOCKS: on = ss->opt.noLocks; break; - case SSL_ENABLE_SESSION_TICKETS: - on = ss->opt.enableSessionTickets; - break; - case SSL_ENABLE_DEFLATE: on = ss->opt.enableDeflate; break; - case SSL_ENABLE_RENEGOTIATION: - on = ss->opt.enableRenegotiation; break; - case SSL_REQUIRE_SAFE_NEGOTIATION: - on = ss->opt.requireSafeNegotiation; break; - case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break; - case SSL_CBC_RANDOM_IV: on = ss->opt.cbcRandomIV; break; - case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break; - case SSL_ENABLE_NPN: on = ss->opt.enableNPN; break; - case SSL_ENABLE_ALPN: on = ss->opt.enableALPN; break; - 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; - - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; + case SSL_SOCKS: + on = PR_FALSE; + break; + case SSL_SECURITY: + on = ss->opt.useSecurity; + break; + case SSL_REQUEST_CERTIFICATE: + on = ss->opt.requestCertificate; + break; + case SSL_REQUIRE_CERTIFICATE: + on = ss->opt.requireCertificate; + break; + case SSL_HANDSHAKE_AS_CLIENT: + on = ss->opt.handshakeAsClient; + break; + case SSL_HANDSHAKE_AS_SERVER: + on = ss->opt.handshakeAsServer; + break; + case SSL_ENABLE_TLS: + on = ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_0; + break; + case SSL_ENABLE_SSL3: + on = ss->vrange.min == SSL_LIBRARY_VERSION_3_0; + break; + case SSL_ENABLE_SSL2: + case SSL_V2_COMPATIBLE_HELLO: + on = PR_FALSE; + break; + case SSL_NO_CACHE: + on = ss->opt.noCache; + break; + case SSL_ENABLE_FDX: + on = ss->opt.fdx; + break; + case SSL_ROLLBACK_DETECTION: + on = ss->opt.detectRollBack; + break; + case SSL_NO_STEP_DOWN: + on = PR_FALSE; + break; + case SSL_BYPASS_PKCS11: + on = PR_FALSE; + break; + case SSL_NO_LOCKS: + on = ss->opt.noLocks; + break; + case SSL_ENABLE_SESSION_TICKETS: + on = ss->opt.enableSessionTickets; + break; + case SSL_ENABLE_DEFLATE: + on = ss->opt.enableDeflate; + break; + case SSL_ENABLE_RENEGOTIATION: + on = ss->opt.enableRenegotiation; + break; + case SSL_REQUIRE_SAFE_NEGOTIATION: + on = ss->opt.requireSafeNegotiation; + break; + case SSL_ENABLE_FALSE_START: + on = ss->opt.enableFalseStart; + break; + case SSL_CBC_RANDOM_IV: + on = ss->opt.cbcRandomIV; + break; + case SSL_ENABLE_OCSP_STAPLING: + on = ss->opt.enableOCSPStapling; + break; + case SSL_ENABLE_NPN: + on = ss->opt.enableNPN; + break; + case SSL_ENABLE_ALPN: + on = ss->opt.enableALPN; + break; + 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; + case SSL_REQUIRE_DH_NAMED_GROUPS: + on = ss->opt.requireDHENamedGroups; + break; + case SSL_ENABLE_0RTT_DATA: + on = ss->opt.enable0RttData; + break; + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; } ssl_ReleaseSSL3HandshakeLock(ss); @@ -924,8 +929,8 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) SECStatus SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) { - SECStatus rv = SECSuccess; - PRBool on = PR_FALSE; + SECStatus rv = SECSuccess; + PRBool on = PR_FALSE; if (!pOn) { PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -935,58 +940,100 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) ssl_SetDefaultsFromEnvironment(); switch (which) { - case SSL_SOCKS: on = PR_FALSE; break; - case SSL_SECURITY: on = ssl_defaults.useSecurity; break; - case SSL_REQUEST_CERTIFICATE: on = ssl_defaults.requestCertificate; break; - case SSL_REQUIRE_CERTIFICATE: on = ssl_defaults.requireCertificate; break; - case SSL_HANDSHAKE_AS_CLIENT: on = ssl_defaults.handshakeAsClient; break; - case SSL_HANDSHAKE_AS_SERVER: on = ssl_defaults.handshakeAsServer; break; - case SSL_ENABLE_TLS: - on = versions_defaults_stream.max >= SSL_LIBRARY_VERSION_TLS_1_0; - break; - case SSL_ENABLE_SSL3: - on = versions_defaults_stream.min == SSL_LIBRARY_VERSION_3_0; - break; - case SSL_ENABLE_SSL2: on = ssl_defaults.enableSSL2; break; - case SSL_NO_CACHE: on = ssl_defaults.noCache; break; - case SSL_ENABLE_FDX: on = ssl_defaults.fdx; break; - case SSL_V2_COMPATIBLE_HELLO: on = ssl_defaults.v2CompatibleHello; break; - case SSL_ROLLBACK_DETECTION: on = ssl_defaults.detectRollBack; break; - case SSL_NO_STEP_DOWN: on = ssl_defaults.noStepDown; break; - case SSL_BYPASS_PKCS11: on = ssl_defaults.bypassPKCS11; break; - case SSL_NO_LOCKS: on = ssl_defaults.noLocks; break; - case SSL_ENABLE_SESSION_TICKETS: - on = ssl_defaults.enableSessionTickets; - break; - case SSL_ENABLE_DEFLATE: on = ssl_defaults.enableDeflate; break; - case SSL_ENABLE_RENEGOTIATION: - on = ssl_defaults.enableRenegotiation; break; - case SSL_REQUIRE_SAFE_NEGOTIATION: - on = ssl_defaults.requireSafeNegotiation; - break; - case SSL_ENABLE_FALSE_START: on = ssl_defaults.enableFalseStart; break; - case SSL_CBC_RANDOM_IV: on = ssl_defaults.cbcRandomIV; break; - case SSL_ENABLE_OCSP_STAPLING: - on = ssl_defaults.enableOCSPStapling; - break; - case SSL_ENABLE_NPN: on = ssl_defaults.enableNPN; break; - case SSL_ENABLE_ALPN: on = ssl_defaults.enableALPN; break; - case SSL_REUSE_SERVER_ECDHE_KEY: - on = ssl_defaults.reuseServerECDHEKey; - break; - 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; - - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; + case SSL_SOCKS: + on = PR_FALSE; + break; + case SSL_SECURITY: + on = ssl_defaults.useSecurity; + break; + case SSL_REQUEST_CERTIFICATE: + on = ssl_defaults.requestCertificate; + break; + case SSL_REQUIRE_CERTIFICATE: + on = ssl_defaults.requireCertificate; + break; + case SSL_HANDSHAKE_AS_CLIENT: + on = ssl_defaults.handshakeAsClient; + break; + case SSL_HANDSHAKE_AS_SERVER: + on = ssl_defaults.handshakeAsServer; + break; + case SSL_ENABLE_TLS: + on = versions_defaults_stream.max >= SSL_LIBRARY_VERSION_TLS_1_0; + break; + case SSL_ENABLE_SSL3: + on = versions_defaults_stream.min == SSL_LIBRARY_VERSION_3_0; + break; + case SSL_ENABLE_SSL2: + case SSL_V2_COMPATIBLE_HELLO: + on = PR_FALSE; + break; + case SSL_NO_CACHE: + on = ssl_defaults.noCache; + break; + case SSL_ENABLE_FDX: + on = ssl_defaults.fdx; + break; + case SSL_ROLLBACK_DETECTION: + on = ssl_defaults.detectRollBack; + break; + case SSL_NO_STEP_DOWN: + on = PR_FALSE; + break; + case SSL_BYPASS_PKCS11: + on = PR_FALSE; + break; + case SSL_NO_LOCKS: + on = ssl_defaults.noLocks; + break; + case SSL_ENABLE_SESSION_TICKETS: + on = ssl_defaults.enableSessionTickets; + break; + case SSL_ENABLE_DEFLATE: + on = ssl_defaults.enableDeflate; + break; + case SSL_ENABLE_RENEGOTIATION: + on = ssl_defaults.enableRenegotiation; + break; + case SSL_REQUIRE_SAFE_NEGOTIATION: + on = ssl_defaults.requireSafeNegotiation; + break; + case SSL_ENABLE_FALSE_START: + on = ssl_defaults.enableFalseStart; + break; + case SSL_CBC_RANDOM_IV: + on = ssl_defaults.cbcRandomIV; + break; + case SSL_ENABLE_OCSP_STAPLING: + on = ssl_defaults.enableOCSPStapling; + break; + case SSL_ENABLE_NPN: + on = ssl_defaults.enableNPN; + break; + case SSL_ENABLE_ALPN: + on = ssl_defaults.enableALPN; + break; + case SSL_REUSE_SERVER_ECDHE_KEY: + on = ssl_defaults.reuseServerECDHEKey; + break; + 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; + case SSL_ENABLE_0RTT_DATA: + on = ssl_defaults.enable0RttData; + break; + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; } *pOn = on; @@ -1012,171 +1059,160 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) ssl_SetDefaultsFromEnvironment(); switch (which) { - case SSL_SOCKS: - ssl_defaults.useSocks = PR_FALSE; - if (on) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - break; + case SSL_SOCKS: + ssl_defaults.useSocks = PR_FALSE; + if (on) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + break; - case SSL_SECURITY: - ssl_defaults.useSecurity = on; - break; + case SSL_SECURITY: + ssl_defaults.useSecurity = on; + break; - case SSL_REQUEST_CERTIFICATE: - ssl_defaults.requestCertificate = on; - break; + case SSL_REQUEST_CERTIFICATE: + ssl_defaults.requestCertificate = on; + break; - case SSL_REQUIRE_CERTIFICATE: - ssl_defaults.requireCertificate = on; - break; + case SSL_REQUIRE_CERTIFICATE: + ssl_defaults.requireCertificate = on; + break; - case SSL_HANDSHAKE_AS_CLIENT: - if ( ssl_defaults.handshakeAsServer && on ) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - ssl_defaults.handshakeAsClient = on; - break; + case SSL_HANDSHAKE_AS_CLIENT: + if (ssl_defaults.handshakeAsServer && on) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + ssl_defaults.handshakeAsClient = on; + break; - case SSL_HANDSHAKE_AS_SERVER: - if ( ssl_defaults.handshakeAsClient && on ) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - ssl_defaults.handshakeAsServer = on; - break; + case SSL_HANDSHAKE_AS_SERVER: + if (ssl_defaults.handshakeAsClient && on) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + ssl_defaults.handshakeAsServer = on; + break; - case SSL_ENABLE_TLS: - ssl_EnableTLS(&versions_defaults_stream, on); - break; + case SSL_ENABLE_TLS: + ssl_EnableTLS(&versions_defaults_stream, on); + break; - case SSL_ENABLE_SSL3: - ssl_EnableSSL3(&versions_defaults_stream, on); - break; + case SSL_ENABLE_SSL3: + ssl_EnableSSL3(&versions_defaults_stream, on); + break; - case SSL_ENABLE_SSL2: - ssl_defaults.enableSSL2 = on; - if (on) { - ssl_defaults.v2CompatibleHello = on; - } - break; + case SSL_ENABLE_SSL2: + case SSL_V2_COMPATIBLE_HELLO: + /* We no longer support SSL v2. + * However, if an old application requests to disable SSL v2, + * we shouldn't fail. + */ + if (on) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + break; - case SSL_NO_CACHE: - ssl_defaults.noCache = on; - break; + case SSL_NO_CACHE: + ssl_defaults.noCache = on; + break; - case SSL_ENABLE_FDX: - if (on && ssl_defaults.noLocks) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - ssl_defaults.fdx = on; - break; + case SSL_ENABLE_FDX: + if (on && ssl_defaults.noLocks) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + ssl_defaults.fdx = on; + break; - case SSL_V2_COMPATIBLE_HELLO: - ssl_defaults.v2CompatibleHello = on; - if (!on) { - ssl_defaults.enableSSL2 = on; - } - break; - - case SSL_ROLLBACK_DETECTION: - ssl_defaults.detectRollBack = on; - break; - - case SSL_NO_STEP_DOWN: - ssl_defaults.noStepDown = on; - if (on) - SSL_DisableDefaultExportCipherSuites(); - break; - - case SSL_BYPASS_PKCS11: - if (PR_FALSE != on) { - if (PR_SUCCESS == SSL_BypassSetup()) { -#ifdef NO_PKCS11_BYPASS - ssl_defaults.bypassPKCS11 = PR_FALSE; -#else - ssl_defaults.bypassPKCS11 = on; -#endif - } else { + case SSL_ROLLBACK_DETECTION: + ssl_defaults.detectRollBack = on; + break; + + case SSL_NO_STEP_DOWN: + break; + + case SSL_BYPASS_PKCS11: + break; + + case SSL_NO_LOCKS: + if (on && ssl_defaults.fdx) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - } else { - ssl_defaults.bypassPKCS11 = PR_FALSE; - } - break; + if (on && ssl_force_locks) + on = PR_FALSE; /* silent override */ + ssl_defaults.noLocks = on; + if (on) { + locksEverDisabled = PR_TRUE; + strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED."); + } + break; - case SSL_NO_LOCKS: - if (on && ssl_defaults.fdx) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - if (on && ssl_force_locks) - on = PR_FALSE; /* silent override */ - ssl_defaults.noLocks = on; - if (on) { - locksEverDisabled = PR_TRUE; - strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED."); - } - break; + case SSL_ENABLE_SESSION_TICKETS: + ssl_defaults.enableSessionTickets = on; + break; - case SSL_ENABLE_SESSION_TICKETS: - ssl_defaults.enableSessionTickets = on; - break; + case SSL_ENABLE_DEFLATE: + ssl_defaults.enableDeflate = on; + break; - case SSL_ENABLE_DEFLATE: - ssl_defaults.enableDeflate = on; - break; + case SSL_ENABLE_RENEGOTIATION: + ssl_defaults.enableRenegotiation = on; + break; - case SSL_ENABLE_RENEGOTIATION: - ssl_defaults.enableRenegotiation = on; - break; + case SSL_REQUIRE_SAFE_NEGOTIATION: + ssl_defaults.requireSafeNegotiation = on; + break; - case SSL_REQUIRE_SAFE_NEGOTIATION: - ssl_defaults.requireSafeNegotiation = on; - break; + case SSL_ENABLE_FALSE_START: + ssl_defaults.enableFalseStart = on; + break; - case SSL_ENABLE_FALSE_START: - ssl_defaults.enableFalseStart = on; - break; + case SSL_CBC_RANDOM_IV: + ssl_defaults.cbcRandomIV = on; + break; - case SSL_CBC_RANDOM_IV: - ssl_defaults.cbcRandomIV = on; - break; + case SSL_ENABLE_OCSP_STAPLING: + ssl_defaults.enableOCSPStapling = on; + break; - case SSL_ENABLE_OCSP_STAPLING: - ssl_defaults.enableOCSPStapling = on; - break; + case SSL_ENABLE_NPN: + break; - case SSL_ENABLE_NPN: - ssl_defaults.enableNPN = on; - break; + case SSL_ENABLE_ALPN: + ssl_defaults.enableALPN = on; + break; - case SSL_ENABLE_ALPN: - ssl_defaults.enableALPN = on; - break; + case SSL_REUSE_SERVER_ECDHE_KEY: + ssl_defaults.reuseServerECDHEKey = on; + break; - case SSL_REUSE_SERVER_ECDHE_KEY: - ssl_defaults.reuseServerECDHEKey = on; - break; + case SSL_ENABLE_FALLBACK_SCSV: + ssl_defaults.enableFallbackSCSV = on; + break; - case SSL_ENABLE_FALLBACK_SCSV: - 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_SERVER_DHE: - ssl_defaults.enableServerDhe = on; - break; + case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: + ssl_defaults.enableSignedCertTimestamps = on; + break; - case SSL_ENABLE_EXTENDED_MASTER_SECRET: - ssl_defaults.enableExtendedMS = on; - break; + case SSL_ENABLE_0RTT_DATA: + ssl_defaults.enable0RttData = on; + break; - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } return SECSuccess; } @@ -1186,12 +1222,12 @@ static PRBool ssl_IsRemovedCipherSuite(PRInt32 suite) { switch (suite) { - case SSL_FORTEZZA_DMS_WITH_NULL_SHA: - case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: - case SSL_FORTEZZA_DMS_WITH_RC4_128_SHA: - return PR_TRUE; - default: - return PR_FALSE; + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: + case SSL_FORTEZZA_DMS_WITH_RC4_128_SHA: + return PR_TRUE; + default: + return PR_FALSE; } } @@ -1202,36 +1238,33 @@ ssl_IsRemovedCipherSuite(PRInt32 suite) SECStatus SSL_SetPolicy(long which, int policy) { - if ((which & 0xfffe) == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA) { - /* one of the two old FIPS ciphers */ - if (which == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA) - which = SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA; - else if (which == SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA) - which = SSL_RSA_FIPS_WITH_DES_CBC_SHA; - } if (ssl_IsRemovedCipherSuite(which)) return SECSuccess; return SSL_CipherPolicySet(which, policy); } SECStatus -SSL_CipherPolicySet(PRInt32 which, PRInt32 policy) +ssl_CipherPolicySet(PRInt32 which, PRInt32 policy) { - SECStatus rv = ssl_Init(); - - if (rv != SECSuccess) { - return rv; - } + SECStatus rv = SECSuccess; if (ssl_IsRemovedCipherSuite(which)) { rv = SECSuccess; - } else if (SSL_IS_SSL2_CIPHER(which)) { - rv = ssl2_SetPolicy(which, policy); } else { rv = ssl3_SetPolicy((ssl3CipherSuite)which, policy); } return rv; } +SECStatus +SSL_CipherPolicySet(PRInt32 which, PRInt32 policy) +{ + SECStatus rv = ssl_Init(); + + if (rv != SECSuccess) { + return rv; + } + return ssl_CipherPolicySet(which, policy); +} SECStatus SSL_CipherPolicyGet(PRInt32 which, PRInt32 *oPolicy) @@ -1245,8 +1278,6 @@ SSL_CipherPolicyGet(PRInt32 which, PRInt32 *oPolicy) if (ssl_IsRemovedCipherSuite(which)) { *oPolicy = SSL_NOT_ALLOWED; rv = SECSuccess; - } else if (SSL_IS_SSL2_CIPHER(which)) { - rv = ssl2_GetPolicy(which, oPolicy); } else { rv = ssl3_GetPolicy((ssl3CipherSuite)which, oPolicy); } @@ -1261,19 +1292,20 @@ SSL_CipherPolicyGet(PRInt32 which, PRInt32 *oPolicy) SECStatus SSL_EnableCipher(long which, PRBool enabled) { - if ((which & 0xfffe) == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA) { - /* one of the two old FIPS ciphers */ - if (which == SSL_RSA_OLDFIPS_WITH_3DES_EDE_CBC_SHA) - which = SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA; - else if (which == SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA) - which = SSL_RSA_FIPS_WITH_DES_CBC_SHA; - } if (ssl_IsRemovedCipherSuite(which)) return SECSuccess; return SSL_CipherPrefSetDefault(which, enabled); } SECStatus +ssl_CipherPrefSetDefault(PRInt32 which, PRBool enabled) +{ + if (ssl_IsRemovedCipherSuite(which)) + return SECSuccess; + return ssl3_CipherPrefSetDefault((ssl3CipherSuite)which, enabled); +} + +SECStatus SSL_CipherPrefSetDefault(PRInt32 which, PRBool enabled) { SECStatus rv = ssl_Init(); @@ -1281,25 +1313,13 @@ SSL_CipherPrefSetDefault(PRInt32 which, PRBool enabled) if (rv != SECSuccess) { return rv; } - - if (ssl_IsRemovedCipherSuite(which)) - return SECSuccess; - if (enabled && ssl_defaults.noStepDown && SSL_IsExportCipherSuite(which)) { - PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); - return SECFailure; - } - if (SSL_IS_SSL2_CIPHER(which)) { - rv = ssl2_CipherPrefSetDefault(which, enabled); - } else { - rv = ssl3_CipherPrefSetDefault((ssl3CipherSuite)which, enabled); - } - return rv; + return ssl_CipherPrefSetDefault(which, enabled); } SECStatus SSL_CipherPrefGetDefault(PRInt32 which, PRBool *enabled) { - SECStatus rv; + SECStatus rv; if (!enabled) { PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -1308,8 +1328,6 @@ SSL_CipherPrefGetDefault(PRInt32 which, PRBool *enabled) if (ssl_IsRemovedCipherSuite(which)) { *enabled = PR_FALSE; rv = SECSuccess; - } else if (SSL_IS_SSL2_CIPHER(which)) { - rv = ssl2_CipherPrefGetDefault(which, enabled); } else { rv = ssl3_CipherPrefGetDefault((ssl3CipherSuite)which, enabled); } @@ -1319,7 +1337,6 @@ SSL_CipherPrefGetDefault(PRInt32 which, PRBool *enabled) SECStatus SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled) { - SECStatus rv; sslSocket *ss = ssl_FindSocket(fd); if (!ss) { @@ -1328,22 +1345,13 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled) } if (ssl_IsRemovedCipherSuite(which)) return SECSuccess; - if (enabled && ss->opt.noStepDown && SSL_IsExportCipherSuite(which)) { - PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); - return SECFailure; - } - if (SSL_IS_SSL2_CIPHER(which)) { - rv = ssl2_CipherPrefSet(ss, which, enabled); - } else { - rv = ssl3_CipherPrefSet(ss, (ssl3CipherSuite)which, enabled); - } - return rv; + return ssl3_CipherPrefSet(ss, (ssl3CipherSuite)which, enabled); } SECStatus SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled) { - SECStatus rv; + SECStatus rv; sslSocket *ss = ssl_FindSocket(fd); if (!enabled) { @@ -1358,8 +1366,6 @@ SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled) if (ssl_IsRemovedCipherSuite(which)) { *enabled = PR_FALSE; rv = SECSuccess; - } else if (SSL_IS_SSL2_CIPHER(which)) { - rv = ssl2_CipherPrefGet(ss, which, enabled); } else { rv = ssl3_CipherPrefGet(ss, (ssl3CipherSuite)which, enabled); } @@ -1369,8 +1375,16 @@ SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled) SECStatus NSS_SetDomesticPolicy(void) { - SECStatus status = SECSuccess; + SECStatus status = SECSuccess; const PRUint16 *cipher; + SECStatus rv; + PRUint32 policy; + + /* If we've already defined some policy oids, skip changing them */ + rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &policy); + if ((rv == SECSuccess) && (policy & NSS_USE_POLICY_IN_SSL)) { + return ssl_Init(); /* make sure the policies have bee loaded */ + } for (cipher = SSL_ImplementedCiphers; *cipher != 0; ++cipher) { status = SSL_SetPolicy(*cipher, SSL_ALLOWED); @@ -1393,13 +1407,54 @@ NSS_SetFrancePolicy(void) } SECStatus -SSL_DHEGroupPrefSet(PRFileDesc *fd, - SSLDHEGroupType *groups, +SSL_NamedGroupConfig(PRFileDesc *fd, const SSLNamedGroup *groups, + unsigned int numGroups) +{ + unsigned int i; + unsigned int j = 0; + sslSocket *ss = ssl_FindSocket(fd); + + if (!ss) { + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); + return SECFailure; + } + + if (!groups) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (numGroups > SSL_NAMED_GROUP_COUNT) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + memset((void *)ss->namedGroupPreferences, 0, + sizeof(ss->namedGroupPreferences)); + for (i = 0; i < numGroups; ++i) { + const sslNamedGroupDef *groupDef = ssl_LookupNamedGroup(groups[i]); + if (!ssl_NamedGroupEnabled(ss, groupDef)) { + ss->namedGroupPreferences[j++] = groupDef; + } + } + + return SECSuccess; +} + +SECStatus +SSL_DHEGroupPrefSet(PRFileDesc *fd, const SSLDHEGroupType *groups, PRUint16 num_groups) { sslSocket *ss; - - if ((num_groups && !groups) || (!num_groups && groups)) { + const SSLDHEGroupType *list; + unsigned int count; + int i, k, j; + const sslNamedGroupDef *enabled[SSL_NAMED_GROUP_COUNT] = { 0 }; + static const SSLDHEGroupType default_dhe_groups[] = { + ssl_ff_dhe_2048_group + }; + + if ((num_groups && !groups) || (!num_groups && groups) || + num_groups > SSL_NAMED_GROUP_COUNT) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -1410,25 +1465,73 @@ SSL_DHEGroupPrefSet(PRFileDesc *fd, return SECFailure; } - if (ss->ssl3.dheGroups) { - PORT_Free(ss->ssl3.dheGroups); - ss->ssl3.dheGroups = NULL; - ss->ssl3.numDHEGroups = 0; + if (groups) { + list = groups; + count = num_groups; + } else { + list = default_dhe_groups; + count = PR_ARRAY_SIZE(default_dhe_groups); + } + + /* save enabled ec groups and clear ss->namedGroupPreferences */ + k = 0; + for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { + if (ss->namedGroupPreferences[i] && + ss->namedGroupPreferences[i]->keaType != ssl_kea_dh) { + enabled[k++] = ss->namedGroupPreferences[i]; + } + ss->namedGroupPreferences[i] = NULL; } - if (groups) { - ss->ssl3.dheGroups = PORT_NewArray(SSLDHEGroupType, num_groups); - if (!ss->ssl3.dheGroups) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; + ss->ssl3.dhePreferredGroup = NULL; + for (i = 0; i < count; ++i) { + PRBool duplicate = PR_FALSE; + SSLNamedGroup name; + const sslNamedGroupDef *groupDef; + switch (list[i]) { + case ssl_ff_dhe_2048_group: + name = ssl_grp_ffdhe_2048; + break; + case ssl_ff_dhe_3072_group: + name = ssl_grp_ffdhe_3072; + break; + case ssl_ff_dhe_4096_group: + name = ssl_grp_ffdhe_4096; + break; + case ssl_ff_dhe_6144_group: + name = ssl_grp_ffdhe_6144; + break; + case ssl_ff_dhe_8192_group: + name = ssl_grp_ffdhe_8192; + break; + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + groupDef = ssl_LookupNamedGroup(name); + PORT_Assert(groupDef); + if (!ss->ssl3.dhePreferredGroup) { + ss->ssl3.dhePreferredGroup = groupDef; + } + PORT_Assert(k < SSL_NAMED_GROUP_COUNT); + for (j = 0; j < k; ++j) { + /* skip duplicates */ + if (enabled[j] == groupDef) { + duplicate = PR_TRUE; + break; + } } - PORT_Memcpy(ss->ssl3.dheGroups, groups, - sizeof(SSLDHEGroupType) * num_groups); + if (!duplicate) { + enabled[k++] = groupDef; + } + } + for (i = 0; i < k; ++i) { + ss->namedGroupPreferences[i] = enabled[i]; } + return SECSuccess; } - PRCallOnceType gWeakDHParamsRegisterOnce; int gWeakDHParamsRegisterError; @@ -1438,6 +1541,7 @@ int gWeakDHParamsError; * even though we only make use of it's parameters through gWeakDHParam. */ static PQGParams *gWeakParamsPQG; static ssl3DHParams *gWeakDHParams; +#define WEAK_DHE_SIZE 1024 static PRStatus ssl3_CreateWeakDHParams(void) @@ -1447,7 +1551,7 @@ ssl3_CreateWeakDHParams(void) PORT_Assert(!gWeakDHParams && !gWeakParamsPQG); - rv = PK11_PQG_ParamGenV2(1024, 160, 64 /*maximum seed that will work*/, + rv = PK11_PQG_ParamGenV2(WEAK_DHE_SIZE, 160, 64 /*maximum seed that will work*/, &gWeakParamsPQG, &vfy); if (rv != SECSuccess) { gWeakDHParamsError = PORT_GetError(); @@ -1457,7 +1561,7 @@ ssl3_CreateWeakDHParams(void) rv = PK11_PQG_VerifyParams(gWeakParamsPQG, vfy, &passed); if (rv != SECSuccess || passed != SECSuccess) { SSL_DBG(("%d: PK11_PQG_VerifyParams failed in ssl3_CreateWeakDHParams", - SSL_GETPID())); + SSL_GETPID())); gWeakDHParamsError = PORT_GetError(); return PR_FAILURE; } @@ -1468,6 +1572,7 @@ ssl3_CreateWeakDHParams(void) return PR_FAILURE; } + gWeakDHParams->name = ssl_grp_ffdhe_custom; gWeakDHParams->prime.data = gWeakParamsPQG->prime.data; gWeakDHParams->prime.len = gWeakParamsPQG->prime.len; gWeakDHParams->base.data = gWeakParamsPQG->base.data; @@ -1536,69 +1641,163 @@ SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled) #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, -}; +const ssl3DHParams * +ssl_GetDHEParams(const sslNamedGroupDef *groupDef) +{ + switch (groupDef->name) { + case ssl_grp_ffdhe_2048: + return &ff_dhe_2048_params; + case ssl_grp_ffdhe_3072: + return &ff_dhe_3072_params; + case ssl_grp_ffdhe_4096: + return &ff_dhe_4096_params; + case ssl_grp_ffdhe_6144: + return &ff_dhe_6144_params; + case ssl_grp_ffdhe_8192: + return &ff_dhe_8192_params; + case ssl_grp_ffdhe_custom: + PORT_Assert(gWeakDHParams); + return gWeakDHParams; + default: + PORT_Assert(0); + } + return NULL; +} -static SSLDHEGroupType -selectDHEGroup(sslSocket *ss, const SSLDHEGroupType *groups, PRUint16 num_groups) +/* This validates dh_Ys against the group prime. */ +PRBool +ssl_IsValidDHEShare(const SECItem *dh_p, const SECItem *dh_Ys) { - if (!groups || !num_groups) - return ssl_dhe_group_none; + unsigned int size_p = SECKEY_BigIntegerBitLength(dh_p); + unsigned int size_y = SECKEY_BigIntegerBitLength(dh_Ys); + unsigned int commonPart; + int cmp; - /* 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]; + if (dh_p->len == 0 || dh_Ys->len == 0) { + return PR_FALSE; + } + /* Check that the prime is at least odd. */ + if ((dh_p->data[dh_p->len - 1] & 0x01) == 0) { + return PR_FALSE; + } + /* dh_Ys can't be 1, or bigger than dh_p. */ + if (size_y <= 1 || size_y > size_p) { + return PR_FALSE; + } + /* If dh_Ys is shorter, then it's definitely smaller than p-1. */ + if (size_y < size_p) { + return PR_TRUE; + } + + /* Compare the common part of each, minus the final octet. */ + commonPart = (size_p + 7) / 8; + PORT_Assert(commonPart <= dh_Ys->len); + PORT_Assert(commonPart <= dh_p->len); + cmp = PORT_Memcmp(dh_Ys->data + dh_Ys->len - commonPart, + dh_p->data + dh_p->len - commonPart, commonPart - 1); + if (cmp < 0) { + return PR_TRUE; + } + if (cmp > 0) { + return PR_FALSE; + } + + /* The last octet of the prime is the only thing that is different and that + * has to be two greater than the share, otherwise we have Ys == p - 1, + * and that means small subgroups. */ + if (dh_Ys->data[dh_Ys->len - 1] >= (dh_p->data[dh_p->len - 1] - 1)) { + return PR_FALSE; + } + + return PR_TRUE; } -/* Ensure DH parameters have been selected */ +/* Checks that the provided DH parameters match those in one of the named groups + * that we have enabled. The groups are defined in dhe-param.c and are those + * defined in Appendix A of draft-ietf-tls-negotiated-ff-dhe. + * + * |groupDef| and |dhParams| are optional outparams that identify the group and + * its parameters respectively (if this is successful). */ SECStatus -ssl3_SelectDHParams(sslSocket *ss) +ssl_ValidateDHENamedGroup(sslSocket *ss, + const SECItem *dh_p, + const SECItem *dh_g, + const sslNamedGroupDef **groupDef, + const ssl3DHParams **dhParams) { - SSLDHEGroupType selectedGroup = ssl_dhe_group_none; + unsigned int i; - 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); + for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { + const ssl3DHParams *params; + if (!ss->namedGroupPreferences[i]) { + continue; + } + if (ss->namedGroupPreferences[i]->keaType != ssl_kea_dh) { + continue; } - if (selectedGroup == ssl_dhe_group_none || - selectedGroup >= ssl_dhe_group_max) { - return SECFailure; + params = ssl_GetDHEParams(ss->namedGroupPreferences[i]); + PORT_Assert(params); + if (SECITEM_ItemsAreEqual(¶ms->prime, dh_p)) { + if (!SECITEM_ItemsAreEqual(¶ms->base, dh_g)) { + return SECFailure; + } + if (groupDef) + *groupDef = ss->namedGroupPreferences[i]; + if (dhParams) + *dhParams = params; + return SECSuccess; } + } - ss->dheParams = all_ssl3DHParams[selectedGroup]; + return SECFailure; +} + +/* Ensure DH parameters have been selected. This just picks the first enabled + * FFDHE group in ssl_named_groups, or the weak one if it was enabled. */ +SECStatus +ssl_SelectDHEGroup(sslSocket *ss, const sslNamedGroupDef **groupDef) +{ + unsigned int i; + static const sslNamedGroupDef weak_group_def = { + ssl_grp_ffdhe_custom, WEAK_DHE_SIZE, ssl_kea_dh, + SEC_OID_TLS_DHE_CUSTOM, PR_TRUE + }; + + /* Only select weak groups in TLS 1.2 and earlier, but not if the client has + * indicated that it supports an FFDHE named group. */ + if (ss->ssl3.dheWeakGroupEnabled && + ss->version < SSL_LIBRARY_VERSION_TLS_1_3 && + !ss->xtnData.peerSupportsFfdheGroups) { + *groupDef = &weak_group_def; + return SECSuccess; + } + if (ss->ssl3.dhePreferredGroup && + ssl_NamedGroupEnabled(ss, ss->ssl3.dhePreferredGroup)) { + *groupDef = ss->ssl3.dhePreferredGroup; + return SECSuccess; + } + for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { + if (ss->namedGroupPreferences[i] && + ss->namedGroupPreferences[i]->keaType == ssl_kea_dh) { + *groupDef = ss->namedGroupPreferences[i]; + return SECSuccess; + } } - return SECSuccess; + *groupDef = NULL; + PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); + return SECFailure; } /* LOCKS ??? XXX */ static PRFileDesc * ssl_ImportFD(PRFileDesc *model, PRFileDesc *fd, SSLProtocolVariant variant) { - sslSocket * ns = NULL; - PRStatus rv; - PRNetAddr addr; - SECStatus status = ssl_Init(); + sslSocket *ns = NULL; + PRStatus rv; + PRNetAddr addr; + SECStatus status = ssl_Init(); if (status != SECSuccess) { return NULL; @@ -1608,10 +1807,10 @@ ssl_ImportFD(PRFileDesc *model, PRFileDesc *fd, SSLProtocolVariant variant) /* Just create a default socket if we're given NULL for the model */ ns = ssl_NewSocket((PRBool)(!ssl_defaults.noLocks), variant); } else { - sslSocket * ss = ssl_FindSocket(model); + sslSocket *ss = ssl_FindSocket(model); if (ss == NULL || ss->protocolVariant != variant) { SSL_DBG(("%d: SSL[%d]: bad model socket in ssl_ImportFD", - SSL_GETPID(), model)); + SSL_GETPID(), model)); return NULL; } ns = ssl_DupSocket(ss); @@ -1622,12 +1821,12 @@ ssl_ImportFD(PRFileDesc *model, PRFileDesc *fd, SSLProtocolVariant variant) rv = ssl_PushIOLayer(ns, fd, PR_TOP_IO_LAYER); if (rv != PR_SUCCESS) { ssl_FreeSocket(ns); - SET_ERROR_CODE + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return NULL; } #if defined(DEBUG) || defined(FORCE_PR_ASSERT) { - sslSocket * ss = ssl_FindSocket(fd); + sslSocket *ss = ssl_FindSocket(fd); PORT_Assert(ss == ns); } #endif @@ -1692,13 +1891,13 @@ ssl_NextProtoNegoCallback(void *arg, PRFileDesc *fd, } /* For each protocol in server preference, see if we support it. */ - for (i = 0; i < protos_len; ) { - for (j = 0; j < ss->opt.nextProtoNego.len; ) { + for (i = 0; i < protos_len;) { + for (j = 0; j < ss->opt.nextProtoNego.len;) { if (protos[i] == ss->opt.nextProtoNego.data[j] && - PORT_Memcmp(&protos[i+1], &ss->opt.nextProtoNego.data[j+1], - protos[i]) == 0) { + PORT_Memcmp(&protos[i + 1], &ss->opt.nextProtoNego.data[j + 1], + protos[i]) == 0) { /* We found a match. */ - ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; + ss->xtnData.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED; result = &protos[i]; goto found; } @@ -1711,7 +1910,7 @@ ssl_NextProtoNegoCallback(void *arg, PRFileDesc *fd, * protocols configured, or none of its options match ours. In this case we * request our favoured protocol. */ /* This will be treated as a failure for ALPN. */ - ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP; + ss->xtnData.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP; result = ss->opt.nextProtoNego.data; found: @@ -1730,7 +1929,7 @@ SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data, { sslSocket *ss; SECStatus rv; - SECItem dataItem = { siBuffer, (unsigned char *) data, length }; + SECItem dataItem = { siBuffer, (unsigned char *)data, length }; ss = ssl_FindSocket(fd); if (!ss) { @@ -1770,16 +1969,16 @@ SSL_GetNextProto(PRFileDesc *fd, SSLNextProtoState *state, unsigned char *buf, return SECFailure; } - *state = ss->ssl3.nextProtoState; + *state = ss->xtnData.nextProtoState; - if (ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && - ss->ssl3.nextProto.data) { - if (ss->ssl3.nextProto.len > bufLenMax) { + if (ss->xtnData.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT && + ss->xtnData.nextProto.data) { + if (ss->xtnData.nextProto.len > bufLenMax) { PORT_SetError(SEC_ERROR_OUTPUT_LEN); return SECFailure; } - PORT_Memcpy(buf, ss->ssl3.nextProto.data, ss->ssl3.nextProto.len); - *bufLen = ss->ssl3.nextProto.len; + PORT_Memcpy(buf, ss->xtnData.nextProto.data, ss->xtnData.nextProto.len); + *bufLen = ss->xtnData.nextProto.len; } else { *bufLen = 0; } @@ -1787,9 +1986,10 @@ SSL_GetNextProto(PRFileDesc *fd, SSLNextProtoState *state, unsigned char *buf, return SECSuccess; } -SECStatus SSL_SetSRTPCiphers(PRFileDesc *fd, - const PRUint16 *ciphers, - unsigned int numCiphers) +SECStatus +SSL_SetSRTPCiphers(PRFileDesc *fd, + const PRUint16 *ciphers, + unsigned int numCiphers) { sslSocket *ss; unsigned int i; @@ -1821,8 +2021,9 @@ SECStatus SSL_SetSRTPCiphers(PRFileDesc *fd, ciphers[i]; } else { SSL_DBG(("%d: SSL[%d]: invalid or unimplemented SRTP cipher " - "suite specified: 0x%04hx", SSL_GETPID(), fd, - ciphers[i])); + "suite specified: 0x%04hx", + SSL_GETPID(), fd, + ciphers[i])); } } @@ -1837,7 +2038,7 @@ SECStatus SSL_SetSRTPCiphers(PRFileDesc *fd, SECStatus SSL_GetSRTPCipher(PRFileDesc *fd, PRUint16 *cipher) { - sslSocket * ss; + sslSocket *ss; ss = ssl_FindSocket(fd); if (!ss) { @@ -1847,22 +2048,20 @@ SSL_GetSRTPCipher(PRFileDesc *fd, PRUint16 *cipher) return SECFailure; } - if (!ss->ssl3.dtlsSRTPCipherSuite) { + if (!ss->xtnData.dtlsSRTPCipherSuite) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - *cipher = ss->ssl3.dtlsSRTPCipherSuite; + *cipher = ss->xtnData.dtlsSRTPCipherSuite; return SECSuccess; } PRFileDesc * SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd) { - sslSocket * sm = NULL, *ss = NULL; - int i; - sslServerCerts * mc = NULL; - sslServerCerts * sc = NULL; + sslSocket *sm = NULL, *ss = NULL; + PRCList *cursor; if (model == NULL) { PR_SetError(SEC_ERROR_INVALID_ARGS, 0); @@ -1881,69 +2080,51 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd) return NULL; } - ss->opt = sm->opt; + ss->opt = sm->opt; ss->vrange = sm->vrange; PORT_Memcpy(ss->cipherSuites, sm->cipherSuites, sizeof sm->cipherSuites); 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; + PORT_Memcpy(ss->ssl3.signatureSchemes, sm->ssl3.signatureSchemes, + sizeof(ss->ssl3.signatureSchemes[0]) * + sm->ssl3.signatureSchemeCount); + ss->ssl3.signatureSchemeCount = sm->ssl3.signatureSchemeCount; + ss->ssl3.downgradeCheckVersion = sm->ssl3.downgradeCheckVersion; if (!ss->opt.useSecurity) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } - /* This int should be SSLKEAType, but CC on Irix complains, - * during the for loop. - */ - for (i=kt_null; i < kt_kea_size; i++) { - mc = &(sm->serverCerts[i]); - sc = &(ss->serverCerts[i]); - if (mc->serverCert && mc->serverCertChain) { - if (sc->serverCert) { - CERT_DestroyCertificate(sc->serverCert); - } - sc->serverCert = CERT_DupCertificate(mc->serverCert); - if (sc->serverCertChain) { - CERT_DestroyCertificateList(sc->serverCertChain); - } - sc->serverCertChain = CERT_DupCertList(mc->serverCertChain); - if (!sc->serverCertChain) - goto loser; - if (sm->certStatusArray[i]) { - if (ss->certStatusArray[i]) { - SECITEM_FreeArray(ss->certStatusArray[i], PR_TRUE); - ss->certStatusArray[i] = NULL; - } - ss->certStatusArray[i] = SECITEM_DupArray(NULL, sm->certStatusArray[i]); - if (!ss->certStatusArray[i]) - goto loser; - } - } - if (mc->serverKeyPair) { - if (sc->serverKeyPair) { - ssl3_FreeKeyPair(sc->serverKeyPair); - } - sc->serverKeyPair = ssl3_GetKeyPairRef(mc->serverKeyPair); - sc->serverKeyBits = mc->serverKeyBits; - } + while (!PR_CLIST_IS_EMPTY(&ss->serverCerts)) { + cursor = PR_LIST_TAIL(&ss->serverCerts); + PR_REMOVE_LINK(cursor); + ssl_FreeServerCert((sslServerCert *)cursor); } - if (sm->stepDownKeyPair) { - if (ss->stepDownKeyPair) { - ssl3_FreeKeyPair(ss->stepDownKeyPair); - } - ss->stepDownKeyPair = ssl3_GetKeyPairRef(sm->stepDownKeyPair); + for (cursor = PR_NEXT_LINK(&sm->serverCerts); + cursor != &sm->serverCerts; + cursor = PR_NEXT_LINK(cursor)) { + sslServerCert *sc = ssl_CopyServerCert((sslServerCert *)cursor); + if (!sc) + return NULL; + PR_APPEND_LINK(&sc->link, &ss->serverCerts); } - if (sm->ephemeralECDHKeyPair) { - if (ss->ephemeralECDHKeyPair) { - ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair); - } - ss->ephemeralECDHKeyPair = - ssl3_GetKeyPairRef(sm->ephemeralECDHKeyPair); + + ssl_FreeEphemeralKeyPairs(ss); + for (cursor = PR_NEXT_LINK(&sm->ephemeralKeyPairs); + cursor != &sm->ephemeralKeyPairs; + cursor = PR_NEXT_LINK(cursor)) { + sslEphemeralKeyPair *mkp = (sslEphemeralKeyPair *)cursor; + sslEphemeralKeyPair *skp = ssl_CopyEphemeralKeyPair(mkp); + if (!skp) + return NULL; + PR_APPEND_LINK(&skp->link, &ss->ephemeralKeyPairs); } + PORT_Memcpy((void *)ss->namedGroupPreferences, + sm->namedGroupPreferences, + sizeof(ss->namedGroupPreferences)); + ss->additionalShares = sm->additionalShares; + /* copy trust anchor names */ if (sm->ssl3.ca_list) { if (ss->ssl3.ca_list) { @@ -1951,53 +2132,147 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd) } ss->ssl3.ca_list = CERT_DupDistNames(sm->ssl3.ca_list); if (!ss->ssl3.ca_list) { - goto loser; + return NULL; } } if (sm->authCertificate) - ss->authCertificate = sm->authCertificate; + ss->authCertificate = sm->authCertificate; if (sm->authCertificateArg) - ss->authCertificateArg = sm->authCertificateArg; + ss->authCertificateArg = sm->authCertificateArg; if (sm->getClientAuthData) - ss->getClientAuthData = sm->getClientAuthData; + ss->getClientAuthData = sm->getClientAuthData; if (sm->getClientAuthDataArg) - ss->getClientAuthDataArg = sm->getClientAuthDataArg; + ss->getClientAuthDataArg = sm->getClientAuthDataArg; if (sm->sniSocketConfig) - ss->sniSocketConfig = sm->sniSocketConfig; + ss->sniSocketConfig = sm->sniSocketConfig; if (sm->sniSocketConfigArg) - ss->sniSocketConfigArg = sm->sniSocketConfigArg; + ss->sniSocketConfigArg = sm->sniSocketConfigArg; if (sm->handleBadCert) - ss->handleBadCert = sm->handleBadCert; + ss->handleBadCert = sm->handleBadCert; if (sm->badCertArg) - ss->badCertArg = sm->badCertArg; + ss->badCertArg = sm->badCertArg; if (sm->handshakeCallback) - ss->handshakeCallback = sm->handshakeCallback; + ss->handshakeCallback = sm->handshakeCallback; if (sm->handshakeCallbackData) ss->handshakeCallbackData = sm->handshakeCallbackData; if (sm->pkcs11PinArg) - ss->pkcs11PinArg = sm->pkcs11PinArg; + ss->pkcs11PinArg = sm->pkcs11PinArg; return fd; -loser: - return NULL; +} + +/* + * Get the user supplied range + */ +static SECStatus +ssl3_GetRangePolicy(SSLProtocolVariant protocolVariant, SSLVersionRange *prange) +{ + SECStatus rv; + PRUint32 policy; + PRInt32 option; + + /* only use policy constraints if we've set the apply ssl policy bit */ + rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &policy); + if ((rv != SECSuccess) || !(policy & NSS_USE_POLICY_IN_SSL)) { + return SECFailure; + } + rv = NSS_OptionGet(VERSIONS_POLICY_MIN(protocolVariant), &option); + if (rv != SECSuccess) { + return rv; + } + prange->min = (PRUint16)option; + rv = NSS_OptionGet(VERSIONS_POLICY_MAX(protocolVariant), &option); + if (rv != SECSuccess) { + return rv; + } + prange->max = (PRUint16)option; + if (prange->max < prange->min) { + return SECFailure; /* don't accept an invalid policy */ + } + return SECSuccess; +} + +/* + * Constrain a single protocol variant's range based on the user policy + */ +static SECStatus +ssl3_ConstrainVariantRangeByPolicy(SSLProtocolVariant protocolVariant) +{ + SSLVersionRange vrange; + SSLVersionRange pvrange; + SECStatus rv; + + vrange = *VERSIONS_DEFAULTS(protocolVariant); + rv = ssl3_GetRangePolicy(protocolVariant, &pvrange); + if (rv != SECSuccess) { + return SECSuccess; /* we don't have any policy */ + } + vrange.min = PR_MAX(vrange.min, pvrange.min); + vrange.max = PR_MIN(vrange.max, pvrange.max); + if (vrange.max >= vrange.min) { + *VERSIONS_DEFAULTS(protocolVariant) = vrange; + } else { + /* there was no overlap, turn off range altogether */ + pvrange.min = pvrange.max = SSL_LIBRARY_VERSION_NONE; + *VERSIONS_DEFAULTS(protocolVariant) = pvrange; + } + return SECSuccess; +} + +static PRBool +ssl_VersionIsSupportedByPolicy(SSLProtocolVariant protocolVariant, + SSL3ProtocolVersion version) +{ + SSLVersionRange pvrange; + SECStatus rv; + + rv = ssl3_GetRangePolicy(protocolVariant, &pvrange); + if (rv == SECSuccess) { + if ((version > pvrange.max) || (version < pvrange.min)) { + return PR_FALSE; /* disallowed by policy */ + } + } + return PR_TRUE; +} + +/* + * This is called at SSL init time to constrain the existing range based + * on user supplied policy. + */ +SECStatus +ssl3_ConstrainRangeByPolicy(void) +{ + SECStatus rv; + rv = ssl3_ConstrainVariantRangeByPolicy(ssl_variant_stream); + if (rv != SECSuccess) { + return rv; + } + rv = ssl3_ConstrainVariantRangeByPolicy(ssl_variant_datagram); + if (rv != SECSuccess) { + return rv; + } + return SECSuccess; } PRBool ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant, SSL3ProtocolVersion version) { - switch (protocolVariant) { - case ssl_variant_stream: - return (version >= SSL_LIBRARY_VERSION_3_0 && - version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED); - case ssl_variant_datagram: - return (version >= SSL_LIBRARY_VERSION_TLS_1_1 && - version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED); - default: - /* Can't get here */ - PORT_Assert(PR_FALSE); + if (!ssl_VersionIsSupportedByPolicy(protocolVariant, version)) { return PR_FALSE; } + switch (protocolVariant) { + case ssl_variant_stream: + return (version >= SSL_LIBRARY_VERSION_3_0 && + version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED); + case ssl_variant_datagram: + return (version >= SSL_LIBRARY_VERSION_TLS_1_1 && + version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED); + default: + /* Can't get here */ + PORT_Assert(PR_FALSE); + return PR_FALSE; + } } /* Returns PR_TRUE if the given version range is valid and @@ -2010,7 +2285,28 @@ ssl3_VersionRangeIsValid(SSLProtocolVariant protocolVariant, return vrange && vrange->min <= vrange->max && ssl3_VersionIsSupported(protocolVariant, vrange->min) && - ssl3_VersionIsSupported(protocolVariant, vrange->max); + ssl3_VersionIsSupported(protocolVariant, vrange->max) && + (vrange->min > SSL_LIBRARY_VERSION_3_0 || + vrange->max < SSL_LIBRARY_VERSION_TLS_1_3); +} + +const SECItem * +SSL_PeerSignedCertTimestamps(PRFileDesc *fd) +{ + sslSocket *ss = ssl_FindSocket(fd); + + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerSignedCertTimestamps", + SSL_GETPID(), fd)); + return NULL; + } + + if (!ss->sec.ci.sid) { + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); + return NULL; + } + + return &ss->sec.ci.sid->u.ssl3.signedCertTimestamps; } SECStatus @@ -2023,17 +2319,21 @@ SSL_VersionRangeGetSupported(SSLProtocolVariant protocolVariant, } switch (protocolVariant) { - case ssl_variant_stream: - vrange->min = SSL_LIBRARY_VERSION_3_0; - vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED; - break; - case ssl_variant_datagram: - vrange->min = SSL_LIBRARY_VERSION_TLS_1_1; - vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED; - break; - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; + case ssl_variant_stream: + vrange->min = SSL_LIBRARY_VERSION_3_0; + vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED; + // We don't allow SSLv3 and TLSv1.3 together. + if (vrange->max == SSL_LIBRARY_VERSION_TLS_1_3) { + vrange->min = SSL_LIBRARY_VERSION_TLS_1_0; + } + break; + case ssl_variant_datagram: + vrange->min = SSL_LIBRARY_VERSION_TLS_1_1; + vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED; + break; + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } return SECSuccess; @@ -2044,7 +2344,8 @@ SSL_VersionRangeGetDefault(SSLProtocolVariant protocolVariant, SSLVersionRange *vrange) { if ((protocolVariant != ssl_variant_stream && - protocolVariant != ssl_variant_datagram) || !vrange) { + protocolVariant != ssl_variant_datagram) || + !vrange) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -2074,8 +2375,8 @@ SSL_VersionRangeGet(PRFileDesc *fd, SSLVersionRange *vrange) sslSocket *ss = ssl_FindSocket(fd); if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL3_VersionRangeGet", - SSL_GETPID(), fd)); + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_VersionRangeGet", + SSL_GETPID(), fd)); return SECFailure; } @@ -2101,8 +2402,8 @@ SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange) sslSocket *ss = ssl_FindSocket(fd); if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL3_VersionRangeSet", - SSL_GETPID(), fd)); + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_VersionRangeSet", + SSL_GETPID(), fd)); return SECFailure; } @@ -2114,6 +2415,14 @@ SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange) ssl_Get1stHandshakeLock(ss); ssl_GetSSL3HandshakeLock(ss); + if (ss->ssl3.downgradeCheckVersion && + ss->vrange.max > ss->ssl3.downgradeCheckVersion) { + PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE); + ssl_ReleaseSSL3HandshakeLock(ss); + ssl_Release1stHandshakeLock(ss); + return SECFailure; + } + ss->vrange = *vrange; ssl_ReleaseSSL3HandshakeLock(ss); @@ -2122,20 +2431,54 @@ SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange) return SECSuccess; } +SECStatus +SSL_SetDowngradeCheckVersion(PRFileDesc *fd, PRUint16 version) +{ + sslSocket *ss = ssl_FindSocket(fd); + SECStatus rv = SECFailure; + + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetDowngradeCheckVersion", + SSL_GETPID(), fd)); + return SECFailure; + } + + if (version && !ssl3_VersionIsSupported(ss->protocolVariant, version)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + ssl_Get1stHandshakeLock(ss); + ssl_GetSSL3HandshakeLock(ss); + + if (version && version < ss->vrange.max) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto loser; + } + ss->ssl3.downgradeCheckVersion = version; + rv = SECSuccess; + +loser: + ssl_ReleaseSSL3HandshakeLock(ss); + ssl_Release1stHandshakeLock(ss); + + return rv; +} + const SECItemArray * SSL_PeerStapledOCSPResponses(PRFileDesc *fd) { sslSocket *ss = ssl_FindSocket(fd); if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerStapledOCSPResponses", - SSL_GETPID(), fd)); - return NULL; + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerStapledOCSPResponses", + SSL_GETPID(), fd)); + return NULL; } if (!ss->sec.ci.sid) { - PORT_SetError(SEC_ERROR_NOT_INITIALIZED); - return NULL; + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); + return NULL; } return &ss->sec.ci.sid->peerCertStatus; @@ -2146,14 +2489,14 @@ SSL_PeerStapledOCSPResponses(PRFileDesc *fd) ** They all get called through the NSPRIOMethods table below. */ -static PRFileDesc * PR_CALLBACK +static PRFileDesc *PR_CALLBACK ssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout) { - sslSocket *ss; - sslSocket *ns = NULL; - PRFileDesc *newfd = NULL; + sslSocket *ss; + sslSocket *ns = NULL; + PRFileDesc *newfd = NULL; PRFileDesc *osfd; - PRStatus status; + PRStatus status; ss = ssl_GetPrivate(fd); if (!ss) { @@ -2184,7 +2527,7 @@ ssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout) ssl_ReleaseSSL3HandshakeLock(ss); ssl_Release1stHandshakeLock(ss); SSL_UNLOCK_WRITER(ss); - SSL_UNLOCK_READER(ss); /* ss isn't used below here. */ + SSL_UNLOCK_READER(ss); /* ss isn't used below here. */ if (ns == NULL) goto loser; @@ -2197,12 +2540,12 @@ ssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout) /* Now start server connection handshake with client. ** Don't need locks here because nobody else has a reference to ns yet. */ - if ( ns->opt.useSecurity ) { - if ( ns->opt.handshakeAsClient ) { - ns->handshake = ssl2_BeginClientHandshake; + if (ns->opt.useSecurity) { + if (ns->opt.handshakeAsClient) { + ns->handshake = ssl_BeginClientHandshake; ss->handshaking = sslHandshakingAsClient; } else { - ns->handshake = ssl2_BeginServerHandshake; + ns->handshake = ssl_BeginServerHandshake; ss->handshaking = sslHandshakingAsServer; } } @@ -2221,7 +2564,7 @@ static PRStatus PR_CALLBACK ssl_Connect(PRFileDesc *fd, const PRNetAddr *sockaddr, PRIntervalTime timeout) { sslSocket *ss; - PRStatus rv; + PRStatus rv; ss = ssl_GetPrivate(fd); if (!ss) { @@ -2245,8 +2588,8 @@ ssl_Connect(PRFileDesc *fd, const PRNetAddr *sockaddr, PRIntervalTime timeout) static PRStatus PR_CALLBACK ssl_Bind(PRFileDesc *fd, const PRNetAddr *addr) { - sslSocket * ss = ssl_GetPrivate(fd); - PRStatus rv; + sslSocket *ss = ssl_GetPrivate(fd); + PRStatus rv; if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in bind", SSL_GETPID(), fd)); @@ -2265,8 +2608,8 @@ ssl_Bind(PRFileDesc *fd, const PRNetAddr *addr) static PRStatus PR_CALLBACK ssl_Listen(PRFileDesc *fd, PRIntn backlog) { - sslSocket * ss = ssl_GetPrivate(fd); - PRStatus rv; + sslSocket *ss = ssl_GetPrivate(fd); + PRStatus rv; if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in listen", SSL_GETPID(), fd)); @@ -2285,8 +2628,8 @@ ssl_Listen(PRFileDesc *fd, PRIntn backlog) static PRStatus PR_CALLBACK ssl_Shutdown(PRFileDesc *fd, PRIntn how) { - sslSocket * ss = ssl_GetPrivate(fd); - PRStatus rv; + sslSocket *ss = ssl_GetPrivate(fd); + PRStatus rv; if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in shutdown", SSL_GETPID(), fd)); @@ -2314,7 +2657,7 @@ static PRStatus PR_CALLBACK ssl_Close(PRFileDesc *fd) { sslSocket *ss; - PRStatus rv; + PRStatus rv; ss = ssl_GetPrivate(fd); if (!ss) { @@ -2342,7 +2685,7 @@ ssl_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags, PRIntervalTime timeout) { sslSocket *ss; - int rv; + int rv; ss = ssl_GetPrivate(fd); if (!ss) { @@ -2353,7 +2696,7 @@ ssl_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags, ss->rTimeout = timeout; if (!ss->opt.fdx) ss->wTimeout = timeout; - rv = (*ss->ops->recv)(ss, (unsigned char*)buf, len, flags); + rv = (*ss->ops->recv)(ss, (unsigned char *)buf, len, flags); SSL_UNLOCK_READER(ss); return rv; } @@ -2363,7 +2706,7 @@ ssl_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags, PRIntervalTime timeout) { sslSocket *ss; - int rv; + int rv; ss = ssl_GetPrivate(fd); if (!ss) { @@ -2374,7 +2717,7 @@ ssl_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags, ss->wTimeout = timeout; if (!ss->opt.fdx) ss->rTimeout = timeout; - rv = (*ss->ops->send)(ss, (const unsigned char*)buf, len, flags); + rv = (*ss->ops->send)(ss, (const unsigned char *)buf, len, flags); SSL_UNLOCK_WRITER(ss); return rv; } @@ -2383,7 +2726,7 @@ static int PR_CALLBACK ssl_Read(PRFileDesc *fd, void *buf, PRInt32 len) { sslSocket *ss; - int rv; + int rv; ss = ssl_GetPrivate(fd); if (!ss) { @@ -2394,7 +2737,7 @@ ssl_Read(PRFileDesc *fd, void *buf, PRInt32 len) ss->rTimeout = PR_INTERVAL_NO_TIMEOUT; if (!ss->opt.fdx) ss->wTimeout = PR_INTERVAL_NO_TIMEOUT; - rv = (*ss->ops->read)(ss, (unsigned char*)buf, len); + rv = (*ss->ops->read)(ss, (unsigned char *)buf, len); SSL_UNLOCK_READER(ss); return rv; } @@ -2403,7 +2746,7 @@ static int PR_CALLBACK ssl_Write(PRFileDesc *fd, const void *buf, PRInt32 len) { sslSocket *ss; - int rv; + int rv; ss = ssl_GetPrivate(fd); if (!ss) { @@ -2414,7 +2757,7 @@ ssl_Write(PRFileDesc *fd, const void *buf, PRInt32 len) ss->wTimeout = PR_INTERVAL_NO_TIMEOUT; if (!ss->opt.fdx) ss->rTimeout = PR_INTERVAL_NO_TIMEOUT; - rv = (*ss->ops->write)(ss, (const unsigned char*)buf, len); + rv = (*ss->ops->write)(ss, (const unsigned char *)buf, len); SSL_UNLOCK_WRITER(ss); return rv; } @@ -2437,9 +2780,9 @@ ssl_GetPeerName(PRFileDesc *fd, PRNetAddr *addr) SECStatus ssl_GetPeerInfo(sslSocket *ss) { - PRFileDesc * osfd; - int rv; - PRNetAddr sin; + PRFileDesc *osfd; + int rv; + PRNetAddr sin; osfd = ss->fd->lower; @@ -2476,35 +2819,6 @@ ssl_GetSockName(PRFileDesc *fd, PRNetAddr *name) } SECStatus -SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses, - SSLKEAType kea) -{ - sslSocket *ss; - - ss = ssl_FindSocket(fd); - if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetStapledOCSPResponses", - SSL_GETPID(), fd)); - return SECFailure; - } - - if ( kea <= 0 || kea >= kt_kea_size) { - SSL_DBG(("%d: SSL[%d]: invalid key in SSL_SetStapledOCSPResponses", - SSL_GETPID(), fd)); - return SECFailure; - } - - if (ss->certStatusArray[kea]) { - SECITEM_FreeArray(ss->certStatusArray[kea], PR_TRUE); - ss->certStatusArray[kea] = NULL; - } - if (responses) { - ss->certStatusArray[kea] = SECITEM_DupArray(NULL, responses); - } - return (ss->certStatusArray[kea] || !responses) ? SECSuccess : SECFailure; -} - -SECStatus SSL_SetSockPeerID(PRFileDesc *fd, const char *peerID) { sslSocket *ss; @@ -2531,15 +2845,15 @@ static PRInt16 PR_CALLBACK ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags) { sslSocket *ss; - PRInt16 new_flags = how_flags; /* should select on these flags. */ - PRNetAddr addr; + PRInt16 new_flags = how_flags; /* should select on these flags. */ + PRNetAddr addr; *p_out_flags = 0; ss = ssl_GetPrivate(fd); if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in SSL_Poll", SSL_GETPID(), fd)); - return 0; /* don't poll on this socket */ + return 0; /* don't poll on this socket */ } if (ss->opt.useSecurity && @@ -2565,40 +2879,38 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags) new_flags |= PR_POLL_READ; } } else - /* First handshake is in progress */ - if (ss->lastWriteBlocked) { + /* First handshake is in progress */ + if (ss->lastWriteBlocked) { if (new_flags & PR_POLL_READ) { /* The caller is waiting for data to be received, ** but the initial handshake is blocked on write, or the ** client's first handshake record has not been written. ** The code should select on write, not read. */ - new_flags ^= PR_POLL_READ; /* don't select on read. */ - new_flags |= PR_POLL_WRITE; /* do select on write. */ + new_flags ^= PR_POLL_READ; /* don't select on read. */ + new_flags |= PR_POLL_WRITE; /* do select on write. */ } } else if (new_flags & PR_POLL_WRITE) { - /* The caller is trying to write, but the handshake is - ** blocked waiting for data to read, and the first - ** handshake has been sent. So do NOT to poll on write - ** unless we did false start. - */ - if (!(ss->version >= SSL_LIBRARY_VERSION_3_0 && - ss->ssl3.hs.canFalseStart)) { - new_flags ^= PR_POLL_WRITE; /* don't select on write. */ - } - new_flags |= PR_POLL_READ; /* do select on read. */ + /* The caller is trying to write, but the handshake is + ** blocked waiting for data to read, and the first + ** handshake has been sent. So do NOT to poll on write + ** unless we did false start. + */ + if (!ss->ssl3.hs.canFalseStart) { + new_flags ^= PR_POLL_WRITE; /* don't select on write. */ + } + new_flags |= PR_POLL_READ; /* do select on read. */ } } } else if ((new_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) { - *p_out_flags = PR_POLL_READ; /* it's ready already. */ + *p_out_flags = PR_POLL_READ; /* it's ready already. */ return new_flags; } else if ((ss->lastWriteBlocked) && (how_flags & PR_POLL_READ) && (ss->pendingBuf.len != 0)) { /* write data waiting to be sent */ - new_flags |= PR_POLL_WRITE; /* also select on write. */ + new_flags |= PR_POLL_WRITE; /* also select on write. */ } - if (ss->version >= SSL_LIBRARY_VERSION_3_0 && - ss->ssl3.hs.restartTarget != NULL) { + if (ss->ssl3.hs.restartTarget != NULL) { /* Read and write will block until the asynchronous callback completes * (e.g. until SSL_AuthCertificateComplete is called), so don't tell * the caller to poll the socket unless there is pending write data. @@ -2626,8 +2938,8 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags) } if (new_flags && (fd->lower->methods->poll != NULL)) { - PRInt16 lower_out_flags = 0; - PRInt16 lower_new_flags; + PRInt16 lower_out_flags = 0; + PRInt16 lower_new_flags; lower_new_flags = fd->lower->methods->poll(fd->lower, new_flags, &lower_out_flags); if ((lower_new_flags & lower_out_flags) && (how_flags != new_flags)) { @@ -2640,7 +2952,7 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags) new_flags = how_flags; } else { *p_out_flags = lower_out_flags; - new_flags = lower_new_flags; + new_flags = lower_new_flags; } } @@ -2665,14 +2977,13 @@ ssl_TransmitFile(PRFileDesc *sd, PRFileDesc *fd, return sd->methods->sendfile(sd, &sfd, flags, timeout); } - PRBool ssl_FdIsBlocking(PRFileDesc *fd) { PRSocketOptionData opt; - PRStatus status; + PRStatus status; - opt.option = PR_SockOpt_Nonblocking; + opt.option = PR_SockOpt_Nonblocking; opt.value.non_blocking = PR_FALSE; status = PR_GetSocketOption(fd, &opt); if (status != PR_SUCCESS) @@ -2686,23 +2997,23 @@ ssl_SocketIsBlocking(sslSocket *ss) return ssl_FdIsBlocking(ss->fd); } -PRInt32 sslFirstBufSize = 8 * 1024; -PRInt32 sslCopyLimit = 1024; +PRInt32 sslFirstBufSize = 8 * 1024; +PRInt32 sslCopyLimit = 1024; static PRInt32 PR_CALLBACK ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors, PRIntervalTime timeout) { - PRInt32 i; - PRInt32 bufLen; - PRInt32 left; - PRInt32 rv; - PRInt32 sent = 0; - const PRInt32 first_len = sslFirstBufSize; - const PRInt32 limit = sslCopyLimit; - PRBool blocking; - PRIOVec myIov = { 0, 0 }; - char buf[MAX_FRAGMENT_LENGTH]; + PRInt32 i; + PRInt32 bufLen; + PRInt32 left; + PRInt32 rv; + PRInt32 sent = 0; + const PRInt32 first_len = sslFirstBufSize; + const PRInt32 limit = sslCopyLimit; + PRBool blocking; + PRIOVec myIov; + char buf[MAX_FRAGMENT_LENGTH]; if (vectors < 0) { PORT_SetError(PR_INVALID_ARGUMENT_ERROR); @@ -2721,28 +3032,37 @@ ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors, blocking = ssl_FdIsBlocking(fd); #define K16 sizeof(buf) -#define KILL_VECTORS while (vectors && !iov->iov_len) { ++iov; --vectors; } -#define GET_VECTOR do { myIov = *iov++; --vectors; KILL_VECTORS } while (0) -#define HANDLE_ERR(rv, len) \ - if (rv != len) { \ - if (rv < 0) { \ - if (!blocking \ - && (PR_GetError() == PR_WOULD_BLOCK_ERROR) \ - && (sent > 0)) { \ - return sent; \ - } else { \ - return -1; \ - } \ - } \ +#define KILL_VECTORS \ + while (vectors && !iov->iov_len) { \ + ++iov; \ + --vectors; \ + } +#define GET_VECTOR \ + do { \ + myIov = *iov++; \ + --vectors; \ + KILL_VECTORS \ + } while (0) +#define HANDLE_ERR(rv, len) \ + if (rv != len) { \ + if (rv < 0) { \ + if (!blocking && \ + (PR_GetError() == PR_WOULD_BLOCK_ERROR) && \ + (sent > 0)) { \ + return sent; \ + } else { \ + return -1; \ + } \ + } \ /* Only a nonblocking socket can have partial sends */ \ - PR_ASSERT(!blocking); \ - return sent + rv; \ + PR_ASSERT(!blocking); \ + return sent + rv; \ } -#define SEND(bfr, len) \ - do { \ +#define SEND(bfr, len) \ + do { \ rv = ssl_Send(fd, bfr, len, 0, timeout); \ - HANDLE_ERR(rv, len) \ - sent += len; \ + HANDLE_ERR(rv, len) \ + sent += len; \ } while (0) /* Make sure the first write is at least 8 KB, if possible. */ @@ -2762,23 +3082,23 @@ ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors, GET_VECTOR; toCopy = PR_MIN(left, myIov.iov_len); PORT_Memcpy(buf + bufLen, myIov.iov_base, toCopy); - bufLen += toCopy; - left -= toCopy; + bufLen += toCopy; + left -= toCopy; myIov.iov_base += toCopy; - myIov.iov_len -= toCopy; + myIov.iov_len -= toCopy; } - SEND( buf, bufLen ); + SEND(buf, bufLen); } while (vectors || myIov.iov_len) { - PRInt32 addLen; + PRInt32 addLen; if (!myIov.iov_len) { GET_VECTOR; } while (myIov.iov_len >= K16) { SEND(myIov.iov_base, K16); myIov.iov_base += K16; - myIov.iov_len -= K16; + myIov.iov_len -= K16; } if (!myIov.iov_len) continue; @@ -2788,13 +3108,13 @@ ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors, } else if ((addLen = iov->iov_len % K16) + myIov.iov_len <= limit) { /* Addlen is already computed. */; } else if (vectors > 1 && - iov[1].iov_len % K16 + addLen + myIov.iov_len <= 2 * limit) { - addLen = limit - myIov.iov_len; + iov[1].iov_len % K16 + addLen + myIov.iov_len <= 2 * limit) { + addLen = limit - myIov.iov_len; } else addLen = 0; if (!addLen) { - SEND( myIov.iov_base, myIov.iov_len ); + SEND(myIov.iov_base, myIov.iov_len); myIov.iov_len = 0; continue; } @@ -2804,25 +3124,24 @@ ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors, GET_VECTOR; PORT_Memcpy(buf + bufLen, myIov.iov_base, addLen); myIov.iov_base += addLen; - myIov.iov_len -= addLen; - bufLen += addLen; - - left = PR_MIN( limit, K16 - bufLen); - if (!vectors /* no more left */ - || myIov.iov_len > 0 /* we didn't use that one all up */ - || bufLen >= K16 /* it's full. */ - ) { + myIov.iov_len -= addLen; + bufLen += addLen; + + left = PR_MIN(limit, K16 - bufLen); + if (!vectors /* no more left */ + || myIov.iov_len > 0 /* we didn't use that one all up */ + || bufLen >= K16 /* it's full. */) { addLen = 0; } else if ((addLen = iov->iov_len % K16) <= left) { /* Addlen is already computed. */; } else if (vectors > 1 && - iov[1].iov_len % K16 + addLen <= left + limit) { - addLen = left; + iov[1].iov_len % K16 + addLen <= left + limit) { + addLen = left; } else addLen = 0; } while (addLen); - SEND( buf, bufLen ); + SEND(buf, bufLen); } return sent; } @@ -2859,14 +3178,16 @@ ssl_FSync(PRFileDesc *fd) } static PRInt32 PR_CALLBACK -ssl_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence how) { +ssl_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence how) +{ PORT_Assert(0); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return SECFailure; } static PRInt64 PR_CALLBACK -ssl_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence how) { +ssl_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence how) +{ PRInt64 res; PORT_Assert(0); @@ -2911,85 +3232,83 @@ ssl_SendTo(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, static const PRIOMethods ssl_methods = { PR_DESC_LAYERED, - ssl_Close, /* close */ - ssl_Read, /* read */ - ssl_Write, /* write */ - ssl_Available, /* available */ - ssl_Available64, /* available64 */ - ssl_FSync, /* fsync */ - ssl_Seek, /* seek */ - ssl_Seek64, /* seek64 */ - ssl_FileInfo, /* fileInfo */ - ssl_FileInfo64, /* fileInfo64 */ - ssl_WriteV, /* writev */ - ssl_Connect, /* connect */ - ssl_Accept, /* accept */ - ssl_Bind, /* bind */ - ssl_Listen, /* listen */ - ssl_Shutdown, /* shutdown */ - ssl_Recv, /* recv */ - ssl_Send, /* send */ - ssl_RecvFrom, /* recvfrom */ - ssl_SendTo, /* sendto */ - ssl_Poll, /* poll */ - PR_EmulateAcceptRead, /* acceptread */ - ssl_TransmitFile, /* transmitfile */ - ssl_GetSockName, /* getsockname */ - ssl_GetPeerName, /* getpeername */ - NULL, /* getsockopt OBSOLETE */ - NULL, /* setsockopt OBSOLETE */ - NULL, /* getsocketoption */ - NULL, /* setsocketoption */ - PR_EmulateSendFile, /* Send a (partial) file with header/trailer*/ - NULL, /* reserved for future use */ - NULL, /* reserved for future use */ - NULL, /* reserved for future use */ - NULL, /* reserved for future use */ - NULL /* reserved for future use */ + ssl_Close, /* close */ + ssl_Read, /* read */ + ssl_Write, /* write */ + ssl_Available, /* available */ + ssl_Available64, /* available64 */ + ssl_FSync, /* fsync */ + ssl_Seek, /* seek */ + ssl_Seek64, /* seek64 */ + ssl_FileInfo, /* fileInfo */ + ssl_FileInfo64, /* fileInfo64 */ + ssl_WriteV, /* writev */ + ssl_Connect, /* connect */ + ssl_Accept, /* accept */ + ssl_Bind, /* bind */ + ssl_Listen, /* listen */ + ssl_Shutdown, /* shutdown */ + ssl_Recv, /* recv */ + ssl_Send, /* send */ + ssl_RecvFrom, /* recvfrom */ + ssl_SendTo, /* sendto */ + ssl_Poll, /* poll */ + PR_EmulateAcceptRead, /* acceptread */ + ssl_TransmitFile, /* transmitfile */ + ssl_GetSockName, /* getsockname */ + ssl_GetPeerName, /* getpeername */ + NULL, /* getsockopt OBSOLETE */ + NULL, /* setsockopt OBSOLETE */ + NULL, /* getsocketoption */ + NULL, /* setsocketoption */ + PR_EmulateSendFile, /* Send a (partial) file with header/trailer*/ + NULL, /* reserved for future use */ + NULL, /* reserved for future use */ + NULL, /* reserved for future use */ + NULL, /* reserved for future use */ + NULL /* reserved for future use */ }; - static PRIOMethods combined_methods; static void ssl_SetupIOMethods(void) { - PRIOMethods *new_methods = &combined_methods; + PRIOMethods *new_methods = &combined_methods; const PRIOMethods *nspr_methods = PR_GetDefaultIOMethods(); - const PRIOMethods *my_methods = &ssl_methods; + const PRIOMethods *my_methods = &ssl_methods; *new_methods = *nspr_methods; - new_methods->file_type = my_methods->file_type; - new_methods->close = my_methods->close; - new_methods->read = my_methods->read; - new_methods->write = my_methods->write; - new_methods->available = my_methods->available; - new_methods->available64 = my_methods->available64; - new_methods->fsync = my_methods->fsync; - new_methods->seek = my_methods->seek; - new_methods->seek64 = my_methods->seek64; - new_methods->fileInfo = my_methods->fileInfo; - new_methods->fileInfo64 = my_methods->fileInfo64; - new_methods->writev = my_methods->writev; - new_methods->connect = my_methods->connect; - new_methods->accept = my_methods->accept; - new_methods->bind = my_methods->bind; - new_methods->listen = my_methods->listen; - new_methods->shutdown = my_methods->shutdown; - new_methods->recv = my_methods->recv; - new_methods->send = my_methods->send; - new_methods->recvfrom = my_methods->recvfrom; - new_methods->sendto = my_methods->sendto; - new_methods->poll = my_methods->poll; - new_methods->acceptread = my_methods->acceptread; - new_methods->transmitfile = my_methods->transmitfile; - new_methods->getsockname = my_methods->getsockname; - new_methods->getpeername = my_methods->getpeername; -/* new_methods->getsocketoption = my_methods->getsocketoption; */ -/* new_methods->setsocketoption = my_methods->setsocketoption; */ - new_methods->sendfile = my_methods->sendfile; - + new_methods->file_type = my_methods->file_type; + new_methods->close = my_methods->close; + new_methods->read = my_methods->read; + new_methods->write = my_methods->write; + new_methods->available = my_methods->available; + new_methods->available64 = my_methods->available64; + new_methods->fsync = my_methods->fsync; + new_methods->seek = my_methods->seek; + new_methods->seek64 = my_methods->seek64; + new_methods->fileInfo = my_methods->fileInfo; + new_methods->fileInfo64 = my_methods->fileInfo64; + new_methods->writev = my_methods->writev; + new_methods->connect = my_methods->connect; + new_methods->accept = my_methods->accept; + new_methods->bind = my_methods->bind; + new_methods->listen = my_methods->listen; + new_methods->shutdown = my_methods->shutdown; + new_methods->recv = my_methods->recv; + new_methods->send = my_methods->send; + new_methods->recvfrom = my_methods->recvfrom; + new_methods->sendto = my_methods->sendto; + new_methods->poll = my_methods->poll; + new_methods->acceptread = my_methods->acceptread; + new_methods->transmitfile = my_methods->transmitfile; + new_methods->getsockname = my_methods->getsockname; + new_methods->getpeername = my_methods->getpeername; + /* new_methods->getsocketoption = my_methods->getsocketoption; */ + /* new_methods->setsocketoption = my_methods->setsocketoption; */ + new_methods->sendfile = my_methods->sendfile; } static PRCallOnceType initIoLayerOnce; @@ -3006,8 +3325,8 @@ ssl_InitIOLayer(void) static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, PRDescIdentity id) { - PRFileDesc *layer = NULL; - PRStatus status; + PRFileDesc *layer = NULL; + PRStatus status; if (!ssl_inited) { status = PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer); @@ -3055,24 +3374,24 @@ ssl_MakeLocks(sslSocket *ss) ss->firstHandshakeLock = PZ_NewMonitor(nssILockSSL); if (!ss->firstHandshakeLock) goto loser; - ss->ssl3HandshakeLock = PZ_NewMonitor(nssILockSSL); + ss->ssl3HandshakeLock = PZ_NewMonitor(nssILockSSL); if (!ss->ssl3HandshakeLock) goto loser; - ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL); + ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL); if (!ss->specLock) goto loser; - ss->recvBufLock = PZ_NewMonitor(nssILockSSL); + ss->recvBufLock = PZ_NewMonitor(nssILockSSL); if (!ss->recvBufLock) goto loser; - ss->xmitBufLock = PZ_NewMonitor(nssILockSSL); + ss->xmitBufLock = PZ_NewMonitor(nssILockSSL); if (!ss->xmitBufLock) goto loser; - ss->writerThread = NULL; + ss->writerThread = NULL; if (ssl_lock_readers) { - ss->recvLock = PZ_NewLock(nssILockSSL); + ss->recvLock = PZ_NewLock(nssILockSSL); if (!ss->recvLock) goto loser; - ss->sendLock = PZ_NewLock(nssILockSSL); + ss->sendLock = PZ_NewLock(nssILockSSL); if (!ss->sendLock) goto loser; } @@ -3086,19 +3405,19 @@ loser: #define NSS_HAVE_GETENV 1 #endif -#define LOWER(x) (x | 0x20) /* cheap ToLower function ignores LOCALE */ +#define LOWER(x) (x | 0x20) /* cheap ToLower function ignores LOCALE */ static void ssl_SetDefaultsFromEnvironment(void) { -#if defined( NSS_HAVE_GETENV ) +#if defined(NSS_HAVE_GETENV) static int firsttime = 1; if (firsttime) { - char * ev; + char *ev; firsttime = 0; #ifdef DEBUG - ev = getenv("SSLDEBUGFILE"); + ev = PR_GetEnvSecure("SSLDEBUGFILE"); if (ev && ev[0]) { ssl_trace_iob = fopen(ev, "w"); } @@ -3106,19 +3425,20 @@ ssl_SetDefaultsFromEnvironment(void) ssl_trace_iob = stderr; } #ifdef TRACE - ev = getenv("SSLTRACE"); + ev = PR_GetEnvSecure("SSLTRACE"); if (ev && ev[0]) { ssl_trace = atoi(ev); SSL_TRACE(("SSL: tracing set to %d", ssl_trace)); } #endif /* TRACE */ - ev = getenv("SSLDEBUG"); + ev = PR_GetEnvSecure("SSLDEBUG"); if (ev && ev[0]) { ssl_debug = atoi(ev); SSL_TRACE(("SSL: debugging set to %d", ssl_debug)); } #endif /* DEBUG */ - ev = getenv("SSLKEYLOGFILE"); +#ifdef NSS_ALLOW_SSLKEYLOGFILE + ev = PR_GetEnvSecure("SSLKEYLOGFILE"); if (ev && ev[0]) { ssl_keylog_iob = fopen(ev, "a"); if (!ssl_keylog_iob) { @@ -3131,22 +3451,15 @@ ssl_SetDefaultsFromEnvironment(void) SSL_TRACE(("SSL: logging SSL/TLS secrets to %s", ev)); } } -#ifndef NO_PKCS11_BYPASS - ev = getenv("SSLBYPASS"); - if (ev && ev[0]) { - ssl_defaults.bypassPKCS11 = (ev[0] == '1'); - SSL_TRACE(("SSL: bypass default set to %d", \ - ssl_defaults.bypassPKCS11)); - } -#endif /* NO_PKCS11_BYPASS */ - ev = getenv("SSLFORCELOCKS"); +#endif + ev = PR_GetEnvSecure("SSLFORCELOCKS"); if (ev && ev[0] == '1') { ssl_force_locks = PR_TRUE; ssl_defaults.noLocks = 0; strcpy(lockStatus + LOCKSTATUS_OFFSET, "FORCED. "); SSL_TRACE(("SSL: force_locks set to %d", ssl_force_locks)); } - ev = getenv("NSS_SSL_ENABLE_RENEGOTIATION"); + ev = PR_GetEnvSecure("NSS_SSL_ENABLE_RENEGOTIATION"); if (ev) { if (ev[0] == '1' || LOWER(ev[0]) == 'u') ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_UNRESTRICTED; @@ -3159,13 +3472,13 @@ ssl_SetDefaultsFromEnvironment(void) SSL_TRACE(("SSL: enableRenegotiation set to %d", ssl_defaults.enableRenegotiation)); } - ev = getenv("NSS_SSL_REQUIRE_SAFE_NEGOTIATION"); + ev = PR_GetEnvSecure("NSS_SSL_REQUIRE_SAFE_NEGOTIATION"); if (ev && ev[0] == '1') { ssl_defaults.requireSafeNegotiation = PR_TRUE; SSL_TRACE(("SSL: requireSafeNegotiation set to %d", - PR_TRUE)); + PR_TRUE)); } - ev = getenv("NSS_SSL_CBC_RANDOM_IV"); + ev = PR_GetEnvSecure("NSS_SSL_CBC_RANDOM_IV"); if (ev && ev[0] == '0') { ssl_defaults.cbcRandomIV = PR_FALSE; SSL_TRACE(("SSL: cbcRandomIV set to 0")); @@ -3174,13 +3487,172 @@ ssl_SetDefaultsFromEnvironment(void) #endif /* NSS_HAVE_GETENV */ } +const sslNamedGroupDef * +ssl_LookupNamedGroup(SSLNamedGroup group) +{ + unsigned int i; + + for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { + if (ssl_named_groups[i].name == group) { + return &ssl_named_groups[i]; + } + } + return NULL; +} + +PRBool +ssl_NamedGroupEnabled(const sslSocket *ss, const sslNamedGroupDef *groupDef) +{ + unsigned int i; + + if (!groupDef) { + return PR_FALSE; + } + + for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { + if (ss->namedGroupPreferences[i] && + ss->namedGroupPreferences[i] == groupDef) { + return PR_TRUE; + } + } + return PR_FALSE; +} + +/* Returns a reference counted object that contains a key pair. + * Or NULL on failure. Initial ref count is 1. + * Uses the keys in the pair as input. Adopts the keys given. + */ +sslKeyPair * +ssl_NewKeyPair(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey) +{ + sslKeyPair *pair; + + if (!privKey || !pubKey) { + PORT_SetError(PR_INVALID_ARGUMENT_ERROR); + return NULL; + } + pair = PORT_ZNew(sslKeyPair); + if (!pair) + return NULL; /* error code is set. */ + pair->privKey = privKey; + pair->pubKey = pubKey; + pair->refCount = 1; + return pair; /* success */ +} + +sslKeyPair * +ssl_GetKeyPairRef(sslKeyPair *keyPair) +{ + PR_ATOMIC_INCREMENT(&keyPair->refCount); + return keyPair; +} + +void +ssl_FreeKeyPair(sslKeyPair *keyPair) +{ + PRInt32 newCount = PR_ATOMIC_DECREMENT(&keyPair->refCount); + if (!newCount) { + SECKEY_DestroyPrivateKey(keyPair->privKey); + SECKEY_DestroyPublicKey(keyPair->pubKey); + PORT_Free(keyPair); + } +} + +/* Ephemeral key handling. */ +sslEphemeralKeyPair * +ssl_NewEphemeralKeyPair(const sslNamedGroupDef *group, + SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey) +{ + sslKeyPair *keys; + sslEphemeralKeyPair *pair; + + if (!group) { + PORT_SetError(PR_INVALID_ARGUMENT_ERROR); + return NULL; + } + + keys = ssl_NewKeyPair(privKey, pubKey); + if (!keys) { + return NULL; + } + + pair = PORT_ZNew(sslEphemeralKeyPair); + if (!pair) { + ssl_FreeKeyPair(keys); + return NULL; /* error already set */ + } + + PR_INIT_CLIST(&pair->link); + pair->group = group; + pair->keys = keys; + + return pair; +} + +sslEphemeralKeyPair * +ssl_CopyEphemeralKeyPair(sslEphemeralKeyPair *keyPair) +{ + sslEphemeralKeyPair *pair; + + pair = PORT_ZNew(sslEphemeralKeyPair); + if (!pair) { + return NULL; /* error already set */ + } + + PR_INIT_CLIST(&pair->link); + pair->group = keyPair->group; + pair->keys = ssl_GetKeyPairRef(keyPair->keys); + + return pair; +} + +void +ssl_FreeEphemeralKeyPair(sslEphemeralKeyPair *keyPair) +{ + ssl_FreeKeyPair(keyPair->keys); + PR_REMOVE_LINK(&keyPair->link); + PORT_Free(keyPair); +} + +PRBool +ssl_HaveEphemeralKeyPair(const sslSocket *ss, const sslNamedGroupDef *groupDef) +{ + return ssl_LookupEphemeralKeyPair((sslSocket *)ss, groupDef) != NULL; +} + +sslEphemeralKeyPair * +ssl_LookupEphemeralKeyPair(sslSocket *ss, const sslNamedGroupDef *groupDef) +{ + PRCList *cursor; + for (cursor = PR_NEXT_LINK(&ss->ephemeralKeyPairs); + cursor != &ss->ephemeralKeyPairs; + cursor = PR_NEXT_LINK(cursor)) { + sslEphemeralKeyPair *keyPair = (sslEphemeralKeyPair *)cursor; + if (keyPair->group == groupDef) { + return keyPair; + } + } + return NULL; +} + +void +ssl_FreeEphemeralKeyPairs(sslSocket *ss) +{ + while (!PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs)) { + PRCList *cursor = PR_LIST_TAIL(&ss->ephemeralKeyPairs); + ssl_FreeEphemeralKeyPair((sslEphemeralKeyPair *)cursor); + } +} + /* ** Create a newsocket structure for a file descriptor. */ static sslSocket * ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant) { + SECStatus rv; sslSocket *ss; + int i; ssl_SetDefaultsFromEnvironment(); @@ -3188,76 +3660,83 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant) makeLocks = PR_TRUE; /* Make a new socket and get it ready */ - ss = (sslSocket*) PORT_ZAlloc(sizeof(sslSocket)); - if (ss) { - /* This should be of type SSLKEAType, but CC on IRIX - * complains during the for loop. - */ - int i; - SECStatus status; - - ss->opt = ssl_defaults; - ss->opt.useSocks = PR_FALSE; - ss->opt.noLocks = !makeLocks; - ss->vrange = *VERSIONS_DEFAULTS(protocolVariant); - ss->protocolVariant = protocolVariant; - - ss->peerID = NULL; - ss->rTimeout = PR_INTERVAL_NO_TIMEOUT; - ss->wTimeout = PR_INTERVAL_NO_TIMEOUT; - ss->cTimeout = PR_INTERVAL_NO_TIMEOUT; - ss->cipherSpecs = NULL; - ss->sizeCipherSpecs = 0; /* produced lazily */ - ss->preferredCipher = NULL; - ss->url = NULL; - - for (i=kt_null; i < kt_kea_size; i++) { - sslServerCerts * sc = ss->serverCerts + i; - sc->serverCert = NULL; - sc->serverCertChain = NULL; - sc->serverKeyPair = NULL; - sc->serverKeyBits = 0; - ss->certStatusArray[i] = NULL; - } - ss->stepDownKeyPair = NULL; - - ss->dheParams = NULL; - ss->dheKeyPair = NULL; - - ss->dbHandle = CERT_GetDefaultCertDB(); - - /* Provide default implementation of hooks */ - ss->authCertificate = SSL_AuthCertificate; - ss->authCertificateArg = (void *)ss->dbHandle; - ss->sniSocketConfig = NULL; - ss->sniSocketConfigArg = NULL; - ss->getClientAuthData = NULL; - ss->handleBadCert = NULL; - ss->badCertArg = NULL; - ss->pkcs11PinArg = NULL; - ss->ephemeralECDHKeyPair = NULL; - - ssl_ChooseOps(ss); - ssl2_InitSocketPolicy(ss); - ssl3_InitSocketPolicy(ss); - PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight); - - if (makeLocks) { - status = ssl_MakeLocks(ss); - if (status != SECSuccess) - goto loser; - } - status = ssl_CreateSecurityInfo(ss); - if (status != SECSuccess) + ss = (sslSocket *)PORT_ZAlloc(sizeof(sslSocket)); + if (!ss) { + return NULL; + } + ss->opt = ssl_defaults; + if (protocolVariant == ssl_variant_datagram) { + ss->opt.enableRenegotiation = SSL_RENEGOTIATE_NEVER; + } + ss->opt.useSocks = PR_FALSE; + ss->opt.noLocks = !makeLocks; + ss->vrange = *VERSIONS_DEFAULTS(protocolVariant); + ss->protocolVariant = protocolVariant; + + ss->peerID = NULL; + ss->rTimeout = PR_INTERVAL_NO_TIMEOUT; + ss->wTimeout = PR_INTERVAL_NO_TIMEOUT; + ss->cTimeout = PR_INTERVAL_NO_TIMEOUT; + ss->url = NULL; + + PR_INIT_CLIST(&ss->serverCerts); + PR_INIT_CLIST(&ss->ephemeralKeyPairs); + + ss->dbHandle = CERT_GetDefaultCertDB(); + + /* Provide default implementation of hooks */ + ss->authCertificate = SSL_AuthCertificate; + ss->authCertificateArg = (void *)ss->dbHandle; + ss->sniSocketConfig = NULL; + ss->sniSocketConfigArg = NULL; + ss->getClientAuthData = NULL; + ss->handleBadCert = NULL; + ss->badCertArg = NULL; + ss->pkcs11PinArg = NULL; + + ssl_ChooseOps(ss); + ssl3_InitSocketPolicy(ss); + for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { + ss->namedGroupPreferences[i] = &ssl_named_groups[i]; + } + ss->additionalShares = 0; + PR_INIT_CLIST(&ss->ssl3.hs.remoteExtensions); + PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight); + PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs); + PR_INIT_CLIST(&ss->ssl3.hs.bufferedEarlyData); + if (makeLocks) { + rv = ssl_MakeLocks(ss); + if (rv != SECSuccess) goto loser; - status = ssl_InitGather(&ss->gs); - if (status != SECSuccess) { -loser: - ssl_DestroySocketContents(ss); - ssl_DestroyLocks(ss); - PORT_Free(ss); - ss = NULL; - } } + rv = ssl_CreateSecurityInfo(ss); + if (rv != SECSuccess) + goto loser; + rv = ssl3_InitGather(&ss->gs); + if (rv != SECSuccess) + goto loser; + ssl3_InitExtensionData(&ss->xtnData); return ss; + +loser: + ssl_DestroySocketContents(ss); + ssl_DestroyLocks(ss); + PORT_Free(ss); + return NULL; +} + +/** + * DEPRECATED: Will always return false. + */ +SECStatus +SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey, + PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites, + PRBool *pcanbypass, void *pwArg) +{ + if (!pcanbypass) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + *pcanbypass = PR_FALSE; + return SECSuccess; } |