summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/sslsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/sslsock.c')
-rw-r--r--security/nss/lib/ssl/sslsock.c704
1 files changed, 501 insertions, 203 deletions
diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c
index 99828c85b..e08d5e232 100644
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -11,6 +11,7 @@
#include "cert.h"
#include "keyhi.h"
#include "ssl.h"
+#include "sslexp.h"
#include "sslimpl.h"
#include "sslproto.h"
#include "nspr.h"
@@ -52,38 +53,35 @@ static const sslSocketOps ssl_secure_ops = { /* SSL. */
** default settings for socket enables
*/
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, /* 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
+ .nextProtoNego = { siBuffer, NULL, 0 },
+ .maxEarlyDataSize = 1 << 16,
+ .useSecurity = PR_TRUE,
+ .useSocks = PR_FALSE,
+ .requestCertificate = PR_FALSE,
+ .requireCertificate = SSL_REQUIRE_FIRST_HANDSHAKE,
+ .handshakeAsClient = PR_FALSE,
+ .handshakeAsServer = PR_FALSE,
+ .noCache = PR_FALSE,
+ .fdx = PR_FALSE,
+ .detectRollBack = PR_TRUE,
+ .noLocks = PR_FALSE,
+ .enableSessionTickets = PR_FALSE,
+ .enableDeflate = PR_FALSE,
+ .enableRenegotiation = SSL_RENEGOTIATE_REQUIRES_XTN,
+ .requireSafeNegotiation = PR_FALSE,
+ .enableFalseStart = PR_FALSE,
+ .cbcRandomIV = PR_TRUE,
+ .enableOCSPStapling = PR_FALSE,
+ .enableNPN = PR_FALSE,
+ .enableALPN = PR_TRUE,
+ .reuseServerECDHEKey = PR_TRUE,
+ .enableFallbackSCSV = PR_FALSE,
+ .enableServerDhe = PR_TRUE,
+ .enableExtendedMS = PR_FALSE,
+ .enableSignedCertTimestamps = PR_FALSE,
+ .requireDHENamedGroups = PR_FALSE,
+ .enable0RttData = PR_FALSE,
+ .enableTls13CompatMode = PR_FALSE
};
/*
@@ -107,10 +105,7 @@ static SSLVersionRange versions_defaults_datagram = {
(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 */
@@ -122,6 +117,7 @@ FILE *ssl_trace_iob;
#ifdef NSS_ALLOW_SSLKEYLOGFILE
FILE *ssl_keylog_iob;
+PZLock *ssl_keylog_lock;
#endif
char lockStatus[] = "Locks are ENABLED. ";
@@ -300,6 +296,7 @@ ssl_DupSocket(sslSocket *os)
if (ss->opt.useSecurity) {
PRCList *cursor;
+
for (cursor = PR_NEXT_LINK(&os->serverCerts);
cursor != &os->serverCerts;
cursor = PR_NEXT_LINK(cursor)) {
@@ -309,7 +306,6 @@ ssl_DupSocket(sslSocket *os)
PR_APPEND_LINK(&sc->link, &ss->serverCerts);
}
- PR_INIT_CLIST(&ss->ephemeralKeyPairs);
for (cursor = PR_NEXT_LINK(&os->ephemeralKeyPairs);
cursor != &os->ephemeralKeyPairs;
cursor = PR_NEXT_LINK(cursor)) {
@@ -320,6 +316,18 @@ ssl_DupSocket(sslSocket *os)
PR_APPEND_LINK(&skp->link, &ss->ephemeralKeyPairs);
}
+ for (cursor = PR_NEXT_LINK(&os->extensionHooks);
+ cursor != &os->extensionHooks;
+ cursor = PR_NEXT_LINK(cursor)) {
+ sslCustomExtensionHooks *oh = (sslCustomExtensionHooks *)cursor;
+ sslCustomExtensionHooks *sh = PORT_ZNew(sslCustomExtensionHooks);
+ if (!sh) {
+ goto loser;
+ }
+ *sh = *oh;
+ PR_APPEND_LINK(&sh->link, &ss->extensionHooks);
+ }
+
/*
* 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.
@@ -347,6 +355,8 @@ ssl_DupSocket(sslSocket *os)
os->namedGroupPreferences,
sizeof(ss->namedGroupPreferences));
ss->additionalShares = os->additionalShares;
+ ss->resumptionTokenCallback = os->resumptionTokenCallback;
+ ss->resumptionTokenContext = os->resumptionTokenContext;
/* Create security data */
rv = ssl_CopySecurityInfo(ss, os);
@@ -354,6 +364,7 @@ ssl_DupSocket(sslSocket *os)
goto loser;
}
}
+
return ss;
loser:
@@ -422,9 +433,16 @@ ssl_DestroySocketContents(sslSocket *ss)
PR_REMOVE_LINK(cursor);
ssl_FreeServerCert((sslServerCert *)cursor);
}
+
+ /* Remove extension handlers. */
+ ssl_ClearPRCList(&ss->extensionHooks, NULL);
+
ssl_FreeEphemeralKeyPairs(ss);
SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE);
ssl3_FreeSniNameArray(&ss->xtnData);
+
+ ssl_ClearPRCList(&ss->ssl3.hs.dtlsSentHandshake, NULL);
+ ssl_ClearPRCList(&ss->ssl3.hs.dtlsRcvdHandshake, NULL);
}
/*
@@ -501,7 +519,7 @@ PrepareSocket(sslSocket *ss)
}
SECStatus
-SSL_Enable(PRFileDesc *fd, int which, PRBool on)
+SSL_Enable(PRFileDesc *fd, int which, PRIntn on)
{
return SSL_OptionSet(fd, which, on);
}
@@ -513,9 +531,9 @@ static PRBool ssl_VersionIsSupportedByPolicy(
* ssl.h in the section "SSL version range setting API".
*/
static void
-ssl_EnableTLS(SSLVersionRange *vrange, PRBool on)
+ssl_EnableTLS(SSLVersionRange *vrange, PRIntn enable)
{
- if (on) {
+ 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)) {
@@ -523,14 +541,14 @@ ssl_EnableTLS(SSLVersionRange *vrange, PRBool on)
}
}
if (SSL_ALL_VERSIONS_DISABLED(vrange)) {
- if (on) {
+ 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 (on) {
+ 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);
@@ -550,9 +568,9 @@ ssl_EnableTLS(SSLVersionRange *vrange, PRBool on)
* ssl.h in the section "SSL version range setting API".
*/
static void
-ssl_EnableSSL3(SSLVersionRange *vrange, PRBool on)
+ssl_EnableSSL3(SSLVersionRange *vrange, PRIntn enable)
{
- if (on) {
+ if (enable) {
/* don't turn it on if ssl3 disallowed by by policy */
if (!ssl_VersionIsSupportedByPolicy(ssl_variant_stream,
SSL_LIBRARY_VERSION_3_0)) {
@@ -560,14 +578,14 @@ ssl_EnableSSL3(SSLVersionRange *vrange, PRBool on)
}
}
if (SSL_ALL_VERSIONS_DISABLED(vrange)) {
- if (on) {
+ if (enable) {
vrange->min = SSL_LIBRARY_VERSION_3_0;
vrange->max = SSL_LIBRARY_VERSION_3_0;
} /* else don't change anything */
return;
}
- if (on) {
+ 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.
@@ -586,7 +604,7 @@ ssl_EnableSSL3(SSLVersionRange *vrange, PRBool on)
}
SECStatus
-SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
+SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRIntn val)
{
sslSocket *ss = ssl_FindSocket(fd);
SECStatus rv = SECSuccess;
@@ -605,63 +623,63 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
case SSL_SOCKS:
ss->opt.useSocks = PR_FALSE;
rv = PrepareSocket(ss);
- if (on) {
+ if (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
}
break;
case SSL_SECURITY:
- ss->opt.useSecurity = on;
+ ss->opt.useSecurity = val;
rv = PrepareSocket(ss);
break;
case SSL_REQUEST_CERTIFICATE:
- ss->opt.requestCertificate = on;
+ ss->opt.requestCertificate = val;
break;
case SSL_REQUIRE_CERTIFICATE:
- ss->opt.requireCertificate = on;
+ ss->opt.requireCertificate = val;
break;
case SSL_HANDSHAKE_AS_CLIENT:
- if (ss->opt.handshakeAsServer && on) {
+ if (ss->opt.handshakeAsServer && val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
break;
}
- ss->opt.handshakeAsClient = on;
+ ss->opt.handshakeAsClient = val;
break;
case SSL_HANDSHAKE_AS_SERVER:
- if (ss->opt.handshakeAsClient && on) {
+ if (ss->opt.handshakeAsClient && val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
break;
}
- ss->opt.handshakeAsServer = on;
+ ss->opt.handshakeAsServer = val;
break;
case SSL_ENABLE_TLS:
if (IS_DTLS(ss)) {
- if (on) {
+ if (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure; /* not allowed */
}
break;
}
- ssl_EnableTLS(&ss->vrange, on);
+ ssl_EnableTLS(&ss->vrange, val);
break;
case SSL_ENABLE_SSL3:
if (IS_DTLS(ss)) {
- if (on) {
+ if (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure; /* not allowed */
}
break;
}
- ssl_EnableSSL3(&ss->vrange, on);
+ ssl_EnableSSL3(&ss->vrange, val);
break;
case SSL_ENABLE_SSL2:
@@ -670,26 +688,26 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
* However, if an old application requests to disable SSL v2,
* we shouldn't fail.
*/
- if (on) {
+ if (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
}
break;
case SSL_NO_CACHE:
- ss->opt.noCache = on;
+ ss->opt.noCache = val;
break;
case SSL_ENABLE_FDX:
- if (on && ss->opt.noLocks) {
+ if (val && ss->opt.noLocks) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
}
- ss->opt.fdx = on;
+ ss->opt.fdx = val;
break;
case SSL_ROLLBACK_DETECTION:
- ss->opt.detectRollBack = on;
+ ss->opt.detectRollBack = val;
break;
case SSL_NO_STEP_DOWN:
@@ -699,14 +717,14 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
break;
case SSL_NO_LOCKS:
- if (on && ss->opt.fdx) {
+ if (val && 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) {
+ if (val && ssl_force_locks)
+ val = PR_FALSE; /* silent override */
+ ss->opt.noLocks = val;
+ if (val) {
locksEverDisabled = PR_TRUE;
strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED.");
} else if (!holdingLocks) {
@@ -718,71 +736,75 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
break;
case SSL_ENABLE_SESSION_TICKETS:
- ss->opt.enableSessionTickets = on;
+ ss->opt.enableSessionTickets = val;
break;
case SSL_ENABLE_DEFLATE:
- ss->opt.enableDeflate = on;
+ ss->opt.enableDeflate = val;
break;
case SSL_ENABLE_RENEGOTIATION:
- if (IS_DTLS(ss) && on != SSL_RENEGOTIATE_NEVER) {
+ if (IS_DTLS(ss) && val != SSL_RENEGOTIATE_NEVER) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
break;
}
- ss->opt.enableRenegotiation = on;
+ ss->opt.enableRenegotiation = val;
break;
case SSL_REQUIRE_SAFE_NEGOTIATION:
- ss->opt.requireSafeNegotiation = on;
+ ss->opt.requireSafeNegotiation = val;
break;
case SSL_ENABLE_FALSE_START:
- ss->opt.enableFalseStart = on;
+ ss->opt.enableFalseStart = val;
break;
case SSL_CBC_RANDOM_IV:
- ss->opt.cbcRandomIV = on;
+ ss->opt.cbcRandomIV = val;
break;
case SSL_ENABLE_OCSP_STAPLING:
- ss->opt.enableOCSPStapling = on;
+ ss->opt.enableOCSPStapling = val;
break;
case SSL_ENABLE_NPN:
break;
case SSL_ENABLE_ALPN:
- ss->opt.enableALPN = on;
+ ss->opt.enableALPN = val;
break;
case SSL_REUSE_SERVER_ECDHE_KEY:
- ss->opt.reuseServerECDHEKey = on;
+ ss->opt.reuseServerECDHEKey = val;
break;
case SSL_ENABLE_FALLBACK_SCSV:
- ss->opt.enableFallbackSCSV = on;
+ ss->opt.enableFallbackSCSV = val;
break;
case SSL_ENABLE_SERVER_DHE:
- ss->opt.enableServerDhe = on;
+ ss->opt.enableServerDhe = val;
break;
case SSL_ENABLE_EXTENDED_MASTER_SECRET:
- ss->opt.enableExtendedMS = on;
+ ss->opt.enableExtendedMS = val;
break;
case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
- ss->opt.enableSignedCertTimestamps = on;
+ ss->opt.enableSignedCertTimestamps = val;
break;
case SSL_REQUIRE_DH_NAMED_GROUPS:
- ss->opt.requireDHENamedGroups = on;
+ ss->opt.requireDHENamedGroups = val;
break;
case SSL_ENABLE_0RTT_DATA:
- ss->opt.enable0RttData = on;
+ ss->opt.enable0RttData = val;
+ break;
+
+ case SSL_ENABLE_TLS13_COMPAT_MODE:
+ ss->opt.enableTls13CompatMode = val;
break;
default:
@@ -804,19 +826,19 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
}
SECStatus
-SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
+SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRIntn *pVal)
{
sslSocket *ss = ssl_FindSocket(fd);
SECStatus rv = SECSuccess;
- PRBool on = PR_FALSE;
+ PRIntn val = PR_FALSE;
- if (!pOn) {
+ if (!pVal) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in Enable", SSL_GETPID(), fd));
- *pOn = PR_FALSE;
+ *pVal = PR_FALSE;
return SECFailure;
}
@@ -825,98 +847,101 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
switch (which) {
case SSL_SOCKS:
- on = PR_FALSE;
+ val = PR_FALSE;
break;
case SSL_SECURITY:
- on = ss->opt.useSecurity;
+ val = ss->opt.useSecurity;
break;
case SSL_REQUEST_CERTIFICATE:
- on = ss->opt.requestCertificate;
+ val = ss->opt.requestCertificate;
break;
case SSL_REQUIRE_CERTIFICATE:
- on = ss->opt.requireCertificate;
+ val = ss->opt.requireCertificate;
break;
case SSL_HANDSHAKE_AS_CLIENT:
- on = ss->opt.handshakeAsClient;
+ val = ss->opt.handshakeAsClient;
break;
case SSL_HANDSHAKE_AS_SERVER:
- on = ss->opt.handshakeAsServer;
+ val = ss->opt.handshakeAsServer;
break;
case SSL_ENABLE_TLS:
- on = ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_0;
+ val = ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_0;
break;
case SSL_ENABLE_SSL3:
- on = ss->vrange.min == SSL_LIBRARY_VERSION_3_0;
+ val = ss->vrange.min == SSL_LIBRARY_VERSION_3_0;
break;
case SSL_ENABLE_SSL2:
case SSL_V2_COMPATIBLE_HELLO:
- on = PR_FALSE;
+ val = PR_FALSE;
break;
case SSL_NO_CACHE:
- on = ss->opt.noCache;
+ val = ss->opt.noCache;
break;
case SSL_ENABLE_FDX:
- on = ss->opt.fdx;
+ val = ss->opt.fdx;
break;
case SSL_ROLLBACK_DETECTION:
- on = ss->opt.detectRollBack;
+ val = ss->opt.detectRollBack;
break;
case SSL_NO_STEP_DOWN:
- on = PR_FALSE;
+ val = PR_FALSE;
break;
case SSL_BYPASS_PKCS11:
- on = PR_FALSE;
+ val = PR_FALSE;
break;
case SSL_NO_LOCKS:
- on = ss->opt.noLocks;
+ val = ss->opt.noLocks;
break;
case SSL_ENABLE_SESSION_TICKETS:
- on = ss->opt.enableSessionTickets;
+ val = ss->opt.enableSessionTickets;
break;
case SSL_ENABLE_DEFLATE:
- on = ss->opt.enableDeflate;
+ val = ss->opt.enableDeflate;
break;
case SSL_ENABLE_RENEGOTIATION:
- on = ss->opt.enableRenegotiation;
+ val = ss->opt.enableRenegotiation;
break;
case SSL_REQUIRE_SAFE_NEGOTIATION:
- on = ss->opt.requireSafeNegotiation;
+ val = ss->opt.requireSafeNegotiation;
break;
case SSL_ENABLE_FALSE_START:
- on = ss->opt.enableFalseStart;
+ val = ss->opt.enableFalseStart;
break;
case SSL_CBC_RANDOM_IV:
- on = ss->opt.cbcRandomIV;
+ val = ss->opt.cbcRandomIV;
break;
case SSL_ENABLE_OCSP_STAPLING:
- on = ss->opt.enableOCSPStapling;
+ val = ss->opt.enableOCSPStapling;
break;
case SSL_ENABLE_NPN:
- on = ss->opt.enableNPN;
+ val = ss->opt.enableNPN;
break;
case SSL_ENABLE_ALPN:
- on = ss->opt.enableALPN;
+ val = ss->opt.enableALPN;
break;
case SSL_REUSE_SERVER_ECDHE_KEY:
- on = ss->opt.reuseServerECDHEKey;
+ val = ss->opt.reuseServerECDHEKey;
break;
case SSL_ENABLE_FALLBACK_SCSV:
- on = ss->opt.enableFallbackSCSV;
+ val = ss->opt.enableFallbackSCSV;
break;
case SSL_ENABLE_SERVER_DHE:
- on = ss->opt.enableServerDhe;
+ val = ss->opt.enableServerDhe;
break;
case SSL_ENABLE_EXTENDED_MASTER_SECRET:
- on = ss->opt.enableExtendedMS;
+ val = ss->opt.enableExtendedMS;
break;
case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
- on = ss->opt.enableSignedCertTimestamps;
+ val = ss->opt.enableSignedCertTimestamps;
break;
case SSL_REQUIRE_DH_NAMED_GROUPS:
- on = ss->opt.requireDHENamedGroups;
+ val = ss->opt.requireDHENamedGroups;
break;
case SSL_ENABLE_0RTT_DATA:
- on = ss->opt.enable0RttData;
+ val = ss->opt.enable0RttData;
+ break;
+ case SSL_ENABLE_TLS13_COMPAT_MODE:
+ val = ss->opt.enableTls13CompatMode;
break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -926,17 +951,17 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss);
- *pOn = on;
+ *pVal = val;
return rv;
}
SECStatus
-SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
+SSL_OptionGetDefault(PRInt32 which, PRIntn *pVal)
{
SECStatus rv = SECSuccess;
- PRBool on = PR_FALSE;
+ PRIntn val = PR_FALSE;
- if (!pOn) {
+ if (!pVal) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@@ -945,114 +970,117 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
switch (which) {
case SSL_SOCKS:
- on = PR_FALSE;
+ val = PR_FALSE;
break;
case SSL_SECURITY:
- on = ssl_defaults.useSecurity;
+ val = ssl_defaults.useSecurity;
break;
case SSL_REQUEST_CERTIFICATE:
- on = ssl_defaults.requestCertificate;
+ val = ssl_defaults.requestCertificate;
break;
case SSL_REQUIRE_CERTIFICATE:
- on = ssl_defaults.requireCertificate;
+ val = ssl_defaults.requireCertificate;
break;
case SSL_HANDSHAKE_AS_CLIENT:
- on = ssl_defaults.handshakeAsClient;
+ val = ssl_defaults.handshakeAsClient;
break;
case SSL_HANDSHAKE_AS_SERVER:
- on = ssl_defaults.handshakeAsServer;
+ val = ssl_defaults.handshakeAsServer;
break;
case SSL_ENABLE_TLS:
- on = versions_defaults_stream.max >= SSL_LIBRARY_VERSION_TLS_1_0;
+ val = 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;
+ val = versions_defaults_stream.min == SSL_LIBRARY_VERSION_3_0;
break;
case SSL_ENABLE_SSL2:
case SSL_V2_COMPATIBLE_HELLO:
- on = PR_FALSE;
+ val = PR_FALSE;
break;
case SSL_NO_CACHE:
- on = ssl_defaults.noCache;
+ val = ssl_defaults.noCache;
break;
case SSL_ENABLE_FDX:
- on = ssl_defaults.fdx;
+ val = ssl_defaults.fdx;
break;
case SSL_ROLLBACK_DETECTION:
- on = ssl_defaults.detectRollBack;
+ val = ssl_defaults.detectRollBack;
break;
case SSL_NO_STEP_DOWN:
- on = PR_FALSE;
+ val = PR_FALSE;
break;
case SSL_BYPASS_PKCS11:
- on = PR_FALSE;
+ val = PR_FALSE;
break;
case SSL_NO_LOCKS:
- on = ssl_defaults.noLocks;
+ val = ssl_defaults.noLocks;
break;
case SSL_ENABLE_SESSION_TICKETS:
- on = ssl_defaults.enableSessionTickets;
+ val = ssl_defaults.enableSessionTickets;
break;
case SSL_ENABLE_DEFLATE:
- on = ssl_defaults.enableDeflate;
+ val = ssl_defaults.enableDeflate;
break;
case SSL_ENABLE_RENEGOTIATION:
- on = ssl_defaults.enableRenegotiation;
+ val = ssl_defaults.enableRenegotiation;
break;
case SSL_REQUIRE_SAFE_NEGOTIATION:
- on = ssl_defaults.requireSafeNegotiation;
+ val = ssl_defaults.requireSafeNegotiation;
break;
case SSL_ENABLE_FALSE_START:
- on = ssl_defaults.enableFalseStart;
+ val = ssl_defaults.enableFalseStart;
break;
case SSL_CBC_RANDOM_IV:
- on = ssl_defaults.cbcRandomIV;
+ val = ssl_defaults.cbcRandomIV;
break;
case SSL_ENABLE_OCSP_STAPLING:
- on = ssl_defaults.enableOCSPStapling;
+ val = ssl_defaults.enableOCSPStapling;
break;
case SSL_ENABLE_NPN:
- on = ssl_defaults.enableNPN;
+ val = ssl_defaults.enableNPN;
break;
case SSL_ENABLE_ALPN:
- on = ssl_defaults.enableALPN;
+ val = ssl_defaults.enableALPN;
break;
case SSL_REUSE_SERVER_ECDHE_KEY:
- on = ssl_defaults.reuseServerECDHEKey;
+ val = ssl_defaults.reuseServerECDHEKey;
break;
case SSL_ENABLE_FALLBACK_SCSV:
- on = ssl_defaults.enableFallbackSCSV;
+ val = ssl_defaults.enableFallbackSCSV;
break;
case SSL_ENABLE_SERVER_DHE:
- on = ssl_defaults.enableServerDhe;
+ val = ssl_defaults.enableServerDhe;
break;
case SSL_ENABLE_EXTENDED_MASTER_SECRET:
- on = ssl_defaults.enableExtendedMS;
+ val = ssl_defaults.enableExtendedMS;
break;
case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
- on = ssl_defaults.enableSignedCertTimestamps;
+ val = ssl_defaults.enableSignedCertTimestamps;
break;
case SSL_ENABLE_0RTT_DATA:
- on = ssl_defaults.enable0RttData;
+ val = ssl_defaults.enable0RttData;
+ break;
+ case SSL_ENABLE_TLS13_COMPAT_MODE:
+ val = ssl_defaults.enableTls13CompatMode;
break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
}
- *pOn = on;
+ *pVal = val;
return rv;
}
/* XXX Use Global Lock to protect this stuff. */
SECStatus
-SSL_EnableDefault(int which, PRBool on)
+SSL_EnableDefault(int which, PRIntn val)
{
- return SSL_OptionSetDefault(which, on);
+ return SSL_OptionSetDefault(which, val);
}
SECStatus
-SSL_OptionSetDefault(PRInt32 which, PRBool on)
+SSL_OptionSetDefault(PRInt32 which, PRIntn val)
{
SECStatus status = ssl_Init();
@@ -1065,46 +1093,46 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
switch (which) {
case SSL_SOCKS:
ssl_defaults.useSocks = PR_FALSE;
- if (on) {
+ if (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
break;
case SSL_SECURITY:
- ssl_defaults.useSecurity = on;
+ ssl_defaults.useSecurity = val;
break;
case SSL_REQUEST_CERTIFICATE:
- ssl_defaults.requestCertificate = on;
+ ssl_defaults.requestCertificate = val;
break;
case SSL_REQUIRE_CERTIFICATE:
- ssl_defaults.requireCertificate = on;
+ ssl_defaults.requireCertificate = val;
break;
case SSL_HANDSHAKE_AS_CLIENT:
- if (ssl_defaults.handshakeAsServer && on) {
+ if (ssl_defaults.handshakeAsServer && val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
- ssl_defaults.handshakeAsClient = on;
+ ssl_defaults.handshakeAsClient = val;
break;
case SSL_HANDSHAKE_AS_SERVER:
- if (ssl_defaults.handshakeAsClient && on) {
+ if (ssl_defaults.handshakeAsClient && val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
- ssl_defaults.handshakeAsServer = on;
+ ssl_defaults.handshakeAsServer = val;
break;
case SSL_ENABLE_TLS:
- ssl_EnableTLS(&versions_defaults_stream, on);
+ ssl_EnableTLS(&versions_defaults_stream, val);
break;
case SSL_ENABLE_SSL3:
- ssl_EnableSSL3(&versions_defaults_stream, on);
+ ssl_EnableSSL3(&versions_defaults_stream, val);
break;
case SSL_ENABLE_SSL2:
@@ -1113,26 +1141,26 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
* However, if an old application requests to disable SSL v2,
* we shouldn't fail.
*/
- if (on) {
+ if (val) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
break;
case SSL_NO_CACHE:
- ssl_defaults.noCache = on;
+ ssl_defaults.noCache = val;
break;
case SSL_ENABLE_FDX:
- if (on && ssl_defaults.noLocks) {
+ if (val && ssl_defaults.noLocks) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
- ssl_defaults.fdx = on;
+ ssl_defaults.fdx = val;
break;
case SSL_ROLLBACK_DETECTION:
- ssl_defaults.detectRollBack = on;
+ ssl_defaults.detectRollBack = val;
break;
case SSL_NO_STEP_DOWN:
@@ -1142,76 +1170,80 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
break;
case SSL_NO_LOCKS:
- if (on && ssl_defaults.fdx) {
+ if (val && 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) {
+ if (val && ssl_force_locks)
+ val = PR_FALSE; /* silent override */
+ ssl_defaults.noLocks = val;
+ if (val) {
locksEverDisabled = PR_TRUE;
strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED.");
}
break;
case SSL_ENABLE_SESSION_TICKETS:
- ssl_defaults.enableSessionTickets = on;
+ ssl_defaults.enableSessionTickets = val;
break;
case SSL_ENABLE_DEFLATE:
- ssl_defaults.enableDeflate = on;
+ ssl_defaults.enableDeflate = val;
break;
case SSL_ENABLE_RENEGOTIATION:
- ssl_defaults.enableRenegotiation = on;
+ ssl_defaults.enableRenegotiation = val;
break;
case SSL_REQUIRE_SAFE_NEGOTIATION:
- ssl_defaults.requireSafeNegotiation = on;
+ ssl_defaults.requireSafeNegotiation = val;
break;
case SSL_ENABLE_FALSE_START:
- ssl_defaults.enableFalseStart = on;
+ ssl_defaults.enableFalseStart = val;
break;
case SSL_CBC_RANDOM_IV:
- ssl_defaults.cbcRandomIV = on;
+ ssl_defaults.cbcRandomIV = val;
break;
case SSL_ENABLE_OCSP_STAPLING:
- ssl_defaults.enableOCSPStapling = on;
+ ssl_defaults.enableOCSPStapling = val;
break;
case SSL_ENABLE_NPN:
break;
case SSL_ENABLE_ALPN:
- ssl_defaults.enableALPN = on;
+ ssl_defaults.enableALPN = val;
break;
case SSL_REUSE_SERVER_ECDHE_KEY:
- ssl_defaults.reuseServerECDHEKey = on;
+ ssl_defaults.reuseServerECDHEKey = val;
break;
case SSL_ENABLE_FALLBACK_SCSV:
- ssl_defaults.enableFallbackSCSV = on;
+ ssl_defaults.enableFallbackSCSV = val;
break;
case SSL_ENABLE_SERVER_DHE:
- ssl_defaults.enableServerDhe = on;
+ ssl_defaults.enableServerDhe = val;
break;
case SSL_ENABLE_EXTENDED_MASTER_SECRET:
- ssl_defaults.enableExtendedMS = on;
+ ssl_defaults.enableExtendedMS = val;
break;
case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
- ssl_defaults.enableSignedCertTimestamps = on;
+ ssl_defaults.enableSignedCertTimestamps = val;
break;
case SSL_ENABLE_0RTT_DATA:
- ssl_defaults.enable0RttData = on;
+ ssl_defaults.enable0RttData = val;
+ break;
+
+ case SSL_ENABLE_TLS13_COMPAT_MODE:
+ ssl_defaults.enableTls13CompatMode = val;
break;
default:
@@ -1221,6 +1253,18 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
return SECSuccess;
}
+SECStatus
+SSLExp_SetMaxEarlyDataSize(PRFileDesc *fd, PRUint32 size)
+{
+ sslSocket *ss = ssl_FindSocket(fd);
+ if (!ss) {
+ return SECFailure; /* Error code already set. */
+ }
+
+ ss->opt.maxEarlyDataSize = size;
+ return SECSuccess;
+}
+
/* function tells us if the cipher suite is one that we no longer support. */
static PRBool
ssl_IsRemovedCipherSuite(PRInt32 suite)
@@ -2124,6 +2168,25 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
return NULL;
PR_APPEND_LINK(&skp->link, &ss->ephemeralKeyPairs);
}
+
+ while (!PR_CLIST_IS_EMPTY(&ss->extensionHooks)) {
+ cursor = PR_LIST_TAIL(&ss->extensionHooks);
+ PR_REMOVE_LINK(cursor);
+ PORT_Free(cursor);
+ }
+ for (cursor = PR_NEXT_LINK(&sm->extensionHooks);
+ cursor != &sm->extensionHooks;
+ cursor = PR_NEXT_LINK(cursor)) {
+ SECStatus rv;
+ sslCustomExtensionHooks *hook = (sslCustomExtensionHooks *)cursor;
+ rv = SSL_InstallExtensionHooks(ss->fd, hook->type,
+ hook->writer, hook->writerArg,
+ hook->handler, hook->handlerArg);
+ if (rv != SECSuccess) {
+ return NULL;
+ }
+ }
+
PORT_Memcpy((void *)ss->namedGroupPreferences,
sm->namedGroupPreferences,
sizeof(ss->namedGroupPreferences));
@@ -2214,7 +2277,7 @@ ssl3_GetEffectiveVersionPolicy(SSLProtocolVariant variant,
return SECSuccess;
}
-/*
+/*
* Assumes that rangeParam values are within the supported boundaries,
* but should contain all potentially allowed versions, even if they contain
* conflicting versions.
@@ -3124,7 +3187,7 @@ ssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors,
}
blocking = ssl_FdIsBlocking(fd);
-#define K16 sizeof(buf)
+#define K16 ((int)sizeof(buf))
#define KILL_VECTORS \
while (vectors && !iov->iov_len) { \
++iov; \
@@ -3411,7 +3474,6 @@ ssl_InitIOLayer(void)
{
ssl_layer_id = PR_GetUniqueIdentity("SSL");
ssl_SetupIOMethods();
- ssl_inited = PR_TRUE;
return PR_SUCCESS;
}
@@ -3421,15 +3483,13 @@ ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, PRDescIdentity id)
PRFileDesc *layer = NULL;
PRStatus status;
- if (!ssl_inited) {
- status = PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer);
- if (status != PR_SUCCESS)
- goto loser;
+ status = PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer);
+ if (status != PR_SUCCESS) {
+ goto loser;
}
-
- if (ns == NULL)
+ if (ns == NULL) {
goto loser;
-
+ }
layer = PR_CreateIOLayerStub(ssl_layer_id, &combined_methods);
if (layer == NULL)
goto loser;
@@ -3542,6 +3602,12 @@ ssl_SetDefaultsFromEnvironment(void)
ssl_keylog_iob);
}
SSL_TRACE(("SSL: logging SSL/TLS secrets to %s", ev));
+ ssl_keylog_lock = PR_NewLock();
+ if (!ssl_keylog_lock) {
+ SSL_TRACE(("SSL: failed to create key log lock"));
+ fclose(ssl_keylog_iob);
+ ssl_keylog_iob = NULL;
+ }
}
}
#endif
@@ -3746,7 +3812,6 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
SECStatus rv;
sslSocket *ss;
int i;
-
ssl_SetDefaultsFromEnvironment();
if (ssl_force_locks)
@@ -3777,6 +3842,7 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
PR_INIT_CLIST(&ss->serverCerts);
PR_INIT_CLIST(&ss->ephemeralKeyPairs);
+ PR_INIT_CLIST(&ss->extensionHooks);
ss->dbHandle = CERT_GetDefaultCertDB();
@@ -3804,7 +3870,11 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight);
PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs);
PR_INIT_CLIST(&ss->ssl3.hs.bufferedEarlyData);
- ssl3_InitExtensionData(&ss->xtnData);
+ ssl3_InitExtensionData(&ss->xtnData, ss);
+ PR_INIT_CLIST(&ss->ssl3.hs.dtlsSentHandshake);
+ PR_INIT_CLIST(&ss->ssl3.hs.dtlsRcvdHandshake);
+ dtls_InitTimers(ss);
+
if (makeLocks) {
rv = ssl_MakeLocks(ss);
if (rv != SECSuccess)
@@ -3816,6 +3886,10 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
rv = ssl3_InitGather(&ss->gs);
if (rv != SECSuccess)
goto loser;
+ rv = ssl3_InitState(ss);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
return ss;
loser:
@@ -3840,3 +3914,227 @@ SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey,
*pcanbypass = PR_FALSE;
return SECSuccess;
}
+
+/* Functions that are truly experimental use EXP, functions that are no longer
+ * experimental use PUB.
+ *
+ * When initially defining a new API, add that API here using the EXP() macro
+ * and name the function with a SSLExp_ prefix. Define the experimental API as
+ * a macro in sslexp.h using the SSL_EXPERIMENTAL_API() macro defined there.
+ *
+ * Once an API is stable and proven, move the macro definition in sslexp.h to a
+ * proper function declaration in ssl.h. Keeping the function in this list
+ * ensures that code built against the release that contained the experimental
+ * API will continue to work; use PUB() to reference the public function.
+ */
+#define EXP(n) \
+ { \
+ "SSL_" #n, SSLExp_##n \
+ }
+#define PUB(n) \
+ { \
+ "SSL_" #n, SSL_##n \
+ }
+struct {
+ const char *const name;
+ void *function;
+} ssl_experimental_functions[] = {
+#ifndef SSL_DISABLE_EXPERIMENTAL_API
+ EXP(GetExtensionSupport),
+ EXP(HelloRetryRequestCallback),
+ EXP(InstallExtensionHooks),
+ EXP(KeyUpdate),
+ EXP(SendSessionTicket),
+ EXP(SetMaxEarlyDataSize),
+ EXP(SetupAntiReplay),
+ EXP(SetResumptionTokenCallback),
+ EXP(SetResumptionToken),
+ EXP(GetResumptionTokenInfo),
+ EXP(DestroyResumptionTokenInfo),
+#endif
+ { "", NULL }
+};
+#undef EXP
+#undef PUB
+
+void *
+SSL_GetExperimentalAPI(const char *name)
+{
+ unsigned int i;
+ for (i = 0; i < PR_ARRAY_SIZE(ssl_experimental_functions); ++i) {
+ if (strcmp(name, ssl_experimental_functions[i].name) == 0) {
+ return ssl_experimental_functions[i].function;
+ }
+ }
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_EXPERIMENTAL_API);
+ return NULL;
+}
+
+void
+ssl_ClearPRCList(PRCList *list, void (*f)(void *))
+{
+ PRCList *cursor;
+
+ while (!PR_CLIST_IS_EMPTY(list)) {
+ cursor = PR_LIST_TAIL(list);
+
+ PR_REMOVE_LINK(cursor);
+ if (f) {
+ f(cursor);
+ }
+ PORT_Free(cursor);
+ }
+}
+
+/* Experimental APIs for session cache handling. */
+
+SECStatus
+SSLExp_SetResumptionTokenCallback(PRFileDesc *fd,
+ SSLResumptionTokenCallback cb,
+ void *ctx)
+{
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetResumptionTokenCallback",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
+
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+ ss->resumptionTokenCallback = cb;
+ ss->resumptionTokenContext = ctx;
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+
+ return SECSuccess;
+}
+
+SECStatus
+SSLExp_SetResumptionToken(PRFileDesc *fd, const PRUint8 *token,
+ unsigned int len)
+{
+ sslSocket *ss = ssl_FindSocket(fd);
+
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetResumptionToken",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
+
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+
+ if (ss->firstHsDone || ss->ssl3.hs.ws != idle_handshake ||
+ ss->sec.isServer || len == 0 || !token) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto done;
+ }
+
+ // We override any previously set session.
+ if (ss->sec.ci.sid) {
+ ssl_FreeSID(ss->sec.ci.sid);
+ ss->sec.ci.sid = NULL;
+ }
+
+ PRINT_BUF(50, (ss, "incoming resumption token", token, len));
+
+ ss->sec.ci.sid = ssl3_NewSessionID(ss, PR_FALSE);
+ if (!ss->sec.ci.sid) {
+ goto done;
+ }
+
+ /* Populate NewSessionTicket values */
+ SECStatus rv = ssl_DecodeResumptionToken(ss->sec.ci.sid, token, len);
+ if (rv != SECSuccess) {
+ // If decoding fails, we assume the token is bad.
+ PORT_SetError(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR);
+ ssl_FreeSID(ss->sec.ci.sid);
+ ss->sec.ci.sid = NULL;
+ goto done;
+ }
+
+ // Make sure that the token is valid.
+ if (!ssl_IsResumptionTokenValid(ss)) {
+ ssl_FreeSID(ss->sec.ci.sid);
+ ss->sec.ci.sid = NULL;
+ PORT_SetError(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR);
+ goto done;
+ }
+
+ /* Use the sid->cached as marker that this is from an external cache and
+ * we don't have to look up anything in the NSS internal cache. */
+ ss->sec.ci.sid->cached = in_external_cache;
+ // This has to be 2 to not free this in sendClientHello.
+ ss->sec.ci.sid->references = 2;
+ ss->sec.ci.sid->lastAccessTime = ssl_TimeSec();
+
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+ return SECSuccess;
+
+done:
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+
+ return SECFailure;
+}
+
+SECStatus
+SSLExp_DestroyResumptionTokenInfo(SSLResumptionTokenInfo *token)
+{
+ if (!token) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ if (token->peerCert) {
+ CERT_DestroyCertificate(token->peerCert);
+ }
+ PORT_Free(token->alpnSelection);
+ PORT_Memset(token, 0, token->length);
+ return SECSuccess;
+}
+
+SECStatus
+SSLExp_GetResumptionTokenInfo(const PRUint8 *tokenData, unsigned int tokenLen,
+ SSLResumptionTokenInfo *tokenOut, PRUintn len)
+{
+ if (!tokenData || !tokenOut || !tokenLen ||
+ len > sizeof(SSLResumptionTokenInfo)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ sslSessionID sid = { 0 };
+ SSLResumptionTokenInfo token;
+
+ /* Populate sid values */
+ if (ssl_DecodeResumptionToken(&sid, tokenData, tokenLen) != SECSuccess) {
+ // If decoding fails, we assume the token is bad.
+ PORT_SetError(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR);
+ return SECFailure;
+ }
+
+ token.peerCert = CERT_DupCertificate(sid.peerCert);
+
+ token.alpnSelectionLen = sid.u.ssl3.alpnSelection.len;
+ token.alpnSelection = PORT_ZAlloc(token.alpnSelectionLen);
+ if (!token.alpnSelection) {
+ return SECFailure;
+ }
+ PORT_Memcpy(token.alpnSelection, sid.u.ssl3.alpnSelection.data,
+ token.alpnSelectionLen);
+
+ if (sid.u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) {
+ token.maxEarlyDataSize =
+ sid.u.ssl3.locked.sessionTicket.max_early_data_size;
+ } else {
+ token.maxEarlyDataSize = 0;
+ }
+
+ token.length = PR_MIN(sizeof(SSLResumptionTokenInfo), len);
+ PORT_Memcpy(tokenOut, &token, token.length);
+
+ ssl_DestroySID(&sid, PR_FALSE);
+ return SECSuccess;
+}