mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
crypto/tls: consolidate signatures handling in SKE and CV
ServerKeyExchange and CertificateVerify can share the same logic for picking a signature algorithm (based on the certificate public key and advertised algorithms), selecting a hash algorithm (depending on TLS version) and signature verification. Refactor the code to achieve code reuse, have common error checking (especially for intersecting supported signature algorithms) and to prepare for addition of new signature algorithms. Code should be easier to read since version-dependent logic is concentrated at one place. Change-Id: I978dec3815d28e33c3cfbc85f0c704b1894c25a3 Reviewed-on: https://go-review.googlesource.com/79735 Reviewed-by: Filippo Valsorda <filippo@golang.org> Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
3ca5b7c5b2
commit
c89d75f981
6 changed files with 245 additions and 198 deletions
|
|
@ -10,7 +10,6 @@ import (
|
|||
"crypto/rsa"
|
||||
"crypto/subtle"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
|
@ -520,59 +519,15 @@ func (hs *serverHandshakeState) doFullHandshake() error {
|
|||
}
|
||||
|
||||
// Determine the signature type.
|
||||
var signatureAlgorithm SignatureScheme
|
||||
var sigType uint8
|
||||
if certVerify.hasSignatureAndHash {
|
||||
signatureAlgorithm = certVerify.signatureAlgorithm
|
||||
if !isSupportedSignatureAlgorithm(signatureAlgorithm, supportedSignatureAlgorithms) {
|
||||
return errors.New("tls: unsupported hash function for client certificate")
|
||||
}
|
||||
sigType = signatureFromSignatureScheme(signatureAlgorithm)
|
||||
} else {
|
||||
// Before TLS 1.2 the signature algorithm was implicit
|
||||
// from the key type, and only one hash per signature
|
||||
// algorithm was possible. Leave signatureAlgorithm
|
||||
// unset.
|
||||
switch pub.(type) {
|
||||
case *ecdsa.PublicKey:
|
||||
sigType = signatureECDSA
|
||||
case *rsa.PublicKey:
|
||||
sigType = signatureRSA
|
||||
}
|
||||
_, sigType, hashFunc, err := pickSignatureAlgorithm(pub, []SignatureScheme{certVerify.signatureAlgorithm}, supportedSignatureAlgorithms, c.vers)
|
||||
if err != nil {
|
||||
c.sendAlert(alertIllegalParameter)
|
||||
return err
|
||||
}
|
||||
|
||||
switch key := pub.(type) {
|
||||
case *ecdsa.PublicKey:
|
||||
if sigType != signatureECDSA {
|
||||
err = errors.New("tls: bad signature type for client's ECDSA certificate")
|
||||
break
|
||||
}
|
||||
ecdsaSig := new(ecdsaSignature)
|
||||
if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
|
||||
break
|
||||
}
|
||||
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
|
||||
err = errors.New("tls: ECDSA signature contained zero or negative values")
|
||||
break
|
||||
}
|
||||
var digest []byte
|
||||
if digest, _, err = hs.finishedHash.hashForClientCertificate(sigType, signatureAlgorithm, hs.masterSecret); err != nil {
|
||||
break
|
||||
}
|
||||
if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
|
||||
err = errors.New("tls: ECDSA verification failure")
|
||||
}
|
||||
case *rsa.PublicKey:
|
||||
if sigType != signatureRSA {
|
||||
err = errors.New("tls: bad signature type for client's RSA certificate")
|
||||
break
|
||||
}
|
||||
var digest []byte
|
||||
var hashFunc crypto.Hash
|
||||
if digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(sigType, signatureAlgorithm, hs.masterSecret); err != nil {
|
||||
break
|
||||
}
|
||||
err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
|
||||
var digest []byte
|
||||
if digest, err = hs.finishedHash.hashForClientCertificate(sigType, hashFunc, hs.masterSecret); err == nil {
|
||||
err = verifyHandshakeSignature(sigType, pub, hashFunc, digest, certVerify.signature)
|
||||
}
|
||||
if err != nil {
|
||||
c.sendAlert(alertBadCertificate)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue