/* -*- 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. * Various other functions. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include"seccomon.h" #include"cert.h" #include"keyhi.h" #include"ssl.h" #include"sslexp.h" #include"sslimpl.h" #include"sslproto.h" #include"nspr.h" #include"private/pprio.h" #include"nss.h" #include"pk11pqg.h" #include"pk11pub.h" #include"tls13ech.h" #include"tls13psk.h" #include"tls13subcerts.h"
/* SRTP_NULL_HMAC_SHA1_80 and SRTP_NULL_HMAC_SHA1_32 are not implemented. */ staticconst PRUint16 srtpCiphers[] = {
SRTP_AES128_CM_HMAC_SHA1_80,
SRTP_AES128_CM_HMAC_SHA1_32,
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 \
}
/* ** Lookup a socket structure from a file descriptor. ** Only functions called through the PRIOMethods table should use this. ** Other app-callable functions should use ssl_FindSocket.
*/ static sslSocket *
ssl_GetPrivate(PRFileDesc *fd)
{
sslSocket *ss;
ss = (sslSocket *)fd->secret; /* Set ss->fd lazily. We can't rely on the value of ss->fd set by * ssl_PushIOLayer because another PR_PushIOLayer call will switch the * contents of the PRFileDesc pointed by ss->fd and the new layer. * See bug 807250.
*/
ss->fd = fd; return ss;
}
/* This function tries to find the SSL layer in the stack. * It searches for the first SSL layer at or below the argument fd, * and failing that, it searches for the nearest SSL layer above the * argument fd. It returns the private sslSocket from the found layer.
*/
sslSocket *
ssl_FindSocket(PRFileDesc *fd)
{
PRFileDesc *layer;
sslSocket *ss;
ss = (sslSocket *)layer->secret; /* Set ss->fd lazily. We can't rely on the value of ss->fd set by * ssl_PushIOLayer because another PR_PushIOLayer call will switch the * contents of the PRFileDesc pointed by ss->fd and the new layer. * See bug 807250.
*/
ss->fd = layer; return ss;
}
if (ss->peerID != NULL)
PORT_Free(ss->peerID); if (ss->url != 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);
}
/* * free an sslSocket struct, and all the stuff that hangs off of it
*/ void
ssl_FreeSocket(sslSocket *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);
ssl_GetXmitBufLock(ss);
ssl_GetSpecWriteLock(ss);
ssl_DestroySocketContents(ss);
/* Release all the locks acquired above. */
SSL_UNLOCK_READER(ss);
SSL_UNLOCK_WRITER(ss);
ssl_Release1stHandshakeLock(ss);
ssl_ReleaseRecvBufLock(ss);
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_ReleaseXmitBufLock(ss);
ssl_ReleaseSpecWriteLock(ss);
/* Implements the semantics for SSL_OptionSet(SSL_ENABLE_TLS, on) described in * ssl.h in the section "SSL version range setting API".
*/ staticvoid
ssl_EnableTLS(SSLVersionRange *vrange, PRIntn enable)
{ if (enable) { /* 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 (enable) {
vrange->min = SSL_LIBRARY_VERSION_TLS_1_0;
vrange->max = SSL_LIBRARY_VERSION_TLS_1_0;
} /* else don't change anything */ return;
}
if (enable) { /* Expand the range of enabled version to include TLS 1.0 */
vrange->min = PR_MIN(vrange->min, SSL_LIBRARY_VERSION_TLS_1_0);
vrange->max = PR_MAX(vrange->max, SSL_LIBRARY_VERSION_TLS_1_0);
} else { /* Disable all TLS versions, leaving only SSL 3.0 if it was enabled */ if (vrange->min == SSL_LIBRARY_VERSION_3_0) {
vrange->max = SSL_LIBRARY_VERSION_3_0;
} else { /* Only TLS was enabled, so now no versions are. */
vrange->min = SSL_LIBRARY_VERSION_NONE;
vrange->max = SSL_LIBRARY_VERSION_NONE;
}
}
}
/* Implements the semantics for SSL_OptionSet(SSL_ENABLE_SSL3, on) described in * ssl.h in the section "SSL version range setting API".
*/ staticvoid
ssl_EnableSSL3(SSLVersionRange *vrange, PRIntn enable)
{ if (enable) { /* 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 (enable) {
vrange->min = SSL_LIBRARY_VERSION_3_0;
vrange->max = SSL_LIBRARY_VERSION_3_0;
} /* else don't change anything */ return;
}
if (enable) { /* 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 { /* 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);
} else { /* Only SSL 3.0 was enabled, so now no versions are. */
vrange->min = SSL_LIBRARY_VERSION_NONE;
vrange->max = SSL_LIBRARY_VERSION_NONE;
}
}
}
switch (which) { case SSL_SOCKS:
ss->opt.useSocks = PR_FALSE;
rv = PrepareSocket(ss); if (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
} break;
case SSL_SECURITY:
ss->opt.useSecurity = val;
rv = PrepareSocket(ss); break;
case SSL_REQUEST_CERTIFICATE:
ss->opt.requestCertificate = val; break;
case SSL_REQUIRE_CERTIFICATE:
ss->opt.requireCertificate = val; break;
case SSL_HANDSHAKE_AS_CLIENT: if (ss->opt.handshakeAsServer && val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure; break;
}
ss->opt.handshakeAsClient = val; break;
case SSL_HANDSHAKE_AS_SERVER: if (ss->opt.handshakeAsClient && val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure; break;
}
ss->opt.handshakeAsServer = val; break;
case SSL_ENABLE_TLS: if (IS_DTLS(ss)) { if (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure; /* not allowed */
} break;
}
ssl_EnableTLS(&ss->vrange, val); break;
case SSL_ENABLE_SSL3: if (IS_DTLS(ss)) { if (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure; /* not allowed */
} break;
}
ssl_EnableSSL3(&ss->vrange, val); 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 (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
} break;
case SSL_NO_CACHE:
ss->opt.noCache = val; break;
case SSL_ENABLE_FDX: if (val && ss->opt.noLocks) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
}
ss->opt.fdx = val; break;
case SSL_ROLLBACK_DETECTION:
ss->opt.detectRollBack = val; break;
case SSL_NO_STEP_DOWN: break;
case SSL_BYPASS_PKCS11: break;
case SSL_NO_LOCKS: if (val && ss->opt.fdx) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
} if (val && ssl_force_locks)
val = PR_FALSE; /* silent override */
ss->opt.noLocks = val; if (!val && !holdingLocks) {
rv = ssl_MakeLocks(ss); if (rv != SECSuccess) {
ss->opt.noLocks = PR_TRUE;
}
} break;
case SSL_ENABLE_SESSION_TICKETS:
ss->opt.enableSessionTickets = val; break;
case SSL_ENABLE_DEFLATE:
ss->opt.enableDeflate = val; break;
case SSL_ENABLE_RENEGOTIATION: if (IS_DTLS(ss) && val != SSL_RENEGOTIATE_NEVER) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure; break;
}
ss->opt.enableRenegotiation = val; break;
case SSL_REQUIRE_SAFE_NEGOTIATION:
ss->opt.requireSafeNegotiation = val; break;
case SSL_ENABLE_FALSE_START:
ss->opt.enableFalseStart = val; break;
case SSL_CBC_RANDOM_IV:
ss->opt.cbcRandomIV = val; break;
case SSL_ENABLE_OCSP_STAPLING:
ss->opt.enableOCSPStapling = val; break;
case SSL_ENABLE_DELEGATED_CREDENTIALS:
ss->opt.enableDelegatedCredentials = val; break;
case SSL_ENABLE_NPN: break;
case SSL_ENABLE_ALPN:
ss->opt.enableALPN = val; break;
case SSL_REUSE_SERVER_ECDHE_KEY:
ss->opt.reuseServerECDHEKey = val; break;
case SSL_ENABLE_FALLBACK_SCSV:
ss->opt.enableFallbackSCSV = val; break;
case SSL_ENABLE_SERVER_DHE:
ss->opt.enableServerDhe = val; break;
case SSL_ENABLE_EXTENDED_MASTER_SECRET:
ss->opt.enableExtendedMS = val; break;
case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
ss->opt.enableSignedCertTimestamps = val; break;
case SSL_REQUIRE_DH_NAMED_GROUPS:
ss->opt.requireDHENamedGroups = val; break;
case SSL_ENABLE_0RTT_DATA:
ss->opt.enable0RttData = val; break;
case SSL_RECORD_SIZE_LIMIT: if (val < 64 || val > (MAX_FRAGMENT_LENGTH + 1)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
} else {
ss->opt.recordSizeLimit = val;
} break;
case SSL_ENABLE_TLS13_COMPAT_MODE:
ss->opt.enableTls13CompatMode = val; break;
case SSL_ENABLE_DTLS_SHORT_HEADER:
ss->opt.enableDtlsShortHeader = val; break;
case SSL_ENABLE_HELLO_DOWNGRADE_CHECK:
ss->opt.enableHelloDowngradeCheck = val; break;
case SSL_ENABLE_V2_COMPATIBLE_HELLO:
ss->opt.enableV2CompatibleHello = val; break;
case SSL_ENABLE_POST_HANDSHAKE_AUTH:
ss->opt.enablePostHandshakeAuth = val; break;
case SSL_SUPPRESS_END_OF_EARLY_DATA:
ss->opt.suppressEndOfEarlyData = val; break;
case SSL_ENABLE_GREASE:
ss->opt.enableGrease = val; break;
case SSL_ENABLE_CH_EXTENSION_PERMUTATION:
ss->opt.enableChXtnPermutation = val; break;
/* We can't use the macros for releasing the locks here, * because ss->opt.noLocks might have changed just above. * We must release these locks (monitors) here, if we aquired them above, * regardless of the current value of ss->opt.noLocks.
*/ if (holdingLocks) {
PZ_ExitMonitor((ss)->ssl3HandshakeLock);
PZ_ExitMonitor((ss)->firstHandshakeLock);
}
switch (which) { case SSL_SOCKS:
val = PR_FALSE; break; case SSL_SECURITY:
val = ss->opt.useSecurity; break; case SSL_REQUEST_CERTIFICATE:
val = ss->opt.requestCertificate; break; case SSL_REQUIRE_CERTIFICATE:
val = ss->opt.requireCertificate; break; case SSL_HANDSHAKE_AS_CLIENT:
val = ss->opt.handshakeAsClient; break; case SSL_HANDSHAKE_AS_SERVER:
val = ss->opt.handshakeAsServer; break; case SSL_ENABLE_TLS:
val = ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_0; break; case SSL_ENABLE_SSL3:
val = ss->vrange.min == SSL_LIBRARY_VERSION_3_0; break; case SSL_ENABLE_SSL2: case SSL_V2_COMPATIBLE_HELLO:
val = PR_FALSE; break; case SSL_NO_CACHE:
val = ss->opt.noCache; break; case SSL_ENABLE_FDX:
val = ss->opt.fdx; break; case SSL_ROLLBACK_DETECTION:
val = ss->opt.detectRollBack; break; case SSL_NO_STEP_DOWN:
val = PR_FALSE; break; case SSL_BYPASS_PKCS11:
val = PR_FALSE; break; case SSL_NO_LOCKS:
val = ss->opt.noLocks; break; case SSL_ENABLE_SESSION_TICKETS:
val = ss->opt.enableSessionTickets; break; case SSL_ENABLE_DEFLATE:
val = ss->opt.enableDeflate; break; case SSL_ENABLE_RENEGOTIATION:
val = ss->opt.enableRenegotiation; break; case SSL_REQUIRE_SAFE_NEGOTIATION:
val = ss->opt.requireSafeNegotiation; break; case SSL_ENABLE_FALSE_START:
val = ss->opt.enableFalseStart; break; case SSL_CBC_RANDOM_IV:
val = ss->opt.cbcRandomIV; break; case SSL_ENABLE_OCSP_STAPLING:
val = ss->opt.enableOCSPStapling; break; case SSL_ENABLE_DELEGATED_CREDENTIALS:
val = ss->opt.enableDelegatedCredentials; break; case SSL_ENABLE_NPN:
val = PR_FALSE; break; case SSL_ENABLE_ALPN:
val = ss->opt.enableALPN; break; case SSL_REUSE_SERVER_ECDHE_KEY:
val = ss->opt.reuseServerECDHEKey; break; case SSL_ENABLE_FALLBACK_SCSV:
val = ss->opt.enableFallbackSCSV; break; case SSL_ENABLE_SERVER_DHE:
val = ss->opt.enableServerDhe; break; case SSL_ENABLE_EXTENDED_MASTER_SECRET:
val = ss->opt.enableExtendedMS; break; case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
val = ss->opt.enableSignedCertTimestamps; break; case SSL_REQUIRE_DH_NAMED_GROUPS:
val = ss->opt.requireDHENamedGroups; break; case SSL_ENABLE_0RTT_DATA:
val = ss->opt.enable0RttData; break; case SSL_RECORD_SIZE_LIMIT:
val = ss->opt.recordSizeLimit; break; case SSL_ENABLE_TLS13_COMPAT_MODE:
val = ss->opt.enableTls13CompatMode; break; case SSL_ENABLE_DTLS_SHORT_HEADER:
val = ss->opt.enableDtlsShortHeader; break; case SSL_ENABLE_HELLO_DOWNGRADE_CHECK:
val = ss->opt.enableHelloDowngradeCheck; break; case SSL_ENABLE_V2_COMPATIBLE_HELLO:
val = ss->opt.enableV2CompatibleHello; break; case SSL_ENABLE_POST_HANDSHAKE_AUTH:
val = ss->opt.enablePostHandshakeAuth; break; case SSL_SUPPRESS_END_OF_EARLY_DATA:
val = ss->opt.suppressEndOfEarlyData; break; default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
}
if (!pVal) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
ssl_SetDefaultsFromEnvironment();
switch (which) { case SSL_SOCKS:
val = PR_FALSE; break; case SSL_SECURITY:
val = ssl_defaults.useSecurity; break; case SSL_REQUEST_CERTIFICATE:
val = ssl_defaults.requestCertificate; break; case SSL_REQUIRE_CERTIFICATE:
val = ssl_defaults.requireCertificate; break; case SSL_HANDSHAKE_AS_CLIENT:
val = ssl_defaults.handshakeAsClient; break; case SSL_HANDSHAKE_AS_SERVER:
val = ssl_defaults.handshakeAsServer; break; case SSL_ENABLE_TLS:
val = versions_defaults_stream.max >= SSL_LIBRARY_VERSION_TLS_1_0; break; case SSL_ENABLE_SSL3:
val = versions_defaults_stream.min == SSL_LIBRARY_VERSION_3_0; break; case SSL_ENABLE_SSL2: case SSL_V2_COMPATIBLE_HELLO:
val = PR_FALSE; break; case SSL_NO_CACHE:
val = ssl_defaults.noCache; break; case SSL_ENABLE_FDX:
val = ssl_defaults.fdx; break; case SSL_ROLLBACK_DETECTION:
val = ssl_defaults.detectRollBack; break; case SSL_NO_STEP_DOWN:
val = PR_FALSE; break; case SSL_BYPASS_PKCS11:
val = PR_FALSE; break; case SSL_NO_LOCKS:
val = ssl_defaults.noLocks; break; case SSL_ENABLE_SESSION_TICKETS:
val = ssl_defaults.enableSessionTickets; break; case SSL_ENABLE_DEFLATE:
val = ssl_defaults.enableDeflate; break; case SSL_ENABLE_RENEGOTIATION:
val = ssl_defaults.enableRenegotiation; break; case SSL_REQUIRE_SAFE_NEGOTIATION:
val = ssl_defaults.requireSafeNegotiation; break; case SSL_ENABLE_FALSE_START:
val = ssl_defaults.enableFalseStart; break; case SSL_CBC_RANDOM_IV:
val = ssl_defaults.cbcRandomIV; break; case SSL_ENABLE_OCSP_STAPLING:
val = ssl_defaults.enableOCSPStapling; break; case SSL_ENABLE_DELEGATED_CREDENTIALS:
val = ssl_defaults.enableDelegatedCredentials; break; case SSL_ENABLE_NPN:
val = PR_FALSE; break; case SSL_ENABLE_ALPN:
val = ssl_defaults.enableALPN; break; case SSL_REUSE_SERVER_ECDHE_KEY:
val = ssl_defaults.reuseServerECDHEKey; break; case SSL_ENABLE_FALLBACK_SCSV:
val = ssl_defaults.enableFallbackSCSV; break; case SSL_ENABLE_SERVER_DHE:
val = ssl_defaults.enableServerDhe; break; case SSL_ENABLE_EXTENDED_MASTER_SECRET:
val = ssl_defaults.enableExtendedMS; break; case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
val = ssl_defaults.enableSignedCertTimestamps; break; case SSL_ENABLE_0RTT_DATA:
val = ssl_defaults.enable0RttData; break; case SSL_RECORD_SIZE_LIMIT:
val = ssl_defaults.recordSizeLimit; break; case SSL_ENABLE_TLS13_COMPAT_MODE:
val = ssl_defaults.enableTls13CompatMode; break; case SSL_ENABLE_DTLS_SHORT_HEADER:
val = ssl_defaults.enableDtlsShortHeader; break; case SSL_ENABLE_HELLO_DOWNGRADE_CHECK:
val = ssl_defaults.enableHelloDowngradeCheck; break; case SSL_ENABLE_V2_COMPATIBLE_HELLO:
val = ssl_defaults.enableV2CompatibleHello; break; case SSL_ENABLE_POST_HANDSHAKE_AUTH:
val = ssl_defaults.enablePostHandshakeAuth; break; case SSL_SUPPRESS_END_OF_EARLY_DATA:
val = ssl_defaults.suppressEndOfEarlyData; break; default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
}
*pVal = val; return rv;
}
/* XXX Use Global Lock to protect this stuff. */
SECStatus
SSL_EnableDefault(int which, PRIntn val)
{ return SSL_OptionSetDefault(which, val);
}
SECStatus
SSL_OptionSetDefault(PRInt32 which, PRIntn val)
{
SECStatus status = ssl_Init();
if (status != SECSuccess) { return status;
}
ssl_SetDefaultsFromEnvironment();
switch (which) { case SSL_SOCKS:
ssl_defaults.useSocks = PR_FALSE; if (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
} break;
case SSL_SECURITY:
ssl_defaults.useSecurity = val; break;
case SSL_REQUEST_CERTIFICATE:
ssl_defaults.requestCertificate = val; break;
case SSL_REQUIRE_CERTIFICATE:
ssl_defaults.requireCertificate = val; break;
case SSL_HANDSHAKE_AS_CLIENT: if (ssl_defaults.handshakeAsServer && val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
ssl_defaults.handshakeAsClient = val; break;
case SSL_HANDSHAKE_AS_SERVER: if (ssl_defaults.handshakeAsClient && val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
ssl_defaults.handshakeAsServer = val; break;
case SSL_ENABLE_TLS:
ssl_EnableTLS(&versions_defaults_stream, val); break;
case SSL_ENABLE_SSL3:
ssl_EnableSSL3(&versions_defaults_stream, val); 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 (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
} break;
case SSL_NO_CACHE:
ssl_defaults.noCache = val; break;
case SSL_ENABLE_FDX: if (val && ssl_defaults.noLocks) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
ssl_defaults.fdx = val; break;
case SSL_ROLLBACK_DETECTION:
ssl_defaults.detectRollBack = val; break;
case SSL_NO_STEP_DOWN: break;
case SSL_BYPASS_PKCS11: break;
case SSL_NO_LOCKS: if (val && ssl_defaults.fdx) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
} if (val && ssl_force_locks)
val = PR_FALSE; /* silent override */
ssl_defaults.noLocks = val; break;
case SSL_ENABLE_SESSION_TICKETS:
ssl_defaults.enableSessionTickets = val; break;
case SSL_ENABLE_DEFLATE:
ssl_defaults.enableDeflate = val; break;
case SSL_ENABLE_RENEGOTIATION:
ssl_defaults.enableRenegotiation = val; break;
case SSL_REQUIRE_SAFE_NEGOTIATION:
ssl_defaults.requireSafeNegotiation = val; break;
case SSL_ENABLE_FALSE_START:
ssl_defaults.enableFalseStart = val; break;
case SSL_CBC_RANDOM_IV:
ssl_defaults.cbcRandomIV = val; break;
case SSL_ENABLE_OCSP_STAPLING:
ssl_defaults.enableOCSPStapling = val; break;
case SSL_ENABLE_DELEGATED_CREDENTIALS:
ssl_defaults.enableDelegatedCredentials = val; break;
case SSL_ENABLE_NPN: break;
case SSL_ENABLE_ALPN:
ssl_defaults.enableALPN = val; break;
case SSL_REUSE_SERVER_ECDHE_KEY:
ssl_defaults.reuseServerECDHEKey = val; break;
case SSL_ENABLE_FALLBACK_SCSV:
ssl_defaults.enableFallbackSCSV = val; break;
case SSL_ENABLE_SERVER_DHE:
ssl_defaults.enableServerDhe = val; break;
case SSL_ENABLE_EXTENDED_MASTER_SECRET:
ssl_defaults.enableExtendedMS = val; break;
case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
ssl_defaults.enableSignedCertTimestamps = val; break;
case SSL_ENABLE_0RTT_DATA:
ssl_defaults.enable0RttData = val; break;
case SSL_RECORD_SIZE_LIMIT: if (val < 64 || val > (MAX_FRAGMENT_LENGTH + 1)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
ssl_defaults.recordSizeLimit = val; break;
case SSL_ENABLE_TLS13_COMPAT_MODE:
ssl_defaults.enableTls13CompatMode = val; break;
case SSL_ENABLE_DTLS_SHORT_HEADER:
ssl_defaults.enableDtlsShortHeader = val; break;
case SSL_ENABLE_HELLO_DOWNGRADE_CHECK:
ssl_defaults.enableHelloDowngradeCheck = val; break;
case SSL_ENABLE_V2_COMPATIBLE_HELLO:
ssl_defaults.enableV2CompatibleHello = val; break;
case SSL_ENABLE_POST_HANDSHAKE_AUTH:
ssl_defaults.enablePostHandshakeAuth = val; break;
case SSL_SUPPRESS_END_OF_EARLY_DATA:
ssl_defaults.suppressEndOfEarlyData = val; break;
/* function tells us if the cipher suite is one that we no longer support. */ 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;
}
}
/* Part of the public NSS API. * Since this is a global (not per-socket) setting, we cannot use the * HandshakeLock to protect this. Probably want a global lock.
*/
SECStatus
SSL_SetPolicy(long which, int policy)
{ if (ssl_IsRemovedCipherSuite(which)) return SECSuccess; return SSL_CipherPolicySet(which, policy);
}
/* Part of the public NSS API. * Since this is a global (not per-socket) setting, we cannot use the * HandshakeLock to protect this. Probably want a global lock. * These changes have no effect on any sslSockets already created.
*/
SECStatus
SSL_EnableCipher(long which, PRBool enabled)
{ if (ssl_IsRemovedCipherSuite(which)) return SECSuccess; return SSL_CipherPrefSetDefault(which, enabled);
}
if (!enabled) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
} if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in CipherPrefGet", SSL_GETPID(), fd));
*enabled = PR_FALSE; return SECFailure;
} if (ssl_IsRemovedCipherSuite(which)) {
*enabled = PR_FALSE;
rv = SECSuccess;
} else {
rv = ssl3_CipherPrefGet(ss, (ssl3CipherSuite)which, enabled);
} return rv;
}
/* The client can call this function to be aware of the current
* CipherSuites order. */
SECStatus
SSLExp_CipherSuiteOrderGet(PRFileDesc *fd, PRUint16 *cipherOrder, unsignedint *numCiphers)
{ if (!fd) {
SSL_DBG(("%d: SSL: file descriptor in CipherSuiteOrderGet is null",
SSL_GETPID()));
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
} if (!cipherOrder || !numCiphers) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
sslSocket *ss = ssl_FindSocket(fd); if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in CipherSuiteOrderGet", SSL_GETPID(),
fd)); return SECFailure; /* Error code already set. */
}
/* This function permits reorder the CipherSuites List for the Handshake
* (Client Hello). */
SECStatus
SSLExp_CipherSuiteOrderSet(PRFileDesc *fd, const PRUint16 *cipherOrder,
PRUint16 numCiphers)
{ if (!fd) {
SSL_DBG(("%d: SSL: file descriptor in CipherSuiteOrderGet is null",
SSL_GETPID()));
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
} if (!cipherOrder || !numCiphers || numCiphers > ssl_V3_SUITES_IMPLEMENTED) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
sslSocket *ss = ssl_FindSocket(fd); if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in CipherSuiteOrderSet", SSL_GETPID(),
fd)); return SECFailure; /* Error code already set. */
}
ssl3CipherSuiteCfg tmpSuiteCfg[ssl_V3_SUITES_IMPLEMENTED];
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss); /* For each cipherSuite given as input, verify that it is
* known to NSS and only present in the list once. */ for (unsignedint i = 0; i < numCiphers; i++) { const ssl3CipherSuiteCfg *suiteCfg =
ssl_LookupCipherSuiteCfg(cipherOrder[i], ss->cipherSuites); if (!suiteCfg) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss); return SECFailure;
} for (unsignedint j = i + 1; j < numCiphers; j++) { /* This is a duplicate entry. */ if (cipherOrder[i] == cipherOrder[j]) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss); return SECFailure;
}
}
tmpSuiteCfg[i] = *suiteCfg;
tmpSuiteCfg[i].enabled = PR_TRUE;
} /* Find all defined ciphersuites not present in the input list and append * them after the preferred. This guarantees that the socket will always
* have a complete list of size ssl_V3_SUITES_IMPLEMENTED */ unsignedint cfgIdx = numCiphers; for (unsignedint i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
PRBool received = PR_FALSE; for (unsignedint j = 0; j < numCiphers; j++) { if (ss->cipherSuites[i].cipher_suite ==
tmpSuiteCfg[j].cipher_suite) {
received = PR_TRUE; break;
}
} if (!received) {
tmpSuiteCfg[cfgIdx] = ss->cipherSuites[i];
tmpSuiteCfg[cfgIdx++].enabled = PR_FALSE;
}
}
PORT_Assert(cfgIdx == ssl_V3_SUITES_IMPLEMENTED); /* now we can rewrite the socket with the desired order */
PORT_Memcpy(ss->cipherSuites, tmpSuiteCfg, sizeof(tmpSuiteCfg));
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss); return SECSuccess;
}
/* 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 been loaded */
}
for (cipher = SSL_ImplementedCiphers; *cipher != 0; ++cipher) {
status = SSL_SetPolicy(*cipher, SSL_ALLOWED); if (status != SECSuccess) break;
} return status;
}
ss = ssl_FindSocket(fd); if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in SSL_DHEGroupPrefSet", SSL_GETPID(), fd)); return SECFailure;
}
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;
}
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;
}
} if (!duplicate) {
enabled[k++] = groupDef;
}
} for (i = 0; i < k; ++i) {
ss->namedGroupPreferences[i] = enabled[i];
}
return SECSuccess;
}
PRCallOnceType gWeakDHParamsRegisterOnce; int gWeakDHParamsRegisterError;
PRCallOnceType gWeakDHParamsOnce; int gWeakDHParamsError; /* As our code allocates type PQGParams, we'll keep it around,
* even though we only make use of it's parameters through gWeakDHParam. */ static PQGParams *gWeakParamsPQG; static ssl3DHParams *gWeakDHParams; #define WEAK_DHE_SIZE 1024
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;
}
/* This validates dh_Ys against the group prime. */
PRBool
ssl_IsValidDHEShare(const SECItem *dh_p, const SECItem *dh_Ys)
{ unsignedint size_p = SECKEY_BigIntegerBitLength(dh_p); unsignedint size_y = SECKEY_BigIntegerBitLength(dh_Ys); unsignedint commonPart; int cmp;
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;
}
/* 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
ssl_ValidateDHENamedGroup(sslSocket *ss, const SECItem *dh_p, const SECItem *dh_g, const sslNamedGroupDef **groupDef, const ssl3DHParams **dhParams)
{ unsignedint i;
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;
}
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;
}
}
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)
{ unsignedint i; staticconst sslNamedGroupDef weak_group_def = {
ssl_grp_ffdhe_custom, WEAK_DHE_SIZE, ssl_kea_dh,
SEC_OID_TLS_DHE_CUSTOM, PR_TRUE
};
PRInt32 minDH;
SECStatus rv;
// make sure we select a group consistent with our // current policy policy
rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &minDH); if (rv != SECSuccess || minDH <= 0) {
minDH = DH_MIN_P_BITS;
}
/* 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 &&
weak_group_def.bits >= minDH) {
*groupDef = &weak_group_def; return SECSuccess;
} if (ss->ssl3.dhePreferredGroup &&
ssl_NamedGroupEnabled(ss, ss->ssl3.dhePreferredGroup) &&
ss->ssl3.dhePreferredGroup->bits >= minDH) {
*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 &&
ss->namedGroupPreferences[i]->bits >= minDH) {
*groupDef = ss->namedGroupPreferences[i]; return SECSuccess;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.