summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/crypto/ssh
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/crypto/ssh')
-rw-r--r--vendor/golang.org/x/crypto/ssh/cipher.go62
-rw-r--r--vendor/golang.org/x/crypto/ssh/client_auth.go24
-rw-r--r--vendor/golang.org/x/crypto/ssh/common.go83
-rw-r--r--vendor/golang.org/x/crypto/ssh/doc.go10
-rw-r--r--vendor/golang.org/x/crypto/ssh/handshake.go9
-rw-r--r--vendor/golang.org/x/crypto/ssh/kex.go24
-rw-r--r--vendor/golang.org/x/crypto/ssh/keys.go69
-rw-r--r--vendor/golang.org/x/crypto/ssh/mac.go42
-rw-r--r--vendor/golang.org/x/crypto/ssh/server.go36
-rw-r--r--vendor/golang.org/x/crypto/ssh/transport.go4
10 files changed, 260 insertions, 103 deletions
diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go
index 6a5b582aa..7554ed57a 100644
--- a/vendor/golang.org/x/crypto/ssh/cipher.go
+++ b/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -8,6 +8,7 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/des"
+ "crypto/fips140"
"crypto/rc4"
"crypto/subtle"
"encoding/binary"
@@ -15,6 +16,7 @@ import (
"fmt"
"hash"
"io"
+ "slices"
"golang.org/x/crypto/chacha20"
"golang.org/x/crypto/internal/poly1305"
@@ -93,41 +95,41 @@ func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream,
}
// cipherModes documents properties of supported ciphers. Ciphers not included
-// are not supported and will not be negotiated, even if explicitly requested in
-// ClientConfig.Crypto.Ciphers.
-var cipherModes = map[string]*cipherMode{
- // Ciphers from RFC 4344, which introduced many CTR-based ciphers. Algorithms
- // are defined in the order specified in the RFC.
- CipherAES128CTR: {16, aes.BlockSize, streamCipherMode(0, newAESCTR)},
- CipherAES192CTR: {24, aes.BlockSize, streamCipherMode(0, newAESCTR)},
- CipherAES256CTR: {32, aes.BlockSize, streamCipherMode(0, newAESCTR)},
-
- // Ciphers from RFC 4345, which introduces security-improved arcfour ciphers.
- // They are defined in the order specified in the RFC.
- InsecureCipherRC4128: {16, 0, streamCipherMode(1536, newRC4)},
- InsecureCipherRC4256: {32, 0, streamCipherMode(1536, newRC4)},
-
- // Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.
- // Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and
- // RC4) has problems with weak keys, and should be used with caution."
- // RFC 4345 introduces improved versions of Arcfour.
- InsecureCipherRC4: {16, 0, streamCipherMode(0, newRC4)},
-
- // AEAD ciphers
- CipherAES128GCM: {16, 12, newGCMCipher},
- CipherAES256GCM: {32, 12, newGCMCipher},
- CipherChaCha20Poly1305: {64, 0, newChaCha20Cipher},
-
+// are not supported and will not be negotiated, even if explicitly configured.
+// When FIPS mode is enabled, only FIPS-approved algorithms are included.
+var cipherModes = map[string]*cipherMode{}
+
+func init() {
+ cipherModes[CipherAES128CTR] = &cipherMode{16, aes.BlockSize, streamCipherMode(0, newAESCTR)}
+ cipherModes[CipherAES192CTR] = &cipherMode{24, aes.BlockSize, streamCipherMode(0, newAESCTR)}
+ cipherModes[CipherAES256CTR] = &cipherMode{32, aes.BlockSize, streamCipherMode(0, newAESCTR)}
+ // Use of GCM with arbitrary IVs is not allowed in FIPS 140-only mode,
+ // we'll wire it up to NewGCMForSSH in Go 1.26.
+ //
+ // For now it means we'll work with fips140=on but not fips140=only.
+ cipherModes[CipherAES128GCM] = &cipherMode{16, 12, newGCMCipher}
+ cipherModes[CipherAES256GCM] = &cipherMode{32, 12, newGCMCipher}
+
+ if fips140.Enabled() {
+ defaultCiphers = slices.DeleteFunc(defaultCiphers, func(algo string) bool {
+ _, ok := cipherModes[algo]
+ return !ok
+ })
+ return
+ }
+
+ cipherModes[CipherChaCha20Poly1305] = &cipherMode{64, 0, newChaCha20Cipher}
+ // Insecure ciphers not included in the default configuration.
+ cipherModes[InsecureCipherRC4128] = &cipherMode{16, 0, streamCipherMode(1536, newRC4)}
+ cipherModes[InsecureCipherRC4256] = &cipherMode{32, 0, streamCipherMode(1536, newRC4)}
+ cipherModes[InsecureCipherRC4] = &cipherMode{16, 0, streamCipherMode(0, newRC4)}
// CBC mode is insecure and so is not included in the default config.
// (See https://www.ieee-security.org/TC/SP2013/papers/4977a526.pdf). If absolutely
// needed, it's possible to specify a custom Config to enable it.
// You should expect that an active attacker can recover plaintext if
// you do.
- InsecureCipherAES128CBC: {16, aes.BlockSize, newAESCBCCipher},
-
- // 3des-cbc is insecure and is not included in the default
- // config.
- InsecureCipherTripleDESCBC: {24, des.BlockSize, newTripleDESCBCCipher},
+ cipherModes[InsecureCipherAES128CBC] = &cipherMode{16, aes.BlockSize, newAESCBCCipher}
+ cipherModes[InsecureCipherTripleDESCBC] = &cipherMode{24, des.BlockSize, newTripleDESCBCCipher}
}
// prefixLen is the length of the packet prefix that contains the packet length
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go
index c12818fdc..3127e4990 100644
--- a/vendor/golang.org/x/crypto/ssh/client_auth.go
+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -9,6 +9,7 @@ import (
"errors"
"fmt"
"io"
+ "slices"
"strings"
)
@@ -83,7 +84,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
// success
return nil
} else if ok == authFailure {
- if m := auth.method(); !contains(tried, m) {
+ if m := auth.method(); !slices.Contains(tried, m) {
tried = append(tried, m)
}
}
@@ -97,7 +98,7 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
findNext:
for _, a := range config.Auth {
candidateMethod := a.method()
- if contains(tried, candidateMethod) {
+ if slices.Contains(tried, candidateMethod) {
continue
}
for _, meth := range methods {
@@ -117,15 +118,6 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {
return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", tried)
}
-func contains(list []string, e string) bool {
- for _, s := range list {
- if s == e {
- return true
- }
- }
- return false
-}
-
// An AuthMethod represents an instance of an RFC 4252 authentication method.
type AuthMethod interface {
// auth authenticates user over transport t.
@@ -255,7 +247,7 @@ func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (MultiA
// Fallback to use if there is no "server-sig-algs" extension or a
// common algorithm cannot be found. We use the public key format if the
// MultiAlgorithmSigner supports it, otherwise we return an error.
- if !contains(as.Algorithms(), underlyingAlgo(keyFormat)) {
+ if !slices.Contains(as.Algorithms(), underlyingAlgo(keyFormat)) {
return "", fmt.Errorf("ssh: no common public key signature algorithm, server only supports %q for key type %q, signer only supports %v",
underlyingAlgo(keyFormat), keyFormat, as.Algorithms())
}
@@ -284,7 +276,7 @@ func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (MultiA
// Filter algorithms based on those supported by MultiAlgorithmSigner.
var keyAlgos []string
for _, algo := range algorithmsForKeyFormat(keyFormat) {
- if contains(as.Algorithms(), underlyingAlgo(algo)) {
+ if slices.Contains(as.Algorithms(), underlyingAlgo(algo)) {
keyAlgos = append(keyAlgos, algo)
}
}
@@ -334,7 +326,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
// the key try to use the obtained algorithm as if "server-sig-algs" had
// not been implemented if supported from the algorithm signer.
if !ok && idx < origSignersLen && isRSACert(algo) && algo != CertAlgoRSAv01 {
- if contains(as.Algorithms(), KeyAlgoRSA) {
+ if slices.Contains(as.Algorithms(), KeyAlgoRSA) {
// We retry using the compat algorithm after all signers have
// been tried normally.
signers = append(signers, &multiAlgorithmSigner{
@@ -385,7 +377,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
// contain the "publickey" method, do not attempt to authenticate with any
// other keys. According to RFC 4252 Section 7, the latter can occur when
// additional authentication methods are required.
- if success == authSuccess || !contains(methods, cb.method()) {
+ if success == authSuccess || !slices.Contains(methods, cb.method()) {
return success, methods, err
}
}
@@ -434,7 +426,7 @@ func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {
// servers send the key type instead. OpenSSH allows any algorithm
// that matches the public key, so we do the same.
// https://github.com/openssh/openssh-portable/blob/86bdd385/sshconnect2.c#L709
- if !contains(algorithmsForKeyFormat(key.Type()), msg.Algo) {
+ if !slices.Contains(algorithmsForKeyFormat(key.Type()), msg.Algo) {
return false, nil
}
if !bytes.Equal(msg.PubKey, pubKey) {
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go
index 8bfad16c4..2e44e9c9e 100644
--- a/vendor/golang.org/x/crypto/ssh/common.go
+++ b/vendor/golang.org/x/crypto/ssh/common.go
@@ -6,6 +6,7 @@ package ssh
import (
"crypto"
+ "crypto/fips140"
"crypto/rand"
"fmt"
"io"
@@ -256,6 +257,40 @@ type Algorithms struct {
PublicKeyAuths []string
}
+func init() {
+ if fips140.Enabled() {
+ defaultHostKeyAlgos = slices.DeleteFunc(defaultHostKeyAlgos, func(algo string) bool {
+ _, err := hashFunc(underlyingAlgo(algo))
+ return err != nil
+ })
+ defaultPubKeyAuthAlgos = slices.DeleteFunc(defaultPubKeyAuthAlgos, func(algo string) bool {
+ _, err := hashFunc(underlyingAlgo(algo))
+ return err != nil
+ })
+ }
+}
+
+func hashFunc(format string) (crypto.Hash, error) {
+ switch format {
+ case KeyAlgoRSASHA256, KeyAlgoECDSA256, KeyAlgoSKED25519, KeyAlgoSKECDSA256:
+ return crypto.SHA256, nil
+ case KeyAlgoECDSA384:
+ return crypto.SHA384, nil
+ case KeyAlgoRSASHA512, KeyAlgoECDSA521:
+ return crypto.SHA512, nil
+ case KeyAlgoED25519:
+ // KeyAlgoED25519 doesn't pre-hash.
+ return 0, nil
+ case KeyAlgoRSA, InsecureKeyAlgoDSA:
+ if fips140.Enabled() {
+ return 0, fmt.Errorf("ssh: hash algorithm for format %q not allowed in FIPS 140 mode", format)
+ }
+ return crypto.SHA1, nil
+ default:
+ return 0, fmt.Errorf("ssh: hash algorithm for format %q not mapped", format)
+ }
+}
+
// SupportedAlgorithms returns algorithms currently implemented by this package,
// excluding those with security issues, which are returned by
// InsecureAlgorithms. The algorithms listed here are in preference order.
@@ -283,21 +318,6 @@ func InsecureAlgorithms() Algorithms {
var supportedCompressions = []string{compressionNone}
-// hashFuncs keeps the mapping of supported signature algorithms to their
-// respective hashes needed for signing and verification.
-var hashFuncs = map[string]crypto.Hash{
- KeyAlgoRSA: crypto.SHA1,
- KeyAlgoRSASHA256: crypto.SHA256,
- KeyAlgoRSASHA512: crypto.SHA512,
- InsecureKeyAlgoDSA: crypto.SHA1,
- KeyAlgoECDSA256: crypto.SHA256,
- KeyAlgoECDSA384: crypto.SHA384,
- KeyAlgoECDSA521: crypto.SHA512,
- // KeyAlgoED25519 doesn't pre-hash.
- KeyAlgoSKECDSA256: crypto.SHA256,
- KeyAlgoSKED25519: crypto.SHA256,
-}
-
// algorithmsForKeyFormat returns the supported signature algorithms for a given
// public key format (PublicKey.Type), in order of preference. See RFC 8332,
// Section 2. See also the note in sendKexInit on backwards compatibility.
@@ -312,11 +332,40 @@ func algorithmsForKeyFormat(keyFormat string) []string {
}
}
+// keyFormatForAlgorithm returns the key format corresponding to the given
+// signature algorithm. It returns an empty string if the signature algorithm is
+// invalid or unsupported.
+func keyFormatForAlgorithm(sigAlgo string) string {
+ switch sigAlgo {
+ case KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512:
+ return KeyAlgoRSA
+ case CertAlgoRSAv01, CertAlgoRSASHA256v01, CertAlgoRSASHA512v01:
+ return CertAlgoRSAv01
+ case KeyAlgoED25519,
+ KeyAlgoSKED25519,
+ KeyAlgoSKECDSA256,
+ KeyAlgoECDSA256,
+ KeyAlgoECDSA384,
+ KeyAlgoECDSA521,
+ InsecureKeyAlgoDSA,
+ InsecureCertAlgoDSAv01,
+ CertAlgoECDSA256v01,
+ CertAlgoECDSA384v01,
+ CertAlgoECDSA521v01,
+ CertAlgoSKECDSA256v01,
+ CertAlgoED25519v01,
+ CertAlgoSKED25519v01:
+ return sigAlgo
+ default:
+ return ""
+ }
+}
+
// isRSA returns whether algo is a supported RSA algorithm, including certificate
// algorithms.
func isRSA(algo string) bool {
algos := algorithmsForKeyFormat(KeyAlgoRSA)
- return contains(algos, underlyingAlgo(algo))
+ return slices.Contains(algos, underlyingAlgo(algo))
}
func isRSACert(algo string) bool {
@@ -515,7 +564,7 @@ func (c *Config) SetDefaults() {
if kexAlgoMap[k] != nil {
// Ignore the KEX if we have no kexAlgoMap definition.
kexs = append(kexs, k)
- if k == KeyExchangeCurve25519 && !contains(c.KeyExchanges, keyExchangeCurve25519LibSSH) {
+ if k == KeyExchangeCurve25519 && !slices.Contains(c.KeyExchanges, keyExchangeCurve25519LibSSH) {
kexs = append(kexs, keyExchangeCurve25519LibSSH)
}
}
diff --git a/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/golang.org/x/crypto/ssh/doc.go
index 04ccce346..5b4de9eff 100644
--- a/vendor/golang.org/x/crypto/ssh/doc.go
+++ b/vendor/golang.org/x/crypto/ssh/doc.go
@@ -17,8 +17,18 @@ References:
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
[SSH-CERTS]: https://datatracker.ietf.org/doc/html/draft-miller-ssh-cert-01
+ [FIPS 140-3 mode]: https://go.dev/doc/security/fips140
This package does not fall under the stability promise of the Go language itself,
so its API may be changed when pressing needs arise.
+
+# FIPS 140-3 mode
+
+When the program is in [FIPS 140-3 mode], this package behaves as if only SP
+800-140C and SP 800-140D approved cipher suites, signature algorithms,
+certificate public key types and sizes, and key exchange and derivation
+algorithms were implemented. Others are silently ignored and not negotiated, or
+rejected. This set may depend on the algorithms supported by the FIPS 140-3 Go
+Cryptographic Module selected with GOFIPS140, and may change across Go versions.
*/
package ssh
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
index a90bfe331..4be3cbb6d 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -10,6 +10,7 @@ import (
"io"
"log"
"net"
+ "slices"
"strings"
"sync"
)
@@ -527,7 +528,7 @@ func (t *handshakeTransport) sendKexInit() error {
switch s := k.(type) {
case MultiAlgorithmSigner:
for _, algo := range algorithmsForKeyFormat(keyFormat) {
- if contains(s.Algorithms(), underlyingAlgo(algo)) {
+ if slices.Contains(s.Algorithms(), underlyingAlgo(algo)) {
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algo)
}
}
@@ -679,7 +680,7 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
return err
}
- if t.sessionID == nil && ((isClient && contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && contains(clientInit.KexAlgos, kexStrictClient))) {
+ if t.sessionID == nil && ((isClient && slices.Contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && slices.Contains(clientInit.KexAlgos, kexStrictClient))) {
t.strictMode = true
if err := t.conn.setStrictMode(); err != nil {
return err
@@ -736,7 +737,7 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
// On the server side, after the first SSH_MSG_NEWKEYS, send a SSH_MSG_EXT_INFO
// message with the server-sig-algs extension if the client supports it. See
// RFC 8308, Sections 2.4 and 3.1, and [PROTOCOL], Section 1.9.
- if !isClient && firstKeyExchange && contains(clientInit.KexAlgos, "ext-info-c") {
+ if !isClient && firstKeyExchange && slices.Contains(clientInit.KexAlgos, "ext-info-c") {
supportedPubKeyAuthAlgosList := strings.Join(t.publicKeyAuthAlgorithms, ",")
extInfo := &extInfoMsg{
NumExtensions: 2,
@@ -790,7 +791,7 @@ func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data []byte, a
func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner {
for _, k := range hostKeys {
if s, ok := k.(MultiAlgorithmSigner); ok {
- if !contains(s.Algorithms(), underlyingAlgo(algo)) {
+ if !slices.Contains(s.Algorithms(), underlyingAlgo(algo)) {
continue
}
}
diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go
index 78aaf0310..5f7fdd851 100644
--- a/vendor/golang.org/x/crypto/ssh/kex.go
+++ b/vendor/golang.org/x/crypto/ssh/kex.go
@@ -8,12 +8,14 @@ import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
+ "crypto/fips140"
"crypto/rand"
"encoding/binary"
"errors"
"fmt"
"io"
"math/big"
+ "slices"
"golang.org/x/crypto/curve25519"
)
@@ -395,9 +397,27 @@ func ecHash(curve elliptic.Curve) crypto.Hash {
return crypto.SHA512
}
+// kexAlgoMap defines the supported KEXs. KEXs not included are not supported
+// and will not be negotiated, even if explicitly configured. When FIPS mode is
+// enabled, only FIPS-approved algorithms are included.
var kexAlgoMap = map[string]kexAlgorithm{}
func init() {
+ // mlkem768x25519-sha256 we'll work with fips140=on but not fips140=only
+ // until Go 1.26.
+ kexAlgoMap[KeyExchangeMLKEM768X25519] = &mlkem768WithCurve25519sha256{}
+ kexAlgoMap[KeyExchangeECDHP521] = &ecdh{elliptic.P521()}
+ kexAlgoMap[KeyExchangeECDHP384] = &ecdh{elliptic.P384()}
+ kexAlgoMap[KeyExchangeECDHP256] = &ecdh{elliptic.P256()}
+
+ if fips140.Enabled() {
+ defaultKexAlgos = slices.DeleteFunc(defaultKexAlgos, func(algo string) bool {
+ _, ok := kexAlgoMap[algo]
+ return !ok
+ })
+ return
+ }
+
p, _ := new(big.Int).SetString(oakleyGroup2, 16)
kexAlgoMap[InsecureKeyExchangeDH1SHA1] = &dhGroup{
g: new(big.Int).SetInt64(2),
@@ -431,14 +451,10 @@ func init() {
hashFunc: crypto.SHA512,
}
- kexAlgoMap[KeyExchangeECDHP521] = &ecdh{elliptic.P521()}
- kexAlgoMap[KeyExchangeECDHP384] = &ecdh{elliptic.P384()}
- kexAlgoMap[KeyExchangeECDHP256] = &ecdh{elliptic.P256()}
kexAlgoMap[KeyExchangeCurve25519] = &curve25519sha256{}
kexAlgoMap[keyExchangeCurve25519LibSSH] = &curve25519sha256{}
kexAlgoMap[InsecureKeyExchangeDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
kexAlgoMap[KeyExchangeDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
- kexAlgoMap[KeyExchangeMLKEM768X25519] = &mlkem768WithCurve25519sha256{}
}
// curve25519sha256 implements the curve25519-sha256 (formerly known as
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
index a28c0de50..a035956fc 100644
--- a/vendor/golang.org/x/crypto/ssh/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -27,6 +27,7 @@ import (
"fmt"
"io"
"math/big"
+ "slices"
"strings"
"golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"
@@ -89,6 +90,11 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
}
return cert, nil, nil
}
+ if keyFormat := keyFormatForAlgorithm(algo); keyFormat != "" {
+ return nil, nil, fmt.Errorf("ssh: signature algorithm %q isn't a key format; key is malformed and should be re-encoded with type %q",
+ algo, keyFormat)
+ }
+
return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo)
}
@@ -191,9 +197,10 @@ func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey
return "", nil, nil, "", nil, io.EOF
}
-// ParseAuthorizedKey parses a public key from an authorized_keys
-// file used in OpenSSH according to the sshd(8) manual page.
+// ParseAuthorizedKey parses a public key from an authorized_keys file used in
+// OpenSSH according to the sshd(8) manual page. Invalid lines are ignored.
func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
+ var lastErr error
for len(in) > 0 {
end := bytes.IndexByte(in, '\n')
if end != -1 {
@@ -222,6 +229,8 @@ func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []str
if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
return out, comment, options, rest, nil
+ } else {
+ lastErr = err
}
// No key type recognised. Maybe there's an options field at
@@ -264,12 +273,18 @@ func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []str
if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
options = candidateOptions
return out, comment, options, rest, nil
+ } else {
+ lastErr = err
}
in = rest
continue
}
+ if lastErr != nil {
+ return nil, "", nil, nil, fmt.Errorf("ssh: no key found; last parsing error for ignored line: %w", lastErr)
+ }
+
return nil, "", nil, nil, errors.New("ssh: no key found")
}
@@ -395,11 +410,11 @@ func NewSignerWithAlgorithms(signer AlgorithmSigner, algorithms []string) (Multi
}
for _, algo := range algorithms {
- if !contains(supportedAlgos, algo) {
+ if !slices.Contains(supportedAlgos, algo) {
return nil, fmt.Errorf("ssh: algorithm %q is not supported for key type %q",
algo, signer.PublicKey().Type())
}
- if !contains(signerAlgos, algo) {
+ if !slices.Contains(signerAlgos, algo) {
return nil, fmt.Errorf("ssh: algorithm %q is restricted for the provided signer", algo)
}
}
@@ -486,10 +501,13 @@ func (r *rsaPublicKey) Marshal() []byte {
func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
supportedAlgos := algorithmsForKeyFormat(r.Type())
- if !contains(supportedAlgos, sig.Format) {
+ if !slices.Contains(supportedAlgos, sig.Format) {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
}
- hash := hashFuncs[sig.Format]
+ hash, err := hashFunc(sig.Format)
+ if err != nil {
+ return err
+ }
h := hash.New()
h.Write(data)
digest := h.Sum(nil)
@@ -606,7 +624,11 @@ func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
- h := hashFuncs[sig.Format].New()
+ hash, err := hashFunc(sig.Format)
+ if err != nil {
+ return err
+ }
+ h := hash.New()
h.Write(data)
digest := h.Sum(nil)
@@ -651,7 +673,11 @@ func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm
return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
}
- h := hashFuncs[k.PublicKey().Type()].New()
+ hash, err := hashFunc(k.PublicKey().Type())
+ if err != nil {
+ return nil, err
+ }
+ h := hash.New()
h.Write(data)
digest := h.Sum(nil)
r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
@@ -801,8 +827,11 @@ func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
-
- h := hashFuncs[sig.Format].New()
+ hash, err := hashFunc(sig.Format)
+ if err != nil {
+ return err
+ }
+ h := hash.New()
h.Write(data)
digest := h.Sum(nil)
@@ -905,8 +934,11 @@ func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
if sig.Format != k.Type() {
return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
}
-
- h := hashFuncs[sig.Format].New()
+ hash, err := hashFunc(sig.Format)
+ if err != nil {
+ return err
+ }
+ h := hash.New()
h.Write([]byte(k.application))
appDigest := h.Sum(nil)
@@ -1009,7 +1041,11 @@ func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
return fmt.Errorf("invalid size %d for Ed25519 public key", l)
}
- h := hashFuncs[sig.Format].New()
+ hash, err := hashFunc(sig.Format)
+ if err != nil {
+ return err
+ }
+ h := hash.New()
h.Write([]byte(k.application))
appDigest := h.Sum(nil)
@@ -1112,11 +1148,14 @@ func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm
algorithm = s.pubKey.Type()
}
- if !contains(s.Algorithms(), algorithm) {
+ if !slices.Contains(s.Algorithms(), algorithm) {
return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type())
}
- hashFunc := hashFuncs[algorithm]
+ hashFunc, err := hashFunc(algorithm)
+ if err != nil {
+ return nil, err
+ }
var digest []byte
if hashFunc != 0 {
h := hashFunc.New()
diff --git a/vendor/golang.org/x/crypto/ssh/mac.go b/vendor/golang.org/x/crypto/ssh/mac.go
index de2639d57..87d626fbb 100644
--- a/vendor/golang.org/x/crypto/ssh/mac.go
+++ b/vendor/golang.org/x/crypto/ssh/mac.go
@@ -7,11 +7,13 @@ package ssh
// Message authentication support
import (
+ "crypto/fips140"
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"hash"
+ "slices"
)
type macMode struct {
@@ -46,23 +48,37 @@ func (t truncatingMAC) Size() int {
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
-var macModes = map[string]*macMode{
- HMACSHA512ETM: {64, true, func(key []byte) hash.Hash {
+// macModes defines the supported MACs. MACs not included are not supported
+// and will not be negotiated, even if explicitly configured. When FIPS mode is
+// enabled, only FIPS-approved algorithms are included.
+var macModes = map[string]*macMode{}
+
+func init() {
+ macModes[HMACSHA512ETM] = &macMode{64, true, func(key []byte) hash.Hash {
return hmac.New(sha512.New, key)
- }},
- HMACSHA256ETM: {32, true, func(key []byte) hash.Hash {
+ }}
+ macModes[HMACSHA256ETM] = &macMode{32, true, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key)
- }},
- HMACSHA512: {64, false, func(key []byte) hash.Hash {
+ }}
+ macModes[HMACSHA512] = &macMode{64, false, func(key []byte) hash.Hash {
return hmac.New(sha512.New, key)
- }},
- HMACSHA256: {32, false, func(key []byte) hash.Hash {
+ }}
+ macModes[HMACSHA256] = &macMode{32, false, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key)
- }},
- HMACSHA1: {20, false, func(key []byte) hash.Hash {
+ }}
+
+ if fips140.Enabled() {
+ defaultMACs = slices.DeleteFunc(defaultMACs, func(algo string) bool {
+ _, ok := macModes[algo]
+ return !ok
+ })
+ return
+ }
+
+ macModes[HMACSHA1] = &macMode{20, false, func(key []byte) hash.Hash {
return hmac.New(sha1.New, key)
- }},
- InsecureHMACSHA196: {20, false, func(key []byte) hash.Hash {
+ }}
+ macModes[InsecureHMACSHA196] = &macMode{20, false, func(key []byte) hash.Hash {
return truncatingMAC{12, hmac.New(sha1.New, key)}
- }},
+ }}
}
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 98679ba5b..064dcbaf5 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -10,6 +10,7 @@ import (
"fmt"
"io"
"net"
+ "slices"
"strings"
)
@@ -43,6 +44,9 @@ type Permissions struct {
// pass data from the authentication callbacks to the server
// application layer.
Extensions map[string]string
+
+ // ExtraData allows to store user defined data.
+ ExtraData map[any]any
}
type GSSAPIWithMICConfig struct {
@@ -126,6 +130,21 @@ type ServerConfig struct {
// Permissions.Extensions entry.
PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
+ // VerifiedPublicKeyCallback, if non-nil, is called after a client
+ // successfully confirms having control over a key that was previously
+ // approved by PublicKeyCallback. The permissions object passed to the
+ // callback is the one returned by PublicKeyCallback for the given public
+ // key and its ownership is transferred to the callback. The returned
+ // Permissions object can be the same object, optionally modified, or a
+ // completely new object. If VerifiedPublicKeyCallback is non-nil,
+ // PublicKeyCallback is not allowed to return a PartialSuccessError, which
+ // can instead be returned by VerifiedPublicKeyCallback.
+ //
+ // VerifiedPublicKeyCallback does not affect which authentication methods
+ // are included in the list of methods that can be attempted by the client.
+ VerifiedPublicKeyCallback func(conn ConnMetadata, key PublicKey, permissions *Permissions,
+ signatureAlgorithm string) (*Permissions, error)
+
// KeyboardInteractiveCallback, if non-nil, is called when
// keyboard-interactive authentication is selected (RFC
// 4256). The client object's Challenge function should be
@@ -246,7 +265,7 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
fullConf.PublicKeyAuthAlgorithms = defaultPubKeyAuthAlgos
} else {
for _, algo := range fullConf.PublicKeyAuthAlgorithms {
- if !contains(SupportedAlgorithms().PublicKeyAuths, algo) && !contains(InsecureAlgorithms().PublicKeyAuths, algo) {
+ if !slices.Contains(SupportedAlgorithms().PublicKeyAuths, algo) && !slices.Contains(InsecureAlgorithms().PublicKeyAuths, algo) {
c.Close()
return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo)
}
@@ -631,7 +650,7 @@ userAuthLoop:
return nil, parseError(msgUserAuthRequest)
}
algo := string(algoBytes)
- if !contains(config.PublicKeyAuthAlgorithms, underlyingAlgo(algo)) {
+ if !slices.Contains(config.PublicKeyAuthAlgorithms, underlyingAlgo(algo)) {
authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
break
}
@@ -652,6 +671,9 @@ userAuthLoop:
candidate.pubKeyData = pubKeyData
candidate.perms, candidate.result = authConfig.PublicKeyCallback(s, pubKey)
_, isPartialSuccessError := candidate.result.(*PartialSuccessError)
+ if isPartialSuccessError && config.VerifiedPublicKeyCallback != nil {
+ return nil, errors.New("ssh: invalid library usage: PublicKeyCallback must not return partial success when VerifiedPublicKeyCallback is defined")
+ }
if (candidate.result == nil || isPartialSuccessError) &&
candidate.perms != nil &&
@@ -695,7 +717,7 @@ userAuthLoop:
// ssh-rsa-cert-v01@openssh.com algorithm with ssh-rsa public
// key type. The algorithm and public key type must be
// consistent: both must be certificate algorithms, or neither.
- if !contains(algorithmsForKeyFormat(pubKey.Type()), algo) {
+ if !slices.Contains(algorithmsForKeyFormat(pubKey.Type()), algo) {
authErr = fmt.Errorf("ssh: public key type %q not compatible with selected algorithm %q",
pubKey.Type(), algo)
break
@@ -705,7 +727,7 @@ userAuthLoop:
// algorithm name that corresponds to algo with
// sig.Format. This is usually the same, but
// for certs, the names differ.
- if !contains(config.PublicKeyAuthAlgorithms, sig.Format) {
+ if !slices.Contains(config.PublicKeyAuthAlgorithms, sig.Format) {
authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format)
break
}
@@ -722,6 +744,12 @@ userAuthLoop:
authErr = candidate.result
perms = candidate.perms
+ if authErr == nil && config.VerifiedPublicKeyCallback != nil {
+ // Only call VerifiedPublicKeyCallback after the key has been accepted
+ // and successfully verified. If authErr is non-nil, the key is not
+ // considered verified and the callback must not run.
+ perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, algo)
+ }
}
case "gssapi-with-mic":
if authConfig.GSSAPIWithMICConfig == nil {
diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go
index 663619845..fa3dd6a42 100644
--- a/vendor/golang.org/x/crypto/ssh/transport.go
+++ b/vendor/golang.org/x/crypto/ssh/transport.go
@@ -8,6 +8,7 @@ import (
"bufio"
"bytes"
"errors"
+ "fmt"
"io"
"log"
)
@@ -254,6 +255,9 @@ var (
// (to setup server->client keys) or clientKeys (for client->server keys).
func newPacketCipher(d direction, algs DirectionAlgorithms, kex *kexResult) (packetCipher, error) {
cipherMode := cipherModes[algs.Cipher]
+ if cipherMode == nil {
+ return nil, fmt.Errorf("ssh: unsupported cipher %v", algs.Cipher)
+ }
iv := make([]byte, cipherMode.ivSize)
key := make([]byte, cipherMode.keySize)