"crypto/rsa"
"crypto/subtle"
"crypto/x509"
- "encoding/asn1"
"errors"
"fmt"
"io"
}
// 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)