Implement rsa_pkcs1_sha256_legacy.

See draft-davidben-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.

Change-Id: Iac4aa96a4963cbc33688c252e958a572c5c3b511
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46187
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
David Benjamin 2021-02-25 01:37:16 -05:00 committed by CQ bot account: commit-bot@chromium.org
parent 2c1c9fa5cb
commit a3437c09c7
8 changed files with 201 additions and 115 deletions

View File

@ -1051,6 +1051,11 @@ OPENSSL_EXPORT int SSL_set_ocsp_response(SSL *ssl,
#define SSL_SIGN_RSA_PSS_RSAE_SHA512 0x0806 #define SSL_SIGN_RSA_PSS_RSAE_SHA512 0x0806
#define SSL_SIGN_ED25519 0x0807 #define SSL_SIGN_ED25519 0x0807
// SSL_SIGN_RSA_PKCS1_SHA256_LEGACY is a backport of RSASSA-PKCS1-v1_5 with
// SHA-256 to TLS 1.3. It is disabled by default and only defined for client
// certificates.
#define SSL_SIGN_RSA_PKCS1_SHA256_LEGACY 0x0420
// SSL_SIGN_RSA_PKCS1_MD5_SHA1 is an internal signature algorithm used to // SSL_SIGN_RSA_PKCS1_MD5_SHA1 is an internal signature algorithm used to
// specify raw RSASSA-PKCS1-v1_5 with an MD5/SHA-1 concatenation, as used in TLS // specify raw RSASSA-PKCS1-v1_5 with an MD5/SHA-1 concatenation, as used in TLS
// before TLS 1.2. // before TLS 1.2.

View File

@ -99,29 +99,46 @@ typedef struct {
int curve; int curve;
const EVP_MD *(*digest_func)(void); const EVP_MD *(*digest_func)(void);
bool is_rsa_pss; bool is_rsa_pss;
bool tls12_ok;
bool tls13_ok;
} SSL_SIGNATURE_ALGORITHM; } SSL_SIGNATURE_ALGORITHM;
static const SSL_SIGNATURE_ALGORITHM kSignatureAlgorithms[] = { 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, {SSL_SIGN_RSA_PKCS1_MD5_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_md5_sha1,
false}, /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false},
{SSL_SIGN_RSA_PKCS1_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_sha1, false}, {SSL_SIGN_RSA_PKCS1_SHA1, EVP_PKEY_RSA, NID_undef, &EVP_sha1,
{SSL_SIGN_RSA_PKCS1_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, false}, /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false},
{SSL_SIGN_RSA_PKCS1_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, false}, {SSL_SIGN_RSA_PKCS1_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256,
{SSL_SIGN_RSA_PKCS1_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, false}, /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false},
{SSL_SIGN_RSA_PKCS1_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384,
/*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false},
{SSL_SIGN_RSA_PKCS1_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512,
/*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false},
{SSL_SIGN_RSA_PSS_RSAE_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256, true}, // Legacy PKCS#1 v1.5 code points are only allowed in TLS 1.3. See
{SSL_SIGN_RSA_PSS_RSAE_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384, true}, // draft-davidben-tls13-pkcs1-00.
{SSL_SIGN_RSA_PSS_RSAE_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512, true}, {SSL_SIGN_RSA_PKCS1_SHA256_LEGACY, EVP_PKEY_RSA, NID_undef, &EVP_sha256,
/*is_rsa_pss=*/false, /*tls12_ok=*/false, /*tls13_ok=*/true},
{SSL_SIGN_ECDSA_SHA1, EVP_PKEY_EC, NID_undef, &EVP_sha1, false}, {SSL_SIGN_RSA_PSS_RSAE_SHA256, EVP_PKEY_RSA, NID_undef, &EVP_sha256,
/*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true},
{SSL_SIGN_RSA_PSS_RSAE_SHA384, EVP_PKEY_RSA, NID_undef, &EVP_sha384,
/*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true},
{SSL_SIGN_RSA_PSS_RSAE_SHA512, EVP_PKEY_RSA, NID_undef, &EVP_sha512,
/*is_rsa_pss=*/true, /*tls12_ok=*/true, /*tls13_ok=*/true},
{SSL_SIGN_ECDSA_SHA1, EVP_PKEY_EC, NID_undef, &EVP_sha1,
/*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/false},
{SSL_SIGN_ECDSA_SECP256R1_SHA256, EVP_PKEY_EC, NID_X9_62_prime256v1, {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},
{SSL_SIGN_ECDSA_SECP384R1_SHA384, EVP_PKEY_EC, NID_secp384r1, &EVP_sha384, {SSL_SIGN_ECDSA_SECP384R1_SHA384, EVP_PKEY_EC, NID_secp384r1, &EVP_sha384,
false}, /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true},
{SSL_SIGN_ECDSA_SECP521R1_SHA512, EVP_PKEY_EC, NID_secp521r1, &EVP_sha512, {SSL_SIGN_ECDSA_SECP521R1_SHA512, EVP_PKEY_EC, NID_secp521r1, &EVP_sha512,
false}, /*is_rsa_pss=*/false, /*tls12_ok=*/true, /*tls13_ok=*/true},
{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},
}; };
static const SSL_SIGNATURE_ALGORITHM *get_signature_algorithm(uint16_t sigalg) { static const SSL_SIGNATURE_ALGORITHM *get_signature_algorithm(uint16_t sigalg) {
@ -144,7 +161,7 @@ bool ssl_has_private_key(const SSL_HANDSHAKE *hs) {
} }
static bool pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey, static bool 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); const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
if (alg == NULL || if (alg == NULL ||
EVP_PKEY_id(pkey) != alg->pkey_type) { EVP_PKEY_id(pkey) != alg->pkey_type) {
@ -152,8 +169,14 @@ static bool pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
} }
if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
// RSA keys may only be used with RSA-PSS. if (!alg->tls13_ok) {
if (alg->pkey_type == EVP_PKEY_RSA && !alg->is_rsa_pss) { return false;
}
// Legacy PKCS#1 v1.5 code points for TLS 1.3 are client-only. See
// draft-davidben-tls13-pkcs1-00.
bool is_client_sign = ssl->server == is_verify;
if (alg->pkey_type == EVP_PKEY_RSA && !alg->is_rsa_pss && !is_client_sign) {
return false; return false;
} }
@ -164,6 +187,8 @@ static bool pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey))) != alg->curve)) { EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(pkey))) != alg->curve)) {
return false; return false;
} }
} else if (!alg->tls12_ok) {
return false;
} }
return true; return true;
@ -171,7 +196,7 @@ static bool pkey_supports_algorithm(const SSL *ssl, EVP_PKEY *pkey,
static bool setup_ctx(SSL *ssl, EVP_MD_CTX *ctx, EVP_PKEY *pkey, static bool setup_ctx(SSL *ssl, EVP_MD_CTX *ctx, EVP_PKEY *pkey,
uint16_t sigalg, bool is_verify) { uint16_t sigalg, bool is_verify) {
if (!pkey_supports_algorithm(ssl, pkey, sigalg)) { if (!pkey_supports_algorithm(ssl, pkey, sigalg, is_verify)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
return false; return false;
} }
@ -288,7 +313,8 @@ enum ssl_private_key_result_t ssl_private_key_decrypt(SSL_HANDSHAKE *hs,
bool ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs, bool ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
uint16_t sigalg) { uint16_t sigalg) {
SSL *const ssl = hs->ssl; SSL *const ssl = hs->ssl;
if (!pkey_supports_algorithm(ssl, hs->local_pubkey.get(), sigalg)) { if (!pkey_supports_algorithm(ssl, hs->local_pubkey.get(), sigalg,
/*is_verify=*/false)) {
return false; return false;
} }

View File

@ -211,6 +211,9 @@ const (
// EdDSA algorithms // EdDSA algorithms
signatureEd25519 signatureAlgorithm = 0x0807 signatureEd25519 signatureAlgorithm = 0x0807
signatureEd448 signatureAlgorithm = 0x0808 signatureEd448 signatureAlgorithm = 0x0808
// draft-davidben-tls13-pkcs1-00
signatureRSAPKCS1WithSHA256Legacy signatureAlgorithm = 0x0420
) )
// supportedSignatureAlgorithms contains the default supported signature // supportedSignatureAlgorithms contains the default supported signature

View File

@ -1070,7 +1070,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13) input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
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 { if err != nil {
return err return err
} }
@ -1214,14 +1214,14 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
privKey := chainToSend.PrivateKey privKey := chainToSend.PrivateKey
var err error var err error
certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms) certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, privKey, c.config, certReq.signatureAlgorithms)
if err != nil { if err != nil {
c.sendAlert(alertInternalError) c.sendAlert(alertInternalError)
return err return err
} }
input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13) 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 { if err != nil {
c.sendAlert(alertInternalError) c.sendAlert(alertInternalError)
return err return err
@ -1437,7 +1437,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
privKey := c.config.Certificates[0].PrivateKey privKey := c.config.Certificates[0].PrivateKey
if certVerify.hasSignatureAlgorithm { if certVerify.hasSignatureAlgorithm {
certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms) certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, privKey, c.config, certReq.signatureAlgorithms)
if err != nil { if err != nil {
c.sendAlert(alertInternalError) c.sendAlert(alertInternalError)
return err return err
@ -1445,7 +1445,7 @@ func (hs *clientHandshakeState) doFullHandshake() error {
} }
if c.vers > VersionSSL30 { if c.vers > VersionSSL30 {
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 { if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
} }
@ -1576,13 +1576,7 @@ func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) erro
return errors.New("tls: failed to parse public key from delegated credential: " + err.Error()) return errors.New("tls: failed to parse public key from delegated credential: " + err.Error())
} }
verifier, err := getSigner(c.vers, hs.peerPublicKey, c.config, dc.algorithm, true) if err := verifyMessage(c.isClient, c.vers, leafPublicKey, c.config, dc.algorithm, delegatedCredentialSignedMessage(dc.signedBytes, dc.algorithm, certs[0].Raw), dc.signature); err != nil {
if err != nil {
c.sendAlert(alertBadCertificate)
return errors.New("tls: failed to get verifier for delegated credential: " + err.Error())
}
if err := verifier.verifyMessage(leafPublicKey, delegatedCredentialSignedMessage(dc.signedBytes, dc.algorithm, certs[0].Raw), dc.signature); err != nil {
c.sendAlert(alertBadCertificate) c.sendAlert(alertBadCertificate)
return errors.New("tls: failed to verify delegated credential: " + err.Error()) return errors.New("tls: failed to verify delegated credential: " + err.Error())
} }

View File

@ -976,14 +976,14 @@ ResendHelloRetryRequest:
privKey := hs.cert.PrivateKey privKey := hs.cert.PrivateKey
var err error var err error
certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, config, hs.clientHello.signatureAlgorithms) certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.isClient, c.vers, privKey, config, hs.clientHello.signatureAlgorithms)
if err != nil { if err != nil {
c.sendAlert(alertInternalError) c.sendAlert(alertInternalError)
return err return err
} }
input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13) 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 { if err != nil {
c.sendAlert(alertInternalError) c.sendAlert(alertInternalError)
return err return err
@ -1147,7 +1147,7 @@ ResendHelloRetryRequest:
c.peerSignatureAlgorithm = certVerify.signatureAlgorithm c.peerSignatureAlgorithm = certVerify.signatureAlgorithm
input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13) 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) c.sendAlert(alertBadCertificate)
return err return err
} }
@ -1884,7 +1884,7 @@ func (hs *serverHandshakeState) doFullHandshake() error {
} }
if c.vers > VersionSSL30 { if c.vers > VersionSSL30 {
err = verifyMessage(c.vers, pub, c.config, sigAlg, hs.finishedHash.buffer, certVerify.signature) err = verifyMessage(c.isClient, c.vers, pub, c.config, sigAlg, hs.finishedHash.buffer, certVerify.signature)
} else { } else {
// SSL 3.0's client certificate construction is // SSL 3.0's client certificate construction is
// incompatible with signatureAlgorithm. // incompatible with signatureAlgorithm.

View File

@ -65,13 +65,13 @@ func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certi
var sigAlg signatureAlgorithm var sigAlg signatureAlgorithm
if ka.version >= VersionTLS12 { if ka.version >= VersionTLS12 {
sigAlg, err = selectSignatureAlgorithm(ka.version, cert.PrivateKey, config, clientHello.signatureAlgorithms) sigAlg, err = selectSignatureAlgorithm(false /* server */, ka.version, cert.PrivateKey, config, clientHello.signatureAlgorithms)
if err != nil { if err != nil {
return nil, err 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 { if err != nil {
return nil, errors.New("failed to sign RSA parameters: " + err.Error()) return nil, errors.New("failed to sign RSA parameters: " + err.Error())
} }
@ -492,13 +492,13 @@ func (ka *signedKeyAgreement) signParameters(config *Config, cert *Certificate,
var sigAlg signatureAlgorithm var sigAlg signatureAlgorithm
var err error var err error
if ka.version >= VersionTLS12 { if ka.version >= VersionTLS12 {
sigAlg, err = selectSignatureAlgorithm(ka.version, cert.PrivateKey, config, clientHello.signatureAlgorithms) sigAlg, err = selectSignatureAlgorithm(false /* server */, ka.version, cert.PrivateKey, config, clientHello.signatureAlgorithms)
if err != nil { if err != nil {
return nil, err 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 { if err != nil {
return nil, err return nil, err
} }
@ -574,7 +574,7 @@ func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clie
} }
sig = sig[2:] 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 // ecdheKeyAgreement implements a TLS key agreement where the server

View File

@ -102,6 +102,10 @@ type ShimConfiguration struct {
// This is currently used to control tests that enable all curves but may // This is currently used to control tests that enable all curves but may
// automatically disable tests in the future. // automatically disable tests in the future.
AllCurves []int AllCurves []int
// AllSignatureAlgorithms is the list of all signature algorithm code points
// supported by the shim.
AllSignatureAlgorithms []int
} }
// Setup shimConfig defaults aligning with BoringSSL. // Setup shimConfig defaults aligning with BoringSSL.
@ -390,12 +394,7 @@ func createDelegatedCredential(config delegatedCredentialConfig, parentDER []byt
dc = append(dc, pubBytes...) dc = append(dc, pubBytes...)
var dummyConfig Config var dummyConfig Config
parentSigner, err := getSigner(tlsVersion, parentPriv, &dummyConfig, config.algo, false /* not for verification */) parentSignature, err := signMessage(false /* server */, tlsVersion, parentPriv, &dummyConfig, config.algo, delegatedCredentialSignedMessage(dc, config.algo, parentDER))
if err != nil {
return nil, nil, err
}
parentSignature, err := parentSigner.signMessage(parentPriv, &dummyConfig, delegatedCredentialSignedMessage(dc, config.algo, parentDER))
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -1645,16 +1644,16 @@ func runTest(statusChan chan statusMsg, test *testCase, shimPath string, mallocN
case failed && !test.shouldFail: case failed && !test.shouldFail:
msg = "unexpected failure" msg = "unexpected failure"
case !failed && test.shouldFail: case !failed && test.shouldFail:
msg = "unexpected success" msg = fmt.Sprintf("unexpected success (wanted failure with %q / %q)", expectedError, test.expectedLocalError)
case failed && !correctFailure: case failed && !correctFailure:
msg = "bad error (wanted '" + expectedError + "' / '" + test.expectedLocalError + "')" msg = fmt.Sprintf("bad error (wanted %q / %q)", expectedError, test.expectedLocalError)
case mustFail: case mustFail:
msg = "test failure" msg = "test failure"
default: default:
panic("internal error") panic("internal error")
} }
return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s\n%s", msg, localError, childError, stdout, stderr, extraStderr) return fmt.Errorf("%s: local error %q, child error %q, stdout:\n%s\nstderr:\n%s\n%s", msg, localError, childError, stdout, stderr, extraStderr)
} }
if len(extraStderr) > 0 || (!failed && len(stderr) > 0) { if len(extraStderr) > 0 || (!failed && len(stderr) > 0) {
@ -9894,6 +9893,7 @@ var testSignatureAlgorithms = []struct {
}{ }{
{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, testCertRSA}, {"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, testCertRSA},
{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, testCertRSA}, {"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, testCertRSA},
{"RSA_PKCS1_SHA256_LEGACY", signatureRSAPKCS1WithSHA256Legacy, testCertRSA},
{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, testCertRSA}, {"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, testCertRSA},
{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, testCertRSA}, {"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, testCertRSA},
{"ECDSA_SHA1", signatureECDSAWithSHA1, testCertECDSAP256}, {"ECDSA_SHA1", signatureECDSAWithSHA1, testCertECDSAP256},
@ -9942,51 +9942,94 @@ func addSignatureAlgorithmTests() {
continue 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.cert == testCertECDSAP224 {
shouldFail = true
}
// 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 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"
rejectByDefault = true
}
if rejectByDefault {
defaultError = ":WRONG_SIGNATURE_TYPE:"
defaultLocalError = "remote error"
}
suffix := "-" + alg.name + "-" + ver.name 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
}
for _, testType := range []testType{clientTest, serverTest} { var shouldFail bool
prefix := "Client-" isTLS12PKCS1 := hasComponent(alg.name, "PKCS1") && !hasComponent(alg.name, "LEGACY")
if testType == serverTest { isTLS13PKCS1 := hasComponent(alg.name, "PKCS1") && hasComponent(alg.name, "LEGACY")
prefix = "Server-"
// TLS 1.3 removes a number of signature algorithms.
if ver.version >= VersionTLS13 && (alg.cert == testCertECDSAP224 || alg.id == signatureECDSAWithSHA1 || isTLS12PKCS1) {
shouldFail = true
}
// The backported RSA-PKCS1 code points only exist for TLS 1.3
// client certificates.
if (ver.version < VersionTLS13 || signTestType == serverTest) && isTLS13PKCS1 {
shouldFail = true
}
// By default, BoringSSL does not sign with these algorithms.
signDefault := true
if isTLS13PKCS1 {
signDefault = false
}
// By default, BoringSSL does not accept these algorithms.
verifyDefault := true
if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 || isTLS13PKCS1 {
verifyDefault = false
}
var signError, signLocalError, verifyError, verifyLocalError string
if shouldFail {
signError = ":NO_COMMON_SIGNATURE_ALGORITHMS:"
signLocalError = "remote error: handshake failure"
verifyError = ":WRONG_SIGNATURE_TYPE:"
verifyLocalError = "remote error"
signDefault = false
verifyDefault = false
}
var signDefaultError, signDefaultLocalError string
if !signDefault {
signDefaultError = ":NO_COMMON_SIGNATURE_ALGORITHMS:"
signDefaultLocalError = "remote error: handshake failure"
}
var verifyDefaultError, verifyDefaultLocalError string
if !verifyDefault {
verifyDefaultError = ":WRONG_SIGNATURE_TYPE:"
verifyDefaultLocalError = "remote error"
} }
// Test the shim using the algorithm for signing. // Test the shim using the algorithm for signing.
signTestFlags := []string{
"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
}
signTestFlags = append(signTestFlags, flagInts("-curves", shimConfig.AllCurves)...)
signTestFlags = append(signTestFlags, flagInts("-signing-prefs", shimConfig.AllSignatureAlgorithms)...)
signTest := testCase{ signTest := testCase{
testType: testType, testType: signTestType,
name: prefix + "Sign" + suffix, name: signPrefix + "Sign" + suffix,
config: Config{
MaxVersion: ver.version,
VerifySignatureAlgorithms: []signatureAlgorithm{
fakeSigAlg1,
alg.id,
fakeSigAlg2,
},
},
flags: signTestFlags,
shouldFail: shouldFail,
expectedError: signError,
expectedLocalError: signLocalError,
expectations: connectionExpectations{
peerSignatureAlgorithm: alg.id,
},
}
// Test whether the shim enables the algorithm by default.
signDefaultTest := testCase{
testType: signTestType,
name: signPrefix + "SignDefault" + suffix,
config: Config{ config: Config{
MaxVersion: ver.version, MaxVersion: ver.version,
VerifySignatureAlgorithms: []signatureAlgorithm{ VerifySignatureAlgorithms: []signatureAlgorithm{
@ -10002,9 +10045,9 @@ func addSignatureAlgorithmTests() {
}, },
flagInts("-curves", shimConfig.AllCurves)..., flagInts("-curves", shimConfig.AllCurves)...,
), ),
shouldFail: shouldFail, shouldFail: !signDefault,
expectedError: signError, expectedError: signDefaultError,
expectedLocalError: signLocalError, expectedLocalError: signDefaultLocalError,
expectations: connectionExpectations{ expectations: connectionExpectations{
peerSignatureAlgorithm: alg.id, peerSignatureAlgorithm: alg.id,
}, },
@ -10013,8 +10056,8 @@ func addSignatureAlgorithmTests() {
// Test that the shim will select the algorithm when configured to only // Test that the shim will select the algorithm when configured to only
// support it. // support it.
negotiateTest := testCase{ negotiateTest := testCase{
testType: testType, testType: signTestType,
name: prefix + "Sign-Negotiate" + suffix, name: signPrefix + "Sign-Negotiate" + suffix,
config: Config{ config: Config{
MaxVersion: ver.version, MaxVersion: ver.version,
VerifySignatureAlgorithms: allAlgorithms, VerifySignatureAlgorithms: allAlgorithms,
@ -10032,24 +10075,26 @@ func addSignatureAlgorithmTests() {
}, },
} }
if testType == serverTest { if signTestType == serverTest {
// TLS 1.2 servers only sign on some cipher suites. // TLS 1.2 servers only sign on some cipher suites.
signTest.config.CipherSuites = signingCiphers signTest.config.CipherSuites = signingCiphers
signDefaultTest.config.CipherSuites = signingCiphers
negotiateTest.config.CipherSuites = signingCiphers negotiateTest.config.CipherSuites = signingCiphers
} else { } else {
// TLS 1.2 clients only sign when the server requests certificates. // TLS 1.2 clients only sign when the server requests certificates.
signTest.config.ClientAuth = RequireAnyClientCert signTest.config.ClientAuth = RequireAnyClientCert
signDefaultTest.config.ClientAuth = RequireAnyClientCert
negotiateTest.config.ClientAuth = RequireAnyClientCert negotiateTest.config.ClientAuth = RequireAnyClientCert
} }
testCases = append(testCases, signTest) testCases = append(testCases, signTest, signDefaultTest)
if ver.version >= VersionTLS12 && !shouldFail { if ver.version >= VersionTLS12 && !shouldFail {
testCases = append(testCases, negotiateTest) testCases = append(testCases, negotiateTest)
} }
// Test the shim using the algorithm for verifying. // Test the shim using the algorithm for verifying.
verifyTest := testCase{ verifyTest := testCase{
testType: testType, testType: verifyTestType,
name: prefix + "Verify" + suffix, name: verifyPrefix + "Verify" + suffix,
config: Config{ config: Config{
MaxVersion: ver.version, MaxVersion: ver.version,
Certificates: []Certificate{getRunnerCertificate(alg.cert)}, Certificates: []Certificate{getRunnerCertificate(alg.cert)},
@ -10081,8 +10126,8 @@ func addSignatureAlgorithmTests() {
// Test whether the shim expects the algorithm enabled by default. // Test whether the shim expects the algorithm enabled by default.
defaultTest := testCase{ defaultTest := testCase{
testType: testType, testType: verifyTestType,
name: prefix + "VerifyDefault" + suffix, name: verifyPrefix + "VerifyDefault" + suffix,
config: Config{ config: Config{
MaxVersion: ver.version, MaxVersion: ver.version,
Certificates: []Certificate{getRunnerCertificate(alg.cert)}, Certificates: []Certificate{getRunnerCertificate(alg.cert)},
@ -10090,10 +10135,10 @@ func addSignatureAlgorithmTests() {
alg.id, alg.id,
}, },
Bugs: ProtocolBugs{ Bugs: ProtocolBugs{
SkipECDSACurveCheck: rejectByDefault, SkipECDSACurveCheck: !verifyDefault,
IgnoreSignatureVersionChecks: rejectByDefault, IgnoreSignatureVersionChecks: !verifyDefault,
// Some signature algorithms may not be advertised. // Some signature algorithms may not be advertised.
IgnorePeerSignatureAlgorithmPreferences: rejectByDefault, IgnorePeerSignatureAlgorithmPreferences: !verifyDefault,
}, },
}, },
flags: append( flags: append(
@ -10102,16 +10147,16 @@ func addSignatureAlgorithmTests() {
), ),
// Resume the session to assert the peer signature // Resume the session to assert the peer signature
// algorithm is reported on both handshakes. // algorithm is reported on both handshakes.
resumeSession: !rejectByDefault, resumeSession: verifyDefault,
shouldFail: rejectByDefault, shouldFail: !verifyDefault,
expectedError: defaultError, expectedError: verifyDefaultError,
expectedLocalError: defaultLocalError, expectedLocalError: verifyDefaultLocalError,
} }
// Test whether the shim handles invalid signatures for this algorithm. // Test whether the shim handles invalid signatures for this algorithm.
invalidTest := testCase{ invalidTest := testCase{
testType: testType, testType: verifyTestType,
name: prefix + "InvalidSignature" + suffix, name: verifyPrefix + "InvalidSignature" + suffix,
config: Config{ config: Config{
MaxVersion: ver.version, MaxVersion: ver.version,
Certificates: []Certificate{getRunnerCertificate(alg.cert)}, Certificates: []Certificate{getRunnerCertificate(alg.cert)},
@ -10131,7 +10176,7 @@ func addSignatureAlgorithmTests() {
expectedError: ":BAD_SIGNATURE:", expectedError: ":BAD_SIGNATURE:",
} }
if testType == serverTest { if verifyTestType == serverTest {
// TLS 1.2 servers only verify when they request client certificates. // TLS 1.2 servers only verify when they request client certificates.
verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate") verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate")
defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate") defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate")
@ -16798,6 +16843,14 @@ func main() {
} }
} }
if shimConfig.AllSignatureAlgorithms == nil {
for _, alg := range testSignatureAlgorithms {
if alg.id != 0 {
shimConfig.AllSignatureAlgorithms = append(shimConfig.AllSignatureAlgorithms, int(alg.id))
}
}
}
addBasicTests() addBasicTests()
addCipherSuiteTests() addCipherSuiteTests()
addBadECDSASignatureTests() addBadECDSASignatureTests()

View File

@ -26,7 +26,7 @@ type signer interface {
verifyMessage(key crypto.PublicKey, msg, sig []byte) error verifyMessage(key crypto.PublicKey, msg, sig []byte) error
} }
func selectSignatureAlgorithm(version uint16, key crypto.PrivateKey, config *Config, peerSigAlgs []signatureAlgorithm) (signatureAlgorithm, error) { func selectSignatureAlgorithm(isClient bool, version uint16, key crypto.PrivateKey, config *Config, peerSigAlgs []signatureAlgorithm) (signatureAlgorithm, error) {
// If the client didn't specify any signature_algorithms extension then // If the client didn't specify any signature_algorithms extension then
// we can assume that it supports SHA1. See // we can assume that it supports SHA1. See
// http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
@ -39,7 +39,7 @@ func selectSignatureAlgorithm(version uint16, key crypto.PrivateKey, config *Con
continue continue
} }
signer, err := getSigner(version, key, config, sigAlg, false) signer, err := getSigner(isClient, version, key, config, sigAlg, false)
if err != nil { if err != nil {
continue continue
} }
@ -51,7 +51,7 @@ func selectSignatureAlgorithm(version uint16, key crypto.PrivateKey, config *Con
return 0, errors.New("tls: no common signature algorithms") 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 { if config.Bugs.InvalidSignature {
newMsg := make([]byte, len(msg)) newMsg := make([]byte, len(msg))
copy(newMsg, msg) copy(newMsg, msg)
@ -59,7 +59,7 @@ func signMessage(version uint16, key crypto.PrivateKey, config *Config, sigAlg s
msg = newMsg msg = newMsg
} }
signer, err := getSigner(version, key, config, sigAlg, false) signer, err := getSigner(isClient, version, key, config, sigAlg, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -67,12 +67,12 @@ func signMessage(version uint16, key crypto.PrivateKey, config *Config, sigAlg s
return signer.signMessage(key, config, msg) 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 && !isSupportedSignatureAlgorithm(sigAlg, config.verifySignatureAlgorithms()) { if version >= VersionTLS12 && !isSupportedSignatureAlgorithm(sigAlg, config.verifySignatureAlgorithms()) {
return errors.New("tls: unsupported signature algorithm") 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 { if err != nil {
return err return err
} }
@ -272,7 +272,7 @@ func (e *ed25519Signer) verifyMessage(key crypto.PublicKey, msg, sig []byte) err
return nil return nil
} }
func getSigner(version uint16, key interface{}, config *Config, sigAlg signatureAlgorithm, isVerify bool) (signer, error) { func getSigner(isClient bool, version uint16, key interface{}, config *Config, sigAlg signatureAlgorithm, isVerify bool) (signer, error) {
// TLS 1.1 and below use legacy signature algorithms. // TLS 1.1 and below use legacy signature algorithms.
if version < VersionTLS12 { if version < VersionTLS12 {
if config.Bugs.UseLegacySigningAlgorithm == 0 || isVerify { if config.Bugs.UseLegacySigningAlgorithm == 0 || isVerify {
@ -290,6 +290,7 @@ func getSigner(version uint16, key interface{}, config *Config, sigAlg signature
sigAlg = config.Bugs.UseLegacySigningAlgorithm sigAlg = config.Bugs.UseLegacySigningAlgorithm
} }
isClientSign := isClient != isVerify
switch sigAlg { switch sigAlg {
case signatureRSAPKCS1WithMD5: case signatureRSAPKCS1WithMD5:
if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks { if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
@ -311,6 +312,10 @@ func getSigner(version uint16, key interface{}, config *Config, sigAlg signature
if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks { if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
return &rsaPKCS1Signer{crypto.SHA512}, nil return &rsaPKCS1Signer{crypto.SHA512}, nil
} }
case signatureRSAPKCS1WithSHA256Legacy:
if (isClientSign && version >= VersionTLS13) || config.Bugs.IgnoreSignatureVersionChecks {
return &rsaPKCS1Signer{crypto.SHA256}, nil
}
case signatureECDSAWithSHA1: case signatureECDSAWithSHA1:
return &ecdsaSigner{version, config, nil, crypto.SHA1}, nil return &ecdsaSigner{version, config, nil, crypto.SHA1}, nil
case signatureECDSAWithP256AndSHA256: case signatureECDSAWithP256AndSHA256: