ssh: fix error message on unsupported cipher

Until now, when ssh keys using one of these[1] ciphers were passed, we were
giving a parse error "ssh: parse error in message type 0".

With this fix, we parse it successfully and return the correct error message.

[1] aes{128,256}-gcm@openssh.com and chacha20-poly1305@openssh.com

Fixes golang/go#52135

Change-Id: I3010fff43c48f29f21edb8d63f44e167861a054e
GitHub-Last-Rev: 14ac7e97306d41cba48053b9c60f2ffc7caded45
GitHub-Pull-Request: golang/crypto#324
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/709275
Reviewed-by: Nicola Murino <nicola.murino@gmail.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Auto-Submit: Nicola Murino <nicola.murino@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/ssh/keys.go b/ssh/keys.go
index a035956..47a0753 100644
--- a/ssh/keys.go
+++ b/ssh/keys.go
@@ -1490,6 +1490,7 @@
 	NumKeys      uint32
 	PubKey       []byte
 	PrivKeyBlock []byte
+	Rest         []byte `ssh:"rest"`
 }
 
 type openSSHPrivateKey struct {
diff --git a/ssh/keys_test.go b/ssh/keys_test.go
index 661e3cb..a1165ec 100644
--- a/ssh/keys_test.go
+++ b/ssh/keys_test.go
@@ -271,6 +271,21 @@
 	}
 }
 
+func TestParseEncryptedPrivateKeysWithUnsupportedCiphers(t *testing.T) {
+    for _, tt := range testdata.UnsupportedCipherData {
+        t.Run(tt.Name, func(t *testing.T){
+            _, err := ParsePrivateKeyWithPassphrase(tt.PEMBytes, []byte(tt.EncryptionKey))
+            if err == nil {
+                t.Fatalf("expected 'unknown cipher' error for %q, got nil", tt.Name)
+                // If this cipher is now supported, remove it from testdata.UnsupportedCipherData
+            }
+            if !strings.Contains(err.Error(), "unknown cipher") {
+                t.Errorf("wanted 'unknown cipher' error, got %v", err.Error())
+            }
+        })
+    }
+}
+
 func TestParseEncryptedPrivateKeysWithIncorrectPassphrase(t *testing.T) {
 	pem := testdata.PEMEncryptedKeys[0].PEMBytes
 	for i := 0; i < 4096; i++ {
diff --git a/ssh/testdata/keys.go b/ssh/testdata/keys.go
index 6e48841..adb4244 100644
--- a/ssh/testdata/keys.go
+++ b/ssh/testdata/keys.go
@@ -310,6 +310,53 @@
 	},
 }
 
+var UnsupportedCipherData = []struct {
+    Name string
+    EncryptionKey string
+    PEMBytes []byte
+} {
+	0: {
+		Name:              "ed25519-encrypted-chacha20-poly1305",
+		EncryptionKey:     "password",
+		PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAAHWNoYWNoYTIwLXBvbHkxMzA1QG9wZW5zc2guY29tAAAABm
+JjcnlwdAAAABgAAAAQdPyPIjXDRAVHskY0yp9SWwAAAGQAAAABAAAAMwAAAAtzc2gtZWQy
+NTUxOQAAACBi6qXITEUrmNce/c2lfozxALlKH3o/6sll8G7wzl1lvQAAAJDNlW1sEkvnK0
+8EecF1vHdPk85yClbh3KkHv09mbGAX/Gk6cJpYEGgJSkO7OEF4kG9DVGGd17+TZbTnM4LD
+vYAJZExx2XLgJFEtHCVmJjYzwxx7yC7+s6u/XjrSlZS60RHunOPKyq+C+s48sejXvmX+t5
+0ZoVCI8aftT0ycis3gvLU9sCwJ2UnF6kAV226Z4g2aLkuJbgCDTEcYCRD64K1r
+-----END OPENSSH PRIVATE KEY-----
+`),
+	},
+	1: {
+		Name:              "ed25519-encrypted-aes128-gcm",
+		EncryptionKey:     "password",
+		PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAAFmFlczEyOC1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA
+AAGAAAABBeMJIOqiyFwNCvDv6f8tQeAAAAZAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAA
+IGYpUcb3tGp9kF6pppcUdq3EPMr85BaSUdhiXGbhS5YNAAAAkNBtMEu0UlLgToThuQc+4m
+/o0DfFIERu0sspQivn5RJHCtulVKfU9BMiEnF0+LOMOABMlYesgLOtoMxwm4ZCSWH54kZk
+vaFyyvvxY+RLDuWNQZCryffIA4+iLCUQR1EdxMDiJweKnGJuD64a+9xTJt47A3Vq4SYzji
+EuVmM0FqS8lbT2ynYSe3va0Qyw13jEO5qbtCuyG+C5GejL7kX4Z64=
+-----END OPENSSH PRIVATE KEY-----
+`),
+	},
+	2: {
+		Name:              "ed25519-encrypted-aes256-gcm",
+		EncryptionKey:     "password",
+		PEMBytes: []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAAFmFlczI1Ni1nY21Ab3BlbnNzaC5jb20AAAAGYmNyeXB0AA
+AAGAAAABBR1p3vH2Wr/HPL+q20L2rjAAAAZAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAA
+IM3tT1xrAuOHcrBdoLRo/ojWZsAw2lHfF5hJgFEOts5MAAAAkH/YGrDhDw8u+F8e4P+84B
+tAzvp55Lf1Yl7y34BrVmqlWqw/7boqahOp6iYJHNpcuanzc5T6s7Z3wSSYodbY1uvFOfbj
+rtP6rIHQIY5J2C40WOYJN8IkZlkwDXwZY0qoE9699ZYmWdwsXRZ7QDhjd2W8ziyZBsttiB
+kv2ceuJMLT04TrKc2+RUkj4CQYnz7p8EkgZlUozx8wBSxKFGnkP7k=
+-----END OPENSSH PRIVATE KEY-----
+`),
+	},
+}
+
+
 // SKData contains a list of PubKeys backed by U2F/FIDO2 Security Keys and their test data.
 var SKData = []struct {
 	Name         string