"crypto/ed25519"
"crypto/elliptic"
"crypto/rsa"
- "encoding/asn1"
"errors"
"fmt"
"hash"
"io"
+
+ "crypto/go.cypherpunks.ru/gogost/v5/gost3410"
)
// verifyHandshakeSignature verifies a signature against pre-hashed
if !ok {
return fmt.Errorf("expected an ECDSA public key, got %T", pubkey)
}
- ecdsaSig := new(ecdsaSignature)
- if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
- return err
- }
- if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
- return errors.New("ECDSA signature contained zero or negative values")
- }
- if !ecdsa.Verify(pubKey, signed, ecdsaSig.R, ecdsaSig.S) {
+ if !ecdsa.VerifyASN1(pubKey, signed, sig) {
return errors.New("ECDSA verification failure")
}
case signatureEd25519:
if err := rsa.VerifyPSS(pubKey, hashFunc, signed, sig, signOpts); err != nil {
return err
}
+ case signatureGOST:
+ pubKey, ok := pubkey.(*gost3410.PublicKey)
+ if !ok {
+ return fmt.Errorf("expected GOST public key, got %T", pubkey)
+ }
+ ok, err := gost3410.PublicKeyReverseDigestAndSignature{Pub: pubKey}.VerifyDigest(signed, sig)
+ if err != nil {
+ return err
+ }
+ if !ok {
+ return errors.New("tls: GOST verification failure")
+ }
default:
return errors.New("internal error: unknown signature type")
}
sigType = signatureECDSA
case Ed25519:
sigType = signatureEd25519
+ case GOSTR34102012256A, GOSTR34102012256B, GOSTR34102012256C, GOSTR34102012256D, GOSTR34102012512A, GOSTR34102012512B, GOSTR34102012512C:
+ sigType = signatureGOST
default:
- return 0, 0, fmt.Errorf("unsupported signature algorithm: %#04x", signatureAlgorithm)
+ return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm)
}
switch signatureAlgorithm {
case PKCS1WithSHA1, ECDSAWithSHA1:
hash = crypto.SHA512
case Ed25519:
hash = directSigning
+ case GOSTR34102012256A, GOSTR34102012256B, GOSTR34102012256C, GOSTR34102012256D:
+ hash = crypto.GOSTR34112012256
+ case GOSTR34102012512A, GOSTR34102012512B, GOSTR34102012512C:
+ hash = crypto.GOSTR34112012512
default:
- return 0, 0, fmt.Errorf("unsupported signature algorithm: %#04x", signatureAlgorithm)
+ return 0, 0, fmt.Errorf("unsupported signature algorithm: %v", signatureAlgorithm)
}
return sigType, hash, nil
}
}
}
+var rsaSignatureSchemes = []struct {
+ scheme SignatureScheme
+ minModulusBytes int
+ maxVersion uint16
+}{
+ // RSA-PSS is used with PSSSaltLengthEqualsHash, and requires
+ // emLen >= hLen + sLen + 2
+ {PSSWithSHA256, crypto.SHA256.Size()*2 + 2, VersionTLS13},
+ {PSSWithSHA384, crypto.SHA384.Size()*2 + 2, VersionTLS13},
+ {PSSWithSHA512, crypto.SHA512.Size()*2 + 2, VersionTLS13},
+ // PKCS #1 v1.5 uses prefixes from hashPrefixes in crypto/rsa, and requires
+ // emLen >= len(prefix) + hLen + 11
+ // TLS 1.3 dropped support for PKCS #1 v1.5 in favor of RSA-PSS.
+ {PKCS1WithSHA256, 19 + crypto.SHA256.Size() + 11, VersionTLS12},
+ {PKCS1WithSHA384, 19 + crypto.SHA384.Size() + 11, VersionTLS12},
+ {PKCS1WithSHA512, 19 + crypto.SHA512.Size() + 11, VersionTLS12},
+ {PKCS1WithSHA1, 15 + crypto.SHA1.Size() + 11, VersionTLS12},
+}
+
// 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.
+// FIPS filtering is applied in the caller, selectSignatureScheme.
func signatureSchemesForCertificate(version uint16, cert *Certificate) []SignatureScheme {
priv, ok := cert.PrivateKey.(crypto.Signer)
if !ok {
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{
- // Temporarily disable RSA-PSS in TLS 1.2, see Issue 32425.
- // PSSWithSHA256,
- // PSSWithSHA384,
- // PSSWithSHA512,
- PKCS1WithSHA256,
- PKCS1WithSHA384,
- PKCS1WithSHA512,
- PKCS1WithSHA1,
+ size := pub.Size()
+ sigAlgs = make([]SignatureScheme, 0, len(rsaSignatureSchemes))
+ for _, candidate := range rsaSignatureSchemes {
+ if size >= candidate.minModulusBytes && version <= candidate.maxVersion {
+ sigAlgs = append(sigAlgs, candidate.scheme)
}
}
- // TLS 1.3 dropped support for PKCS#1 v1.5 in favor of RSA-PSS.
- return []SignatureScheme{
- PSSWithSHA256,
- PSSWithSHA384,
- PSSWithSHA512,
- }
case ed25519.PublicKey:
- return []SignatureScheme{Ed25519}
+ sigAlgs = []SignatureScheme{Ed25519}
+ case *gost3410.PublicKey:
+ switch pub.C.Name {
+ case "id-tc26-gost-3410-12-256-paramSetA":
+ return []SignatureScheme{GOSTR34102012256A}
+ case "id-tc26-gost-3410-12-256-paramSetB":
+ return []SignatureScheme{GOSTR34102012256B}
+ case "id-tc26-gost-3410-12-256-paramSetC":
+ return []SignatureScheme{GOSTR34102012256C}
+ case "id-tc26-gost-3410-12-256-paramSetD":
+ return []SignatureScheme{GOSTR34102012256D}
+ case "id-tc26-gost-3410-12-512-paramSetA":
+ return []SignatureScheme{GOSTR34102012512A}
+ case "id-tc26-gost-3410-12-512-paramSetB":
+ return []SignatureScheme{GOSTR34102012512B}
+ case "id-tc26-gost-3410-12-512-paramSetC":
+ return []SignatureScheme{GOSTR34102012512C}
+ default:
+ return nil
+ }
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 {
// Pick signature scheme in the peer's preference order, as our
// preference order is not configurable.
for _, preferredAlg := range peerAlgs {
+ if needFIPS() && !isSupportedSignatureAlgorithm(preferredAlg, fipsSupportedSignatureAlgorithms) {
+ continue
+ }
if isSupportedSignatureAlgorithm(preferredAlg, supportedAlgs) {
return preferredAlg, nil
}
return fmt.Errorf("tls: unsupported certificate curve (%s)", pub.Curve.Params().Name)
}
case *rsa.PublicKey:
+ return fmt.Errorf("tls: certificate RSA key size too small for supported signature algorithms")
case ed25519.PublicKey:
+ case *gost3410.PublicKey:
default:
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)
}