aboutsummaryrefslogtreecommitdiff
path: root/src/crypto/tls/key_agreement.go
diff options
context:
space:
mode:
authorFilippo Valsorda <filippo@golang.org>2019-05-16 19:13:29 -0400
committerFilippo Valsorda <filippo@golang.org>2019-05-17 16:13:45 +0000
commitf35338582d0e0e7047fa45be3cb8064c43c50f25 (patch)
tree591f08ef243b8afb1ff450b1277b5ba726080f30 /src/crypto/tls/key_agreement.go
parentee551846fa015a04aaa55e44e8d9b6647156e301 (diff)
downloadgo-f35338582d0e0e7047fa45be3cb8064c43c50f25.tar.gz
go-f35338582d0e0e7047fa45be3cb8064c43c50f25.zip
crypto/tls: add support for Ed25519 certificates in TLS 1.2 and 1.3
Support for Ed25519 certificates was added in CL 175478, this wires them up into the TLS stack according to RFC 8422 (TLS 1.2) and RFC 8446 (TLS 1.3). RFC 8422 also specifies support for TLS 1.0 and 1.1, and I initially implemented that, but even OpenSSL doesn't take the complexity, so I just dropped it. It would have required keeping a buffer of the handshake transcript in order to do the direct Ed25519 signatures. We effectively need to support TLS 1.2 because it shares ClientHello signature algorithms with TLS 1.3. While at it, reordered the advertised signature algorithms in the rough order we would want to use them, also based on what curves have fast constant-time implementations. Client and client auth tests changed because of the change in advertised signature algorithms in ClientHello and CertificateRequest. Fixes #25355 Change-Id: I9fdd839afde4fd6b13fcbc5cc7017fd8c35085ee Reviewed-on: https://go-review.googlesource.com/c/go/+/177698 Run-TryBot: Filippo Valsorda <filippo@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Adam Langley <agl@golang.org>
Diffstat (limited to 'src/crypto/tls/key_agreement.go')
-rw-r--r--src/crypto/tls/key_agreement.go20
1 files changed, 14 insertions, 6 deletions
diff --git a/src/crypto/tls/key_agreement.go b/src/crypto/tls/key_agreement.go
index 488401d038..7428f3bccc 100644
--- a/src/crypto/tls/key_agreement.go
+++ b/src/crypto/tls/key_agreement.go
@@ -105,8 +105,16 @@ func md5SHA1Hash(slices [][]byte) []byte {
// hashForServerKeyExchange hashes the given slices and returns their digest
// using the given hash function (for >= TLS 1.2) or using a default based on
-// the sigType (for earlier TLS versions).
+// the sigType (for earlier TLS versions). For Ed25519 signatures, which don't
+// do pre-hashing, it returns the concatenation of the slices.
func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) []byte {
+ if sigType == signatureEd25519 {
+ var signed []byte
+ for _, slice := range slices {
+ signed = append(signed, slice...)
+ }
+ return signed
+ }
if version >= VersionTLS12 {
h := hashFunc.New()
for _, slice := range slices {
@@ -124,7 +132,7 @@ func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint1
// ecdheKeyAgreement implements a TLS key agreement where the server
// generates an ephemeral EC public/private key pair and signs it. The
// pre-master secret is then calculated using ECDH. The signature may
-// either be ECDSA or RSA.
+// be ECDSA, Ed25519 or RSA.
type ecdheKeyAgreement struct {
version uint16
isRSA bool
@@ -185,13 +193,13 @@ NextCandidate:
return nil, errors.New("tls: certificate cannot be used with the selected cipher suite")
}
- digest := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, hello.random, serverECDHParams)
+ signed := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, hello.random, serverECDHParams)
signOpts := crypto.SignerOpts(hashFunc)
if sigType == signatureRSAPSS {
signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc}
}
- sig, err := priv.Sign(config.rand(), digest, signOpts)
+ sig, err := priv.Sign(config.rand(), signed, signOpts)
if err != nil {
return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error())
}
@@ -294,8 +302,8 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
}
sig = sig[2:]
- digest := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, serverHello.random, serverECDHParams)
- return verifyHandshakeSignature(sigType, cert.PublicKey, hashFunc, digest, sig)
+ signed := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, serverHello.random, serverECDHParams)
+ return verifyHandshakeSignature(sigType, cert.PublicKey, hashFunc, signed, sig)
}
func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {