From a85b8730bfa1f3761b3bbd4beefdefc6893570c5 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Tue, 15 Mar 2022 11:56:56 -0400 Subject: [PATCH] ssh: support rsa-sha2-256/512 for client certificates The server-sig-algs logic was not working for certificate algorithms. Follow-up on CL 392394. Tested with OpenSSH 8.8 configured with PubkeyAcceptedKeyTypes -ssh-rsa-cert-v01@openssh.com Updates golang/go#39885 For golang/go#49952 Change-Id: Ic230dd6f98e96b7938acbd0128ab37d33b70abe5 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/392974 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda Reviewed-by: Roland Shoemaker TryBot-Result: Gopher Robot --- ssh/certs.go | 21 +++++++++++++++------ ssh/client_auth.go | 10 ++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/ssh/certs.go b/ssh/certs.go index c7a4dd0..a69e224 100644 --- a/ssh/certs.go +++ b/ssh/certs.go @@ -483,6 +483,17 @@ func underlyingAlgo(algo string) string { return algo } +// certificateAlgo returns the certificate algorithms that uses the provided +// underlying signature algorithm. +func certificateAlgo(algo string) (certAlgo string, ok bool) { + for certName, algoName := range certKeyAlgoNames { + if algoName == algo { + return certName, true + } + } + return "", false +} + func (cert *Certificate) bytesForSigning() []byte { c2 := *cert c2.Signature = nil @@ -526,13 +537,11 @@ func (c *Certificate) Marshal() []byte { // Type returns the certificate algorithm name. It is part of the PublicKey interface. func (c *Certificate) Type() string { - keyType := c.Key.Type() - for certName, keyName := range certKeyAlgoNames { - if keyName == keyType { - return certName - } + certName, ok := certificateAlgo(c.Key.Type()) + if !ok { + panic("unknown certificate type for key type " + c.Key.Type()) } - panic("unknown certificate type for key type " + keyType) + return certName } // Verify verifies a signature against the certificate's public diff --git a/ssh/client_auth.go b/ssh/client_auth.go index a962a67..409b5ea 100644 --- a/ssh/client_auth.go +++ b/ssh/client_auth.go @@ -234,7 +234,17 @@ func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (as Alg return as, keyFormat } + // The server-sig-algs extension only carries underlying signature + // algorithm, but we are trying to select a protocol-level public key + // algorithm, which might be a certificate type. Extend the list of server + // supported algorithms to include the corresponding certificate algorithms. serverAlgos := strings.Split(string(extPayload), ",") + for _, algo := range serverAlgos { + if certAlgo, ok := certificateAlgo(algo); ok { + serverAlgos = append(serverAlgos, certAlgo) + } + } + keyAlgos := algorithmsForKeyFormat(keyFormat) algo, err := findCommon("public key signature algorithm", keyAlgos, serverAlgos) if err != nil {