diff options
Diffstat (limited to 'security/nss/lib/ssl/ssl3con.c')
-rw-r--r-- | security/nss/lib/ssl/ssl3con.c | 1004 |
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 && |