69522117a6
This only works at TLS 1.2 and above as, before TLS 1.2, there is no way to advertise support for Ed25519 or negotiate the correct signature algorithm. Add tests for this accordingly. For now, this is disabled by default on the verifying side but may be enabled per SSL_CTX. Notably, projects like Chromium which use an external verifier may need changes elsewhere before they can enable it. (On the signing side, we can assume that if the caller gave us an Ed25519 certificate, they mean for us to use it.) BUG=187 Change-Id: Id25b0a677dcbe205ddd26d8dbba11c04bb520756 Reviewed-on: https://boringssl-review.googlesource.com/14450 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
335 lines
9.2 KiB
Go
335 lines
9.2 KiB
Go
// 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)
|
|
}
|