aboutsummaryrefslogtreecommitdiff
path: root/ssl
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@google.com>2021-02-25 01:37:16 -0500
committerBoringssl LUCI CQ <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com>2024-06-18 01:47:29 +0000
commit66d274dfbab9e4f84599f06504987c418ca087d9 (patch)
tree92fcba5c66690cc9cf1a3008c3f4f5ab8a827d35 /ssl
parente1d209d4432846d28c31d84f269f4edcb9a63509 (diff)
downloadboringssl-66d274dfbab9e4f84599f06504987c418ca087d9.zip
boringssl-66d274dfbab9e4f84599f06504987c418ca087d9.tar.gz
boringssl-66d274dfbab9e4f84599f06504987c418ca087d9.tar.bz2
Implement rsa_pkcs1_sha256_legacy.
See draft-ietf-tls13-pkcs1-00. The code point is disabled by default and must be configured in SSL_set_verify_algorithm_prefs and SSL_set_signing_algorithm_prefs. It is also only defined for TLS 1.3 client certificates and otherwise ignored. This required reworking the tests a bit since this is the first signature algorithm that's disabled by default, and the first algorithm that behaves differently between client and server. Bug: 347047841 Change-Id: If4f653a456799ed9f0173159da291a9b6b6556fb Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/69368 Auto-Submit: David Benjamin <davidben@google.com> Reviewed-by: Bob Beck <bbe@google.com> Commit-Queue: David Benjamin <davidben@google.com>
Diffstat (limited to 'ssl')
-rw-r--r--ssl/extensions.cc5
-rw-r--r--ssl/internal.h2
-rw-r--r--ssl/ssl_privkey.cc79
-rw-r--r--ssl/test/runner/common.go3
-rw-r--r--ssl/test/runner/handshake_client.go14
-rw-r--r--ssl/test/runner/handshake_server.go8
-rw-r--r--ssl/test/runner/key_agreement.go10
-rw-r--r--ssl/test/runner/runner.go206
-rw-r--r--ssl/test/runner/sign.go23
9 files changed, 230 insertions, 120 deletions
diff --git a/ssl/extensions.cc b/ssl/extensions.cc
index 586edbd..3f35276 100644
--- a/ssl/extensions.cc
+++ b/ssl/extensions.cc
@@ -446,7 +446,7 @@ bool tls12_check_peer_sigalg(const SSL_HANDSHAKE *hs, uint8_t *out_alert,
// key, the TLS version, and what we advertised.
Span<const uint16_t> sigalgs = tls12_get_verify_sigalgs(hs);
if (std::find(sigalgs.begin(), sigalgs.end(), sigalg) == sigalgs.end() ||
- !ssl_pkey_supports_algorithm(hs->ssl, pkey, sigalg)) {
+ !ssl_pkey_supports_algorithm(hs->ssl, pkey, sigalg, /*is_verify=*/true)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
return false;
@@ -4149,7 +4149,8 @@ bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs,
? MakeConstSpan(kSignSignatureAlgorithms)
: cred->sigalgs;
for (uint16_t sigalg : sigalgs) {
- if (!ssl_pkey_supports_algorithm(ssl, cred->pubkey.get(), sigalg)) {
+ if (!ssl_pkey_supports_algorithm(ssl, cred->pubkey.get(), sigalg,
+ /*is_verify=*/false)) {
continue;
}
diff --git a/ssl/internal.h b/ssl/internal.h
index 7145d13..2e44641 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1094,7 +1094,7 @@ enum ssl_private_key_result_t ssl_private_key_decrypt(SSL_HANDSHAKE *hs,
// ssl_pkey_supports_algorithm returns whether |pkey| may be used to sign
// |sigalg|.
bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
- uint16_t sigalg);
+ uint16_t sigalg, bool is_verify);
// ssl_public_key_verify verifies that the |signature| is valid for the public
// key |pkey| and input |in|, using the signature algorithm |sigalg|.
diff --git a/ssl/ssl_privkey.cc b/ssl/ssl_privkey.cc
index 9cf2c8f..471be76 100644
--- a/ssl/ssl_privkey.cc
+++ b/ssl/ssl_privkey.cc
@@ -85,29 +85,61 @@ typedef struct {
int curve;
const EVP_MD *(*digest_func)(void);
bool is_rsa_pss;
+ bool tls12_ok;
+ bool tls13_ok;
+ bool client_only;
} SSL_SIGNATURE_ALGORITHM;
static const SSL_SIGNATURE_ALGORITHM kSignatureAlgorithms[] = {
+ // PKCS#1 v1.5 code points are only allowed in TLS 1.2.
{SSL_SIGN_RSA_PKCS1_MD5_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_md5_sha1,
- false},
- {SSL_SIGN_RSA_PKCS1_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_sha1, false},
- {SSL_SIGN_RSA_PKCS1_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, false},
- {SSL_SIGN_RSA_PKCS1_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, false},
- {SSL_SIGN_RSA_PKCS1_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, false},
-
- {SSL_SIGN_RSA_PSS_RSAE_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, true},
- {SSL_SIGN_RSA_PSS_RSAE_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, true},
- {SSL_SIGN_RSA_PSS_RSAE_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, true},
-
- {SSL_SIGN_ECDSA_SHA1, EVP_PKEY_EC, NID_undef, &EVP_sha1, false},
+ /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
+ /*client_only=*/false},
+ {SSL_SIGN_RSA_PKCS1_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_sha1,
+ /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
+ /*client_only=*/false},
+ {SSL_SIGN_RSA_PKCS1_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256,
+ /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
+ /*client_only=*/false},
+ {SSL_SIGN_RSA_PKCS1_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384,
+ /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
+ /*client_only=*/false},
+ {SSL_SIGN_RSA_PKCS1_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512,
+ /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
+ /*client_only=*/false},
+
+ // Legacy PKCS#1 v1.5 code points are only allowed in TLS 1.3 and
+ // client-only. See draft-ietf-tls-tls13-pkcs1-00.
+ {SSL_SIGN_RSA_PKCS1_SHA256_LEGACY, EVP_PKEY_RSA, NID_undef, &EVP_sha256,
+ /*is_rsa_pss=*/false, /*tls12_ok=*/false, /*tls13_ok=*/true,
+ /*client_only=*/true},
+
+ {SSL_SIGN_RSA_PSS_RSAE_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256,
+ /*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true,
+ /*client_only=*/false},
+ {SSL_SIGN_RSA_PSS_RSAE_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384,
+ /*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true,
+ /*client_only=*/false},
+ {SSL_SIGN_RSA_PSS_RSAE_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512,
+ /*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true,
+ /*client_only=*/false},
+
+ {SSL_SIGN_ECDSA_SHA1, EVP_PKEY_EC, NID_undef, &EVP_sha1,
+ /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false,
+ /*client_only=*/false},
{SSL_SIGN_ECDSA_SECP256R1_SHA256, EVP_PKEY_EC, NID_X9_62_prime256v1,
- &EVP_sha256, false},
+ &EVP_sha256, /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true,
+ /*client_only=*/false},
{SSL_SIGN_ECDSA_SECP384R1_SHA384, EVP_PKEY_EC, NID_secp384r1, &EVP_sha384,
- false},
+ /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true,
+ /*client_only=*/false},
{SSL_SIGN_ECDSA_SECP521R1_SHA512, EVP_PKEY_EC, NID_secp521r1, &EVP_sha512,
- false},
+ /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true,
+ /*client_only=*/false},
- {SSL_SIGN_ED25519, EVP_PKEY_ED25519, NID_undef, nullptr, false},
+ {SSL_SIGN_ED25519, EVP_PKEY_ED25519, NID_undef, nullptr,
+ /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true,
+ /*client_only=*/false},
};
static const SSL_SIGNATURE_ALGORITHM *get_signature_algorithm(uint16_t sigalg) {
@@ -120,7 +152,7 @@ static const SSL_SIGNATURE_ALGORITHM *get_signature_algorithm(uint16_t sigalg) {
}
bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
- uint16_t sigalg) {
+ uint16_t sigalg, bool is_verify) {
const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
if (alg == NULL || EVP_PKEY_id(pkey) != alg->pkey_type) {
return false;
@@ -152,8 +184,12 @@ bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
}
if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
- // RSA keys may only be used with RSA-PSS.
- if (alg->pkey_type == EVP_PKEY_RSA && !alg->is_rsa_pss) {
+ if (!alg->tls13_ok) {
+ return false;
+ }
+
+ bool is_client_sign = ssl->server == is_verify;
+ if (alg->client_only && !is_client_sign) {
return false;
}
@@ -164,6 +200,8 @@ bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey))) != alg->curve)) {
return false;
}
+ } else if (!alg->tls12_ok) {
+ return false;
}
return true;
@@ -171,7 +209,7 @@ bool ssl_pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
static bool setup_ctx(SSL *ssl, EVP_MD_CTX *ctx, EVP_PKEY *pkey,
uint16_t sigalg, bool is_verify) {
- if (!ssl_pkey_supports_algorithm(ssl, pkey, sigalg)) {
+ if (!ssl_pkey_supports_algorithm(ssl, pkey, sigalg, is_verify)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return false;
}
@@ -448,7 +486,7 @@ void SSL_CTX_set_private_key_method(SSL_CTX *ctx,
ctx->cert->default_credential.get(), key_method));
}
-static constexpr size_t kMaxSignatureAlgorithmNameLen = 23;
+static constexpr size_t kMaxSignatureAlgorithmNameLen = 24;
struct SignatureAlgorithmName {
uint16_t signature_algorithm;
@@ -461,6 +499,7 @@ static const SignatureAlgorithmName kSignatureAlgorithmNames[] = {
{SSL_SIGN_RSA_PKCS1_MD5_SHA1, "rsa_pkcs1_md5_sha1"},
{SSL_SIGN_RSA_PKCS1_SHA1, "rsa_pkcs1_sha1"},
{SSL_SIGN_RSA_PKCS1_SHA256, "rsa_pkcs1_sha256"},
+ {SSL_SIGN_RSA_PKCS1_SHA256_LEGACY, "rsa_pkcs1_sha256_legacy"},
{SSL_SIGN_RSA_PKCS1_SHA384, "rsa_pkcs1_sha384"},
{SSL_SIGN_RSA_PKCS1_SHA512, "rsa_pkcs1_sha512"},
{SSL_SIGN_ECDSA_SHA1, "ecdsa_sha1"},
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 1681c2b..3a8caa1 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -215,6 +215,9 @@ const (
signatureEd25519 signatureAlgorithm = 0x0807
signatureEd448 signatureAlgorithm = 0x0808
+ // draft-ietf-tls-tls13-pkcs1-00
+ signatureRSAPKCS1WithSHA256Legacy signatureAlgorithm = 0x0420
+
// signatureRSAPKCS1WithMD5AndSHA1 is the internal value BoringSSL uses to
// represent the TLS 1.0/1.1 RSA MD5/SHA1 concatenation. We define the
// constant here to test that this doesn't leak into the protocol.
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 7172b3d..a0a81f9 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -1300,9 +1300,9 @@ func (hs *clientHandshakeState) doTLS13Handshake(msg any) error {
c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
if c.peerDelegatedCredential != nil {
- err = verifyMessageDC(c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
+ err = verifyMessageDC(c.isClient, c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
} else {
- err = verifyMessage(c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
+ err = verifyMessage(c.isClient, c.vers, hs.peerPublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
}
if err != nil {
return err
@@ -1452,7 +1452,7 @@ func (hs *clientHandshakeState) doTLS13Handshake(msg any) error {
// Determine the hash to sign.
var err error
- certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, credential, c.config, certReq.signatureAlgorithms)
+ certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, credential, c.config, certReq.signatureAlgorithms)
if err != nil {
c.sendAlert(alertInternalError)
return err
@@ -1460,7 +1460,7 @@ func (hs *clientHandshakeState) doTLS13Handshake(msg any) error {
privKey := credential.PrivateKey
input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
- certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
+ certVerify.signature, err = signMessage(c.isClient, c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
if err != nil {
c.sendAlert(alertInternalError)
return err
@@ -1765,7 +1765,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
// Determine the hash to sign.
if certVerify.hasSignatureAlgorithm {
- certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, credential, c.config, certReq.signatureAlgorithms)
+ certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, credential, c.config, certReq.signatureAlgorithms)
if err != nil {
c.sendAlert(alertInternalError)
return err
@@ -1773,7 +1773,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
}
privKey := c.config.Credential.PrivateKey
- certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
+ certVerify.signature, err = signMessage(c.isClient, c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
}
@@ -1885,7 +1885,7 @@ func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) erro
}
signedMsg := delegatedCredentialSignedMessage(dc.signedBytes, dc.algorithm, certs[0].Raw)
- if err := verifyMessage(c.vers, leafPublicKey, c.config, dc.algorithm, signedMsg, dc.signature); err != nil {
+ if err := verifyMessage(c.isClient, c.vers, leafPublicKey, c.config, dc.algorithm, signedMsg, dc.signature); err != nil {
c.sendAlert(alertBadCertificate)
return errors.New("tls: failed to verify delegated credential: " + err.Error())
}
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 7459b5b..2e87d54 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -1169,7 +1169,7 @@ ResendHelloRetryRequest:
// Determine the hash to sign.
var err error
- certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, hs.cert, config, hs.clientHello.signatureAlgorithms)
+ certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, hs.cert, config, hs.clientHello.signatureAlgorithms)
if err != nil {
c.sendAlert(alertInternalError)
return err
@@ -1177,7 +1177,7 @@ ResendHelloRetryRequest:
privKey := hs.cert.PrivateKey
input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
- certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
+ certVerify.signature, err = signMessage(c.isClient, c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
if err != nil {
c.sendAlert(alertInternalError)
return err
@@ -1362,7 +1362,7 @@ ResendHelloRetryRequest:
c.peerSignatureAlgorithm = certVerify.signatureAlgorithm
input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
- if err := verifyMessage(c.vers, pub, config, certVerify.signatureAlgorithm, input, certVerify.signature); err != nil {
+ if err := verifyMessage(c.isClient, c.vers, pub, config, certVerify.signatureAlgorithm, input, certVerify.signature); err != nil {
c.sendAlert(alertBadCertificate)
return err
}
@@ -2093,7 +2093,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
c.peerSignatureAlgorithm = sigAlg
}
- if err := verifyMessage(c.vers, pub, c.config, sigAlg, hs.finishedHash.buffer, certVerify.signature); err != nil {
+ if err := verifyMessage(c.isClient, c.vers, pub, c.config, sigAlg, hs.finishedHash.buffer, certVerify.signature); err != nil {
c.sendAlert(alertBadCertificate)
return errors.New("could not validate signature of connection nonces: " + err.Error())
}
diff --git a/ssl/test/runner/key_agreement.go b/ssl/test/runner/key_agreement.go
index 39377f8..aff0820 100644
--- a/ssl/test/runner/key_agreement.go
+++ b/ssl/test/runner/key_agreement.go
@@ -65,13 +65,13 @@ func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Crede
var sigAlg signatureAlgorithm
if ka.version >= VersionTLS12 {
- sigAlg, err = selectSignatureAlgorithm(ka.version, cert, config, clientHello.signatureAlgorithms)
+ sigAlg, err = selectSignatureAlgorithm(false /* server */, ka.version, cert, config, clientHello.signatureAlgorithms)
if err != nil {
return nil, err
}
}
- sig, err := signMessage(ka.version, cert.PrivateKey, config, sigAlg, serverRSAParams)
+ sig, err := signMessage(false /* server */, ka.version, cert.PrivateKey, config, sigAlg, serverRSAParams)
if err != nil {
return nil, errors.New("failed to sign RSA parameters: " + err.Error())
}
@@ -489,13 +489,13 @@ func (ka *signedKeyAgreement) signParameters(config *Config, cert *Credential, c
var sigAlg signatureAlgorithm
var err error
if ka.version >= VersionTLS12 {
- sigAlg, err = selectSignatureAlgorithm(ka.version, cert, config, clientHello.signatureAlgorithms)
+ sigAlg, err = selectSignatureAlgorithm(false /* server */, ka.version, cert, config, clientHello.signatureAlgorithms)
if err != nil {
return nil, err
}
}
- sig, err := signMessage(ka.version, cert.PrivateKey, config, sigAlg, msg)
+ sig, err := signMessage(false /* server */, ka.version, cert.PrivateKey, config, sigAlg, msg)
if err != nil {
return nil, err
}
@@ -571,7 +571,7 @@ func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clie
}
sig = sig[2:]
- return verifyMessage(ka.version, publicKey, config, sigAlg, msg, sig)
+ return verifyMessage(true /* client */, ka.version, publicKey, config, sigAlg, msg, sig)
}
// ecdheKeyAgreement implements a TLS key agreement where the server
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 2e1b407..3aab605 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -374,7 +374,7 @@ func createDelegatedCredential(parent *Credential, config delegatedCredentialCon
addUint24LengthPrefixedBytes(dc, pubBytes)
var dummyConfig Config
- parentSignature, err := signMessage(VersionTLS13, parent.PrivateKey, &dummyConfig, config.algo, delegatedCredentialSignedMessage(dc.BytesOrPanic(), config.algo, parent.Leaf.Raw))
+ parentSignature, err := signMessage(false /* server */, VersionTLS13, parent.PrivateKey, &dummyConfig, config.algo, delegatedCredentialSignedMessage(dc.BytesOrPanic(), config.algo, parent.Leaf.Raw))
if err != nil {
panic(err)
}
@@ -1738,16 +1738,16 @@ func runTest(dispatcher *shimDispatcher, statusChan chan statusMsg, test *testCa
case failed && !test.shouldFail:
msg = "unexpected failure"
case !failed && test.shouldFail:
- msg = "unexpected success"
+ msg = fmt.Sprintf("unexpected success (wanted failure with %q / %q)", expectedError, test.expectedLocalError)
case failed && !correctFailure:
- msg = "bad error (wanted '" + expectedError + "' / '" + test.expectedLocalError + "')"
+ msg = fmt.Sprintf("bad error (wanted %q / %q)", expectedError, test.expectedLocalError)
case mustFail:
msg = "test failure"
default:
panic("internal error")
}
- return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s\n%s", msg, localErrString, childErrString, stdout, stderr, extraStderr)
+ return fmt.Errorf("%s: local error %q, child error %q, stdout:\n%s\nstderr:\n%s\n%s", msg, localErrString, childErrString, stdout, stderr, extraStderr)
}
if len(extraStderr) > 0 || (!failed && len(stderr) > 0) {
@@ -10016,6 +10016,7 @@ var testSignatureAlgorithms = []struct {
}{
{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, &rsaCertificate, 0},
{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, &rsaCertificate, 0},
+ {"RSA_PKCS1_SHA256_LEGACY", signatureRSAPKCS1WithSHA256Legacy, &rsaCertificate, 0},
{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, &rsaCertificate, 0},
{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, &rsaCertificate, 0},
{"ECDSA_SHA1", signatureECDSAWithSHA1, &ecdsaP256Certificate, CurveP256},
@@ -10070,61 +10071,95 @@ func addSignatureAlgorithmTests() {
continue
}
- var shouldFail, rejectByDefault bool
- // ecdsa_sha1 does not exist in TLS 1.3.
- if ver.version >= VersionTLS13 && alg.id == signatureECDSAWithSHA1 {
- shouldFail = true
- }
- // RSA-PKCS1 does not exist in TLS 1.3.
- if ver.version >= VersionTLS13 && hasComponent(alg.name, "PKCS1") {
- shouldFail = true
- }
- // SHA-224 has been removed from TLS 1.3 and, in 1.3,
- // the curve has to match the hash size.
- if ver.version >= VersionTLS13 && alg.curve == CurveP224 {
- shouldFail = true
- }
+ suffix := "-" + alg.name + "-" + ver.name
+ for _, signTestType := range []testType{clientTest, serverTest} {
+ signPrefix := "Client-"
+ verifyPrefix := "Server-"
+ verifyTestType := serverTest
+ if signTestType == serverTest {
+ verifyTestType = clientTest
+ signPrefix, verifyPrefix = verifyPrefix, signPrefix
+ }
- // By default, BoringSSL does not enable ecdsa_sha1, ecdsa_secp521_sha512, and ed25519.
- if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 {
- rejectByDefault = true
- }
+ var shouldFail bool
+ isTLS12PKCS1 := hasComponent(alg.name, "PKCS1") && !hasComponent(alg.name, "LEGACY")
+ isTLS13PKCS1 := hasComponent(alg.name, "PKCS1") && hasComponent(alg.name, "LEGACY")
- var curveFlags []string
- var runnerCurves []CurveID
- if alg.curve != 0 && ver.version <= VersionTLS12 {
- // In TLS 1.2, the ECDH curve list also constrains ECDSA keys. Ensure the
- // corresponding curve is enabled. Also include X25519 to ensure the shim
- // and runner have something in common for ECDH.
- curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)})
- runnerCurves = []CurveID{CurveX25519, alg.curve}
- }
+ // TLS 1.3 removes a number of signature algorithms.
+ if ver.version >= VersionTLS13 && (alg.curve == CurveP224 || alg.id == signatureECDSAWithSHA1 || isTLS12PKCS1) {
+ shouldFail = true
+ }
- var signError, signLocalError, verifyError, verifyLocalError, defaultError, defaultLocalError string
- if shouldFail {
- signError = ":NO_COMMON_SIGNATURE_ALGORITHMS:"
- signLocalError = "remote error: handshake failure"
- verifyError = ":WRONG_SIGNATURE_TYPE:"
- verifyLocalError = "remote error: illegal parameter"
- rejectByDefault = true
- }
- if rejectByDefault {
- defaultError = ":WRONG_SIGNATURE_TYPE:"
- defaultLocalError = "remote error: illegal parameter"
- }
+ // The backported RSA-PKCS1 code points only exist for TLS 1.3
+ // client certificates.
+ if (ver.version < VersionTLS13 || signTestType == serverTest) && isTLS13PKCS1 {
+ shouldFail = true
+ }
- suffix := "-" + alg.name + "-" + ver.name
+ // By default, BoringSSL does not sign with these algorithms.
+ signDefault := !shouldFail
+ if isTLS13PKCS1 {
+ signDefault = false
+ }
- for _, testType := range []testType{clientTest, serverTest} {
- prefix := "Client-"
- if testType == serverTest {
- prefix = "Server-"
+ // By default, BoringSSL does not accept these algorithms.
+ verifyDefault := !shouldFail
+ if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 || isTLS13PKCS1 {
+ verifyDefault = false
+ }
+
+ var curveFlags []string
+ var runnerCurves []CurveID
+ if alg.curve != 0 && ver.version <= VersionTLS12 {
+ // In TLS 1.2, the ECDH curve list also constrains ECDSA keys. Ensure the
+ // corresponding curve is enabled. Also include X25519 to ensure the shim
+ // and runner have something in common for ECDH.
+ curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)})
+ runnerCurves = []CurveID{CurveX25519, alg.curve}
+ }
+
+ signError := func(shouldFail bool) string {
+ if !shouldFail {
+ return ""
+ }
+ // In TLS 1.3, the shim should report no common signature algorithms if
+ // it cannot generate a signature. In TLS 1.2 servers, signature
+ // algorithm and cipher selection are integrated, so it is reported as
+ // no shared cipher.
+ if ver.version <= VersionTLS12 && signTestType == serverTest {
+ return ":NO_SHARED_CIPHER:"
+ }
+ return ":NO_COMMON_SIGNATURE_ALGORITHMS:"
+ }
+ signLocalError := func(shouldFail bool) string {
+ if !shouldFail {
+ return ""
+ }
+ // The shim should send handshake_failure when it cannot
+ // negotiate parameters.
+ return "remote error: handshake failure"
+ }
+ verifyError := func(shouldFail bool) string {
+ if !shouldFail {
+ return ""
+ }
+ // If the shim rejects the signature algorithm, but the
+ // runner forcibly selects it anyway, the shim should notice.
+ return ":WRONG_SIGNATURE_TYPE:"
+ }
+ verifyLocalError := func(shouldFail bool) string {
+ if !shouldFail {
+ return ""
+ }
+ // The shim should send an illegal_parameter alert if the runner
+ // uses a signature algorithm it isn't allowed to use.
+ return "remote error: illegal parameter"
}
// Test the shim using the algorithm for signing.
signTest := testCase{
- testType: testType,
- name: prefix + "Sign" + suffix,
+ testType: signTestType,
+ name: signPrefix + "Sign" + suffix,
config: Config{
MaxVersion: ver.version,
CurvePreferences: runnerCurves,
@@ -10137,8 +10172,33 @@ func addSignatureAlgorithmTests() {
shimCertificate: cert,
flags: curveFlags,
shouldFail: shouldFail,
- expectedError: signError,
- expectedLocalError: signLocalError,
+ expectedError: signError(shouldFail),
+ expectedLocalError: signLocalError(shouldFail),
+ expectations: connectionExpectations{
+ peerSignatureAlgorithm: alg.id,
+ },
+ }
+
+ // Test whether the shim enables the algorithm by default.
+ signDefaultTest := testCase{
+ testType: signTestType,
+ name: signPrefix + "SignDefault" + suffix,
+ config: Config{
+ MaxVersion: ver.version,
+ CurvePreferences: runnerCurves,
+ VerifySignatureAlgorithms: []signatureAlgorithm{
+ fakeSigAlg1,
+ alg.id,
+ fakeSigAlg2,
+ },
+ },
+ // cert has been configured with the specified algorithm,
+ // while alg.baseCert uses the defaults.
+ shimCertificate: alg.baseCert,
+ flags: curveFlags,
+ shouldFail: !signDefault,
+ expectedError: signError(!signDefault),
+ expectedLocalError: signLocalError(!signDefault),
expectations: connectionExpectations{
peerSignatureAlgorithm: alg.id,
},
@@ -10147,8 +10207,8 @@ func addSignatureAlgorithmTests() {
// Test that the shim will select the algorithm when configured to only
// support it.
negotiateTest := testCase{
- testType: testType,
- name: prefix + "Sign-Negotiate" + suffix,
+ testType: signTestType,
+ name: signPrefix + "Sign-Negotiate" + suffix,
config: Config{
MaxVersion: ver.version,
CurvePreferences: runnerCurves,
@@ -10161,24 +10221,26 @@ func addSignatureAlgorithmTests() {
},
}
- if testType == serverTest {
+ if signTestType == serverTest {
// TLS 1.2 servers only sign on some cipher suites.
signTest.config.CipherSuites = signingCiphers
+ signDefaultTest.config.CipherSuites = signingCiphers
negotiateTest.config.CipherSuites = signingCiphers
} else {
// TLS 1.2 clients only sign when the server requests certificates.
signTest.config.ClientAuth = RequireAnyClientCert
+ signDefaultTest.config.ClientAuth = RequireAnyClientCert
negotiateTest.config.ClientAuth = RequireAnyClientCert
}
- testCases = append(testCases, signTest)
+ testCases = append(testCases, signTest, signDefaultTest)
if ver.version >= VersionTLS12 && !shouldFail {
testCases = append(testCases, negotiateTest)
}
// Test the shim using the algorithm for verifying.
verifyTest := testCase{
- testType: testType,
- name: prefix + "Verify" + suffix,
+ testType: verifyTestType,
+ name: verifyPrefix + "Verify" + suffix,
config: Config{
MaxVersion: ver.version,
Credential: cert,
@@ -10194,8 +10256,8 @@ func addSignatureAlgorithmTests() {
// algorithm is reported on both handshakes.
resumeSession: !shouldFail,
shouldFail: shouldFail,
- expectedError: verifyError,
- expectedLocalError: verifyLocalError,
+ expectedError: verifyError(shouldFail),
+ expectedLocalError: verifyLocalError(shouldFail),
}
if alg.id != 0 {
verifyTest.flags = append(verifyTest.flags, "-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)))
@@ -10205,16 +10267,16 @@ func addSignatureAlgorithmTests() {
// Test whether the shim expects the algorithm enabled by default.
defaultTest := testCase{
- testType: testType,
- name: prefix + "VerifyDefault" + suffix,
+ testType: verifyTestType,
+ name: verifyPrefix + "VerifyDefault" + suffix,
config: Config{
MaxVersion: ver.version,
Credential: cert,
Bugs: ProtocolBugs{
- SkipECDSACurveCheck: rejectByDefault,
- IgnoreSignatureVersionChecks: rejectByDefault,
+ SkipECDSACurveCheck: !verifyDefault,
+ IgnoreSignatureVersionChecks: !verifyDefault,
// Some signature algorithms may not be advertised.
- IgnorePeerSignatureAlgorithmPreferences: rejectByDefault,
+ IgnorePeerSignatureAlgorithmPreferences: !verifyDefault,
},
},
flags: append(
@@ -10223,16 +10285,16 @@ func addSignatureAlgorithmTests() {
),
// Resume the session to assert the peer signature
// algorithm is reported on both handshakes.
- resumeSession: !rejectByDefault,
- shouldFail: rejectByDefault,
- expectedError: defaultError,
- expectedLocalError: defaultLocalError,
+ resumeSession: verifyDefault,
+ shouldFail: !verifyDefault,
+ expectedError: verifyError(!verifyDefault),
+ expectedLocalError: verifyLocalError(!verifyDefault),
}
// Test whether the shim handles invalid signatures for this algorithm.
invalidTest := testCase{
- testType: testType,
- name: prefix + "InvalidSignature" + suffix,
+ testType: verifyTestType,
+ name: verifyPrefix + "InvalidSignature" + suffix,
config: Config{
MaxVersion: ver.version,
Credential: cert,
@@ -10249,7 +10311,7 @@ func addSignatureAlgorithmTests() {
invalidTest.flags = append(invalidTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
}
- if testType == serverTest {
+ if verifyTestType == serverTest {
// TLS 1.2 servers only verify when they request client certificates.
verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate")
defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate")
diff --git a/ssl/test/runner/sign.go b/ssl/test/runner/sign.go
index a57b2e7..65568a3 100644
--- a/ssl/test/runner/sign.go
+++ b/ssl/test/runner/sign.go
@@ -27,7 +27,7 @@ type signer interface {
verifyMessage(key crypto.PublicKey, msg, sig []byte) error
}
-func selectSignatureAlgorithm(version uint16, cred *Credential, config *Config, peerSigAlgs []signatureAlgorithm) (signatureAlgorithm, error) {
+func selectSignatureAlgorithm(isClient bool, version uint16, cred *Credential, config *Config, peerSigAlgs []signatureAlgorithm) (signatureAlgorithm, error) {
// If the client didn't specify any signature_algorithms extension then
// we can assume that it supports SHA1. See
// http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
@@ -40,7 +40,7 @@ func selectSignatureAlgorithm(version uint16, cred *Credential, config *Config,
continue
}
- signer, err := getSigner(version, cred.PrivateKey, config, sigAlg, false)
+ signer, err := getSigner(isClient, version, cred.PrivateKey, config, sigAlg, false)
if err != nil {
continue
}
@@ -52,7 +52,7 @@ func selectSignatureAlgorithm(version uint16, cred *Credential, config *Config,
return 0, errors.New("tls: no common signature algorithms")
}
-func signMessage(version uint16, key crypto.PrivateKey, config *Config, sigAlg signatureAlgorithm, msg []byte) ([]byte, error) {
+func signMessage(isClient bool, version uint16, key crypto.PrivateKey, config *Config, sigAlg signatureAlgorithm, msg []byte) ([]byte, error) {
if config.Bugs.InvalidSignature {
newMsg := make([]byte, len(msg))
copy(newMsg, msg)
@@ -60,7 +60,7 @@ func signMessage(version uint16, key crypto.PrivateKey, config *Config, sigAlg s
msg = newMsg
}
- signer, err := getSigner(version, key, config, sigAlg, false)
+ signer, err := getSigner(isClient, version, key, config, sigAlg, false)
if err != nil {
return nil, err
}
@@ -68,12 +68,12 @@ func signMessage(version uint16, key crypto.PrivateKey, config *Config, sigAlg s
return signer.signMessage(key, config, msg)
}
-func verifyMessage(version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error {
+func verifyMessage(isClient bool, version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error {
if version >= VersionTLS12 && !slices.Contains(config.verifySignatureAlgorithms(), sigAlg) {
return errors.New("tls: unsupported signature algorithm")
}
- signer, err := getSigner(version, key, config, sigAlg, true)
+ signer, err := getSigner(isClient, version, key, config, sigAlg, true)
if err != nil {
return err
}
@@ -81,12 +81,12 @@ func verifyMessage(version uint16, key crypto.PublicKey, config *Config, sigAlg
return signer.verifyMessage(key, msg, sig)
}
-func verifyMessageDC(version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error {
+func verifyMessageDC(isClient bool, version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error {
if version >= VersionTLS12 && !slices.Contains(config.DelegatedCredentialAlgorithms, sigAlg) {
return errors.New("tls: unsupported signature algorithm")
}
- signer, err := getSigner(version, key, config, sigAlg, true)
+ signer, err := getSigner(isClient, version, key, config, sigAlg, true)
if err != nil {
return err
}
@@ -286,7 +286,7 @@ func (e *ed25519Signer) verifyMessage(key crypto.PublicKey, msg, sig []byte) err
return nil
}
-func getSigner(version uint16, key any, config *Config, sigAlg signatureAlgorithm, isVerify bool) (signer, error) {
+func getSigner(isClient bool, version uint16, key any, config *Config, sigAlg signatureAlgorithm, isVerify bool) (signer, error) {
// TLS 1.1 and below use legacy signature algorithms.
if version < VersionTLS12 || (!isVerify && config.Bugs.AlwaysSignAsLegacyVersion) {
if config.Bugs.SigningAlgorithmForLegacyVersions == 0 || isVerify {
@@ -304,6 +304,7 @@ func getSigner(version uint16, key any, config *Config, sigAlg signatureAlgorith
sigAlg = config.Bugs.SigningAlgorithmForLegacyVersions
}
+ isClientSign := isClient != isVerify
switch sigAlg {
case signatureRSAPKCS1WithMD5:
if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
@@ -325,6 +326,10 @@ func getSigner(version uint16, key any, config *Config, sigAlg signatureAlgorith
if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
return &rsaPKCS1Signer{crypto.SHA512}, nil
}
+ case signatureRSAPKCS1WithSHA256Legacy:
+ if (isClientSign && version >= VersionTLS13) || config.Bugs.IgnoreSignatureVersionChecks {
+ return &rsaPKCS1Signer{crypto.SHA256}, nil
+ }
case signatureECDSAWithSHA1:
return &ecdsaSigner{version, config, nil, crypto.SHA1}, nil
case signatureECDSAWithP256AndSHA256: