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.c1004
1 files changed, 645 insertions, 359 deletions
diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c
index 466fc296f..3b5c69b11 100644
--- a/security/nss/lib/ssl/ssl3con.c
+++ b/security/nss/lib/ssl/ssl3con.c
@@ -93,8 +93,8 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
{ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_FALSE, PR_FALSE},
+ { TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE},
+ { TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE},
/* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA is out of order to work around
* bug 946147.
*/
@@ -114,7 +114,7 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
{ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,SSL_ALLOWED,PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
- { TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_FALSE, PR_FALSE},
+ { TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
@@ -143,7 +143,7 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
/* RSA */
{ TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
- { TLS_RSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_FALSE, PR_FALSE},
+ { TLS_RSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
@@ -501,19 +501,19 @@ ssl3_DecodeContentType(int msgType)
static char line[40];
switch (msgType) {
- case content_change_cipher_spec:
+ case ssl_ct_change_cipher_spec:
rv = "change_cipher_spec (20)";
break;
- case content_alert:
+ case ssl_ct_alert:
rv = "alert (21)";
break;
- case content_handshake:
+ case ssl_ct_handshake:
rv = "handshake (22)";
break;
- case content_application_data:
+ case ssl_ct_application_data:
rv = "application_data (23)";
break;
- case content_ack:
+ case ssl_ct_ack:
rv = "ack (25)";
break;
default:
@@ -656,7 +656,7 @@ ssl_LookupCipherSuiteCfgMutable(ssl3CipherSuite suite,
return NULL;
}
-const static ssl3CipherSuiteCfg *
+const ssl3CipherSuiteCfg *
ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite, const ssl3CipherSuiteCfg *suites)
{
return ssl_LookupCipherSuiteCfgMutable(suite,
@@ -765,6 +765,9 @@ ssl_HasCert(const sslSocket *ss, SSLAuthType authType)
}
return PR_TRUE;
}
+ if (authType == ssl_auth_rsa_sign) {
+ return ssl_HasCert(ss, ssl_auth_rsa_pss);
+ }
return PR_FALSE;
}
@@ -851,9 +854,9 @@ ssl3_config_match_init(sslSocket *ss)
/* Return PR_TRUE if suite is usable. This if the suite is permitted by policy,
* enabled, has a certificate (as needed), has a viable key agreement method, is
* usable with the negotiated TLS version, and is otherwise usable. */
-static PRBool
-config_match(const ssl3CipherSuiteCfg *suite, PRUint8 policy,
- const SSLVersionRange *vrange, const sslSocket *ss)
+PRBool
+ssl3_config_match(const ssl3CipherSuiteCfg *suite, PRUint8 policy,
+ const SSLVersionRange *vrange, const sslSocket *ss)
{
const ssl3CipherSuiteDef *cipher_def;
const ssl3KEADef *kea_def;
@@ -896,7 +899,7 @@ count_cipher_suites(sslSocket *ss, PRUint8 policy)
return 0;
}
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
- if (config_match(&ss->cipherSuites[i], policy, &ss->vrange, ss))
+ if (ssl3_config_match(&ss->cipherSuites[i], policy, &ss->vrange, ss))
count++;
}
if (count == 0) {
@@ -1120,6 +1123,8 @@ ssl3_SignHashes(sslSocket *ss, SSL3Hashes *hash, SECKEYPrivateKey *key,
if (ss->sec.isServer) {
ss->sec.signatureScheme = ss->ssl3.hs.signatureScheme;
+ ss->sec.authType =
+ ssl_SignatureSchemeToAuthType(ss->ssl3.hs.signatureScheme);
}
PRINT_BUF(60, (NULL, "signed hashes", (unsigned char *)buf->data, buf->len));
done:
@@ -1255,6 +1260,7 @@ ssl3_VerifySignedHashes(sslSocket *ss, SSLSignatureScheme scheme, SSL3Hashes *ha
}
if (!ss->sec.isServer) {
ss->sec.signatureScheme = scheme;
+ ss->sec.authType = ssl_SignatureSchemeToAuthType(scheme);
}
loser:
@@ -1506,7 +1512,7 @@ loser:
static SECStatus
ssl3_BuildRecordPseudoHeader(DTLSEpoch epoch,
sslSequenceNumber seqNum,
- SSL3ContentType type,
+ SSLContentType ct,
PRBool includesVersion,
SSL3ProtocolVersion version,
PRBool isDTLS,
@@ -1526,7 +1532,7 @@ ssl3_BuildRecordPseudoHeader(DTLSEpoch epoch,
if (rv != SECSuccess) {
return SECFailure;
}
- rv = sslBuffer_AppendNumber(buf, type, 1);
+ rv = sslBuffer_AppendNumber(buf, ct, 1);
if (rv != SECSuccess) {
return SECFailure;
}
@@ -1994,7 +2000,7 @@ SECStatus
ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
PRBool isServer,
PRBool isDTLS,
- SSL3ContentType type,
+ SSLContentType ct,
const PRUint8 *pIn,
PRUint32 contentLen,
sslBuffer *wrBuf)
@@ -2041,7 +2047,7 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
}
rv = ssl3_BuildRecordPseudoHeader(
- cwSpec->epoch, cwSpec->nextSeqNum, type,
+ cwSpec->epoch, cwSpec->nextSeqNum, ct,
cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->recordVersion,
isDTLS, contentLen, &pseudoHeader);
PORT_Assert(rv == SECSuccess);
@@ -2163,7 +2169,7 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
/* Note: though this can report failure, it shouldn't. */
SECStatus
ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec,
- SSL3ContentType contentType, sslBuffer *wrBuf,
+ SSLContentType contentType, sslBuffer *wrBuf,
PRBool *needsLength)
{
SECStatus rv;
@@ -2175,7 +2181,7 @@ ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec,
return dtls13_InsertCipherTextHeader(ss, cwSpec, wrBuf,
needsLength);
}
- contentType = content_application_data;
+ contentType = ssl_ct_application_data;
}
#endif
rv = sslBuffer_AppendNumber(wrBuf, contentType, 1);
@@ -2202,7 +2208,7 @@ ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec,
}
SECStatus
-ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSL3ContentType type,
+ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSLContentType ct,
const PRUint8 *pIn, PRUint32 contentLen, sslBuffer *wrBuf)
{
PRBool needsLength;
@@ -2222,7 +2228,7 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSL3ContentType type,
return SECFailure;
}
- rv = ssl_InsertRecordHeader(ss, cwSpec, type, wrBuf, &needsLength);
+ rv = ssl_InsertRecordHeader(ss, cwSpec, ct, wrBuf, &needsLength);
if (rv != SECSuccess) {
return SECFailure;
}
@@ -2246,9 +2252,9 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSL3ContentType type,
}
#else
if (cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
- rv = tls13_ProtectRecord(ss, cwSpec, type, pIn, contentLen, wrBuf);
+ rv = tls13_ProtectRecord(ss, cwSpec, ct, pIn, contentLen, wrBuf);
} else {
- rv = ssl3_MACEncryptRecord(cwSpec, ss->sec.isServer, IS_DTLS(ss), type,
+ rv = ssl3_MACEncryptRecord(cwSpec, ss->sec.isServer, IS_DTLS(ss), ct,
pIn, contentLen, wrBuf);
}
#endif
@@ -2270,7 +2276,7 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSL3ContentType type,
}
SECStatus
-ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSL3ContentType type,
+ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSLContentType ct,
const PRUint8 *pIn, unsigned int nIn,
unsigned int *written)
{
@@ -2294,7 +2300,7 @@ ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSL3ContentType type,
}
}
- rv = ssl_ProtectRecord(ss, spec, type, pIn, contentLen, wrBuf);
+ rv = ssl_ProtectRecord(ss, spec, ct, pIn, contentLen, wrBuf);
if (rv != SECSuccess) {
return SECFailure;
}
@@ -2328,7 +2334,7 @@ ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSL3ContentType type,
PRInt32
ssl3_SendRecord(sslSocket *ss,
ssl3CipherSpec *cwSpec, /* non-NULL for DTLS retransmits */
- SSL3ContentType type,
+ SSLContentType ct,
const PRUint8 *pIn, /* input buffer */
PRInt32 nIn, /* bytes of input */
PRInt32 flags)
@@ -2339,7 +2345,7 @@ ssl3_SendRecord(sslSocket *ss,
PRInt32 totalSent = 0;
SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
- SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
+ SSL_GETPID(), ss->fd, ssl3_DecodeContentType(ct),
nIn));
PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
@@ -2349,7 +2355,7 @@ ssl3_SendRecord(sslSocket *ss,
if (ss->ssl3.fatalAlertSent) {
SSL_TRC(3, ("%d: SSL3[%d] Suppress write, fatal alert already sent",
SSL_GETPID(), ss->fd));
- if (type != content_alert) {
+ if (ct != ssl_ct_alert) {
/* If we are sending an alert, then we already have an
* error, so don't overwrite. */
PORT_SetError(SSL_ERROR_HANDSHAKE_FAILED);
@@ -2366,8 +2372,8 @@ ssl3_SendRecord(sslSocket *ss,
if (cwSpec) {
/* cwSpec can only be set for retransmissions of the DTLS handshake. */
PORT_Assert(IS_DTLS(ss) &&
- (type == content_handshake ||
- type == content_change_cipher_spec));
+ (ct == ssl_ct_handshake ||
+ ct == ssl_ct_change_cipher_spec));
spec = cwSpec;
} else {
spec = ss->ssl3.cwSpec;
@@ -2378,7 +2384,7 @@ ssl3_SendRecord(sslSocket *ss,
PRInt32 sent;
ssl_GetSpecReadLock(ss);
- rv = ssl_ProtectNextRecord(ss, spec, type, pIn, nIn, &written);
+ rv = ssl_ProtectNextRecord(ss, spec, ct, pIn, nIn, &written);
ssl_ReleaseSpecReadLock(ss);
if (rv != SECSuccess) {
goto loser;
@@ -2386,7 +2392,7 @@ ssl3_SendRecord(sslSocket *ss,
PORT_Assert(written > 0);
/* DTLS should not fragment non-application data here. */
- if (IS_DTLS(ss) && type != content_application_data) {
+ if (IS_DTLS(ss) && ct != ssl_ct_application_data) {
PORT_Assert(written == nIn);
}
@@ -2535,7 +2541,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in,
* Note that the 0 epoch is OK because flags will never require
* its use, as guaranteed by the PORT_Assert above.
*/
- sent = ssl3_SendRecord(ss, NULL, content_application_data,
+ sent = ssl3_SendRecord(ss, NULL, ssl_ct_application_data,
in + totalSent, toSend, flags);
if (sent < 0) {
if (totalSent > 0 && PR_GetError() == PR_WOULD_BLOCK_ERROR) {
@@ -2618,7 +2624,7 @@ ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
- count = ssl3_SendRecord(ss, NULL, content_handshake,
+ count = ssl3_SendRecord(ss, NULL, ssl_ct_handshake,
ss->sec.ci.sendBuf.buf,
ss->sec.ci.sendBuf.len, flags);
if (count < 0) {
@@ -2744,7 +2750,7 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc)
rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
if (rv == SECSuccess) {
PRInt32 sent;
- sent = ssl3_SendRecord(ss, NULL, content_alert, bytes, 2,
+ sent = ssl3_SendRecord(ss, NULL, ssl_ct_alert, bytes, 2,
(desc == no_certificate) ? ssl_SEND_FLAG_FORCE_INTO_BUFFER : 0);
rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
}
@@ -3041,13 +3047,13 @@ ssl3_SendChangeCipherSpecsInt(sslSocket *ss)
if (!IS_DTLS(ss)) {
PRInt32 sent;
- sent = ssl3_SendRecord(ss, NULL, content_change_cipher_spec,
+ sent = ssl3_SendRecord(ss, NULL, ssl_ct_change_cipher_spec,
&change, 1, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
if (sent < 0) {
return SECFailure; /* error code set by ssl3_SendRecord */
}
} else {
- rv = dtls_QueueMessage(ss, content_change_cipher_spec, &change, 1);
+ rv = dtls_QueueMessage(ss, ssl_ct_change_cipher_spec, &change, 1);
if (rv != SECSuccess) {
return SECFailure;
}
@@ -4002,8 +4008,8 @@ ssl_SignatureSchemeToHashType(SSLSignatureScheme scheme)
return ssl_hash_none;
}
-KeyType
-ssl_SignatureSchemeToKeyType(SSLSignatureScheme scheme)
+static PRBool
+ssl_SignatureSchemeMatchesSpkiOid(SSLSignatureScheme scheme, SECOidTag spkiOid)
{
switch (scheme) {
case ssl_sig_rsa_pkcs1_sha256:
@@ -4013,133 +4019,243 @@ ssl_SignatureSchemeToKeyType(SSLSignatureScheme scheme)
case ssl_sig_rsa_pss_rsae_sha256:
case ssl_sig_rsa_pss_rsae_sha384:
case ssl_sig_rsa_pss_rsae_sha512:
+ case ssl_sig_rsa_pkcs1_sha1md5:
+ return (spkiOid == SEC_OID_X500_RSA_ENCRYPTION) ||
+ (spkiOid == SEC_OID_PKCS1_RSA_ENCRYPTION);
case ssl_sig_rsa_pss_pss_sha256:
case ssl_sig_rsa_pss_pss_sha384:
case ssl_sig_rsa_pss_pss_sha512:
- case ssl_sig_rsa_pkcs1_sha1md5:
- return rsaKey;
+ return spkiOid == SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
case ssl_sig_ecdsa_secp256r1_sha256:
case ssl_sig_ecdsa_secp384r1_sha384:
case ssl_sig_ecdsa_secp521r1_sha512:
case ssl_sig_ecdsa_sha1:
- return ecKey;
+ return spkiOid == SEC_OID_ANSIX962_EC_PUBLIC_KEY;
case ssl_sig_dsa_sha256:
case ssl_sig_dsa_sha384:
case ssl_sig_dsa_sha512:
case ssl_sig_dsa_sha1:
- return dsaKey;
+ return spkiOid == SEC_OID_ANSIX9_DSA_SIGNATURE;
case ssl_sig_none:
case ssl_sig_ed25519:
case ssl_sig_ed448:
break;
}
PORT_Assert(0);
- return nullKey;
+ return PR_FALSE;
}
-static SSLNamedGroup
-ssl_NamedGroupForSignatureScheme(SSLSignatureScheme scheme)
+/* Validate that the signature scheme works for the given key type. */
+static PRBool
+ssl_SignatureSchemeValid(SSLSignatureScheme scheme, SECOidTag spkiOid,
+ PRBool isTls13)
{
- switch (scheme) {
- case ssl_sig_ecdsa_secp256r1_sha256:
- return ssl_grp_ec_secp256r1;
- case ssl_sig_ecdsa_secp384r1_sha384:
- return ssl_grp_ec_secp384r1;
- case ssl_sig_ecdsa_secp521r1_sha512:
- return ssl_grp_ec_secp521r1;
- default:
+ if (!ssl_IsSupportedSignatureScheme(scheme)) {
+ return PR_FALSE;
+ }
+ if (!ssl_SignatureSchemeMatchesSpkiOid(scheme, spkiOid)) {
+ return PR_FALSE;
+ }
+ if (isTls13) {
+ if (ssl_SignatureSchemeToHashType(scheme) == ssl_hash_sha1) {
+ return PR_FALSE;
+ }
+ /* With TLS 1.3, EC keys should have been selected based on calling
+ * ssl_SignatureSchemeFromSpki(), reject them otherwise. */
+ return spkiOid != SEC_OID_ANSIX962_EC_PUBLIC_KEY;
+ }
+ return PR_TRUE;
+}
+
+static SECStatus
+ssl_SignatureSchemeFromPssSpki(CERTSubjectPublicKeyInfo *spki,
+ SSLSignatureScheme *scheme)
+{
+ SECKEYRSAPSSParams pssParam = { 0 };
+ PORTCheapArenaPool arena;
+ SECStatus rv;
+
+ /* The key doesn't have parameters, boo. */
+ if (!spki->algorithm.parameters.len) {
+ *scheme = ssl_sig_none;
+ return SECSuccess;
+ }
+
+ PORT_InitCheapArena(&arena, DER_DEFAULT_CHUNKSIZE);
+ rv = SEC_QuickDERDecodeItem(&arena.arena, &pssParam,
+ SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate),
+ &spki->algorithm.parameters);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ /* Not having hashAlg means SHA-1 and we don't accept that. */
+ if (!pssParam.hashAlg) {
+ goto loser;
+ }
+ switch (SECOID_GetAlgorithmTag(pssParam.hashAlg)) {
+ case SEC_OID_SHA256:
+ *scheme = ssl_sig_rsa_pss_pss_sha256;
break;
+ case SEC_OID_SHA384:
+ *scheme = ssl_sig_rsa_pss_pss_sha384;
+ break;
+ case SEC_OID_SHA512:
+ *scheme = ssl_sig_rsa_pss_pss_sha512;
+ break;
+ default:
+ goto loser;
}
- PORT_Assert(0);
- return 0;
+
+ PORT_DestroyCheapArena(&arena);
+ return SECSuccess;
+
+loser:
+ PORT_DestroyCheapArena(&arena);
+ PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
+ return SECFailure;
}
-/* Validate that the signature scheme works for the given key.
- * If |allowSha1| is set, we allow the use of SHA-1.
- * If |matchGroup| is set, we also check that the group and hash match. */
-static PRBool
-ssl_SignatureSchemeValidForKey(PRBool allowSha1, PRBool matchGroup,
- KeyType keyType,
- const sslNamedGroupDef *ecGroup,
- SSLSignatureScheme scheme)
+static SECStatus
+ssl_SignatureSchemeFromEcSpki(CERTSubjectPublicKeyInfo *spki,
+ SSLSignatureScheme *scheme)
{
- if (!ssl_IsSupportedSignatureScheme(scheme)) {
- return PR_FALSE;
+ const sslNamedGroupDef *group;
+ SECKEYPublicKey *key;
+
+ key = SECKEY_ExtractPublicKey(spki);
+ if (!key) {
+ PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
+ return SECFailure;
}
- if (keyType != ssl_SignatureSchemeToKeyType(scheme)) {
- return PR_FALSE;
+ group = ssl_ECPubKey2NamedGroup(key);
+ SECKEY_DestroyPublicKey(key);
+ if (!group) {
+ PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
+ return SECFailure;
}
- if (!allowSha1 && ssl_SignatureSchemeToHashType(scheme) == ssl_hash_sha1) {
- return PR_FALSE;
+ switch (group->name) {
+ case ssl_grp_ec_secp256r1:
+ *scheme = ssl_sig_ecdsa_secp256r1_sha256;
+ return SECSuccess;
+ case ssl_grp_ec_secp384r1:
+ *scheme = ssl_sig_ecdsa_secp384r1_sha384;
+ return SECSuccess;
+ case ssl_grp_ec_secp521r1:
+ *scheme = ssl_sig_ecdsa_secp521r1_sha512;
+ return SECSuccess;
+ default:
+ break;
}
- if (keyType != ecKey) {
- return PR_TRUE;
+ PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
+ return SECFailure;
+}
+
+/* Newer signature schemes are designed so that a single SPKI can be used with
+ * that scheme. This determines that scheme from the SPKI. If the SPKI doesn't
+ * have a single scheme, |*scheme| is set to ssl_sig_none. */
+static SECStatus
+ssl_SignatureSchemeFromSpki(CERTSubjectPublicKeyInfo *spki,
+ PRBool isTls13, SSLSignatureScheme *scheme)
+{
+ SECOidTag spkiOid = SECOID_GetAlgorithmTag(&spki->algorithm);
+
+ if (spkiOid == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
+ return ssl_SignatureSchemeFromPssSpki(spki, scheme);
}
- if (!ecGroup) {
- return PR_FALSE;
+
+ /* Only do this lookup for TLS 1.3, where the scheme can be determined from
+ * the SPKI alone because the ECDSA key size determines the hash. Earlier
+ * TLS versions allow the same EC key to be used with different hashes. */
+ if (isTls13 && spkiOid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
+ return ssl_SignatureSchemeFromEcSpki(spki, scheme);
}
- /* If |allowSha1| is present and the scheme is ssl_sig_ecdsa_sha1, it's OK.
- * This scheme isn't bound to a specific group. */
- if (allowSha1 && (scheme == ssl_sig_ecdsa_sha1)) {
- return PR_TRUE;
+
+ *scheme = ssl_sig_none;
+ return SECSuccess;
+}
+
+static PRBool
+ssl_SignatureSchemeEnabled(sslSocket *ss, SSLSignatureScheme scheme)
+{
+ unsigned int i;
+ for (i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
+ if (scheme == ss->ssl3.signatureSchemes[i]) {
+ return PR_TRUE;
+ }
}
- if (!matchGroup) {
- return PR_TRUE;
+ return PR_FALSE;
+}
+
+static PRBool
+ssl_SignatureKeyMatchesSpkiOid(const ssl3KEADef *keaDef, SECOidTag spkiOid)
+{
+ switch (spkiOid) {
+ case SEC_OID_X500_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_RSA_ENCRYPTION:
+ case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
+ return keaDef->signKeyType == rsaKey;
+ case SEC_OID_ANSIX9_DSA_SIGNATURE:
+ return keaDef->signKeyType == dsaKey;
+ case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
+ return keaDef->signKeyType == ecKey;
+ default:
+ break;
}
- return ecGroup->name == ssl_NamedGroupForSignatureScheme(scheme);
+ return PR_FALSE;
}
-/* ssl3_CheckSignatureSchemeConsistency checks that the signature
- * algorithm identifier in |sigAndHash| is consistent with the public key in
- * |cert|. It also checks the hash algorithm against the configured signature
- * algorithms. If all the tests pass, SECSuccess is returned. Otherwise,
- * PORT_SetError is called and SECFailure is returned. */
+/* ssl3_CheckSignatureSchemeConsistency checks that the signature algorithm
+ * identifier in |scheme| is consistent with the public key in |cert|. It also
+ * checks the hash algorithm against the configured signature algorithms. If
+ * all the tests pass, SECSuccess is returned. Otherwise, PORT_SetError is
+ * called and SECFailure is returned. */
SECStatus
-ssl_CheckSignatureSchemeConsistency(
- sslSocket *ss, SSLSignatureScheme scheme, CERTCertificate *cert)
+ssl_CheckSignatureSchemeConsistency(sslSocket *ss, SSLSignatureScheme scheme,
+ CERTCertificate *cert)
{
- unsigned int i;
- const sslNamedGroupDef *group = NULL;
- SECKEYPublicKey *key;
- KeyType keyType;
+ SSLSignatureScheme spkiScheme;
PRBool isTLS13 = ss->version == SSL_LIBRARY_VERSION_TLS_1_3;
+ SECOidTag spkiOid;
+ SECStatus rv;
- key = CERT_ExtractPublicKey(cert);
- if (key == NULL) {
- ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
+ rv = ssl_SignatureSchemeFromSpki(&cert->subjectPublicKeyInfo, isTLS13,
+ &spkiScheme);
+ if (rv != SECSuccess) {
return SECFailure;
}
-
- keyType = SECKEY_GetPublicKeyType(key);
- if (keyType == ecKey) {
- group = ssl_ECPubKey2NamedGroup(key);
+ if (spkiScheme != ssl_sig_none) {
+ /* The SPKI in the certificate can only be used for a single scheme. */
+ if (spkiScheme != scheme ||
+ !ssl_SignatureSchemeEnabled(ss, scheme)) {
+ PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
+ return SECFailure;
+ }
+ return SECSuccess;
}
- SECKEY_DestroyPublicKey(key);
+
+ spkiOid = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
/* If we're a client, check that the signature algorithm matches the signing
* key type of the cipher suite. */
- if (!isTLS13 &&
- !ss->sec.isServer &&
- ss->ssl3.hs.kea_def->signKeyType != keyType) {
- PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
- return SECFailure;
+ if (!isTLS13 && !ss->sec.isServer) {
+ if (!ssl_SignatureKeyMatchesSpkiOid(ss->ssl3.hs.kea_def, spkiOid)) {
+ PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
+ return SECFailure;
+ }
}
/* Verify that the signature scheme matches the signing key. */
- if (!ssl_SignatureSchemeValidForKey(!isTLS13 /* allowSha1 */,
- isTLS13 /* matchGroup */,
- keyType, group, scheme)) {
+ if (!ssl_SignatureSchemeValid(scheme, spkiOid, isTLS13)) {
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
return SECFailure;
}
- for (i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
- if (scheme == ss->ssl3.signatureSchemes[i]) {
- return SECSuccess;
- }
+ if (!ssl_SignatureSchemeEnabled(ss, scheme)) {
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
+ return SECFailure;
}
- PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
- return SECFailure;
+
+ return SECSuccess;
}
PRBool
@@ -4153,6 +4269,9 @@ ssl_IsSupportedSignatureScheme(SSLSignatureScheme scheme)
case ssl_sig_rsa_pss_rsae_sha256:
case ssl_sig_rsa_pss_rsae_sha384:
case ssl_sig_rsa_pss_rsae_sha512:
+ case ssl_sig_rsa_pss_pss_sha256:
+ case ssl_sig_rsa_pss_pss_sha384:
+ case ssl_sig_rsa_pss_pss_sha512:
case ssl_sig_ecdsa_secp256r1_sha256:
case ssl_sig_ecdsa_secp384r1_sha384:
case ssl_sig_ecdsa_secp521r1_sha512:
@@ -4164,9 +4283,6 @@ ssl_IsSupportedSignatureScheme(SSLSignatureScheme scheme)
return PR_TRUE;
case ssl_sig_rsa_pkcs1_sha1md5:
- case ssl_sig_rsa_pss_pss_sha256:
- case ssl_sig_rsa_pss_pss_sha384:
- case ssl_sig_rsa_pss_pss_sha512:
case ssl_sig_none:
case ssl_sig_ed25519:
case ssl_sig_ed448:
@@ -4182,6 +4298,9 @@ ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme)
case ssl_sig_rsa_pss_rsae_sha256:
case ssl_sig_rsa_pss_rsae_sha384:
case ssl_sig_rsa_pss_rsae_sha512:
+ case ssl_sig_rsa_pss_pss_sha256:
+ case ssl_sig_rsa_pss_pss_sha384:
+ case ssl_sig_rsa_pss_pss_sha512:
return PR_TRUE;
default:
@@ -4190,6 +4309,41 @@ ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme)
return PR_FALSE;
}
+SSLAuthType
+ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
+{
+ switch (scheme) {
+ case ssl_sig_rsa_pkcs1_sha1:
+ case ssl_sig_rsa_pkcs1_sha1md5:
+ case ssl_sig_rsa_pkcs1_sha256:
+ case ssl_sig_rsa_pkcs1_sha384:
+ case ssl_sig_rsa_pkcs1_sha512:
+ /* We report based on the key type for PSS signatures. */
+ case ssl_sig_rsa_pss_rsae_sha256:
+ case ssl_sig_rsa_pss_rsae_sha384:
+ case ssl_sig_rsa_pss_rsae_sha512:
+ return ssl_auth_rsa_sign;
+ case ssl_sig_rsa_pss_pss_sha256:
+ case ssl_sig_rsa_pss_pss_sha384:
+ case ssl_sig_rsa_pss_pss_sha512:
+ return ssl_auth_rsa_pss;
+ case ssl_sig_ecdsa_secp256r1_sha256:
+ case ssl_sig_ecdsa_secp384r1_sha384:
+ case ssl_sig_ecdsa_secp521r1_sha512:
+ case ssl_sig_ecdsa_sha1:
+ return ssl_auth_ecdsa;
+ case ssl_sig_dsa_sha1:
+ case ssl_sig_dsa_sha256:
+ case ssl_sig_dsa_sha384:
+ case ssl_sig_dsa_sha512:
+ return ssl_auth_dsa;
+
+ default:
+ PORT_Assert(0);
+ }
+ return ssl_auth_null;
+}
+
/* ssl_ConsumeSignatureScheme reads a SSLSignatureScheme (formerly
* SignatureAndHashAlgorithm) structure from |b| and puts the resulting value
* into |out|. |b| and |length| are updated accordingly.
@@ -4617,9 +4771,13 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
* If we have an sid and it comes from an external cache, we use it. */
if (ss->sec.ci.sid && ss->sec.ci.sid->cached == in_external_cache) {
PORT_Assert(!ss->sec.isServer);
- sid = ss->sec.ci.sid;
+ sid = ssl_ReferenceSID(ss->sec.ci.sid);
SSL_TRC(3, ("%d: SSL3[%d]: using external resumption token in ClientHello",
SSL_GETPID(), ss->fd));
+ } else if (ss->sec.ci.sid && ss->statelessResume && type == client_hello_retry) {
+ /* If we are sending a second ClientHello, reuse the same SID
+ * as the original one. */
+ sid = ssl_ReferenceSID(ss->sec.ci.sid);
} else if (!ss->opt.noCache) {
/* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup
* handles expired entries and other details.
@@ -4644,7 +4802,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
suite = ssl_LookupCipherSuiteCfg(sid->u.ssl3.cipherSuite,
ss->cipherSuites);
PORT_Assert(suite);
- if (!suite || !config_match(suite, ss->ssl3.policy, &ss->vrange, ss)) {
+ if (!suite || !ssl3_config_match(suite, ss->ssl3.policy, &ss->vrange, ss)) {
sidOK = PR_FALSE;
}
@@ -4765,9 +4923,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
}
ssl_ReleaseSpecWriteLock(ss);
- if (ss->sec.ci.sid != NULL) {
- ssl_FreeSID(ss->sec.ci.sid); /* decrement ref count, free if zero */
- }
+ ssl_FreeSID(ss->sec.ci.sid); /* release the old sid */
ss->sec.ci.sid = sid;
/* HACK for SCSV in SSL 3.0. On initial handshake, prepend SCSV,
@@ -4792,6 +4948,14 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
PR_RWLock_Rlock(sid->u.ssl3.lock);
}
+ /* Generate a new random if this is the first attempt. */
+ if (type == client_hello_initial) {
+ rv = ssl3_GetNewRandom(ss->ssl3.hs.client_random);
+ if (rv != SECSuccess) {
+ goto loser; /* err set by GetNewRandom. */
+ }
+ }
+
if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3 &&
type == client_hello_initial) {
rv = tls13_SetupClientHello(ss);
@@ -4799,6 +4963,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
goto loser;
}
}
+
if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) {
rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_client_hello);
if (rv != SECSuccess) {
@@ -4870,13 +5035,6 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
goto loser; /* err set by ssl3_AppendHandshake* */
}
- /* Generate a new random if this is the first attempt. */
- if (type == client_hello_initial) {
- rv = ssl3_GetNewRandom(ss->ssl3.hs.client_random);
- if (rv != SECSuccess) {
- goto loser; /* err set by GetNewRandom. */
- }
- }
rv = ssl3_AppendHandshake(ss, ss->ssl3.hs.client_random,
SSL3_RANDOM_LENGTH);
if (rv != SECSuccess) {
@@ -4931,7 +5089,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
}
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
- if (config_match(suite, ss->ssl3.policy, &ss->vrange, ss)) {
+ if (ssl3_config_match(suite, ss->ssl3.policy, &ss->vrange, ss)) {
actual_count++;
if (actual_count > num_suites) {
/* set error card removal/insertion error */
@@ -5394,6 +5552,7 @@ ssl3_GetWrappingKey(sslSocket *ss,
switch (authType) {
case ssl_auth_rsa_decrypt:
case ssl_auth_rsa_sign: /* bad: see Bug 1248320 */
+ case ssl_auth_rsa_pss:
asymWrapMechanism = CKM_RSA_PKCS;
rv = PK11_PubWrapSymKey(asymWrapMechanism, svrPubKey,
unwrappedWrappingKey, &wrappedKey);
@@ -5843,20 +6002,59 @@ ssl3_SendClientKeyExchange(sslSocket *ss)
return rv; /* err code already set. */
}
+/* Used by ssl_PickSignatureScheme(). */
+static PRBool
+ssl_CanUseSignatureScheme(SSLSignatureScheme scheme,
+ const SSLSignatureScheme *peerSchemes,
+ unsigned int peerSchemeCount,
+ PRBool requireSha1,
+ PRBool slotDoesPss)
+{
+ SSLHashType hashType;
+ SECOidTag hashOID;
+ PRUint32 policy;
+ unsigned int i;
+
+ /* Skip RSA-PSS schemes when the certificate's private key slot does
+ * not support this signature mechanism. */
+ if (ssl_IsRsaPssSignatureScheme(scheme) && !slotDoesPss) {
+ return PR_FALSE;
+ }
+
+ hashType = ssl_SignatureSchemeToHashType(scheme);
+ if (requireSha1 && (hashType != ssl_hash_sha1)) {
+ return PR_FALSE;
+ }
+ hashOID = ssl3_HashTypeToOID(hashType);
+ if ((NSS_GetAlgorithmPolicy(hashOID, &policy) == SECSuccess) &&
+ !(policy & NSS_USE_ALG_IN_SSL_KX)) {
+ return PR_FALSE;
+ }
+
+ for (i = 0; i < peerSchemeCount; i++) {
+ if (peerSchemes[i] == scheme) {
+ return PR_TRUE;
+ }
+ }
+ return PR_FALSE;
+}
+
SECStatus
ssl_PickSignatureScheme(sslSocket *ss,
+ CERTCertificate *cert,
SECKEYPublicKey *pubKey,
SECKEYPrivateKey *privKey,
const SSLSignatureScheme *peerSchemes,
unsigned int peerSchemeCount,
PRBool requireSha1)
{
- unsigned int i, j;
- const sslNamedGroupDef *group = NULL;
- KeyType keyType;
+ unsigned int i;
PK11SlotInfo *slot;
PRBool slotDoesPss;
PRBool isTLS13 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
+ SECStatus rv;
+ SSLSignatureScheme scheme;
+ SECOidTag spkiOid;
/* We can't require SHA-1 in TLS 1.3. */
PORT_Assert(!(requireSha1 && isTLS13));
@@ -5874,47 +6072,35 @@ ssl_PickSignatureScheme(sslSocket *ss,
slotDoesPss = PK11_DoesMechanism(slot, auth_alg_defs[ssl_auth_rsa_pss]);
PK11_FreeSlot(slot);
- keyType = SECKEY_GetPublicKeyType(pubKey);
- if (keyType == ecKey) {
- group = ssl_ECPubKey2NamedGroup(pubKey);
+ /* If the certificate SPKI indicates a single scheme, don't search. */
+ rv = ssl_SignatureSchemeFromSpki(&cert->subjectPublicKeyInfo,
+ isTLS13, &scheme);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
-
- /* Here we look for the first local preference that the client has
- * indicated support for in their signature_algorithms extension. */
- for (i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
- SSLHashType hashType;
- SECOidTag hashOID;
- SSLSignatureScheme preferred = ss->ssl3.signatureSchemes[i];
- PRUint32 policy;
-
- if (!ssl_SignatureSchemeValidForKey(!isTLS13 /* allowSha1 */,
- isTLS13 /* matchGroup */,
- keyType, group, preferred)) {
- continue;
+ if (scheme != ssl_sig_none) {
+ if (!ssl_SignatureSchemeEnabled(ss, scheme) ||
+ !ssl_CanUseSignatureScheme(scheme, peerSchemes, peerSchemeCount,
+ requireSha1, slotDoesPss)) {
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
+ return SECFailure;
}
+ ss->ssl3.hs.signatureScheme = scheme;
+ return SECSuccess;
+ }
- /* Skip RSA-PSS schemes when the certificate's private key slot does
- * not support this signature mechanism. */
- if (ssl_IsRsaPssSignatureScheme(preferred) && !slotDoesPss) {
- continue;
- }
+ spkiOid = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
- hashType = ssl_SignatureSchemeToHashType(preferred);
- if (requireSha1 && (hashType != ssl_hash_sha1)) {
- continue;
- }
- hashOID = ssl3_HashTypeToOID(hashType);
- if ((NSS_GetAlgorithmPolicy(hashOID, &policy) == SECSuccess) &&
- !(policy & NSS_USE_ALG_IN_SSL_KX)) {
- /* we ignore hashes we don't support */
- continue;
- }
+ /* Now we have to search based on the key type. Go through our preferred
+ * schemes in order and find the first that can be used. */
+ for (i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
+ scheme = ss->ssl3.signatureSchemes[i];
- for (j = 0; j < peerSchemeCount; j++) {
- if (peerSchemes[j] == preferred) {
- ss->ssl3.hs.signatureScheme = preferred;
- return SECSuccess;
- }
+ if (ssl_SignatureSchemeValid(scheme, spkiOid, isTLS13) &&
+ ssl_CanUseSignatureScheme(scheme, peerSchemes, peerSchemeCount,
+ requireSha1, slotDoesPss)) {
+ ss->ssl3.hs.signatureScheme = scheme;
+ return SECSuccess;
}
}
@@ -5956,17 +6142,19 @@ ssl_PickFallbackSignatureScheme(sslSocket *ss, SECKEYPublicKey *pubKey)
static SECStatus
ssl3_PickServerSignatureScheme(sslSocket *ss)
{
- sslKeyPair *keyPair = ss->sec.serverCert->serverKeyPair;
+ const sslServerCert *cert = ss->sec.serverCert;
PRBool isTLS12 = ss->version >= SSL_LIBRARY_VERSION_TLS_1_2;
if (!isTLS12 || !ssl3_ExtensionNegotiated(ss, ssl_signature_algorithms_xtn)) {
/* If the client didn't provide any signature_algorithms extension then
* we can assume that they support SHA-1: RFC5246, Section 7.4.1.4.1. */
- return ssl_PickFallbackSignatureScheme(ss, keyPair->pubKey);
+ return ssl_PickFallbackSignatureScheme(ss, cert->serverKeyPair->pubKey);
}
/* Sets error code, if needed. */
- return ssl_PickSignatureScheme(ss, keyPair->pubKey, keyPair->privKey,
+ return ssl_PickSignatureScheme(ss, cert->serverCert,
+ cert->serverKeyPair->pubKey,
+ cert->serverKeyPair->privKey,
ss->xtnData.sigSchemes,
ss->xtnData.numSigSchemes,
PR_FALSE /* requireSha1 */);
@@ -5977,23 +6165,18 @@ ssl_PickClientSignatureScheme(sslSocket *ss, const SSLSignatureScheme *schemes,
unsigned int numSchemes)
{
SECKEYPrivateKey *privKey = ss->ssl3.clientPrivateKey;
- SECKEYPublicKey *pubKey;
SECStatus rv;
-
PRBool isTLS13 = (PRBool)ss->version >= SSL_LIBRARY_VERSION_TLS_1_3;
- pubKey = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
+ SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
+
PORT_Assert(pubKey);
- if (!isTLS13 && numSchemes == 0) {
- /* If the server didn't provide any signature algorithms
- * then let's assume they support SHA-1. */
- rv = ssl_PickFallbackSignatureScheme(ss, pubKey);
- SECKEY_DestroyPublicKey(pubKey);
- return rv;
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
+ /* We should have already checked that a signature scheme was
+ * listed in the request. */
+ PORT_Assert(schemes && numSchemes > 0);
}
- PORT_Assert(schemes && numSchemes > 0);
-
if (!isTLS13 &&
(SECKEY_GetPublicKeyType(pubKey) == rsaKey ||
SECKEY_GetPublicKeyType(pubKey) == dsaKey) &&
@@ -6004,7 +6187,8 @@ ssl_PickClientSignatureScheme(sslSocket *ss, const SSLSignatureScheme *schemes,
* older, DSA key size is at most 1024 bits and the hash function must
* be SHA-1.
*/
- rv = ssl_PickSignatureScheme(ss, pubKey, privKey, schemes, numSchemes,
+ rv = ssl_PickSignatureScheme(ss, ss->ssl3.clientCertificate,
+ pubKey, privKey, schemes, numSchemes,
PR_TRUE /* requireSha1 */);
if (rv == SECSuccess) {
SECKEY_DestroyPublicKey(pubKey);
@@ -6013,7 +6197,8 @@ ssl_PickClientSignatureScheme(sslSocket *ss, const SSLSignatureScheme *schemes,
/* If this fails, that's because the peer doesn't advertise SHA-1,
* so fall back to the full negotiation. */
}
- rv = ssl_PickSignatureScheme(ss, pubKey, privKey, schemes, numSchemes,
+ rv = ssl_PickSignatureScheme(ss, ss->ssl3.clientCertificate,
+ pubKey, privKey, schemes, numSchemes,
PR_FALSE /* requireSha1 */);
SECKEY_DestroyPublicKey(pubKey);
return rv;
@@ -6141,7 +6326,7 @@ ssl_ClientSetCipherSuite(sslSocket *ss, SSL3ProtocolVersion version,
ssl3CipherSuiteCfg *suiteCfg = &ss->cipherSuites[i];
if (suite == suiteCfg->cipher_suite) {
SSLVersionRange vrange = { version, version };
- if (!config_match(suiteCfg, ss->ssl3.policy, &vrange, ss)) {
+ if (!ssl3_config_match(suiteCfg, ss->ssl3.policy, &vrange, ss)) {
/* config_match already checks whether the cipher suite is
* acceptable for the version, but the check is repeated here
* in order to give a more precise error code. */
@@ -6201,18 +6386,56 @@ ssl_CheckServerSessionIdCorrectness(sslSocket *ss, SECItem *sidBytes)
/* TLS 1.2: Session ID shouldn't match if we sent a fake. */
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
- return !sentFakeSid || !sidMatch;
+ if (sentFakeSid) {
+ return !sidMatch;
+ }
+ return PR_TRUE;
}
/* TLS 1.3: We sent a session ID. The server's should match. */
- if (sentRealSid || sentFakeSid) {
+ if (!IS_DTLS(ss) && (sentRealSid || sentFakeSid)) {
return sidMatch;
}
- /* TLS 1.3: The server shouldn't send a session ID. */
+ /* TLS 1.3 (no SID)/DTLS 1.3: The server shouldn't send a session ID. */
return sidBytes->len == 0;
}
+static SECStatus
+ssl_CheckServerRandom(sslSocket *ss)
+{
+ /* Check the ServerHello.random per [RFC 8446 Section 4.1.3].
+ *
+ * TLS 1.3 clients receiving a ServerHello indicating TLS 1.2 or below
+ * MUST check that the last 8 bytes are not equal to either of these
+ * values. TLS 1.2 clients SHOULD also check that the last 8 bytes are
+ * not equal to the second value if the ServerHello indicates TLS 1.1 or
+ * below. If a match is found, the client MUST abort the handshake with
+ * an "illegal_parameter" alert.
+ */
+ SSL3ProtocolVersion checkVersion =
+ ss->ssl3.downgradeCheckVersion ? ss->ssl3.downgradeCheckVersion
+ : ss->vrange.max;
+
+ if (checkVersion >= SSL_LIBRARY_VERSION_TLS_1_2 &&
+ checkVersion > ss->version) {
+ /* Both sections use the same sentinel region. */
+ PRUint8 *downgrade_sentinel =
+ ss->ssl3.hs.server_random +
+ SSL3_RANDOM_LENGTH - sizeof(tls13_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))) {
+ return SECFailure;
+ }
+ }
+
+ return SECSuccess;
+}
+
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
* ssl3 ServerHello message.
* Caller must hold Handshake and RecvBuf locks.
@@ -6229,9 +6452,6 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
SSL3AlertDescription desc = illegal_parameter;
const PRUint8 *savedMsg = b;
const PRUint32 savedLength = length;
-#ifndef TLS_1_3_DRAFT_VERSION
- SSL3ProtocolVersion downgradeCheckVersion;
-#endif
SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello handshake",
SSL_GETPID(), ss->fd));
@@ -6341,9 +6561,20 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
goto alert_loser;
}
- /* The server didn't pick 1.3 although we either received a
- * HelloRetryRequest, or we prepared to send early app data. */
+ /* There are three situations in which the server must pick
+ * TLS 1.3.
+ *
+ * 1. We offered ESNI.
+ * 2. We received HRR
+ * 3. We sent early app data.
+ *
+ */
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ if (ss->xtnData.esniPrivateKey) {
+ desc = protocol_version;
+ errCode = SSL_ERROR_UNSUPPORTED_VERSION;
+ goto alert_loser;
+ }
if (isHelloRetry || ss->ssl3.hs.helloRetry) {
/* SSL3_SendAlert() will uncache the SID. */
desc = illegal_parameter;
@@ -6368,39 +6599,19 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
goto alert_loser;
}
-#ifndef TLS_1_3_DRAFT_VERSION
- /* Check the ServerHello.random per
- * [draft-ietf-tls-tls13-11 Section 6.3.1.1].
- *
- * TLS 1.3 clients receiving a TLS 1.2 or below ServerHello MUST check
- * that the top eight octets are not equal to either of these values.
- * TLS 1.2 clients SHOULD also perform this check if the ServerHello
- * indicates TLS 1.1 or below. If a match is found the client MUST
- * abort the handshake with a fatal "illegal_parameter" alert.
- *
- * Disable this test during the TLS 1.3 draft version period.
- */
- downgradeCheckVersion = ss->ssl3.downgradeCheckVersion ? ss->ssl3.downgradeCheckVersion
- : ss->vrange.max;
-
- if (downgradeCheckVersion >= SSL_LIBRARY_VERSION_TLS_1_2 &&
- downgradeCheckVersion > ss->version) {
- /* Both sections use the same sentinel region. */
- PRUint8 *downgrade_sentinel =
- ss->ssl3.hs.server_random +
- SSL3_RANDOM_LENGTH - sizeof(tls13_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))) {
+ if (ss->opt.enableHelloDowngradeCheck
+#ifdef DTLS_1_3_DRAFT_VERSION
+ /* Disable this check while we are on draft DTLS 1.3 versions. */
+ && !IS_DTLS(ss)
+#endif
+ ) {
+ rv = ssl_CheckServerRandom(ss);
+ if (rv != SECSuccess) {
desc = illegal_parameter;
errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO;
goto alert_loser;
}
}
-#endif
/* Finally, now all the version-related checks have passed. */
ss->ssl3.hs.preliminaryInfo |= ssl_preinfo_version;
@@ -6776,12 +6987,12 @@ ssl_HandleDHServerKeyExchange(sslSocket *ss, PRUint8 *b, PRUint32 length)
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
rv = ssl_ConsumeSignatureScheme(ss, &b, &length, &sigScheme);
if (rv != SECSuccess) {
- goto loser; /* malformed or unsupported. */
+ goto alert_loser; /* malformed or unsupported. */
}
rv = ssl_CheckSignatureSchemeConsistency(ss, sigScheme,
ss->sec.peerCert);
if (rv != SECSuccess) {
- goto loser;
+ goto alert_loser;
}
hashAlg = ssl_SignatureSchemeToHashType(sigScheme);
} else {
@@ -7005,7 +7216,8 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena,
SECStatus rv;
SECItem buf;
SSLSignatureScheme *schemes = NULL;
- unsigned int numSchemes = 0;
+ unsigned int numSupported = 0;
+ unsigned int numRemaining = 0;
unsigned int max;
rv = ssl3_ExtConsumeHandshakeVariable(ss, &buf, 2, b, len);
@@ -7024,7 +7236,8 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena,
}
/* Limit the number of schemes we read. */
- max = PR_MIN(buf.len / 2, MAX_SIGNATURE_SCHEMES);
+ numRemaining = buf.len / 2;
+ max = PR_MIN(numRemaining, MAX_SIGNATURE_SCHEMES);
if (arena) {
schemes = PORT_ArenaZNewArray(arena, SSLSignatureScheme, max);
@@ -7036,7 +7249,7 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena,
return SECFailure;
}
- for (; max; --max) {
+ for (; numRemaining && numSupported < MAX_SIGNATURE_SCHEMES; --numRemaining) {
PRUint32 tmp;
rv = ssl3_ExtConsumeHandshakeNumber(ss, &tmp, 2, &buf.data, &buf.len);
if (rv != SECSuccess) {
@@ -7045,11 +7258,11 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena,
return SECFailure;
}
if (ssl_IsSupportedSignatureScheme((SSLSignatureScheme)tmp)) {
- schemes[numSchemes++] = (SSLSignatureScheme)tmp;
+ schemes[numSupported++] = (SSLSignatureScheme)tmp;
}
}
- if (!numSchemes) {
+ if (!numSupported) {
if (!arena) {
PORT_Free(schemes);
}
@@ -7058,7 +7271,7 @@ ssl_ParseSignatureSchemes(const sslSocket *ss, PLArenaPool *arena,
done:
*schemesOut = schemes;
- *numSchemesOut = numSchemes;
+ *numSchemesOut = numSupported;
return SECSuccess;
}
@@ -7114,6 +7327,11 @@ ssl3_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length)
PORT_SetError(SSL_ERROR_RX_MALFORMED_CERT_REQUEST);
goto loser; /* malformed, alert has been sent */
}
+ if (signatureSchemeCount == 0) {
+ errCode = SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM;
+ desc = handshake_failure;
+ goto alert_loser;
+ }
}
rv = ssl3_ParseCertificateRequestCAs(ss, &b, &length, &ca_list);
@@ -7239,16 +7457,25 @@ ssl3_CheckFalseStart(sslSocket *ss)
SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start",
SSL_GETPID(), ss->fd));
} else {
- PRBool maybeFalseStart;
+ PRBool maybeFalseStart = PR_TRUE;
SECStatus rv;
+ rv = ssl_CheckServerRandom(ss);
+ if (rv != SECSuccess) {
+ SSL_TRC(3, ("%d: SSL[%d]: no false start due to possible downgrade",
+ SSL_GETPID(), ss->fd));
+ maybeFalseStart = PR_FALSE;
+ }
+
/* An attacker can control the selected ciphersuite so we only wish to
* do False Start in the case that the selected ciphersuite is
* sufficiently strong that the attack can gain no advantage.
* Therefore we always require an 80-bit cipher. */
- ssl_GetSpecReadLock(ss);
- maybeFalseStart = ss->ssl3.cwSpec->cipherDef->secret_key_size >= 10;
- ssl_ReleaseSpecReadLock(ss);
+ if (maybeFalseStart) {
+ ssl_GetSpecReadLock(ss);
+ maybeFalseStart = ss->ssl3.cwSpec->cipherDef->secret_key_size >= 10;
+ ssl_ReleaseSpecReadLock(ss);
+ }
if (!maybeFalseStart) {
SSL_TRC(3, ("%d: SSL[%d]: no false start due to weak cipher",
@@ -7647,6 +7874,30 @@ ssl3_KEASupportsTickets(const ssl3KEADef *kea_def)
return PR_TRUE;
}
+SECStatus
+ssl3_NegotiateCipherSuiteInner(sslSocket *ss, const SECItem *suites,
+ PRUint16 version, PRUint16 *suitep)
+{
+ unsigned int j;
+ unsigned int i;
+
+ for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
+ ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
+ SSLVersionRange vrange = { version, version };
+ 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;
+ }
+ }
+ }
+ return SECFailure;
+}
+
/* Select a cipher suite.
**
** NOTE: This suite selection algorithm should be the same as the one in
@@ -7665,24 +7916,16 @@ SECStatus
ssl3_NegotiateCipherSuite(sslSocket *ss, const SECItem *suites,
PRBool initHashes)
{
- unsigned int j;
- unsigned int i;
+ PRUint16 selected;
+ SECStatus rv;
- for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
- ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
- SSLVersionRange vrange = { ss->version, ss->version };
- if (!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) {
- ss->ssl3.hs.cipher_suite = suite_i;
- return ssl3_SetupCipherSuite(ss, initHashes);
- }
- }
+ rv = ssl3_NegotiateCipherSuiteInner(ss, suites, ss->version, &selected);
+ if (rv != SECSuccess) {
+ return SECFailure;
}
- return SECFailure;
+
+ ss->ssl3.hs.cipher_suite = selected;
+ return ssl3_SetupCipherSuite(ss, initHashes);
}
/*
@@ -7814,9 +8057,12 @@ ssl3_ServerCallSNICallback(sslSocket *ss)
}
/* Need to tell the client that application has picked
* the name from the offered list and reconfigured the socket.
+ * Don't do this if we negotiated ESNI.
*/
- ssl3_RegisterExtensionSender(ss, &ss->xtnData, ssl_server_name_xtn,
- ssl_SendEmptyExtension);
+ if (!ssl3_ExtensionNegotiated(ss, ssl_tls13_encrypted_sni_xtn)) {
+ ssl3_RegisterExtensionSender(ss, &ss->xtnData, ssl_server_name_xtn,
+ ssl_SendEmptyExtension);
+ }
} else {
/* Callback returned index outside of the boundary. */
PORT_Assert((unsigned int)ret < ss->xtnData.sniNameArrSize);
@@ -7845,6 +8091,7 @@ ssl3_SelectServerCert(sslSocket *ss)
{
const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def;
PRCList *cursor;
+ SECStatus rv;
/* If the client didn't include the supported groups extension, assume just
* P-256 support and disable all the other ECDHE groups. This also affects
@@ -7870,30 +8117,102 @@ ssl3_SelectServerCert(sslSocket *ss)
cursor != &ss->serverCerts;
cursor = PR_NEXT_LINK(cursor)) {
sslServerCert *cert = (sslServerCert *)cursor;
- if (!SSL_CERT_IS(cert, kea_def->authKeyType)) {
- continue;
- }
- if (SSL_CERT_IS_EC(cert) &&
- !ssl_NamedGroupEnabled(ss, cert->namedCurve)) {
- continue;
+ if (kea_def->authKeyType == ssl_auth_rsa_sign) {
+ /* We consider PSS certificates here as well for TLS 1.2. */
+ if (!SSL_CERT_IS(cert, ssl_auth_rsa_sign) &&
+ (!SSL_CERT_IS(cert, ssl_auth_rsa_pss) ||
+ ss->version < SSL_LIBRARY_VERSION_TLS_1_2)) {
+ continue;
+ }
+ } else {
+ if (!SSL_CERT_IS(cert, kea_def->authKeyType)) {
+ continue;
+ }
+ if (SSL_CERT_IS_EC(cert) &&
+ !ssl_NamedGroupEnabled(ss, cert->namedCurve)) {
+ continue;
+ }
}
/* Found one. */
ss->sec.serverCert = cert;
- ss->sec.authType = kea_def->authKeyType;
ss->sec.authKeyBits = cert->serverKeyBits;
/* Don't pick a signature scheme if we aren't going to use it. */
if (kea_def->signKeyType == nullKey) {
+ ss->sec.authType = kea_def->authKeyType;
return SECSuccess;
}
- return ssl3_PickServerSignatureScheme(ss);
+
+ rv = ssl3_PickServerSignatureScheme(ss);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ ss->sec.authType =
+ ssl_SignatureSchemeToAuthType(ss->ssl3.hs.signatureScheme);
+ return SECSuccess;
}
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
return SECFailure;
}
+static SECStatus
+ssl_GenerateServerRandom(sslSocket *ss)
+{
+ SECStatus rv = ssl3_GetNewRandom(ss->ssl3.hs.server_random);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ if (ss->version == ss->vrange.max) {
+ return SECSuccess;
+ }
+#ifdef DTLS_1_3_DRAFT_VERSION
+ if (IS_DTLS(ss)) {
+ return SECSuccess;
+ }
+#endif
+
+ /*
+ * [RFC 8446 Section 4.1.3].
+ *
+ * TLS 1.3 servers which negotiate TLS 1.2 or below in response to a
+ * ClientHello MUST set the last 8 bytes of their Random value specially in
+ * their ServerHello.
+ *
+ * If negotiating TLS 1.2, TLS 1.3 servers MUST set the last 8 bytes of
+ * their Random value to the bytes:
+ *
+ * 44 4F 57 4E 47 52 44 01
+ *
+ * If negotiating TLS 1.1 or below, TLS 1.3 servers MUST, and TLS 1.2
+ * servers SHOULD, set the last 8 bytes of their ServerHello.Random value to
+ * the bytes:
+ *
+ * 44 4F 57 4E 47 52 44 00
+ */
+ 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;
+ }
+
+ return SECSuccess;
+}
+
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
* ssl3 Client Hello message.
* Caller must hold Handshake and RecvBuf locks.
@@ -8088,56 +8407,6 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
}
}
- /* Generate the Server Random now so it is available
- * when we process the ClientKeyShare in TLS 1.3 */
- rv = ssl3_GetNewRandom(ss->ssl3.hs.server_random);
- if (rv != SECSuccess) {
- errCode = SSL_ERROR_GENERATE_RANDOM_FAILURE;
- goto loser;
- }
-
-#ifndef TLS_1_3_DRAFT_VERSION
- /*
- * [draft-ietf-tls-tls13-11 Section 6.3.1.1].
- * TLS 1.3 server implementations which respond to a ClientHello with a
- * client_version indicating TLS 1.2 or below MUST set the last eight
- * bytes of their Random value to the bytes:
- *
- * 44 4F 57 4E 47 52 44 01
- *
- * TLS 1.2 server implementations which respond to a ClientHello with a
- * client_version indicating TLS 1.1 or below SHOULD set the last eight
- * bytes of their Random value to the bytes:
- *
- * 44 4F 57 4E 47 52 44 00
- *
- * TODO(ekr@rtfm.com): Note this change was not added in the SSLv2
- * compat processing code since that will most likely be removed before
- * we ship the final version of TLS 1.3. Bug 1306672.
- */
- if (ss->vrange.max > ss->version) {
- PRUint8 *downgrade_sentinel =
- 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(downgrade_sentinel,
- tls13_downgrade_random,
- sizeof(tls13_downgrade_random));
- break;
- case SSL_LIBRARY_VERSION_TLS_1_2:
- PORT_Memcpy(downgrade_sentinel,
- tls12_downgrade_random,
- sizeof(tls12_downgrade_random));
- break;
- default:
- /* Do not change random. */
- break;
- }
- }
-#endif
-
/* If there is a cookie, then this is a second ClientHello (TLS 1.3). */
if (ssl3_FindExtension(ss, ssl_tls13_cookie_xtn)) {
ss->ssl3.hs.helloRetry = PR_TRUE;
@@ -8397,7 +8666,7 @@ ssl3_HandleClientHelloPart2(sslSocket *ss,
* The product policy won't change during the process lifetime.
* Implemented ("isPresent") shouldn't change for servers.
*/
- if (!config_match(suite, ss->ssl3.policy, &vrange, ss))
+ if (!ssl3_config_match(suite, ss->ssl3.policy, &vrange, ss))
break;
#else
if (!suite->enabled)
@@ -8779,7 +9048,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, unsigned int leng
for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) {
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
SSLVersionRange vrange = { ss->version, ss->version };
- if (!config_match(suite, ss->ssl3.policy, &vrange, ss)) {
+ if (!ssl3_config_match(suite, ss->ssl3.policy, &vrange, ss)) {
continue;
}
for (i = 0; i + 2 < suite_length; i += 3) {
@@ -8884,6 +9153,7 @@ ssl_ConstructServerHello(sslSocket *ss, PRBool helloRetry,
SECStatus rv;
SSL3ProtocolVersion version;
sslSessionID *sid = ss->sec.ci.sid;
+ const PRUint8 *random;
version = PR_MIN(ss->version, SSL_LIBRARY_VERSION_TLS_1_2);
if (IS_DTLS(ss)) {
@@ -8893,9 +9163,17 @@ ssl_ConstructServerHello(sslSocket *ss, PRBool helloRetry,
if (rv != SECSuccess) {
return SECFailure;
}
- /* Random already generated in ssl3_HandleClientHello */
- rv = sslBuffer_Append(messageBuf, helloRetry ? ssl_hello_retry_random : ss->ssl3.hs.server_random,
- SSL3_RANDOM_LENGTH);
+
+ if (helloRetry) {
+ random = ssl_hello_retry_random;
+ } else {
+ rv = ssl_GenerateServerRandom(ss);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ random = ss->ssl3.hs.server_random;
+ }
+ rv = sslBuffer_Append(messageBuf, random, SSL3_RANDOM_LENGTH);
if (rv != SECSuccess) {
return SECFailure;
}
@@ -9368,7 +9646,7 @@ ssl3_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length)
ss->sec.peerCert);
if (rv != SECSuccess) {
errCode = PORT_GetError();
- desc = decrypt_error;
+ desc = illegal_parameter;
goto alert_loser;
}
@@ -9501,6 +9779,23 @@ ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
return pms;
}
+static void
+ssl3_CSwapPK11SymKey(PK11SymKey **x, PK11SymKey **y, PRBool c)
+{
+ uintptr_t mask = (uintptr_t)c;
+ unsigned int i;
+ for (i = 1; i < sizeof(uintptr_t) * 8; i <<= 1) {
+ mask |= mask << i;
+ }
+ uintptr_t x_ptr = (uintptr_t)*x;
+ uintptr_t y_ptr = (uintptr_t)*y;
+ uintptr_t tmp = (x_ptr ^ y_ptr) & mask;
+ x_ptr = x_ptr ^ tmp;
+ y_ptr = y_ptr ^ tmp;
+ *x = (PK11SymKey *)x_ptr;
+ *y = (PK11SymKey *)y_ptr;
+}
+
/* Note: The Bleichenbacher attack on PKCS#1 necessitates that we NEVER
* return any indication of failure of the Client Key Exchange message,
* where that failure is caused by the content of the client's message.
@@ -9521,9 +9816,9 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
{
SECStatus rv;
SECItem enc_pms;
- PK11SymKey *tmpPms[2] = { NULL, NULL };
- PK11SlotInfo *slot;
- int useFauxPms = 0;
+ PK11SymKey *pms = NULL;
+ PK11SymKey *fauxPms = NULL;
+ PK11SlotInfo *slot = NULL;
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
@@ -9544,11 +9839,6 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
}
}
-#define currentPms tmpPms[!useFauxPms]
-#define unusedPms tmpPms[useFauxPms]
-#define realPms tmpPms[1]
-#define fauxPms tmpPms[0]
-
/*
* Get as close to algorithm 2 from RFC 5246; Section 7.4.7.1
* as we can within the constraints of the PKCS#11 interface.
@@ -9603,40 +9893,33 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss,
* the unwrap. Rather, it is the mechanism with which the
* unwrapped pms will be used.
*/
- realPms = PK11_PubUnwrapSymKey(serverKeyPair->privKey, &enc_pms,
- CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0);
+ pms = PK11_PubUnwrapSymKey(serverKeyPair->privKey, &enc_pms,
+ CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0);
/* Temporarily use the PMS if unwrapping the real PMS fails. */
- useFauxPms |= (realPms == NULL);
+ ssl3_CSwapPK11SymKey(&pms, &fauxPms, pms == NULL);
/* Attempt to derive the MS from the PMS. This is the only way to
* check the version field in the RSA PMS. If this fails, we
* then use the faux PMS in place of the PMS. Note that this
* operation should never fail if we are using the faux PMS
* since it is correctly formatted. */
- rv = ssl3_ComputeMasterSecret(ss, currentPms, NULL);
-
- /* If we succeeded, then select the true PMS and discard the
- * FPMS. Else, select the FPMS and select the true PMS */
- useFauxPms |= (rv != SECSuccess);
+ rv = ssl3_ComputeMasterSecret(ss, pms, NULL);
- if (unusedPms) {
- PK11_FreeSymKey(unusedPms);
- }
+ /* If we succeeded, then select the true PMS, else select the FPMS. */
+ ssl3_CSwapPK11SymKey(&pms, &fauxPms, (rv != SECSuccess) & (fauxPms != NULL));
/* This step will derive the MS from the PMS, among other things. */
- rv = ssl3_InitPendingCipherSpecs(ss, currentPms, PR_TRUE);
- PK11_FreeSymKey(currentPms);
+ rv = ssl3_InitPendingCipherSpecs(ss, pms, PR_TRUE);
+
+ /* Clear both PMS. */
+ PK11_FreeSymKey(pms);
+ PK11_FreeSymKey(fauxPms);
if (rv != SECSuccess) {
(void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */
}
-#undef currentPms
-#undef unusedPms
-#undef realPms
-#undef fauxPms
-
return SECSuccess;
}
@@ -10429,6 +10712,9 @@ ssl3_AuthCertificate(sslSocket *ss)
PR_TRUE, isServer);
if (rv != SECSuccess) {
errCode = PORT_GetError();
+ if (errCode == 0) {
+ errCode = SSL_ERROR_BAD_CERTIFICATE;
+ }
if (rv != SECWouldBlock) {
if (ss->handleBadCert) {
rv = (*ss->handleBadCert)(ss->badCertArg, ss->fd);
@@ -11252,7 +11538,7 @@ ssl3_FinishHandshake(sslSocket *ss)
}
SECStatus
-ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType type,
+ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType ct,
PRUint32 dtlsSeq,
const PRUint8 *b, PRUint32 length)
{
@@ -11262,7 +11548,7 @@ ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType type,
PRINT_BUF(50, (ss, "Hash handshake message:", b, length));
- hdr[0] = (PRUint8)type;
+ hdr[0] = (PRUint8)ct;
hdr[1] = (PRUint8)(length >> 16);
hdr[2] = (PRUint8)(length >> 8);
hdr[3] = (PRUint8)(length);
@@ -11302,10 +11588,10 @@ ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType type,
}
SECStatus
-ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType type,
+ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType ct,
const PRUint8 *b, PRUint32 length)
{
- return ssl_HashHandshakeMessageInt(ss, type, ss->ssl3.hs.recvMessageSeq,
+ return ssl_HashHandshakeMessageInt(ss, ct, ss->ssl3.hs.recvMessageSeq,
b, length);
}
@@ -11885,7 +12171,7 @@ ssl3_UnprotectRecord(sslSocket *ss,
PRBool isTLS;
unsigned int good;
unsigned int ivLen = 0;
- SSL3ContentType rType;
+ SSLContentType rType;
SSL3ProtocolVersion rVersion;
unsigned int minLength;
unsigned int originalLen = 0;
@@ -11959,7 +12245,7 @@ ssl3_UnprotectRecord(sslSocket *ss,
return SECFailure;
}
- rType = (SSL3ContentType)cText->hdr[0];
+ rType = (SSLContentType)cText->hdr[0];
rVersion = ((SSL3ProtocolVersion)cText->hdr[1] << 8) |
(SSL3ProtocolVersion)cText->hdr[2];
if (cipher_def->type == type_aead) {
@@ -12071,7 +12357,7 @@ ssl3_UnprotectRecord(sslSocket *ss,
}
SECStatus
-ssl3_HandleNonApplicationData(sslSocket *ss, SSL3ContentType rType,
+ssl3_HandleNonApplicationData(sslSocket *ss, SSLContentType rType,
DTLSEpoch epoch, sslSequenceNumber seqNum,
sslBuffer *databuf)
{
@@ -12089,20 +12375,20 @@ ssl3_HandleNonApplicationData(sslSocket *ss, SSL3ContentType rType,
** they return SECFailure or SECWouldBlock.
*/
switch (rType) {
- case content_change_cipher_spec:
+ case ssl_ct_change_cipher_spec:
rv = ssl3_HandleChangeCipherSpecs(ss, databuf);
break;
- case content_alert:
+ case ssl_ct_alert:
rv = ssl3_HandleAlert(ss, databuf);
break;
- case content_handshake:
+ case ssl_ct_handshake:
if (!IS_DTLS(ss)) {
rv = ssl3_HandleHandshake(ss, databuf);
} else {
rv = dtls_HandleHandshake(ss, epoch, seqNum, databuf);
}
break;
- case content_ack:
+ case ssl_ct_ack:
if (IS_DTLS(ss) && tls13_MaybeTls13(ss)) {
rv = dtls13_HandleAck(ss, databuf);
break;
@@ -12190,7 +12476,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
ssl3CipherSpec *spec = NULL;
PRUint16 recordSizeLimit;
PRBool outOfOrderSpec = PR_FALSE;
- SSL3ContentType rType;
+ SSLContentType rType;
sslBuffer *plaintext = &ss->gs.buf;
SSL3AlertDescription alert = internal_error;
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
@@ -12208,7 +12494,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
/* We're waiting for another ClientHello, which will appear unencrypted.
* Use the content type to tell whether this should be discarded. */
if (ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_hrr &&
- cText->hdr[0] == content_application_data) {
+ cText->hdr[0] == ssl_ct_application_data) {
PORT_Assert(ss->ssl3.hs.ws == wait_client_hello);
return SECSuccess;
}
@@ -12269,7 +12555,7 @@ 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 == content_application_data) {
+ if (spec->epoch == 0 && rType == ssl_ct_application_data) {
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA);
alert = unexpected_message;
rv = SECFailure;
@@ -12304,7 +12590,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
* 0-RTT session that is resumed from a session that did negotiate it.
* We don't care about that corner case right now. */
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
- cText->hdr[0] == content_change_cipher_spec &&
+ cText->hdr[0] == ssl_ct_change_cipher_spec &&
ss->ssl3.hs.ws != idle_handshake &&
cText->buf->len == 1 &&
cText->buf->buf[0] == change_cipher_spec_choice) {
@@ -12364,7 +12650,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
/* Application data records are processed by the caller of this
** function, not by this function.
*/
- if (rType == content_application_data) {
+ if (rType == ssl_ct_application_data) {
if (ss->firstHsDone)
return SECSuccess;
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&