}
// signatureSchemesForCertificate returns the list of supported SignatureSchemes
-// for a given certificate, based on the public key and the protocol version.
+// for a given certificate, based on the public key and the protocol version,
+// and optionally filtered by its explicit SupportedSignatureAlgorithms.
//
// This function must be kept in sync with supportedSignatureAlgorithms.
func signatureSchemesForCertificate(version uint16, cert *Certificate) []SignatureScheme {
return nil
}
+ var sigAlgs []SignatureScheme
switch pub := priv.Public().(type) {
case *ecdsa.PublicKey:
if version != VersionTLS13 {
// In TLS 1.2 and earlier, ECDSA algorithms are not
// constrained to a single curve.
- return []SignatureScheme{
+ sigAlgs = []SignatureScheme{
ECDSAWithP256AndSHA256,
ECDSAWithP384AndSHA384,
ECDSAWithP521AndSHA512,
ECDSAWithSHA1,
}
+ break
}
switch pub.Curve {
case elliptic.P256():
- return []SignatureScheme{ECDSAWithP256AndSHA256}
+ sigAlgs = []SignatureScheme{ECDSAWithP256AndSHA256}
case elliptic.P384():
- return []SignatureScheme{ECDSAWithP384AndSHA384}
+ sigAlgs = []SignatureScheme{ECDSAWithP384AndSHA384}
case elliptic.P521():
- return []SignatureScheme{ECDSAWithP521AndSHA512}
+ sigAlgs = []SignatureScheme{ECDSAWithP521AndSHA512}
default:
return nil
}
case *rsa.PublicKey:
if version != VersionTLS13 {
- return []SignatureScheme{
+ sigAlgs = []SignatureScheme{
// Temporarily disable RSA-PSS in TLS 1.2, see Issue 32425.
// PSSWithSHA256,
// PSSWithSHA384,
PKCS1WithSHA512,
PKCS1WithSHA1,
}
+ break
}
// TLS 1.3 dropped support for PKCS#1 v1.5 in favor of RSA-PSS.
- return []SignatureScheme{
+ sigAlgs = []SignatureScheme{
PSSWithSHA256,
PSSWithSHA384,
PSSWithSHA512,
}
case ed25519.PublicKey:
- return []SignatureScheme{Ed25519}
+ sigAlgs = []SignatureScheme{Ed25519}
default:
return nil
}
+
+ if cert.SupportedSignatureAlgorithms != nil {
+ var filteredSigAlgs []SignatureScheme
+ for _, sigAlg := range sigAlgs {
+ if isSupportedSignatureAlgorithm(sigAlg, cert.SupportedSignatureAlgorithms) {
+ filteredSigAlgs = append(filteredSigAlgs, sigAlg)
+ }
+ }
+ return filteredSigAlgs
+ }
+ return sigAlgs
}
// selectSignatureScheme picks a SignatureScheme from the peer's preference list
// versions that support signature algorithms, so TLS 1.2 and 1.3.
func selectSignatureScheme(vers uint16, c *Certificate, peerAlgs []SignatureScheme) (SignatureScheme, error) {
supportedAlgs := signatureSchemesForCertificate(vers, c)
- if supportedAlgs == nil {
+ if len(supportedAlgs) == 0 {
return 0, unsupportedCertificateError(c)
}
if len(peerAlgs) == 0 && vers == VersionTLS12 {
return fmt.Errorf("tls: unsupported certificate key (%T)", pub)
}
+ if cert.SupportedSignatureAlgorithms != nil {
+ return fmt.Errorf("tls: peer doesn't support the certificate custom signature algorithms")
+ }
+
return fmt.Errorf("tls: internal error: unsupported key (%T)", cert.PrivateKey)
}
Certificate: [][]byte{testRSACertificate},
PrivateKey: testRSAPrivateKey,
}
+ pkcs1Cert := &Certificate{
+ Certificate: [][]byte{testRSACertificate},
+ PrivateKey: testRSAPrivateKey,
+ SupportedSignatureAlgorithms: []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256},
+ }
ecdsaCert := &Certificate{
Certificate: [][]byte{testP256Certificate},
PrivateKey: testP256PrivateKey,
{rsaCert, []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256}, VersionTLS12, PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1},
{rsaCert, []SignatureScheme{PKCS1WithSHA512, PKCS1WithSHA1}, VersionTLS12, PKCS1WithSHA512, signaturePKCS1v15, crypto.SHA512},
{rsaCert, []SignatureScheme{PSSWithSHA256, PKCS1WithSHA256}, VersionTLS12, PKCS1WithSHA256, signaturePKCS1v15, crypto.SHA256},
+ {pkcs1Cert, []SignatureScheme{PSSWithSHA256, PKCS1WithSHA256}, VersionTLS12, PKCS1WithSHA256, signaturePKCS1v15, crypto.SHA256},
{rsaCert, []SignatureScheme{PSSWithSHA384, PKCS1WithSHA1}, VersionTLS13, PSSWithSHA384, signatureRSAPSS, crypto.SHA384},
{ecdsaCert, []SignatureScheme{ECDSAWithSHA1}, VersionTLS12, ECDSAWithSHA1, signatureECDSA, crypto.SHA1},
{ecdsaCert, []SignatureScheme{ECDSAWithP256AndSHA256}, VersionTLS12, ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256},
}
}
+ brokenCert := &Certificate{
+ Certificate: [][]byte{testRSACertificate},
+ PrivateKey: testRSAPrivateKey,
+ SupportedSignatureAlgorithms: []SignatureScheme{Ed25519},
+ }
+
badTests := []struct {
cert *Certificate
peerSigAlgs []SignatureScheme
{rsaCert, []SignatureScheme{0}, VersionTLS12},
{ed25519Cert, []SignatureScheme{ECDSAWithP256AndSHA256, ECDSAWithSHA1}, VersionTLS12},
{ecdsaCert, []SignatureScheme{Ed25519}, VersionTLS12},
+ {brokenCert, []SignatureScheme{Ed25519}, VersionTLS12},
+ {brokenCert, []SignatureScheme{PKCS1WithSHA256}, VersionTLS12},
// RFC 5246, Section 7.4.1.4.1, says to only consider {sha1,ecdsa} as
// default when the extension is missing, and RFC 8422 does not update
// it. Anyway, if a stack supports Ed25519 it better support sigalgs.
{ecdsaCert, []SignatureScheme{ECDSAWithP384AndSHA384}, VersionTLS13},
// TLS 1.3 does not support PKCS1v1.5 or SHA-1.
{rsaCert, []SignatureScheme{PKCS1WithSHA256}, VersionTLS13},
+ {pkcs1Cert, []SignatureScheme{PSSWithSHA256, PKCS1WithSHA256}, VersionTLS13},
{ecdsaCert, []SignatureScheme{ECDSAWithSHA1}, VersionTLS13},
}
// For a server up to TLS 1.2, it can also implement crypto.Decrypter with
// an RSA PublicKey.
PrivateKey crypto.PrivateKey
+ // SupportedSignatureAlgorithms is an optional list restricting what
+ // signature algorithms the PrivateKey can be used for.
+ SupportedSignatureAlgorithms []SignatureScheme
// OCSPStaple contains an optional OCSP response which will be served
// to clients that request it.
OCSPStaple []byte
import (
"bytes"
+ "crypto"
"crypto/x509"
"encoding/json"
"errors"
Certificate: [][]byte{testRSACertificate},
PrivateKey: testRSAPrivateKey,
}
+ pkcs1Cert := &Certificate{
+ Certificate: [][]byte{testRSACertificate},
+ PrivateKey: testRSAPrivateKey,
+ SupportedSignatureAlgorithms: []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256},
+ }
ecdsaCert := &Certificate{
// ECDSA P-256 certificate
Certificate: [][]byte{testP256Certificate},
SignatureSchemes: []SignatureScheme{ECDSAWithP384AndSHA384},
SupportedVersions: []uint16{VersionTLS13},
}, "signature algorithms"},
+ {pkcs1Cert, &ClientHelloInfo{
+ SignatureSchemes: []SignatureScheme{PSSWithSHA256, ECDSAWithP256AndSHA256},
+ SupportedVersions: []uint16{VersionTLS13},
+ }, "signature algorithms"},
{rsaCert, &ClientHelloInfo{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
}
}
}
+
+type brokenSigner struct{ crypto.Signer }
+
+func (s brokenSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
+ // Replace opts with opts.HashFunc(), so rsa.PSSOptions are discarded.
+ return s.Signer.Sign(rand, digest, opts.HashFunc())
+}
+
+// TestPKCS1OnlyCert uses a client certificate with a broken crypto.Signer that
+// always makes PKCS#1 v1.5 signatures, so can't be used with RSA-PSS.
+func TestPKCS1OnlyCert(t *testing.T) {
+ clientConfig := testConfig.Clone()
+ clientConfig.Certificates = []Certificate{{
+ Certificate: [][]byte{testRSACertificate},
+ PrivateKey: brokenSigner{testRSAPrivateKey},
+ }}
+ serverConfig := testConfig.Clone()
+ serverConfig.MaxVersion = VersionTLS12 // TLS 1.3 doesn't support PKCS#1 v1.5
+ serverConfig.ClientAuth = RequireAnyClientCert
+
+ // If RSA-PSS is selected, the handshake should fail.
+ if _, _, err := testHandshake(t, clientConfig, serverConfig); err == nil {
+ // RSA-PSS is temporarily disabled in TLS 1.2. See Issue 32425.
+ // t.Fatal("expected broken certificate to cause connection to fail")
+ }
+
+ clientConfig.Certificates[0].SupportedSignatureAlgorithms =
+ []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256}
+
+ // But if the certificate restricts supported algorithms, RSA-PSS should not
+ // be selected, and the handshake should succeed.
+ if _, _, err := testHandshake(t, clientConfig, serverConfig); err != nil {
+ t.Error(err)
+ }
+}