// Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package runner import ( "crypto" "crypto/ecdsa" "crypto/elliptic" "crypto/md5" "crypto/rsa" "crypto/sha1" _ "crypto/sha256" _ "crypto/sha512" "encoding/asn1" "errors" "fmt" "math/big" "boringssl.googlesource.com/boringssl/ssl/test/runner/ed25519" ) type signer interface { supportsKey(key crypto.PrivateKey) bool signMessage(key crypto.PrivateKey, config *Config, msg []byte) ([]byte, error) verifyMessage(key crypto.PublicKey, msg, sig []byte) error } func selectSignatureAlgorithm(version uint16, key crypto.PrivateKey, 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 if len(peerSigAlgs) == 0 { peerSigAlgs = []signatureAlgorithm{signatureRSAPKCS1WithSHA1, signatureECDSAWithSHA1} } for _, sigAlg := range config.signSignatureAlgorithms() { if !isSupportedSignatureAlgorithm(sigAlg, peerSigAlgs) { continue } signer, err := getSigner(version, key, config, sigAlg, false) if err != nil { continue } if signer.supportsKey(key) { return sigAlg, nil } } return 0, errors.New("tls: no common signature algorithms") } func signMessage(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) newMsg[0] ^= 0x80 msg = newMsg } signer, err := getSigner(version, key, config, sigAlg, false) if err != nil { return nil, err } return signer.signMessage(key, config, msg) } func verifyMessage(version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error { if version >= VersionTLS12 && !isSupportedSignatureAlgorithm(sigAlg, config.verifySignatureAlgorithms()) { return errors.New("tls: unsupported signature algorithm") } signer, err := getSigner(version, key, config, sigAlg, true) if err != nil { return err } return signer.verifyMessage(key, msg, sig) } type rsaPKCS1Signer struct { hash crypto.Hash } func (r *rsaPKCS1Signer) computeHash(msg []byte) []byte { if r.hash == crypto.MD5SHA1 { // crypto.MD5SHA1 is not a real hash function. hashMD5 := md5.New() hashMD5.Write(msg) hashSHA1 := sha1.New() hashSHA1.Write(msg) return hashSHA1.Sum(hashMD5.Sum(nil)) } h := r.hash.New() h.Write(msg) return h.Sum(nil) } func (r *rsaPKCS1Signer) supportsKey(key crypto.PrivateKey) bool { _, ok := key.(*rsa.PrivateKey) return ok } func (r *rsaPKCS1Signer) signMessage(key crypto.PrivateKey, config *Config, msg []byte) ([]byte, error) { rsaKey, ok := key.(*rsa.PrivateKey) if !ok { return nil, errors.New("invalid key type for RSA-PKCS1") } return rsa.SignPKCS1v15(config.rand(), rsaKey, r.hash, r.computeHash(msg)) } func (r *rsaPKCS1Signer) verifyMessage(key crypto.PublicKey, msg, sig []byte) error { rsaKey, ok := key.(*rsa.PublicKey) if !ok { return errors.New("invalid key type for RSA-PKCS1") } return rsa.VerifyPKCS1v15(rsaKey, r.hash, r.computeHash(msg), sig) } type ecdsaSigner struct { version uint16 config *Config curve elliptic.Curve hash crypto.Hash } func (e *ecdsaSigner) isCurveValid(curve elliptic.Curve) bool { if e.config.Bugs.SkipECDSACurveCheck { return true } if e.version <= VersionTLS12 { return true } return e.curve != nil && curve == e.curve } func (e *ecdsaSigner) supportsKey(key crypto.PrivateKey) bool { ecdsaKey, ok := key.(*ecdsa.PrivateKey) return ok && e.isCurveValid(ecdsaKey.Curve) } func maybeCorruptECDSAValue(n *big.Int, typeOfCorruption BadValue, limit *big.Int) *big.Int { switch typeOfCorruption { case BadValueNone: return n case BadValueNegative: return new(big.Int).Neg(n) case BadValueZero: return big.NewInt(0) case BadValueLimit: return limit case BadValueLarge: bad := new(big.Int).Set(limit) return bad.Lsh(bad, 20) default: panic("unknown BadValue type") } } func (e *ecdsaSigner) signMessage(key crypto.PrivateKey, config *Config, msg []byte) ([]byte, error) { ecdsaKey, ok := key.(*ecdsa.PrivateKey) if !ok { return nil, errors.New("invalid key type for ECDSA") } if !e.isCurveValid(ecdsaKey.Curve) { return nil, errors.New("invalid curve for ECDSA") } h := e.hash.New() h.Write(msg) digest := h.Sum(nil) r, s, err := ecdsa.Sign(config.rand(), ecdsaKey, digest) if err != nil { return nil, errors.New("failed to sign ECDHE parameters: " + err.Error()) } order := ecdsaKey.Curve.Params().N r = maybeCorruptECDSAValue(r, config.Bugs.BadECDSAR, order) s = maybeCorruptECDSAValue(s, config.Bugs.BadECDSAS, order) return asn1.Marshal(ecdsaSignature{r, s}) } func (e *ecdsaSigner) verifyMessage(key crypto.PublicKey, msg, sig []byte) error { ecdsaKey, ok := key.(*ecdsa.PublicKey) if !ok { return errors.New("invalid key type for ECDSA") } if !e.isCurveValid(ecdsaKey.Curve) { return errors.New("invalid curve for ECDSA") } 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") } h := e.hash.New() h.Write(msg) if !ecdsa.Verify(ecdsaKey, h.Sum(nil), ecdsaSig.R, ecdsaSig.S) { return errors.New("ECDSA verification failure") } return nil } var pssOptions = rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash} type rsaPSSSigner struct { hash crypto.Hash } func (r *rsaPSSSigner) supportsKey(key crypto.PrivateKey) bool { _, ok := key.(*rsa.PrivateKey) return ok } func (r *rsaPSSSigner) signMessage(key crypto.PrivateKey, config *Config, msg []byte) ([]byte, error) { rsaKey, ok := key.(*rsa.PrivateKey) if !ok { return nil, errors.New("invalid key type for RSA-PSS") } h := r.hash.New() h.Write(msg) return rsa.SignPSS(config.rand(), rsaKey, r.hash, h.Sum(nil), &pssOptions) } func (r *rsaPSSSigner) verifyMessage(key crypto.PublicKey, msg, sig []byte) error { rsaKey, ok := key.(*rsa.PublicKey) if !ok { return errors.New("invalid key type for RSA-PSS") } h := r.hash.New() h.Write(msg) return rsa.VerifyPSS(rsaKey, r.hash, h.Sum(nil), sig, &pssOptions) } type ed25519Signer struct{} func (e *ed25519Signer) supportsKey(key crypto.PrivateKey) bool { _, ok := key.(ed25519.PrivateKey) return ok } func (e *ed25519Signer) signMessage(key crypto.PrivateKey, config *Config, msg []byte) ([]byte, error) { privKey, ok := key.(ed25519.PrivateKey) if !ok { return nil, errors.New("invalid key type for Ed25519") } return ed25519.Sign(privKey, msg), nil } func (e *ed25519Signer) verifyMessage(key crypto.PublicKey, msg, sig []byte) error { pubKey, ok := key.(ed25519.PublicKey) if !ok { return errors.New("invalid key type for Ed25519") } if !ed25519.Verify(pubKey, msg, sig) { return errors.New("invalid Ed25519 signature") } return nil } func getSigner(version uint16, key interface{}, config *Config, sigAlg signatureAlgorithm, isVerify bool) (signer, error) { // TLS 1.1 and below use legacy signature algorithms. if version < VersionTLS12 { if config.Bugs.UseLegacySigningAlgorithm == 0 || isVerify { switch key.(type) { case *rsa.PrivateKey, *rsa.PublicKey: return &rsaPKCS1Signer{crypto.MD5SHA1}, nil case *ecdsa.PrivateKey, *ecdsa.PublicKey: return &ecdsaSigner{version, config, nil, crypto.SHA1}, nil default: return nil, errors.New("unknown key type") } } // Fall through, forcing a particular algorithm. sigAlg = config.Bugs.UseLegacySigningAlgorithm } switch sigAlg { case signatureRSAPKCS1WithMD5: if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks { return &rsaPKCS1Signer{crypto.MD5}, nil } case signatureRSAPKCS1WithSHA1: if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks { return &rsaPKCS1Signer{crypto.SHA1}, nil } case signatureRSAPKCS1WithSHA256: if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks { return &rsaPKCS1Signer{crypto.SHA256}, nil } case signatureRSAPKCS1WithSHA384: if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks { return &rsaPKCS1Signer{crypto.SHA384}, nil } case signatureRSAPKCS1WithSHA512: if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks { return &rsaPKCS1Signer{crypto.SHA512}, nil } case signatureECDSAWithSHA1: return &ecdsaSigner{version, config, nil, crypto.SHA1}, nil case signatureECDSAWithP256AndSHA256: return &ecdsaSigner{version, config, elliptic.P256(), crypto.SHA256}, nil case signatureECDSAWithP384AndSHA384: return &ecdsaSigner{version, config, elliptic.P384(), crypto.SHA384}, nil case signatureECDSAWithP521AndSHA512: return &ecdsaSigner{version, config, elliptic.P521(), crypto.SHA512}, nil case signatureRSAPSSWithSHA256: return &rsaPSSSigner{crypto.SHA256}, nil case signatureRSAPSSWithSHA384: return &rsaPSSSigner{crypto.SHA384}, nil case signatureRSAPSSWithSHA512: return &rsaPSSSigner{crypto.SHA512}, nil case signatureEd25519: return &ed25519Signer{}, nil } return nil, fmt.Errorf("unsupported signature algorithm %04x", sigAlg) }