ssh: accept ed25519 certs

Change-Id: I1cb0146c4b741f6d489edcf86412001ffc007f4f
Reviewed-on: https://go-review.googlesource.com/82256
Reviewed-by: Han-Wen Nienhuys <hanwen@google.com>
Run-TryBot: Han-Wen Nienhuys <hanwen@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/ssh/certs_test.go b/ssh/certs_test.go
index 0200531..c8e7cf5 100644
--- a/ssh/certs_test.go
+++ b/ssh/certs_test.go
@@ -6,10 +6,15 @@
 
 import (
 	"bytes"
+	"crypto/ecdsa"
+	"crypto/elliptic"
 	"crypto/rand"
+	"net"
 	"reflect"
 	"testing"
 	"time"
+
+	"golang.org/x/crypto/ssh/testdata"
 )
 
 // Cert generated by ssh-keygen 6.0p1 Debian-4.
@@ -220,3 +225,111 @@
 		}
 	}
 }
+
+func TestCertTypes(t *testing.T) {
+	var testVars = []struct {
+		name string
+		keys func() Signer
+	}{
+		{
+			name: CertAlgoECDSA256v01,
+			keys: func() Signer {
+				s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap256"])
+				return s
+			},
+		},
+		{
+			name: CertAlgoECDSA384v01,
+			keys: func() Signer {
+				s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap384"])
+				return s
+			},
+		},
+		{
+			name: CertAlgoECDSA521v01,
+			keys: func() Signer {
+				s, _ := ParsePrivateKey(testdata.PEMBytes["ecdsap521"])
+				return s
+			},
+		},
+		{
+			name: CertAlgoED25519v01,
+			keys: func() Signer {
+				s, _ := ParsePrivateKey(testdata.PEMBytes["ed25519"])
+				return s
+			},
+		},
+		{
+			name: CertAlgoRSAv01,
+			keys: func() Signer {
+				s, _ := ParsePrivateKey(testdata.PEMBytes["rsa"])
+				return s
+			},
+		},
+		{
+			name: CertAlgoDSAv01,
+			keys: func() Signer {
+				s, _ := ParsePrivateKey(testdata.PEMBytes["dsa"])
+				return s
+			},
+		},
+	}
+
+	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	if err != nil {
+		t.Fatalf("error generating host key: %v", err)
+	}
+
+	signer, err := NewSignerFromKey(k)
+	if err != nil {
+		t.Fatalf("error generating signer for ssh listener: %v", err)
+	}
+
+	conf := &ServerConfig{
+		PublicKeyCallback: func(c ConnMetadata, k PublicKey) (*Permissions, error) {
+			return new(Permissions), nil
+		},
+	}
+	conf.AddHostKey(signer)
+
+	for _, m := range testVars {
+		t.Run(m.name, func(t *testing.T) {
+
+			c1, c2, err := netPipe()
+			if err != nil {
+				t.Fatalf("netPipe: %v", err)
+			}
+			defer c1.Close()
+			defer c2.Close()
+
+			go NewServerConn(c1, conf)
+
+			priv := m.keys()
+			if err != nil {
+				t.Fatalf("error generating ssh pubkey: %v", err)
+			}
+
+			cert := &Certificate{
+				CertType: UserCert,
+				Key:      priv.PublicKey(),
+			}
+			cert.SignCert(rand.Reader, priv)
+
+			certSigner, err := NewCertSigner(cert, priv)
+			if err != nil {
+				t.Fatalf("error generating cert signer: %v", err)
+			}
+
+			config := &ClientConfig{
+				User:            "user",
+				HostKeyCallback: func(h string, r net.Addr, k PublicKey) error { return nil },
+				Auth:            []AuthMethod{PublicKeys(certSigner)},
+			}
+
+			_, _, _, err = NewClientConn(c2, "", config)
+			if err != nil {
+				t.Fatalf("error connecting: %v", err)
+			}
+		})
+	}
+}
diff --git a/ssh/server.go b/ssh/server.go
index d4df916..b83d473 100644
--- a/ssh/server.go
+++ b/ssh/server.go
@@ -256,7 +256,7 @@
 func isAcceptableAlgo(algo string) bool {
 	switch algo {
 	case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519,
-		CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
+		CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
 		return true
 	}
 	return false
diff --git a/ssh/testdata/keys.go b/ssh/testdata/keys.go
index 3b3d26c..521b6be 100644
--- a/ssh/testdata/keys.go
+++ b/ssh/testdata/keys.go
@@ -24,6 +24,27 @@
 6/ZOXRnPmNAlLUqjShUsUBBngG0u2fqEqA==
 -----END EC PRIVATE KEY-----
 `),
+	"ecdsap256": []byte(`-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIAPCE25zK0PQSnsgVcEbM1mbKTASH4pqb5QJajplDwDZoAoGCCqGSM49
+AwEHoUQDQgAEWy8TxGcIHRh5XGpO4dFVfDjeNY+VkgubQrf/eyFJZHxAn1SKraXU
+qJUjTKj1z622OxYtJ5P7s9CfAEVsTzLCzg==
+-----END EC PRIVATE KEY-----
+`),
+	"ecdsap384": []byte(`-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDBWfSnMuNKq8J9rQLzzEkx3KAoEohSXqhE/4CdjEYtoU2i22HW80DDS
+qQhYNHRAduygBwYFK4EEACKhZANiAAQWaDMAd0HUd8ZiXCX7mYDDnC54gwH/nG43
+VhCUEYmF7HMZm/B9Yn3GjFk3qYEDEvuF/52+NvUKBKKaLbh32AWxMv0ibcoba4cz
+hL9+hWYhUD9XIUlzMWiZ2y6eBE9PdRI=
+-----END EC PRIVATE KEY-----
+`),
+	"ecdsap521": []byte(`-----BEGIN EC PRIVATE KEY-----
+MIHcAgEBBEIBrkYpQcy8KTVHNiAkjlFZwee90224Bu6wz94R4OBo+Ts0eoAQG7SF
+iaygEDMUbx6kTgXTBcKZ0jrWPKakayNZ/kigBwYFK4EEACOhgYkDgYYABADFuvLV
+UoaCDGHcw5uNfdRIsvaLKuWSpLsl48eWGZAwdNG432GDVKduO+pceuE+8XzcyJb+
+uMv+D2b11Q/LQUcHJwE6fqbm8m3EtDKPsoKs0u/XUJb0JsH4J8lkZzbUTjvGYamn
+FFlRjzoB3Oxu8UQgb+MWPedtH9XYBbg9biz4jJLkXQ==
+-----END EC PRIVATE KEY-----
+`),
 	"rsa": []byte(`-----BEGIN RSA PRIVATE KEY-----
 MIICXAIBAAKBgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2
 a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8