summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/ssl3con.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/ssl3con.c')
-rw-r--r--security/nss/lib/ssl/ssl3con.c804
1 files changed, 475 insertions, 329 deletions
diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c
index f3c723bbc..b652dcea3 100644
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -21,6 +21,7 @@
#include "sslerr.h"
#include "ssl3ext.h"
#include "ssl3exthandle.h"
+#include "tls13psk.h"
#include "tls13subcerts.h"
#include "prtime.h"
#include "prinrval.h"
@@ -65,6 +66,7 @@ static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags);
static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType);
static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash);
PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme);
+PRBool ssl_IsRsaeSignatureScheme(SSLSignatureScheme scheme);
PRBool ssl_IsRsaPkcs1SignatureScheme(SSLSignatureScheme scheme);
PRBool ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme);
@@ -391,15 +393,15 @@ static const SSLCipher2Mech alg2Mech[] = {
{ ssl_calg_camellia, CKM_CAMELLIA_CBC },
{ ssl_calg_seed, CKM_SEED_CBC },
{ ssl_calg_aes_gcm, CKM_AES_GCM },
- { ssl_calg_chacha20, CKM_NSS_CHACHA20_POLY1305 },
+ { ssl_calg_chacha20, CKM_CHACHA20_POLY1305 },
};
-const PRUint8 tls13_downgrade_random[] = { 0x44, 0x4F, 0x57, 0x4E,
- 0x47, 0x52, 0x44, 0x01 };
const PRUint8 tls12_downgrade_random[] = { 0x44, 0x4F, 0x57, 0x4E,
- 0x47, 0x52, 0x44, 0x00 };
-PR_STATIC_ASSERT(sizeof(tls13_downgrade_random) ==
- sizeof(tls13_downgrade_random));
+ 0x47, 0x52, 0x44, 0x01 };
+const PRUint8 tls1_downgrade_random[] = { 0x44, 0x4F, 0x57, 0x4E,
+ 0x47, 0x52, 0x44, 0x00 };
+PR_STATIC_ASSERT(sizeof(tls12_downgrade_random) ==
+ sizeof(tls1_downgrade_random));
/* The ECCWrappedKeyInfo structure defines how various pieces of
* information are laid out within wrappedSymmetricWrappingkey
@@ -517,7 +519,7 @@ ssl3_DecodeContentType(int msgType)
rv = "application_data (23)";
break;
case ssl_ct_ack:
- rv = "ack (25)";
+ rv = "ack (26)";
break;
default:
sprintf(line, "*UNKNOWN* record type! (%d)", msgType);
@@ -782,15 +784,19 @@ ssl_HasCert(const sslSocket *ss, PRUint16 maxVersion, SSLAuthType authType)
* Both by policy and by having a token that supports it. */
static PRBool
ssl_SignatureSchemeAccepted(PRUint16 minVersion,
- SSLSignatureScheme scheme)
+ SSLSignatureScheme scheme,
+ PRBool forCert)
{
/* Disable RSA-PSS schemes if there are no tokens to verify them. */
if (ssl_IsRsaPssSignatureScheme(scheme)) {
if (!PK11_TokenExists(auth_alg_defs[ssl_auth_rsa_pss])) {
return PR_FALSE;
}
- } else if (ssl_IsRsaPkcs1SignatureScheme(scheme)) {
- /* Disable PKCS#1 signatures if we are limited to TLS 1.3. */
+ } else if (!forCert && ssl_IsRsaPkcs1SignatureScheme(scheme)) {
+ /* Disable PKCS#1 signatures if we are limited to TLS 1.3.
+ * We still need to advertise PKCS#1 signatures in CH and CR
+ * for certificate signatures.
+ */
if (minVersion >= SSL_LIBRARY_VERSION_TLS_1_3) {
return PR_FALSE;
}
@@ -849,7 +855,8 @@ ssl_CheckSignatureSchemes(sslSocket *ss)
/* Ensure that there is a signature scheme that can be accepted.*/
for (unsigned int i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
if (ssl_SignatureSchemeAccepted(ss->vrange.min,
- ss->ssl3.signatureSchemes[i])) {
+ ss->ssl3.signatureSchemes[i],
+ PR_FALSE /* forCert */)) {
return SECSuccess;
}
}
@@ -878,7 +885,7 @@ ssl_HasSignatureScheme(const sslSocket *ss, SSLAuthType authType)
PRBool acceptable = authType == schemeAuthType ||
(schemeAuthType == ssl_auth_rsa_pss &&
authType == ssl_auth_rsa_sign);
- if (acceptable && ssl_SignatureSchemeAccepted(ss->version, scheme)) {
+ if (acceptable && ssl_SignatureSchemeAccepted(ss->version, scheme, PR_FALSE /* forCert */)) {
return PR_TRUE;
}
}
@@ -911,6 +918,13 @@ ssl3_config_match_init(sslSocket *ss)
if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
return 0;
}
+ if (ss->sec.isServer && ss->psk &&
+ PR_CLIST_IS_EMPTY(&ss->serverCerts) &&
+ (ss->opt.requestCertificate || ss->opt.requireCertificate)) {
+ /* PSK and certificate auth cannot be combined. */
+ PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
+ return 0;
+ }
if (ssl_CheckSignatureSchemes(ss) != SECSuccess) {
return 0; /* Code already set. */
}
@@ -1008,6 +1022,16 @@ ssl3_config_match(const ssl3CipherSuiteCfg *suite, PRUint8 policy,
return PR_FALSE;
}
+ /* If a PSK is selected, disable suites that use a different hash than
+ * the PSK. We advertise non-PSK-compatible suites in the CH, as we could
+ * fallback to certificate auth. The client handler will check hash
+ * compatibility before committing to use the PSK. */
+ if (ss->xtnData.selectedPsk) {
+ if (ss->xtnData.selectedPsk->hash != cipher_def->prf_hash) {
+ return PR_FALSE;
+ }
+ }
+
return ssl3_CipherSuiteAllowedForVersionRange(suite->cipher_suite, vrange);
}
@@ -1739,117 +1763,6 @@ ssl3_BuildRecordPseudoHeader(DTLSEpoch epoch,
return SECSuccess;
}
-static SECStatus
-ssl3_AESGCM(const ssl3KeyMaterial *keys,
- PRBool doDecrypt,
- unsigned char *out,
- unsigned int *outlen,
- unsigned int maxout,
- const unsigned char *in,
- unsigned int inlen,
- const unsigned char *additionalData,
- unsigned int additionalDataLen)
-{
- SECItem param;
- SECStatus rv = SECFailure;
- unsigned char nonce[12];
- unsigned int uOutLen;
- CK_GCM_PARAMS gcmParams;
-
- const int tagSize = 16;
- const int explicitNonceLen = 8;
-
- /* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the
- * nonce is formed. */
- memcpy(nonce, keys->iv, 4);
- if (doDecrypt) {
- memcpy(nonce + 4, in, explicitNonceLen);
- in += explicitNonceLen;
- inlen -= explicitNonceLen;
- *outlen = 0;
- } else {
- if (maxout < explicitNonceLen) {
- PORT_SetError(SEC_ERROR_INPUT_LEN);
- return SECFailure;
- }
- /* Use the 64-bit sequence number as the explicit nonce. */
- memcpy(nonce + 4, additionalData, explicitNonceLen);
- memcpy(out, additionalData, explicitNonceLen);
- out += explicitNonceLen;
- maxout -= explicitNonceLen;
- *outlen = explicitNonceLen;
- }
-
- param.type = siBuffer;
- param.data = (unsigned char *)&gcmParams;
- param.len = sizeof(gcmParams);
- gcmParams.pIv = nonce;
- gcmParams.ulIvLen = sizeof(nonce);
- gcmParams.pAAD = (unsigned char *)additionalData; /* const cast */
- gcmParams.ulAADLen = additionalDataLen;
- gcmParams.ulTagBits = tagSize * 8;
-
- if (doDecrypt) {
- rv = PK11_Decrypt(keys->key, CKM_AES_GCM, &param, out, &uOutLen,
- maxout, in, inlen);
- } else {
- rv = PK11_Encrypt(keys->key, CKM_AES_GCM, &param, out, &uOutLen,
- maxout, in, inlen);
- }
- *outlen += (int)uOutLen;
-
- return rv;
-}
-
-static SECStatus
-ssl3_ChaCha20Poly1305(const ssl3KeyMaterial *keys, PRBool doDecrypt,
- unsigned char *out, unsigned int *outlen, unsigned int maxout,
- const unsigned char *in, unsigned int inlen,
- const unsigned char *additionalData,
- unsigned int additionalDataLen)
-{
- size_t i;
- SECItem param;
- SECStatus rv = SECFailure;
- unsigned int uOutLen;
- unsigned char nonce[12];
- CK_NSS_AEAD_PARAMS aeadParams;
-
- const int tagSize = 16;
-
- /* See
- * https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04#section-2
- * for details of how the nonce is formed. */
- PORT_Memcpy(nonce, keys->iv, 12);
-
- /* XOR the last 8 bytes of the IV with the sequence number. */
- PORT_Assert(additionalDataLen >= 8);
- for (i = 0; i < 8; ++i) {
- nonce[4 + i] ^= additionalData[i];
- }
-
- param.type = siBuffer;
- param.len = sizeof(aeadParams);
- param.data = (unsigned char *)&aeadParams;
- memset(&aeadParams, 0, sizeof(aeadParams));
- aeadParams.pNonce = nonce;
- aeadParams.ulNonceLen = sizeof(nonce);
- aeadParams.pAAD = (unsigned char *)additionalData;
- aeadParams.ulAADLen = additionalDataLen;
- aeadParams.ulTagLen = tagSize;
-
- if (doDecrypt) {
- rv = PK11_Decrypt(keys->key, CKM_NSS_CHACHA20_POLY1305, &param,
- out, &uOutLen, maxout, in, inlen);
- } else {
- rv = PK11_Encrypt(keys->key, CKM_NSS_CHACHA20_POLY1305, &param,
- out, &uOutLen, maxout, in, inlen);
- }
- *outlen = (int)uOutLen;
-
- return rv;
-}
-
/* Initialize encryption and MAC contexts for pending spec.
* Master Secret already is derived.
* Caller holds Spec write lock.
@@ -1867,40 +1780,26 @@ ssl3_InitPendingContexts(sslSocket *ss, ssl3CipherSpec *spec)
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
- macLength = spec->macDef->mac_size;
calg = spec->cipherDef->calg;
PORT_Assert(alg2Mech[calg].calg == calg);
- if (spec->cipherDef->type == type_aead) {
- spec->cipher = NULL;
- spec->cipherContext = NULL;
- switch (calg) {
- case ssl_calg_aes_gcm:
- spec->aead = ssl3_AESGCM;
- break;
- case ssl_calg_chacha20:
- spec->aead = ssl3_ChaCha20Poly1305;
- break;
- default:
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
- }
- return SECSuccess;
- }
-
- /*
- ** Now setup the MAC contexts,
- ** crypto contexts are setup below.
- */
- macParam.data = (unsigned char *)&macLength;
- macParam.len = sizeof(macLength);
- macParam.type = siBuffer;
+ if (spec->cipherDef->type != type_aead) {
+ macLength = spec->macDef->mac_size;
- spec->keyMaterial.macContext = PK11_CreateContextBySymKey(
- spec->macDef->mmech, CKA_SIGN, spec->keyMaterial.macKey, &macParam);
- if (!spec->keyMaterial.macContext) {
- ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
- return SECFailure;
+ /*
+ ** Now setup the MAC contexts,
+ ** crypto contexts are setup below.
+ */
+ macParam.data = (unsigned char *)&macLength;
+ macParam.len = sizeof(macLength);
+ macParam.type = siBuffer;
+
+ spec->keyMaterial.macContext = PK11_CreateContextBySymKey(
+ spec->macDef->mmech, CKA_SIGN, spec->keyMaterial.macKey, &macParam);
+ if (!spec->keyMaterial.macContext) {
+ ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
+ return SECFailure;
+ }
}
/*
@@ -1911,15 +1810,21 @@ ssl3_InitPendingContexts(sslSocket *ss, ssl3CipherSpec *spec)
return SECSuccess;
}
- spec->cipher = (SSLCipher)PK11_CipherOp;
encMechanism = ssl3_Alg2Mech(calg);
encMode = (spec->direction == ssl_secret_write) ? CKA_ENCRYPT : CKA_DECRYPT;
+ if (spec->cipherDef->type == type_aead) {
+ encMode |= CKA_NSS_MESSAGE;
+ iv.data = NULL;
+ iv.len = 0;
+ } else {
+ spec->cipher = (SSLCipher)PK11_CipherOp;
+ iv.data = spec->keyMaterial.iv;
+ iv.len = spec->cipherDef->iv_size;
+ }
/*
* build the context
*/
- iv.data = spec->keyMaterial.iv;
- iv.len = spec->cipherDef->iv_size;
spec->cipherContext = PK11_CreateContextBySymKey(encMechanism, encMode,
spec->keyMaterial.key,
&iv);
@@ -2238,26 +2143,55 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
isDTLS, contentLen, &pseudoHeader);
PORT_Assert(rv == SECSuccess);
if (cwSpec->cipherDef->type == type_aead) {
- const int nonceLen = cwSpec->cipherDef->explicit_nonce_size;
- const int tagLen = cwSpec->cipherDef->tag_size;
+ const unsigned int nonceLen = cwSpec->cipherDef->explicit_nonce_size;
+ const unsigned int tagLen = cwSpec->cipherDef->tag_size;
+ unsigned int ivOffset = 0;
+ CK_GENERATOR_FUNCTION gen;
+ /* ivOut includes the iv and the nonce and is the internal iv/nonce
+ * for the AEAD function. On Encrypt, this is an in/out parameter */
+ unsigned char ivOut[MAX_IV_LENGTH];
+ ivLen = cwSpec->cipherDef->iv_size;
+
+ PORT_Assert((ivLen + nonceLen) <= MAX_IV_LENGTH);
+ PORT_Assert((ivLen + nonceLen) >= sizeof(sslSequenceNumber));
if (nonceLen + contentLen + tagLen > SSL_BUFFER_SPACE(wrBuf)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
- rv = cwSpec->aead(
- &cwSpec->keyMaterial,
- PR_FALSE, /* do encrypt */
- SSL_BUFFER_NEXT(wrBuf), /* output */
- &len, /* out len */
- SSL_BUFFER_SPACE(wrBuf), /* max out */
- pIn, contentLen, /* input */
- SSL_BUFFER_BASE(&pseudoHeader), SSL_BUFFER_LEN(&pseudoHeader));
+ if (nonceLen == 0) {
+ ivOffset = ivLen - sizeof(sslSequenceNumber);
+ gen = CKG_GENERATE_COUNTER_XOR;
+ } else {
+ ivOffset = ivLen;
+ gen = CKG_GENERATE_COUNTER;
+ }
+ ivOffset = tls13_SetupAeadIv(isDTLS, ivOut, cwSpec->keyMaterial.iv,
+ ivOffset, ivLen, cwSpec->epoch);
+ rv = tls13_AEAD(cwSpec->cipherContext,
+ PR_FALSE,
+ gen, ivOffset * BPB, /* iv generator params */
+ ivOut, /* iv in */
+ ivOut, /* iv out */
+ ivLen + nonceLen, /* full iv length */
+ NULL, 0, /* nonce is generated*/
+ SSL_BUFFER_BASE(&pseudoHeader), /* aad */
+ SSL_BUFFER_LEN(&pseudoHeader), /* aadlen */
+ SSL_BUFFER_NEXT(wrBuf) + nonceLen, /* output */
+ &len, /* out len */
+ SSL_BUFFER_SPACE(wrBuf) - nonceLen, /* max out */
+ tagLen,
+ pIn, contentLen); /* input */
if (rv != SECSuccess) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
}
+ len += nonceLen; /* include the nonce at the beginning */
+ /* copy out the generated iv if we are using explict nonces */
+ if (nonceLen) {
+ PORT_Memcpy(SSL_BUFFER_NEXT(wrBuf), ivOut + ivLen, nonceLen);
+ }
rv = sslBuffer_Skip(wrBuf, len, NULL);
PORT_Assert(rv == SECSuccess); /* Can't fail. */
@@ -2406,7 +2340,6 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSLContentType ct,
PORT_Assert(cwSpec->cipherDef->max_records <= RECORD_SEQ_MAX);
if (cwSpec->nextSeqNum >= cwSpec->cipherDef->max_records) {
- /* We should have automatically updated before here in TLS 1.3. */
PORT_Assert(cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_3);
SSL_TRC(3, ("%d: SSL[-]: write sequence number at limit 0x%0llx",
SSL_GETPID(), cwSpec->nextSeqNum));
@@ -2438,7 +2371,18 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSLContentType ct,
}
#else
if (cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ PRUint8 *cipherText = SSL_BUFFER_NEXT(wrBuf);
+ unsigned int bufLen = SSL_BUFFER_LEN(wrBuf);
rv = tls13_ProtectRecord(ss, cwSpec, ct, pIn, contentLen, wrBuf);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ if (IS_DTLS(ss)) {
+ bufLen = SSL_BUFFER_LEN(wrBuf) - bufLen;
+ rv = dtls13_MaskSequenceNumber(ss, cwSpec,
+ SSL_BUFFER_BASE(wrBuf),
+ cipherText, bufLen);
+ }
} else {
rv = ssl3_MACEncryptRecord(cwSpec, ss->sec.isServer, IS_DTLS(ss), ct,
pIn, contentLen, wrBuf);
@@ -4543,6 +4487,21 @@ ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme)
}
PRBool
+ssl_IsRsaeSignatureScheme(SSLSignatureScheme scheme)
+{
+ switch (scheme) {
+ case ssl_sig_rsa_pss_rsae_sha256:
+ case ssl_sig_rsa_pss_rsae_sha384:
+ case ssl_sig_rsa_pss_rsae_sha512:
+ return PR_TRUE;
+
+ default:
+ return PR_FALSE;
+ }
+ return PR_FALSE;
+}
+
+PRBool
ssl_IsRsaPkcs1SignatureScheme(SSLSignatureScheme scheme)
{
switch (scheme) {
@@ -5397,10 +5356,11 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
}
if (extensionBuf.len) {
- /* If we are sending a PSK binder, replace the dummy value. Note that
- * we only set statelessResume on the client in TLS 1.3. */
- if (ss->statelessResume &&
- ss->xtnData.sentSessionTicketInClientHello) {
+ /* If we are sending a PSK binder, replace the dummy value. */
+ if (ssl3_ExtensionAdvertised(ss, ssl_tls13_pre_shared_key_xtn)) {
+ PORT_Assert(ss->psk ||
+ (ss->statelessResume && ss->xtnData.sentSessionTicketInClientHello));
+ PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks));
rv = tls13_WriteExtensionsWithBinder(ss, &extensionBuf);
} else {
rv = ssl3_AppendBufferToHandshakeVariable(ss, &extensionBuf, 2);
@@ -6663,7 +6623,7 @@ ssl_CheckServerSessionIdCorrectness(sslSocket *ss, SECItem *sidBytes)
* fake. Check for the real value. */
if (sentRealSid) {
sidMatch = (sidBytes->len == sid->u.ssl3.sessionIDLength) &&
- PORT_Memcmp(sid->u.ssl3.sessionID, sidBytes->data, sidBytes->len) == 0;
+ (!sidBytes->len || PORT_Memcmp(sid->u.ssl3.sessionID, sidBytes->data, sidBytes->len) == 0);
} else {
/* Otherwise, the session ID was a fake if TLS 1.3 compat mode is
* enabled. If so, check for the fake value. */
@@ -6713,13 +6673,13 @@ ssl_CheckServerRandom(sslSocket *ss)
/* Both sections use the same sentinel region. */
PRUint8 *downgrade_sentinel =
ss->ssl3.hs.server_random +
- SSL3_RANDOM_LENGTH - sizeof(tls13_downgrade_random);
+ SSL3_RANDOM_LENGTH - sizeof(tls12_downgrade_random);
if (!PORT_Memcmp(downgrade_sentinel,
- tls13_downgrade_random,
- sizeof(tls13_downgrade_random)) ||
- !PORT_Memcmp(downgrade_sentinel,
tls12_downgrade_random,
- sizeof(tls12_downgrade_random))) {
+ sizeof(tls12_downgrade_random)) ||
+ !PORT_Memcmp(downgrade_sentinel,
+ tls1_downgrade_random,
+ sizeof(tls1_downgrade_random))) {
return SECFailure;
}
}
@@ -7693,16 +7653,6 @@ ssl3_CompleteHandleCertificateRequest(sslSocket *ss,
/* check what the callback function returned */
if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) {
/* we are missing either the key or cert */
- if (ss->ssl3.clientCertificate) {
- /* got a cert, but no key - free it */
- CERT_DestroyCertificate(ss->ssl3.clientCertificate);
- ss->ssl3.clientCertificate = NULL;
- }
- if (ss->ssl3.clientPrivateKey) {
- /* got a key, but no cert - free it */
- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
- ss->ssl3.clientPrivateKey = NULL;
- }
goto send_no_certificate;
}
/* Setting ssl3.clientCertChain non-NULL will cause
@@ -7712,22 +7662,33 @@ ssl3_CompleteHandleCertificateRequest(sslSocket *ss,
ss->ssl3.clientCertificate,
certUsageSSLClient, PR_FALSE);
if (ss->ssl3.clientCertChain == NULL) {
- CERT_DestroyCertificate(ss->ssl3.clientCertificate);
- ss->ssl3.clientCertificate = NULL;
- SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
- ss->ssl3.clientPrivateKey = NULL;
goto send_no_certificate;
}
if (ss->ssl3.hs.hashType == handshake_hash_record ||
ss->ssl3.hs.hashType == handshake_hash_single) {
rv = ssl_PickClientSignatureScheme(ss, signatureSchemes,
signatureSchemeCount);
+ if (rv != SECSuccess) {
+ /* This should only happen if our schemes changed or
+ * if an RSA-PSS cert was selected, but the token
+ * does not support PSS schemes. */
+ goto send_no_certificate;
+ }
}
break; /* not an error */
case SECFailure:
default:
send_no_certificate:
+ CERT_DestroyCertificate(ss->ssl3.clientCertificate);
+ SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
+ ss->ssl3.clientCertificate = NULL;
+ ss->ssl3.clientPrivateKey = NULL;
+ if (ss->ssl3.clientCertChain) {
+ CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
+ ss->ssl3.clientCertChain = NULL;
+ }
+
if (ss->version > SSL_LIBRARY_VERSION_3_0) {
ss->ssl3.sendEmptyCert = PR_TRUE;
} else {
@@ -8169,26 +8130,53 @@ ssl3_KEASupportsTickets(const ssl3KEADef *kea_def)
return PR_TRUE;
}
+static PRBool
+ssl3_PeerSupportsCipherSuite(const SECItem *peerSuites, uint16_t suite)
+{
+ for (unsigned int i = 0; i + 1 < peerSuites->len; i += 2) {
+ PRUint16 suite_i = (peerSuites->data[i] << 8) | peerSuites->data[i + 1];
+ if (suite_i == suite) {
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
SECStatus
ssl3_NegotiateCipherSuiteInner(sslSocket *ss, const SECItem *suites,
PRUint16 version, PRUint16 *suitep)
{
- unsigned int j;
unsigned int i;
+ SSLVersionRange vrange = { version, version };
- for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
- ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
- SSLVersionRange vrange = { version, version };
+ /* If we negotiated an External PSK and that PSK has a ciphersuite
+ * configured, we need to constrain our choice. If the client does
+ * not support it, negotiate a certificate auth suite and fall back.
+ */
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
+ ss->xtnData.selectedPsk &&
+ ss->xtnData.selectedPsk->type == ssl_psk_external &&
+ ss->xtnData.selectedPsk->zeroRttSuite != TLS_NULL_WITH_NULL_NULL) {
+ PRUint16 pskSuite = ss->xtnData.selectedPsk->zeroRttSuite;
+ ssl3CipherSuiteCfg *pskSuiteCfg = ssl_LookupCipherSuiteCfgMutable(pskSuite,
+ ss->cipherSuites);
+ if (ssl3_config_match(pskSuiteCfg, ss->ssl3.policy, &vrange, ss) &&
+ ssl3_PeerSupportsCipherSuite(suites, pskSuite)) {
+ *suitep = pskSuite;
+ return SECSuccess;
+ }
+ }
+
+ for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
+ ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
if (!ssl3_config_match(suite, ss->ssl3.policy, &vrange, ss)) {
continue;
}
- for (i = 0; i + 1 < suites->len; i += 2) {
- PRUint16 suite_i = (suites->data[i] << 8) | suites->data[i + 1];
- if (suite_i == suite->cipher_suite) {
- *suitep = suite_i;
- return SECSuccess;
- }
+ if (!ssl3_PeerSupportsCipherSuite(suites, suite->cipher_suite)) {
+ continue;
}
+ *suitep = suite->cipher_suite;
+ return SECSuccess;
}
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
return SECFailure;
@@ -8491,20 +8479,24 @@ ssl_GenerateServerRandom(sslSocket *ss)
*/
PRUint8 *downgradeSentinel =
ss->ssl3.hs.server_random +
- SSL3_RANDOM_LENGTH - sizeof(tls13_downgrade_random);
-
- switch (ss->vrange.max) {
- case SSL_LIBRARY_VERSION_TLS_1_3:
- PORT_Memcpy(downgradeSentinel,
- tls13_downgrade_random, sizeof(tls13_downgrade_random));
- break;
- case SSL_LIBRARY_VERSION_TLS_1_2:
- PORT_Memcpy(downgradeSentinel,
- tls12_downgrade_random, sizeof(tls12_downgrade_random));
- break;
- default:
- /* Do not change random. */
- break;
+ SSL3_RANDOM_LENGTH - sizeof(tls12_downgrade_random);
+
+ if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ switch (ss->version) {
+ case SSL_LIBRARY_VERSION_TLS_1_2:
+ /* vrange.max > 1.2, since we didn't early exit above. */
+ PORT_Memcpy(downgradeSentinel,
+ tls12_downgrade_random, sizeof(tls12_downgrade_random));
+ break;
+ case SSL_LIBRARY_VERSION_TLS_1_1:
+ case SSL_LIBRARY_VERSION_TLS_1_0:
+ PORT_Memcpy(downgradeSentinel,
+ tls1_downgrade_random, sizeof(tls1_downgrade_random));
+ break;
+ default:
+ /* Do not change random. */
+ break;
+ }
}
return SECSuccess;
@@ -8607,15 +8599,12 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
goto loser; /* malformed */
}
- /* Grab the client's cookie, if present. */
+ /* Grab the client's cookie, if present. It is checked after version negotiation. */
if (IS_DTLS(ss)) {
rv = ssl3_ConsumeHandshakeVariable(ss, &cookieBytes, 1, &b, &length);
if (rv != SECSuccess) {
goto loser; /* malformed */
}
- if (cookieBytes.len != 0) {
- goto loser; /* We never send cookies in DTLS 1.2. */
- }
}
/* Grab the list of cipher suites. */
@@ -8721,6 +8710,13 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
errCode = SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER;
goto alert_loser;
}
+
+ /* A DTLS 1.3-only client MUST set the legacy_cookie field to zero length.
+ * If a DTLS 1.3 ClientHello is received with any other value in this field,
+ * the server MUST abort the handshake with an "illegal_parameter" alert. */
+ if (IS_DTLS(ss) && cookieBytes.len != 0) {
+ goto alert_loser;
+ }
} else {
/* HRR is TLS1.3-only. We ignore the Cookie extension here. */
if (ss->ssl3.hs.helloRetry) {
@@ -8741,6 +8737,11 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
!memchr(comps.data, ssl_compression_null, comps.len)) {
goto alert_loser;
}
+
+ /* We never send cookies in DTLS 1.2. */
+ if (IS_DTLS(ss) && cookieBytes.len != 0) {
+ goto loser;
+ }
}
/* Now parse the rest of the extensions. */
@@ -9808,10 +9809,31 @@ ssl3_SendServerKeyExchange(sslSocket *ss)
}
SECStatus
-ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint16 minVersion, sslBuffer *buf)
+ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint16 minVersion, PRBool forCert,
+ sslBuffer *buf)
{
+ SSLSignatureScheme filtered[MAX_SIGNATURE_SCHEMES] = { 0 };
+ unsigned int filteredCount = 0;
+
+ SECStatus rv = ssl3_FilterSigAlgs(ss, minVersion, PR_FALSE, forCert,
+ PR_ARRAY_SIZE(filtered),
+ filtered, &filteredCount);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ return ssl3_EncodeFilteredSigAlgs(ss, filtered, filteredCount, buf);
+}
+
+SECStatus
+ssl3_EncodeFilteredSigAlgs(const sslSocket *ss, const SSLSignatureScheme *schemes,
+ PRUint32 numSchemes, sslBuffer *buf)
+{
+ if (!numSchemes) {
+ PORT_SetError(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM);
+ return SECFailure;
+ }
+
unsigned int lengthOffset;
- PRBool found = PR_FALSE;
SECStatus rv;
rv = sslBuffer_Skip(buf, 2, &lengthOffset);
@@ -9819,23 +9841,68 @@ ssl3_EncodeSigAlgs(const sslSocket *ss, PRUint16 minVersion, sslBuffer *buf)
return SECFailure;
}
- for (unsigned int i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
- if (ssl_SignatureSchemeAccepted(minVersion,
- ss->ssl3.signatureSchemes[i])) {
- rv = sslBuffer_AppendNumber(buf, ss->ssl3.signatureSchemes[i], 2);
- if (rv != SECSuccess) {
- return SECFailure;
- }
- found = PR_TRUE;
+ for (unsigned int i = 0; i < numSchemes; ++i) {
+ rv = sslBuffer_AppendNumber(buf, schemes[i], 2);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
}
+ return sslBuffer_InsertLength(buf, lengthOffset, 2);
+}
- if (!found) {
- PORT_SetError(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM);
+/*
+ * In TLS 1.3 we are permitted to advertise support for PKCS#1
+ * schemes. This doesn't affect the signatures in TLS itself, just
+ * those on certificates. Not advertising PKCS#1 signatures creates a
+ * serious compatibility risk as it excludes many certificate chains
+ * that include PKCS#1. Hence, forCert is used to enable advertising
+ * PKCS#1 support. Note that we include these in signature_algorithms
+ * because we don't yet support signature_algorithms_cert. TLS 1.3
+ * requires that PKCS#1 schemes are placed last in the list if they
+ * are present. This sorting can be removed once we support
+ * signature_algorithms_cert.
+ */
+SECStatus
+ssl3_FilterSigAlgs(const sslSocket *ss, PRUint16 minVersion, PRBool disableRsae,
+ PRBool forCert,
+ unsigned int maxSchemes, SSLSignatureScheme *filteredSchemes,
+ unsigned int *numFilteredSchemes)
+{
+ PORT_Assert(filteredSchemes);
+ PORT_Assert(numFilteredSchemes);
+ PORT_Assert(maxSchemes >= ss->ssl3.signatureSchemeCount);
+ if (maxSchemes < ss->ssl3.signatureSchemeCount) {
return SECFailure;
}
- return sslBuffer_InsertLength(buf, lengthOffset, 2);
+ *numFilteredSchemes = 0;
+ PRBool allowUnsortedPkcs1 = forCert && minVersion < SSL_LIBRARY_VERSION_TLS_1_3;
+ for (unsigned int i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
+ if (disableRsae && ssl_IsRsaeSignatureScheme(ss->ssl3.signatureSchemes[i])) {
+ continue;
+ }
+ if (ssl_SignatureSchemeAccepted(minVersion,
+ ss->ssl3.signatureSchemes[i],
+ allowUnsortedPkcs1)) {
+ filteredSchemes[(*numFilteredSchemes)++] = ss->ssl3.signatureSchemes[i];
+ }
+ }
+ if (forCert && !allowUnsortedPkcs1) {
+ for (unsigned int i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
+ if (disableRsae && ssl_IsRsaeSignatureScheme(ss->ssl3.signatureSchemes[i])) {
+ continue;
+ }
+ if (!ssl_SignatureSchemeAccepted(minVersion,
+ ss->ssl3.signatureSchemes[i],
+ PR_FALSE) &&
+ ssl_SignatureSchemeAccepted(minVersion,
+ ss->ssl3.signatureSchemes[i],
+ PR_TRUE)) {
+ filteredSchemes[(*numFilteredSchemes)++] = ss->ssl3.signatureSchemes[i];
+ }
+ }
+ }
+ return SECSuccess;
}
static SECStatus
@@ -9871,7 +9938,7 @@ ssl3_SendCertificateRequest(sslSocket *ss)
length = 1 + certTypesLength + 2 + calen;
if (isTLS12) {
- rv = ssl3_EncodeSigAlgs(ss, ss->version, &sigAlgsBuf);
+ rv = ssl3_EncodeSigAlgs(ss, ss->version, PR_TRUE /* forCert */, &sigAlgsBuf);
if (rv != SECSuccess) {
return rv;
}
@@ -11232,6 +11299,8 @@ static SECStatus ssl3_FinishHandshake(sslSocket *ss);
static SECStatus
ssl3_AlwaysFail(sslSocket *ss)
{
+ /* The caller should have cleared the callback. */
+ ss->ssl3.hs.restartTarget = ssl3_AlwaysFail;
PORT_SetError(PR_INVALID_STATE_ERROR);
return SECFailure;
}
@@ -11324,9 +11393,9 @@ ssl3_ComputeTLSFinished(sslSocket *ss, ssl3CipherSpec *spec,
}
if (spec->version < SSL_LIBRARY_VERSION_TLS_1_2) {
- tls_mac_params.prfMechanism = CKM_TLS_PRF;
+ tls_mac_params.prfHashMechanism = CKM_TLS_PRF;
} else {
- tls_mac_params.prfMechanism = ssl3_GetPrfHashMechanism(ss);
+ tls_mac_params.prfHashMechanism = ssl3_GetPrfHashMechanism(ss);
}
tls_mac_params.ulMacLength = 12;
tls_mac_params.ulServerOrClient = isServer ? 1 : 2;
@@ -11667,7 +11736,6 @@ ssl3_CacheWrappedSecret(sslSocket *ss, sslSessionID *sid,
static SECStatus
ssl3_HandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length)
{
- sslSessionID *sid = ss->sec.ci.sid;
SECStatus rv = SECSuccess;
PRBool isServer = ss->sec.isServer;
PRBool isTLS;
@@ -11811,15 +11879,6 @@ xmit_loser:
return rv;
}
- if (sid->cached == never_cached && !ss->opt.noCache) {
- rv = ssl3_FillInCachedSID(ss, sid, ss->ssl3.crSpec->masterSecret);
-
- /* If the wrap failed, we don't cache the sid.
- * The connection continues normally however.
- */
- ss->ssl3.hs.cacheSID = rv == SECSuccess;
- }
-
if (ss->ssl3.hs.authCertificatePending) {
if (ss->ssl3.hs.restartTarget) {
PR_NOT_REACHED("ssl3_HandleFinished: unexpected restartTarget");
@@ -11884,33 +11943,45 @@ ssl3_FinishHandshake(sslSocket *ss)
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->ssl3.hs.restartTarget == NULL);
+ sslSessionID *sid = ss->sec.ci.sid;
+ SECStatus sidRv = SECFailure;
/* The first handshake is now completed. */
ss->handshake = NULL;
+ if (sid->cached == never_cached && !ss->opt.noCache) {
+ /* If the wrap fails, don't cache the sid. The connection proceeds
+ * normally, so the rv is only used to determine whether we cache. */
+ sidRv = ssl3_FillInCachedSID(ss, sid, ss->ssl3.crSpec->masterSecret);
+ }
+
/* RFC 5077 Section 3.3: "The client MUST NOT treat the ticket as valid
- * until it has verified the server's Finished message." When the server
- * sends a NewSessionTicket in a resumption handshake, we must wait until
- * the handshake is finished (we have verified the server's Finished
- * AND the server's certificate) before we update the ticket in the sid.
- *
- * This must be done before we call ssl_CacheSessionID(ss)
- * because CacheSID requires the session ticket to already be set, and also
- * because of the lazy lock creation scheme used by CacheSID and
- * ssl3_SetSIDSessionTicket.
- */
+ * until it has verified the server's Finished message." When the server
+ * sends a NewSessionTicket in a resumption handshake, we must wait until
+ * the handshake is finished (we have verified the server's Finished
+ * AND the server's certificate) before we update the ticket in the sid.
+ *
+ * This must be done before we call ssl_CacheSessionID(ss)
+ * because CacheSID requires the session ticket to already be set, and also
+ * because of the lazy lock creation scheme used by CacheSID and
+ * ssl3_SetSIDSessionTicket. */
if (ss->ssl3.hs.receivedNewSessionTicket) {
PORT_Assert(!ss->sec.isServer);
- ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &ss->ssl3.hs.newSessionTicket);
- /* The sid took over the ticket data */
+ if (sidRv == SECSuccess) {
+ /* The sid takes over the ticket data */
+ ssl3_SetSIDSessionTicket(ss->sec.ci.sid,
+ &ss->ssl3.hs.newSessionTicket);
+ } else {
+ PORT_Assert(ss->ssl3.hs.newSessionTicket.ticket.data);
+ SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket,
+ PR_FALSE);
+ }
PORT_Assert(!ss->ssl3.hs.newSessionTicket.ticket.data);
ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
}
-
- if (ss->ssl3.hs.cacheSID) {
+ if (sidRv == SECSuccess) {
PORT_Assert(ss->sec.ci.sid->cached == never_cached);
ssl_CacheSessionID(ss);
- ss->ssl3.hs.cacheSID = PR_FALSE;
}
ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
@@ -12308,41 +12379,26 @@ loser : {
return SECFailure;
}
-/* These macros return the given value with the MSB copied to all the other
- * bits. They use the fact that arithmetic shift shifts-in the sign bit.
- * However, this is not ensured by the C standard so you may need to replace
- * them with something else for odd compilers. */
-#define DUPLICATE_MSB_TO_ALL(x) ((unsigned)((int)(x) >> (sizeof(int) * 8 - 1)))
-#define DUPLICATE_MSB_TO_ALL_8(x) ((unsigned char)(DUPLICATE_MSB_TO_ALL(x)))
-
/* SECStatusToMask returns, in constant time, a mask value of all ones if
* rv == SECSuccess. Otherwise it returns zero. */
static unsigned int
SECStatusToMask(SECStatus rv)
{
- unsigned int good;
- /* rv ^ SECSuccess is zero iff rv == SECSuccess. Subtracting one results
- * in the MSB being set to one iff it was zero before. */
- good = rv ^ SECSuccess;
- good--;
- return DUPLICATE_MSB_TO_ALL(good);
+ return PORT_CT_EQ(rv, SECSuccess);
}
-/* ssl_ConstantTimeGE returns 0xff if a>=b and 0x00 otherwise. */
+/* ssl_ConstantTimeGE returns 0xffffffff if a>=b and 0x00 otherwise. */
static unsigned char
ssl_ConstantTimeGE(unsigned int a, unsigned int b)
{
- a -= b;
- return DUPLICATE_MSB_TO_ALL(~a);
+ return PORT_CT_GE(a, b);
}
-/* ssl_ConstantTimeEQ8 returns 0xff if a==b and 0x00 otherwise. */
+/* ssl_ConstantTimeEQ returns 0xffffffff if a==b and 0x00 otherwise. */
static unsigned char
-ssl_ConstantTimeEQ8(unsigned char a, unsigned char b)
+ssl_ConstantTimeEQ(unsigned char a, unsigned char b)
{
- unsigned int c = a ^ b;
- c--;
- return DUPLICATE_MSB_TO_ALL_8(c);
+ return PORT_CT_EQ(a, b);
}
/* ssl_constantTimeSelect return a if mask is 0xFF and b if mask is 0x00 */
@@ -12357,7 +12413,7 @@ ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext,
unsigned int blockSize,
unsigned int macSize)
{
- unsigned int paddingLength, good, t;
+ unsigned int paddingLength, good;
const unsigned int overhead = 1 /* padding length byte */ + macSize;
/* These lengths are all public so we can test them in non-constant
@@ -12368,13 +12424,9 @@ ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext,
paddingLength = plaintext->buf[plaintext->len - 1];
/* SSLv3 padding bytes are random and cannot be checked. */
- t = plaintext->len;
- t -= paddingLength + overhead;
- /* If len >= paddingLength+overhead then the MSB of t is zero. */
- good = DUPLICATE_MSB_TO_ALL(~t);
+ good = PORT_CT_GE(plaintext->len, paddingLength + overhead);
/* SSLv3 requires that the padding is minimal. */
- t = blockSize - (paddingLength + 1);
- good &= DUPLICATE_MSB_TO_ALL(~t);
+ good &= PORT_CT_GE(blockSize, paddingLength + 1);
plaintext->len -= good & (paddingLength + 1);
return (good & SECSuccess) | (~good & SECFailure);
}
@@ -12382,7 +12434,7 @@ ssl_RemoveSSLv3CBCPadding(sslBuffer *plaintext,
SECStatus
ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize)
{
- unsigned int paddingLength, good, t, toCheck, i;
+ unsigned int paddingLength, good, toCheck, i;
const unsigned int overhead = 1 /* padding length byte */ + macSize;
/* These lengths are all public so we can test them in non-constant
@@ -12392,10 +12444,7 @@ ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize)
}
paddingLength = plaintext->buf[plaintext->len - 1];
- t = plaintext->len;
- t -= paddingLength + overhead;
- /* If len >= paddingLength+overhead then the MSB of t is zero. */
- good = DUPLICATE_MSB_TO_ALL(~t);
+ good = PORT_CT_GE(plaintext->len, paddingLength + overhead);
/* The padding consists of a length byte at the end of the record and then
* that many bytes of padding, all with the same value as the length byte.
@@ -12412,10 +12461,9 @@ ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize)
}
for (i = 0; i < toCheck; i++) {
- t = paddingLength - i;
/* If i <= paddingLength then the MSB of t is zero and mask is
* 0xff. Otherwise, mask is 0. */
- unsigned char mask = DUPLICATE_MSB_TO_ALL(~t);
+ unsigned char mask = PORT_CT_LE(i, paddingLength);
unsigned char b = plaintext->buf[plaintext->len - 1 - i];
/* The final |paddingLength+1| bytes should all have the value
* |paddingLength|. Therefore the XOR should be zero. */
@@ -12430,7 +12478,7 @@ ssl_RemoveTLSCBCPadding(sslBuffer *plaintext, unsigned int macSize)
good &= good >> 2;
good &= good >> 1;
good <<= sizeof(good) * 8 - 1;
- good = DUPLICATE_MSB_TO_ALL(good);
+ good = PORT_CT_DUPLICATE_MSB_TO_ALL(good);
plaintext->len -= good & (paddingLength + 1);
return (good & SECSuccess) | (~good & SECFailure);
@@ -12523,7 +12571,7 @@ ssl_CBCExtractMAC(sslBuffer *plaintext,
0, rotateOffset);
for (i = 0; i < macSize; i++) {
for (j = 0; j < macSize; j++) {
- out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ8(j, rotateOffset);
+ out[j] |= rotatedMac[i] & ssl_ConstantTimeEQ(j, rotateOffset);
}
rotateOffset++;
rotateOffset = ssl_constantTimeSelect(ssl_ConstantTimeGE(rotateOffset, macSize),
@@ -12633,21 +12681,50 @@ ssl3_UnprotectRecord(sslSocket *ss,
* ciphertext by a fixed byte count, but it is not true in general.
* Each AEAD cipher should provide a function that returns the
* plaintext length for a given ciphertext. */
- unsigned int decryptedLen =
- cText->buf->len - cipher_def->explicit_nonce_size -
- cipher_def->tag_size;
+ const unsigned int explicitNonceLen = cipher_def->explicit_nonce_size;
+ const unsigned int tagLen = cipher_def->tag_size;
+ unsigned int nonceLen = explicitNonceLen;
+ unsigned int decryptedLen = cText->buf->len - nonceLen - tagLen;
+ /* even though read doesn't return and IV, we still need a space to put
+ * the combined iv/nonce n the gcm 1.2 case*/
+ unsigned char ivOut[MAX_IV_LENGTH];
+ unsigned char *iv = NULL;
+ unsigned char *nonce = NULL;
+
+ ivLen = cipher_def->iv_size;
+
rv = ssl3_BuildRecordPseudoHeader(
spec->epoch, cText->seqNum,
rType, isTLS, rVersion, IS_DTLS(ss), decryptedLen, &header);
PORT_Assert(rv == SECSuccess);
- rv = spec->aead(&spec->keyMaterial,
- PR_TRUE, /* do decrypt */
- plaintext->buf, /* out */
- &plaintext->len, /* outlen */
- plaintext->space, /* maxout */
- cText->buf->buf, /* in */
- cText->buf->len, /* inlen */
- SSL_BUFFER_BASE(&header), SSL_BUFFER_LEN(&header));
+
+ /* build the iv */
+ if (explicitNonceLen == 0) {
+ nonceLen = sizeof(cText->seqNum);
+ iv = spec->keyMaterial.iv;
+ nonce = SSL_BUFFER_BASE(&header);
+ } else {
+ PORT_Memcpy(ivOut, spec->keyMaterial.iv, ivLen);
+ PORT_Memset(ivOut + ivLen, 0, explicitNonceLen);
+ iv = ivOut;
+ nonce = cText->buf->buf;
+ nonceLen = explicitNonceLen;
+ }
+ rv = tls13_AEAD(spec->cipherContext, PR_TRUE,
+ CKG_NO_GENERATE, 0, /* iv generator params
+ * (not used in decrypt)*/
+ iv, /* iv in */
+ NULL, /* iv out */
+ ivLen + explicitNonceLen, /* full iv length */
+ nonce, nonceLen, /* nonce in */
+ SSL_BUFFER_BASE(&header), /* aad */
+ SSL_BUFFER_LEN(&header), /* aadlen */
+ plaintext->buf, /* output */
+ &plaintext->len, /* out len */
+ plaintext->space, /* max out */
+ tagLen,
+ cText->buf->buf + explicitNonceLen, /* input */
+ cText->buf->len - explicitNonceLen); /* input len */
if (rv != SECSuccess) {
good = 0;
}
@@ -12895,6 +12972,12 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
}
isTLS = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0);
if (IS_DTLS(ss)) {
+ if (dtls13_MaskSequenceNumber(ss, spec, cText->hdr,
+ SSL_BUFFER_BASE(cText->buf), SSL_BUFFER_LEN(cText->buf)) != SECSuccess) {
+ ssl_ReleaseSpecReadLock(ss); /*****************************/
+ /* code already set. */
+ return SECFailure;
+ }
if (!dtls_IsRelevant(ss, spec, cText, &cText->seqNum)) {
ssl_ReleaseSpecReadLock(ss); /*****************************/
return SECSuccess;
@@ -12936,7 +13019,10 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
/* Encrypted application data records could arrive before the handshake
* completes in DTLS 1.3. These can look like valid TLS 1.2 application_data
* records in epoch 0, which is never valid. Pretend they didn't decrypt. */
- if (spec->epoch == 0 && rType == ssl_ct_application_data) {
+
+ if (spec->epoch == 0 && ((IS_DTLS(ss) &&
+ dtls_IsDtls13Ciphertext(0, rType)) ||
+ rType == ssl_ct_application_data)) {
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA);
alert = unexpected_message;
rv = SECFailure;
@@ -12975,12 +13061,18 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
ss->ssl3.hs.ws != idle_handshake &&
cText->buf->len == 1 &&
cText->buf->buf[0] == change_cipher_spec_choice) {
- /* Ignore the CCS. */
- return SECSuccess;
+ if (!ss->ssl3.hs.rejectCcs) {
+ /* Allow only the first CCS. */
+ ss->ssl3.hs.rejectCcs = PR_TRUE;
+ return SECSuccess;
+ } else {
+ alert = unexpected_message;
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
+ }
}
- if (IS_DTLS(ss) ||
- (ss->sec.isServer &&
+ if ((IS_DTLS(ss) && !dtls13_AeadLimitReached(spec)) ||
+ (!IS_DTLS(ss) && ss->sec.isServer &&
ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) {
/* Silently drop the packet unless we sent a fatal alert. */
if (ss->ssl3.fatalAlertSent) {
@@ -13103,7 +13195,6 @@ ssl3_InitState(sslSocket *ss)
ss->ssl3.hs.currentSecret = NULL;
ss->ssl3.hs.resumptionMasterSecret = NULL;
ss->ssl3.hs.dheSecret = NULL;
- ss->ssl3.hs.pskBinderKey = NULL;
ss->ssl3.hs.clientEarlyTrafficSecret = NULL;
ss->ssl3.hs.clientHsTrafficSecret = NULL;
ss->ssl3.hs.serverHsTrafficSecret = NULL;
@@ -13477,8 +13568,6 @@ ssl3_DestroySSL3Info(sslSocket *ss)
PK11_FreeSymKey(ss->ssl3.hs.resumptionMasterSecret);
if (ss->ssl3.hs.dheSecret)
PK11_FreeSymKey(ss->ssl3.hs.dheSecret);
- if (ss->ssl3.hs.pskBinderKey)
- PK11_FreeSymKey(ss->ssl3.hs.pskBinderKey);
if (ss->ssl3.hs.clientEarlyTrafficSecret)
PK11_FreeSymKey(ss->ssl3.hs.clientEarlyTrafficSecret);
if (ss->ssl3.hs.clientHsTrafficSecret)
@@ -13497,6 +13586,63 @@ ssl3_DestroySSL3Info(sslSocket *ss)
ss->ssl3.hs.zeroRttState = ssl_0rtt_none;
/* Destroy TLS 1.3 buffered early data. */
tls13_DestroyEarlyData(&ss->ssl3.hs.bufferedEarlyData);
+ /* Destroy TLS 1.3 PSKs */
+ tls13_DestroyPskList(&ss->ssl3.hs.psks);
+}
+
+/*
+ * parse the policy value for a single algorithm in a cipher_suite,
+ * return TRUE if we disallow by the cipher suite by policy
+ * (we don't have to parse any more algorithm policies on this cipher suite),
+ * otherwise return FALSE.
+ * 1. If we don't have the required policy, disable by default, disallow by
+ * policy and return TRUE (no more processing needed).
+ * 2. If we have the required policy, and we are disabled, return FALSE,
+ * (if we are disabled, we only need to parse policy, not default).
+ * 3. If we have the required policy, and we aren't adjusting the defaults
+ * return FALSE. (only parsing the policy, not default).
+ * 4. We have the required policy and we are adjusting the defaults.
+ * If we are setting default = FALSE, set isDisabled to true so that
+ * we don't try to re-enable the cipher suite based on a different
+ * algorithm.
+ */
+PRBool
+ssl_HandlePolicy(int cipher_suite, SECOidTag policyOid,
+ PRUint32 requiredPolicy, PRBool *isDisabled)
+{
+ PRUint32 policy;
+ SECStatus rv;
+
+ /* first fetch the policy for this algorithm */
+ rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
+ if (rv != SECSuccess) {
+ return PR_FALSE; /* no policy value, continue to the next algorithm */
+ }
+ /* first, are we allowed by policy, if not turn off allow and disable */
+ if (!(policy & requiredPolicy)) {
+ ssl_CipherPrefSetDefault(cipher_suite, PR_FALSE);
+ ssl_CipherPolicySet(cipher_suite, SSL_NOT_ALLOWED);
+ return PR_TRUE;
+ }
+ /* If we are already disabled, or the policy isn't setting a default
+ * we are done processing this algorithm */
+ if (*isDisabled || (policy & NSS_USE_DEFAULT_NOT_VALID)) {
+ return PR_FALSE;
+ }
+ /* set the default value for the cipher suite. If we disable the cipher
+ * suite, remember that so we don't process the next default. This has
+ * the effect of disabling the whole cipher suite if any of the
+ * algorithms it uses are disabled by default. We still have to
+ * process the upper level because the cipher suite is still allowed
+ * by policy, and we may still have to disallow it based on other
+ * algorithms in the cipher suite. */
+ if (policy & NSS_USE_DEFAULT_SSL_ENABLE) {
+ ssl_CipherPrefSetDefault(cipher_suite, PR_TRUE);
+ } else {
+ *isDisabled = PR_TRUE;
+ ssl_CipherPrefSetDefault(cipher_suite, PR_FALSE);
+ }
+ return PR_FALSE;
}
#define MAP_NULL(x) (((x) != 0) ? (x) : SEC_OID_NULL_CIPHER)
@@ -13517,30 +13663,30 @@ ssl3_ApplyNSSPolicy(void)
for (i = 1; i < PR_ARRAY_SIZE(cipher_suite_defs); ++i) {
const ssl3CipherSuiteDef *suite = &cipher_suite_defs[i];
SECOidTag policyOid;
+ PRBool isDisabled = PR_FALSE;
+
+ /* if we haven't explicitly disabled it below enable by policy */
+ ssl_CipherPolicySet(suite->cipher_suite, SSL_ALLOWED);
+ /* now check the various key exchange, ciphers and macs and
+ * if we ever disallow by policy, we are done, go to the next cipher
+ */
policyOid = MAP_NULL(kea_defs[suite->key_exchange_alg].oid);
- rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
- if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL_KX)) {
- ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
- ssl_CipherPolicySet(suite->cipher_suite, SSL_NOT_ALLOWED);
+ if (ssl_HandlePolicy(suite->cipher_suite, policyOid,
+ NSS_USE_ALG_IN_SSL_KX, &isDisabled)) {
continue;
}
policyOid = MAP_NULL(ssl_GetBulkCipherDef(suite)->oid);
- rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
- if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL)) {
- ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
- ssl_CipherPolicySet(suite->cipher_suite, SSL_NOT_ALLOWED);
+ if (ssl_HandlePolicy(suite->cipher_suite, policyOid,
+ NSS_USE_ALG_IN_SSL, &isDisabled)) {
continue;
}
if (ssl_GetBulkCipherDef(suite)->type != type_aead) {
policyOid = MAP_NULL(ssl_GetMacDefByAlg(suite->mac_alg)->oid);
- rv = NSS_GetAlgorithmPolicy(policyOid, &policy);
- if (rv == SECSuccess && !(policy & NSS_USE_ALG_IN_SSL)) {
- ssl_CipherPrefSetDefault(suite->cipher_suite, PR_FALSE);
- ssl_CipherPolicySet(suite->cipher_suite,
- SSL_NOT_ALLOWED);
+ if (ssl_HandlePolicy(suite->cipher_suite, policyOid,
+ NSS_USE_ALG_IN_SSL, &isDisabled)) {
continue;
}
}