| // 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" | 
 |  | 
 | 	"./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) | 
 | } |