"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,
// 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
}
case *rsa.PublicKey:
- if version != VersionTLS13 {
- sigAlgs = []SignatureScheme{
- 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)
}
- break
- }
- // TLS 1.3 dropped support for PKCS#1 v1.5 in favor of RSA-PSS.
- sigAlgs = []SignatureScheme{
- PSSWithSHA256,
- PSSWithSHA384,
- PSSWithSHA512,
}
case ed25519.PublicKey:
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
}
// 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)
}