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>
This commit is contained in:
Filippo Valsorda 2019-05-16 19:13:29 -04:00
parent 6c11745f0b
commit 28958b0da6
84 changed files with 4977 additions and 3938 deletions

View file

@ -11,6 +11,7 @@ package main
import (
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
@ -18,7 +19,6 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"flag"
"fmt"
"log"
"math/big"
"net"
@ -34,6 +34,7 @@ var (
isCA = flag.Bool("ca", false, "whether this cert should be its own Certificate Authority")
rsaBits = flag.Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set")
ecdsaCurve = flag.String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521")
ed25519Key = flag.Bool("ed25519", false, "Generate an Ed25519 key")
)
func publicKey(priv interface{}) interface{} {
@ -42,22 +43,8 @@ func publicKey(priv interface{}) interface{} {
return &k.PublicKey
case *ecdsa.PrivateKey:
return &k.PublicKey
default:
return nil
}
}
func pemBlockForKey(priv interface{}) *pem.Block {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
case *ecdsa.PrivateKey:
b, err := x509.MarshalECPrivateKey(k)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to marshal ECDSA private key: %v", err)
os.Exit(2)
}
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
case ed25519.PrivateKey:
return k.Public().(ed25519.PublicKey)
default:
return nil
}
@ -74,7 +61,11 @@ func main() {
var err error
switch *ecdsaCurve {
case "":
priv, err = rsa.GenerateKey(rand.Reader, *rsaBits)
if *ed25519Key {
_, priv, err = ed25519.GenerateKey(rand.Reader)
} else {
priv, err = rsa.GenerateKey(rand.Reader, *rsaBits)
}
case "P224":
priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
case "P256":
@ -84,11 +75,10 @@ func main() {
case "P521":
priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
default:
fmt.Fprintf(os.Stderr, "Unrecognized elliptic curve: %q", *ecdsaCurve)
os.Exit(1)
log.Fatalf("Unrecognized elliptic curve: %q", *ecdsaCurve)
}
if err != nil {
log.Fatalf("failed to generate private key: %s", err)
log.Fatalf("Failed to generate private key: %s", err)
}
var notBefore time.Time
@ -97,8 +87,7 @@ func main() {
} else {
notBefore, err = time.Parse("Jan 2 15:04:05 2006", *validFrom)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err)
os.Exit(1)
log.Fatalf("Failed to parse creation date: %s", err)
}
}
@ -107,7 +96,7 @@ func main() {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
log.Fatalf("failed to generate serial number: %s", err)
log.Fatalf("Failed to generate serial number: %s", err)
}
template := x509.Certificate{
@ -144,26 +133,30 @@ func main() {
certOut, err := os.Create("cert.pem")
if err != nil {
log.Fatalf("failed to open cert.pem for writing: %s", err)
log.Fatalf("Failed to open cert.pem for writing: %s", err)
}
if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
log.Fatalf("failed to write data to cert.pem: %s", err)
log.Fatalf("Failed to write data to cert.pem: %s", err)
}
if err := certOut.Close(); err != nil {
log.Fatalf("error closing cert.pem: %s", err)
log.Fatalf("Error closing cert.pem: %s", err)
}
log.Print("wrote cert.pem\n")
keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Print("failed to open key.pem for writing:", err)
log.Fatalf("Failed to open key.pem for writing:", err)
return
}
if err := pem.Encode(keyOut, pemBlockForKey(priv)); err != nil {
log.Fatalf("failed to write data to key.pem: %s", err)
privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
log.Fatalf("Unable to marshal private key: %v", err)
}
if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil {
log.Fatalf("Failed to write data to key.pem: %s", err)
}
if err := keyOut.Close(); err != nil {
log.Fatalf("error closing key.pem: %s", err)
log.Fatalf("Error closing key.pem: %s", err)
}
log.Print("wrote key.pem\n")
}