Commit ebe3d693 authored by Joël Stemmer's avatar Joël Stemmer Committed by Adam Langley

crypto/tls: return correct hash function when using client certificates in handshake

Commit f1d669ae added support for
AES_256_GCM_SHA384 cipher suites as specified in RFC5289. However, it
did not take the arbitrary hash function into account in the TLS client
handshake when using client certificates.

The hashForClientCertificate method always returned SHA256 as its
hashing function, even if it actually used a different one to calculate
its digest. Setting up the connection would eventually fail with the
error "tls: failed to sign handshake with client certificate:
crypto/rsa: input must be hashed message".

Included is an additional test for this specific situation that uses the
SHA384 hash.

Fixes #9808

Change-Id: Iccbf4ab225633471ef897907c208ad31f92855a3
Reviewed-on: https://go-review.googlesource.com/7040Reviewed-by: 's avatarAdam Langley <agl@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
parent 0a048ce5
......@@ -123,6 +123,7 @@ const (
const (
hashSHA1 uint8 = 2
hashSHA256 uint8 = 4
hashSHA384 uint8 = 5
)
// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
......
......@@ -344,6 +344,16 @@ func TestHandshakeClientCertRSA(t *testing.T) {
runClientTestTLS10(t, test)
runClientTestTLS12(t, test)
test = &clientTest{
name: "ClientCert-RSA-AES256-GCM-SHA384",
command: []string{"openssl", "s_server", "-cipher", "ECDHE-RSA-AES256-GCM-SHA384", "-verify", "1"},
config: &config,
cert: testRSACertificate,
key: testRSAPrivateKey,
}
runClientTestTLS12(t, test)
}
func TestHandshakeClientCertECDSA(t *testing.T) {
......
......@@ -169,16 +169,18 @@ func keysFromMasterSecret(version uint16, tls12Hash crypto.Hash, masterSecret, c
func newFinishedHash(version uint16, tls12Hash crypto.Hash) finishedHash {
if version >= VersionTLS12 {
return finishedHash{tls12Hash.New(), tls12Hash.New(), nil, nil, version, prfForVersion(version, tls12Hash)}
return finishedHash{tls12Hash.New(), tls12Hash.New(), tls12Hash, nil, nil, version, prfForVersion(version, tls12Hash)}
}
return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), version, prfForVersion(version, tls12Hash)}
return finishedHash{sha1.New(), sha1.New(), crypto.MD5SHA1, md5.New(), md5.New(), version, prfForVersion(version, tls12Hash)}
}
// A finishedHash calculates the hash of a set of handshake messages suitable
// for including in a Finished message.
type finishedHash struct {
client hash.Hash
server hash.Hash
server hash.Hash
serverHash crypto.Hash
// Prior to TLS 1.2, an additional MD5 hash is required.
clientMD5 hash.Hash
......@@ -279,7 +281,7 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte {
func (h finishedHash) hashForClientCertificate(sigType uint8) ([]byte, crypto.Hash, uint8) {
if h.version >= VersionTLS12 {
digest := h.server.Sum(nil)
return digest, crypto.SHA256, hashSHA256
return digest, h.serverHash, tls12HashID(h.serverHash)
}
if sigType == signatureECDSA {
digest := h.server.Sum(nil)
......@@ -291,3 +293,15 @@ func (h finishedHash) hashForClientCertificate(sigType uint8) ([]byte, crypto.Ha
digest = h.server.Sum(digest)
return digest, crypto.MD5SHA1, 0 /* not specified in TLS 1.2. */
}
// tls12HashID returns the HashAlgorithm id corresponding to the hash h, as
// specified in RFC 5246, section A.4.1.
func tls12HashID(h crypto.Hash) uint8 {
switch h {
case crypto.SHA256:
return hashSHA256
case crypto.SHA384:
return hashSHA384
}
return 0
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment