2016-06-21 23:19:24 +01:00
|
|
|
// 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"
|
2016-07-09 02:52:12 +01:00
|
|
|
"crypto/elliptic"
|
2016-06-21 23:19:24 +01:00
|
|
|
"crypto/md5"
|
|
|
|
"crypto/rsa"
|
|
|
|
"crypto/sha1"
|
|
|
|
_ "crypto/sha256"
|
|
|
|
_ "crypto/sha512"
|
|
|
|
"encoding/asn1"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"math/big"
|
|
|
|
)
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-07-09 02:52:12 +01:00
|
|
|
func selectSignatureAlgorithm(version uint16, key crypto.PrivateKey, config *Config, peerSigAlgs, ourSigAlgs []signatureAlgorithm) (signatureAlgorithm, error) {
|
2016-06-21 23:19:24 +01:00
|
|
|
// 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 ourSigAlgs {
|
|
|
|
if !isSupportedSignatureAlgorithm(sigAlg, peerSigAlgs) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2016-07-09 02:52:12 +01:00
|
|
|
signer, err := getSigner(version, key, config, sigAlg)
|
2016-06-21 23:19:24 +01:00
|
|
|
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) {
|
2016-07-09 02:52:12 +01:00
|
|
|
signer, err := getSigner(version, key, config, sigAlg)
|
2016-06-21 23:19:24 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return signer.signMessage(key, config, msg)
|
|
|
|
}
|
|
|
|
|
2016-07-09 02:52:12 +01:00
|
|
|
func verifyMessage(version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error {
|
|
|
|
signer, err := getSigner(version, key, config, sigAlg)
|
2016-06-21 23:19:24 +01:00
|
|
|
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 {
|
2016-07-09 02:52:12 +01:00
|
|
|
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
|
2016-06-21 23:19:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ecdsaSigner) supportsKey(key crypto.PrivateKey) bool {
|
2016-07-09 02:52:12 +01:00
|
|
|
ecdsaKey, ok := key.(*ecdsa.PrivateKey)
|
|
|
|
return ok && e.isCurveValid(ecdsaKey.Curve)
|
2016-06-21 23:19:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
2016-07-09 02:52:12 +01:00
|
|
|
if !e.isCurveValid(ecdsaKey.Curve) {
|
|
|
|
return nil, errors.New("invalid curve for ECDSA")
|
|
|
|
}
|
2016-06-21 23:19:24 +01:00
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
2016-07-09 02:52:12 +01:00
|
|
|
if !e.isCurveValid(ecdsaKey.Curve) {
|
|
|
|
return errors.New("invalid curve for ECDSA")
|
|
|
|
}
|
2016-06-21 23:19:24 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2016-06-30 23:30:40 +01:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2016-07-09 02:52:12 +01:00
|
|
|
func getSigner(version uint16, key interface{}, config *Config, sigAlg signatureAlgorithm) (signer, error) {
|
2016-06-21 23:19:24 +01:00
|
|
|
// TLS 1.1 and below use legacy signature algorithms.
|
|
|
|
if version < VersionTLS12 {
|
|
|
|
switch key.(type) {
|
|
|
|
case *rsa.PrivateKey, *rsa.PublicKey:
|
|
|
|
return &rsaPKCS1Signer{crypto.MD5SHA1}, nil
|
|
|
|
case *ecdsa.PrivateKey, *ecdsa.PublicKey:
|
2016-07-09 02:52:12 +01:00
|
|
|
return &ecdsaSigner{version, config, nil, crypto.SHA1}, nil
|
2016-06-21 23:19:24 +01:00
|
|
|
default:
|
|
|
|
return nil, errors.New("unknown key type")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-30 23:30:40 +01:00
|
|
|
// TODO(davidben): Forbid RSASSA-PKCS1-v1_5 in TLS 1.3.
|
2016-06-21 23:19:24 +01:00
|
|
|
switch sigAlg {
|
|
|
|
case signatureRSAPKCS1WithMD5:
|
|
|
|
return &rsaPKCS1Signer{crypto.MD5}, nil
|
|
|
|
case signatureRSAPKCS1WithSHA1:
|
|
|
|
return &rsaPKCS1Signer{crypto.SHA1}, nil
|
|
|
|
case signatureRSAPKCS1WithSHA256:
|
|
|
|
return &rsaPKCS1Signer{crypto.SHA256}, nil
|
|
|
|
case signatureRSAPKCS1WithSHA384:
|
|
|
|
return &rsaPKCS1Signer{crypto.SHA384}, nil
|
|
|
|
case signatureRSAPKCS1WithSHA512:
|
|
|
|
return &rsaPKCS1Signer{crypto.SHA512}, nil
|
|
|
|
case signatureECDSAWithSHA1:
|
2016-07-09 02:52:12 +01:00
|
|
|
return &ecdsaSigner{version, config, nil, crypto.SHA1}, nil
|
2016-06-21 23:19:24 +01:00
|
|
|
case signatureECDSAWithP256AndSHA256:
|
2016-07-09 02:52:12 +01:00
|
|
|
return &ecdsaSigner{version, config, elliptic.P256(), crypto.SHA256}, nil
|
2016-06-21 23:19:24 +01:00
|
|
|
case signatureECDSAWithP384AndSHA384:
|
2016-07-09 02:52:12 +01:00
|
|
|
return &ecdsaSigner{version, config, elliptic.P384(), crypto.SHA384}, nil
|
2016-06-21 23:19:24 +01:00
|
|
|
case signatureECDSAWithP521AndSHA512:
|
2016-07-09 02:52:12 +01:00
|
|
|
return &ecdsaSigner{version, config, elliptic.P521(), crypto.SHA512}, nil
|
2016-06-30 23:30:40 +01:00
|
|
|
case signatureRSAPSSWithSHA256:
|
|
|
|
if version >= VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
|
|
|
|
return &rsaPSSSigner{crypto.SHA256}, nil
|
|
|
|
}
|
|
|
|
case signatureRSAPSSWithSHA384:
|
|
|
|
if version >= VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
|
|
|
|
return &rsaPSSSigner{crypto.SHA384}, nil
|
|
|
|
}
|
|
|
|
case signatureRSAPSSWithSHA512:
|
|
|
|
if version >= VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
|
|
|
|
return &rsaPSSSigner{crypto.SHA512}, nil
|
|
|
|
}
|
2016-06-21 23:19:24 +01:00
|
|
|
}
|
2016-06-30 23:30:40 +01:00
|
|
|
|
|
|
|
return nil, fmt.Errorf("unsupported signature algorithm %04x", sigAlg)
|
2016-06-21 23:19:24 +01:00
|
|
|
}
|