ssh: add MultiAlgorithmSigner

MultiAlgorithmSigner allows to restrict client-side, server-side and
certificate signing algorithms.

Fixes golang/go#52132
Fixes golang/go#36261

Change-Id: I295092f1bba647327aaaf294f110e9157d294159
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/508398
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Nicola Murino
2023-09-20 18:10:30 +00:00
committed by Gopher Robot
parent 3f0842a464
commit 28c53ff63c
9 changed files with 554 additions and 66 deletions
+90
View File
@@ -620,3 +620,93 @@ func TestNoSHA2Support(t *testing.T) {
t.Fatal(err)
}
}
func TestMultiAlgoSignerHandshake(t *testing.T) {
algorithmSigner, ok := testSigners["rsa"].(AlgorithmSigner)
if !ok {
t.Fatal("rsa test signer does not implement the AlgorithmSigner interface")
}
multiAlgoSigner, err := NewSignerWithAlgorithms(algorithmSigner, []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512})
if err != nil {
t.Fatalf("unable to create multi algorithm signer: %v", err)
}
c1, c2, err := netPipe()
if err != nil {
t.Fatalf("netPipe: %v", err)
}
defer c1.Close()
defer c2.Close()
serverConf := &ServerConfig{
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
return &Permissions{}, nil
},
}
serverConf.AddHostKey(multiAlgoSigner)
go NewServerConn(c1, serverConf)
clientConf := &ClientConfig{
User: "test",
Auth: []AuthMethod{Password("testpw")},
HostKeyCallback: FixedHostKey(testSigners["rsa"].PublicKey()),
HostKeyAlgorithms: []string{KeyAlgoRSASHA512},
}
if _, _, _, err := NewClientConn(c2, "", clientConf); err != nil {
t.Fatal(err)
}
}
func TestMultiAlgoSignerNoCommonHostKeyAlgo(t *testing.T) {
algorithmSigner, ok := testSigners["rsa"].(AlgorithmSigner)
if !ok {
t.Fatal("rsa test signer does not implement the AlgorithmSigner interface")
}
multiAlgoSigner, err := NewSignerWithAlgorithms(algorithmSigner, []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512})
if err != nil {
t.Fatalf("unable to create multi algorithm signer: %v", err)
}
c1, c2, err := netPipe()
if err != nil {
t.Fatalf("netPipe: %v", err)
}
defer c1.Close()
defer c2.Close()
// ssh-rsa is disabled server side
serverConf := &ServerConfig{
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
return &Permissions{}, nil
},
}
serverConf.AddHostKey(multiAlgoSigner)
go NewServerConn(c1, serverConf)
// the client only supports ssh-rsa
clientConf := &ClientConfig{
User: "test",
Auth: []AuthMethod{Password("testpw")},
HostKeyCallback: FixedHostKey(testSigners["rsa"].PublicKey()),
HostKeyAlgorithms: []string{KeyAlgoRSA},
}
_, _, _, err = NewClientConn(c2, "", clientConf)
if err == nil {
t.Fatal("succeeded connecting with no common hostkey algorithm")
}
}
func TestPickIncompatibleHostKeyAlgo(t *testing.T) {
algorithmSigner, ok := testSigners["rsa"].(AlgorithmSigner)
if !ok {
t.Fatal("rsa test signer does not implement the AlgorithmSigner interface")
}
multiAlgoSigner, err := NewSignerWithAlgorithms(algorithmSigner, []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512})
if err != nil {
t.Fatalf("unable to create multi algorithm signer: %v", err)
}
signer := pickHostKey([]Signer{multiAlgoSigner}, KeyAlgoRSA)
if signer != nil {
t.Fatal("incompatible signer returned")
}
}