diff options
Diffstat (limited to 'vendor/golang.org/x/crypto')
| -rw-r--r-- | vendor/golang.org/x/crypto/chacha20/chacha_arm64.go | 4 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/chacha20/chacha_arm64.s | 4 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/chacha20/chacha_noasm.go | 4 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/sha3/sha3.go | 14 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/sha3/sha3_s390x.go | 10 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/sha3/shake.go | 29 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/ssh/certs.go | 38 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/ssh/client_auth.go | 96 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/ssh/doc.go | 1 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/ssh/handshake.go | 44 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/ssh/keys.go | 376 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/ssh/messages.go | 14 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/ssh/mux.go | 6 | ||||
| -rw-r--r-- | vendor/golang.org/x/crypto/ssh/server.go | 11 | 
14 files changed, 515 insertions, 136 deletions
diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go index 94c71ac1a..5dfacbb98 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go +++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.go @@ -2,8 +2,8 @@  // Use of this source code is governed by a BSD-style  // license that can be found in the LICENSE file. -//go:build go1.11 && gc && !purego -// +build go1.11,gc,!purego +//go:build gc && !purego +// +build gc,!purego  package chacha20 diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s index 63cae9e6f..f1f66230d 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s +++ b/vendor/golang.org/x/crypto/chacha20/chacha_arm64.s @@ -2,8 +2,8 @@  // Use of this source code is governed by a BSD-style  // license that can be found in the LICENSE file. -//go:build go1.11 && gc && !purego -// +build go1.11,gc,!purego +//go:build gc && !purego +// +build gc,!purego  #include "textflag.h" diff --git a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go index 025b49897..02ff3d05e 100644 --- a/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go +++ b/vendor/golang.org/x/crypto/chacha20/chacha_noasm.go @@ -2,8 +2,8 @@  // Use of this source code is governed by a BSD-style  // license that can be found in the LICENSE file. -//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego -// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego +//go:build (!arm64 && !s390x && !ppc64le) || !gc || purego +// +build !arm64,!s390x,!ppc64le !gc purego  package chacha20 diff --git a/vendor/golang.org/x/crypto/sha3/sha3.go b/vendor/golang.org/x/crypto/sha3/sha3.go index fa182beb4..4884d172a 100644 --- a/vendor/golang.org/x/crypto/sha3/sha3.go +++ b/vendor/golang.org/x/crypto/sha3/sha3.go @@ -121,11 +121,11 @@ func (d *state) padAndPermute(dsbyte byte) {  	copyOut(d, d.buf)  } -// Write absorbs more data into the hash's state. It produces an error -// if more data is written to the ShakeHash after writing +// Write absorbs more data into the hash's state. It panics if any +// output has already been read.  func (d *state) Write(p []byte) (written int, err error) {  	if d.state != spongeAbsorbing { -		panic("sha3: write to sponge after read") +		panic("sha3: Write after Read")  	}  	if d.buf == nil {  		d.buf = d.storage.asBytes()[:0] @@ -182,12 +182,16 @@ func (d *state) Read(out []byte) (n int, err error) {  }  // Sum applies padding to the hash state and then squeezes out the desired -// number of output bytes. +// number of output bytes. It panics if any output has already been read.  func (d *state) Sum(in []byte) []byte { +	if d.state != spongeAbsorbing { +		panic("sha3: Sum after Read") +	} +  	// Make a copy of the original hash so that caller can keep writing  	// and summing.  	dup := d.clone() -	hash := make([]byte, dup.outputLen) +	hash := make([]byte, dup.outputLen, 64) // explicit cap to allow stack allocation  	dup.Read(hash)  	return append(in, hash...)  } diff --git a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go index 63a3edb4c..ec26f147f 100644 --- a/vendor/golang.org/x/crypto/sha3/sha3_s390x.go +++ b/vendor/golang.org/x/crypto/sha3/sha3_s390x.go @@ -49,7 +49,7 @@ type asmState struct {  	buf       []byte          // care must be taken to ensure cap(buf) is a multiple of rate  	rate      int             // equivalent to block size  	storage   [3072]byte      // underlying storage for buf -	outputLen int             // output length if fixed, 0 if not +	outputLen int             // output length for full security  	function  code            // KIMD/KLMD function code  	state     spongeDirection // whether the sponge is absorbing or squeezing  } @@ -72,8 +72,10 @@ func newAsmState(function code) *asmState {  		s.outputLen = 64  	case shake_128:  		s.rate = 168 +		s.outputLen = 32  	case shake_256:  		s.rate = 136 +		s.outputLen = 64  	default:  		panic("sha3: unrecognized function code")  	} @@ -108,7 +110,7 @@ func (s *asmState) resetBuf() {  // It never returns an error.  func (s *asmState) Write(b []byte) (int, error) {  	if s.state != spongeAbsorbing { -		panic("sha3: write to sponge after read") +		panic("sha3: Write after Read")  	}  	length := len(b)  	for len(b) > 0 { @@ -192,8 +194,8 @@ func (s *asmState) Read(out []byte) (n int, err error) {  // Sum appends the current hash to b and returns the resulting slice.  // It does not change the underlying hash state.  func (s *asmState) Sum(b []byte) []byte { -	if s.outputLen == 0 { -		panic("sha3: cannot call Sum on SHAKE functions") +	if s.state != spongeAbsorbing { +		panic("sha3: Sum after Read")  	}  	// Copy the state to preserve the original. diff --git a/vendor/golang.org/x/crypto/sha3/shake.go b/vendor/golang.org/x/crypto/sha3/shake.go index d7be2954a..bb6998402 100644 --- a/vendor/golang.org/x/crypto/sha3/shake.go +++ b/vendor/golang.org/x/crypto/sha3/shake.go @@ -17,26 +17,25 @@ package sha3  import (  	"encoding/binary" +	"hash"  	"io"  ) -// ShakeHash defines the interface to hash functions that -// support arbitrary-length output. +// ShakeHash defines the interface to hash functions that support +// arbitrary-length output. When used as a plain [hash.Hash], it +// produces minimum-length outputs that provide full-strength generic +// security.  type ShakeHash interface { -	// Write absorbs more data into the hash's state. It panics if input is -	// written to it after output has been read from it. -	io.Writer +	hash.Hash  	// Read reads more output from the hash; reading affects the hash's  	// state. (ShakeHash.Read is thus very different from Hash.Sum) -	// It never returns an error. +	// It never returns an error, but subsequent calls to Write or Sum +	// will panic.  	io.Reader  	// Clone returns a copy of the ShakeHash in its current state.  	Clone() ShakeHash - -	// Reset resets the ShakeHash to its initial state. -	Reset()  }  // cSHAKE specific context @@ -81,8 +80,8 @@ func leftEncode(value uint64) []byte {  	return b[i-1:]  } -func newCShake(N, S []byte, rate int, dsbyte byte) ShakeHash { -	c := cshakeState{state: &state{rate: rate, dsbyte: dsbyte}} +func newCShake(N, S []byte, rate, outputLen int, dsbyte byte) ShakeHash { +	c := cshakeState{state: &state{rate: rate, outputLen: outputLen, dsbyte: dsbyte}}  	// leftEncode returns max 9 bytes  	c.initBlock = make([]byte, 0, 9*2+len(N)+len(S)) @@ -119,7 +118,7 @@ func NewShake128() ShakeHash {  	if h := newShake128Asm(); h != nil {  		return h  	} -	return &state{rate: rate128, dsbyte: dsbyteShake} +	return &state{rate: rate128, outputLen: 32, dsbyte: dsbyteShake}  }  // NewShake256 creates a new SHAKE256 variable-output-length ShakeHash. @@ -129,7 +128,7 @@ func NewShake256() ShakeHash {  	if h := newShake256Asm(); h != nil {  		return h  	} -	return &state{rate: rate256, dsbyte: dsbyteShake} +	return &state{rate: rate256, outputLen: 64, dsbyte: dsbyteShake}  }  // NewCShake128 creates a new instance of cSHAKE128 variable-output-length ShakeHash, @@ -142,7 +141,7 @@ func NewCShake128(N, S []byte) ShakeHash {  	if len(N) == 0 && len(S) == 0 {  		return NewShake128()  	} -	return newCShake(N, S, rate128, dsbyteCShake) +	return newCShake(N, S, rate128, 32, dsbyteCShake)  }  // NewCShake256 creates a new instance of cSHAKE256 variable-output-length ShakeHash, @@ -155,7 +154,7 @@ func NewCShake256(N, S []byte) ShakeHash {  	if len(N) == 0 && len(S) == 0 {  		return NewShake256()  	} -	return newCShake(N, S, rate256, dsbyteCShake) +	return newCShake(N, S, rate256, 64, dsbyteCShake)  }  // ShakeSum128 writes an arbitrary-length digest of data into hash. diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go index fc04d03e1..27d0e14aa 100644 --- a/vendor/golang.org/x/crypto/ssh/certs.go +++ b/vendor/golang.org/x/crypto/ssh/certs.go @@ -16,8 +16,9 @@ import (  // Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear  // in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms. -// Unlike key algorithm names, these are not passed to AlgorithmSigner and don't -// appear in the Signature.Format field. +// Unlike key algorithm names, these are not passed to AlgorithmSigner nor +// returned by MultiAlgorithmSigner and don't appear in the Signature.Format +// field.  const (  	CertAlgoRSAv01        = "ssh-rsa-cert-v01@openssh.com"  	CertAlgoDSAv01        = "ssh-dss-cert-v01@openssh.com" @@ -255,10 +256,17 @@ func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {  		return nil, errors.New("ssh: signer and cert have different public key")  	} -	if algorithmSigner, ok := signer.(AlgorithmSigner); ok { +	switch s := signer.(type) { +	case MultiAlgorithmSigner: +		return &multiAlgorithmSigner{ +			AlgorithmSigner: &algorithmOpenSSHCertSigner{ +				&openSSHCertSigner{cert, signer}, s}, +			supportedAlgorithms: s.Algorithms(), +		}, nil +	case AlgorithmSigner:  		return &algorithmOpenSSHCertSigner{ -			&openSSHCertSigner{cert, signer}, algorithmSigner}, nil -	} else { +			&openSSHCertSigner{cert, signer}, s}, nil +	default:  		return &openSSHCertSigner{cert, signer}, nil  	}  } @@ -432,7 +440,9 @@ func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {  }  // SignCert signs the certificate with an authority, setting the Nonce, -// SignatureKey, and Signature fields. +// SignatureKey, and Signature fields. If the authority implements the +// MultiAlgorithmSigner interface the first algorithm in the list is used. This +// is useful if you want to sign with a specific algorithm.  func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {  	c.Nonce = make([]byte, 32)  	if _, err := io.ReadFull(rand, c.Nonce); err != nil { @@ -440,8 +450,20 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {  	}  	c.SignatureKey = authority.PublicKey() -	// Default to KeyAlgoRSASHA512 for ssh-rsa signers. -	if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA { +	if v, ok := authority.(MultiAlgorithmSigner); ok { +		if len(v.Algorithms()) == 0 { +			return errors.New("the provided authority has no signature algorithm") +		} +		// Use the first algorithm in the list. +		sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), v.Algorithms()[0]) +		if err != nil { +			return err +		} +		c.Signature = sig +		return nil +	} else if v, ok := authority.(AlgorithmSigner); ok && v.PublicKey().Type() == KeyAlgoRSA { +		// Default to KeyAlgoRSASHA512 for ssh-rsa signers. +		// TODO: consider using KeyAlgoRSASHA256 as default.  		sig, err := v.SignWithAlgorithm(rand, c.bytesForSigning(), KeyAlgoRSASHA512)  		if err != nil {  			return err diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go index 409b5ea1d..5c3bc2572 100644 --- a/vendor/golang.org/x/crypto/ssh/client_auth.go +++ b/vendor/golang.org/x/crypto/ssh/client_auth.go @@ -71,7 +71,9 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {  	for auth := AuthMethod(new(noneAuth)); auth != nil; {  		ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions)  		if err != nil { -			return err +			// We return the error later if there is no other method left to +			// try. +			ok = authFailure  		}  		if ok == authSuccess {  			// success @@ -101,6 +103,12 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {  				}  			}  		} + +		if auth == nil && err != nil { +			// We have an error and there are no other authentication methods to +			// try, so we return it. +			return err +		}  	}  	return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", tried)  } @@ -217,21 +225,45 @@ func (cb publicKeyCallback) method() string {  	return "publickey"  } -func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (as AlgorithmSigner, algo string) { +func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (MultiAlgorithmSigner, string, error) { +	var as MultiAlgorithmSigner  	keyFormat := signer.PublicKey().Type() -	// Like in sendKexInit, if the public key implements AlgorithmSigner we -	// assume it supports all algorithms, otherwise only the key format one. -	as, ok := signer.(AlgorithmSigner) -	if !ok { -		return algorithmSignerWrapper{signer}, keyFormat +	// If the signer implements MultiAlgorithmSigner we use the algorithms it +	// support, if it implements AlgorithmSigner we assume it supports all +	// algorithms, otherwise only the key format one. +	switch s := signer.(type) { +	case MultiAlgorithmSigner: +		as = s +	case AlgorithmSigner: +		as = &multiAlgorithmSigner{ +			AlgorithmSigner:     s, +			supportedAlgorithms: algorithmsForKeyFormat(underlyingAlgo(keyFormat)), +		} +	default: +		as = &multiAlgorithmSigner{ +			AlgorithmSigner:     algorithmSignerWrapper{signer}, +			supportedAlgorithms: []string{underlyingAlgo(keyFormat)}, +		} +	} + +	getFallbackAlgo := func() (string, error) { +		// 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)) { +			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()) +		} +		return keyFormat, nil  	}  	extPayload, ok := extensions["server-sig-algs"]  	if !ok { -		// If there is no "server-sig-algs" extension, fall back to the key -		// format algorithm. -		return as, keyFormat +		// If there is no "server-sig-algs" extension use the fallback +		// algorithm. +		algo, err := getFallbackAlgo() +		return as, algo, err  	}  	// The server-sig-algs extension only carries underlying signature @@ -245,15 +277,22 @@ func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (as Alg  		}  	} -	keyAlgos := algorithmsForKeyFormat(keyFormat) +	// Filter algorithms based on those supported by MultiAlgorithmSigner. +	var keyAlgos []string +	for _, algo := range algorithmsForKeyFormat(keyFormat) { +		if contains(as.Algorithms(), underlyingAlgo(algo)) { +			keyAlgos = append(keyAlgos, algo) +		} +	} +  	algo, err := findCommon("public key signature algorithm", keyAlgos, serverAlgos)  	if err != nil { -		// If there is no overlap, try the key anyway with the key format -		// algorithm, to support servers that fail to list all supported -		// algorithms. -		return as, keyFormat +		// If there is no overlap, return the fallback algorithm to support +		// servers that fail to list all supported algorithms. +		algo, err := getFallbackAlgo() +		return as, algo, err  	} -	return as, algo +	return as, algo, nil  }  func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) { @@ -267,10 +306,17 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand  		return authFailure, nil, err  	}  	var methods []string +	var errSigAlgo error  	for _, signer := range signers {  		pub := signer.PublicKey() -		as, algo := pickSignatureAlgorithm(signer, extensions) - +		as, algo, err := pickSignatureAlgorithm(signer, extensions) +		if err != nil && errSigAlgo == nil { +			// If we cannot negotiate a signature algorithm store the first +			// error so we can return it to provide a more meaningful message if +			// no other signers work. +			errSigAlgo = err +			continue +		}  		ok, err := validateKey(pub, algo, user, c)  		if err != nil {  			return authFailure, nil, err @@ -317,22 +363,12 @@ 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 || !containsMethod(methods, cb.method()) { +		if success == authSuccess || !contains(methods, cb.method()) {  			return success, methods, err  		}  	} -	return authFailure, methods, nil -} - -func containsMethod(methods []string, method string) bool { -	for _, m := range methods { -		if m == method { -			return true -		} -	} - -	return false +	return authFailure, methods, errSigAlgo  }  // validateKey validates the key provided is acceptable to the server. diff --git a/vendor/golang.org/x/crypto/ssh/doc.go b/vendor/golang.org/x/crypto/ssh/doc.go index f6bff60dc..edbe63340 100644 --- a/vendor/golang.org/x/crypto/ssh/doc.go +++ b/vendor/golang.org/x/crypto/ssh/doc.go @@ -13,6 +13,7 @@ others.  References: +	[PROTOCOL]: https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=HEAD  	[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 diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go index 07a1843e0..70a7369ff 100644 --- a/vendor/golang.org/x/crypto/ssh/handshake.go +++ b/vendor/golang.org/x/crypto/ssh/handshake.go @@ -461,19 +461,24 @@ func (t *handshakeTransport) sendKexInit() error {  	isServer := len(t.hostKeys) > 0  	if isServer {  		for _, k := range t.hostKeys { -			// If k is an AlgorithmSigner, presume it supports all signature algorithms -			// associated with the key format. (Ideally AlgorithmSigner would have a -			// method to advertise supported algorithms, but it doesn't. This means that -			// adding support for a new algorithm is a breaking change, as we will -			// immediately negotiate it even if existing implementations don't support -			// it. If that ever happens, we'll have to figure something out.) -			// If k is not an AlgorithmSigner, we can only assume it only supports the -			// algorithms that matches the key format. (This means that Sign can't pick -			// a different default.) +			// If k is a MultiAlgorithmSigner, we restrict the signature +			// algorithms. If k is a AlgorithmSigner, presume it supports all +			// signature algorithms associated with the key format. If k is not +			// an AlgorithmSigner, we can only assume it only supports the +			// algorithms that matches the key format. (This means that Sign +			// can't pick a different default).  			keyFormat := k.PublicKey().Type() -			if _, ok := k.(AlgorithmSigner); ok { + +			switch s := k.(type) { +			case MultiAlgorithmSigner: +				for _, algo := range algorithmsForKeyFormat(keyFormat) { +					if contains(s.Algorithms(), underlyingAlgo(algo)) { +						msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algo) +					} +				} +			case AlgorithmSigner:  				msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algorithmsForKeyFormat(keyFormat)...) -			} else { +			default:  				msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat)  			}  		} @@ -642,16 +647,20 @@ 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. +	// RFC 8308, Sections 2.4 and 3.1, and [PROTOCOL], Section 1.9.  	if !isClient && firstKeyExchange && contains(clientInit.KexAlgos, "ext-info-c") {  		extInfo := &extInfoMsg{ -			NumExtensions: 1, -			Payload:       make([]byte, 0, 4+15+4+len(supportedPubKeyAuthAlgosList)), +			NumExtensions: 2, +			Payload:       make([]byte, 0, 4+15+4+len(supportedPubKeyAuthAlgosList)+4+16+4+1),  		}  		extInfo.Payload = appendInt(extInfo.Payload, len("server-sig-algs"))  		extInfo.Payload = append(extInfo.Payload, "server-sig-algs"...)  		extInfo.Payload = appendInt(extInfo.Payload, len(supportedPubKeyAuthAlgosList))  		extInfo.Payload = append(extInfo.Payload, supportedPubKeyAuthAlgosList...) +		extInfo.Payload = appendInt(extInfo.Payload, len("ping@openssh.com")) +		extInfo.Payload = append(extInfo.Payload, "ping@openssh.com"...) +		extInfo.Payload = appendInt(extInfo.Payload, 1) +		extInfo.Payload = append(extInfo.Payload, "0"...)  		if err := t.conn.writePacket(Marshal(extInfo)); err != nil {  			return err  		} @@ -685,9 +694,16 @@ 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)) { +				continue +			} +		} +  		if algo == k.PublicKey().Type() {  			return algorithmSignerWrapper{k}  		} +  		k, ok := k.(AlgorithmSigner)  		if !ok {  			continue diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go index dac8ee724..ef1bad731 100644 --- a/vendor/golang.org/x/crypto/ssh/keys.go +++ b/vendor/golang.org/x/crypto/ssh/keys.go @@ -11,13 +11,16 @@ import (  	"crypto/cipher"  	"crypto/dsa"  	"crypto/ecdsa" +	"crypto/ed25519"  	"crypto/elliptic"  	"crypto/md5" +	"crypto/rand"  	"crypto/rsa"  	"crypto/sha256"  	"crypto/x509"  	"encoding/asn1"  	"encoding/base64" +	"encoding/binary"  	"encoding/hex"  	"encoding/pem"  	"errors" @@ -26,7 +29,6 @@ import (  	"math/big"  	"strings" -	"golang.org/x/crypto/ed25519"  	"golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"  ) @@ -295,6 +297,18 @@ func MarshalAuthorizedKey(key PublicKey) []byte {  	return b.Bytes()  } +// MarshalPrivateKey returns a PEM block with the private key serialized in the +// OpenSSH format. +func MarshalPrivateKey(key crypto.PrivateKey, comment string) (*pem.Block, error) { +	return marshalOpenSSHPrivateKey(key, comment, unencryptedOpenSSHMarshaler) +} + +// MarshalPrivateKeyWithPassphrase returns a PEM block holding the encrypted +// private key serialized in the OpenSSH format. +func MarshalPrivateKeyWithPassphrase(key crypto.PrivateKey, comment string, passphrase []byte) (*pem.Block, error) { +	return marshalOpenSSHPrivateKey(key, comment, passphraseProtectedOpenSSHMarshaler(passphrase)) +} +  // PublicKey represents a public key using an unspecified algorithm.  //  // Some PublicKeys provided by this package also implement CryptoPublicKey. @@ -321,7 +335,7 @@ type CryptoPublicKey interface {  // A Signer can create signatures that verify against a public key.  // -// Some Signers provided by this package also implement AlgorithmSigner. +// Some Signers provided by this package also implement MultiAlgorithmSigner.  type Signer interface {  	// PublicKey returns the associated PublicKey.  	PublicKey() PublicKey @@ -336,9 +350,9 @@ type Signer interface {  // An AlgorithmSigner is a Signer that also supports specifying an algorithm to  // use for signing.  // -// An AlgorithmSigner can't advertise the algorithms it supports, so it should -// be prepared to be invoked with every algorithm supported by the public key -// format. +// An AlgorithmSigner can't advertise the algorithms it supports, unless it also +// implements MultiAlgorithmSigner, so it should be prepared to be invoked with +// every algorithm supported by the public key format.  type AlgorithmSigner interface {  	Signer @@ -349,6 +363,75 @@ type AlgorithmSigner interface {  	SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error)  } +// MultiAlgorithmSigner is an AlgorithmSigner that also reports the algorithms +// supported by that signer. +type MultiAlgorithmSigner interface { +	AlgorithmSigner + +	// Algorithms returns the available algorithms in preference order. The list +	// must not be empty, and it must not include certificate types. +	Algorithms() []string +} + +// NewSignerWithAlgorithms returns a signer restricted to the specified +// algorithms. The algorithms must be set in preference order. The list must not +// be empty, and it must not include certificate types. An error is returned if +// the specified algorithms are incompatible with the public key type. +func NewSignerWithAlgorithms(signer AlgorithmSigner, algorithms []string) (MultiAlgorithmSigner, error) { +	if len(algorithms) == 0 { +		return nil, errors.New("ssh: please specify at least one valid signing algorithm") +	} +	var signerAlgos []string +	supportedAlgos := algorithmsForKeyFormat(underlyingAlgo(signer.PublicKey().Type())) +	if s, ok := signer.(*multiAlgorithmSigner); ok { +		signerAlgos = s.Algorithms() +	} else { +		signerAlgos = supportedAlgos +	} + +	for _, algo := range algorithms { +		if !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) { +			return nil, fmt.Errorf("ssh: algorithm %q is restricted for the provided signer", algo) +		} +	} +	return &multiAlgorithmSigner{ +		AlgorithmSigner:     signer, +		supportedAlgorithms: algorithms, +	}, nil +} + +type multiAlgorithmSigner struct { +	AlgorithmSigner +	supportedAlgorithms []string +} + +func (s *multiAlgorithmSigner) Algorithms() []string { +	return s.supportedAlgorithms +} + +func (s *multiAlgorithmSigner) isAlgorithmSupported(algorithm string) bool { +	if algorithm == "" { +		algorithm = underlyingAlgo(s.PublicKey().Type()) +	} +	for _, algo := range s.supportedAlgorithms { +		if algorithm == algo { +			return true +		} +	} +	return false +} + +func (s *multiAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) { +	if !s.isAlgorithmSupported(algorithm) { +		return nil, fmt.Errorf("ssh: algorithm %q is not supported: %v", algorithm, s.supportedAlgorithms) +	} +	return s.AlgorithmSigner.SignWithAlgorithm(rand, data, algorithm) +} +  type rsaPublicKey rsa.PublicKey  func (r *rsaPublicKey) Type() string { @@ -512,6 +595,10 @@ func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {  	return k.SignWithAlgorithm(rand, data, k.PublicKey().Type())  } +func (k *dsaPrivateKey) Algorithms() []string { +	return []string{k.PublicKey().Type()} +} +  func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {  	if algorithm != "" && algorithm != k.PublicKey().Type() {  		return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm) @@ -961,13 +1048,16 @@ func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {  	return s.SignWithAlgorithm(rand, data, s.pubKey.Type())  } +func (s *wrappedSigner) Algorithms() []string { +	return algorithmsForKeyFormat(s.pubKey.Type()) +} +  func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {  	if algorithm == "" {  		algorithm = s.pubKey.Type()  	} -	supportedAlgos := algorithmsForKeyFormat(s.pubKey.Type()) -	if !contains(supportedAlgos, algorithm) { +	if !contains(s.Algorithms(), algorithm) {  		return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type())  	} @@ -1241,28 +1331,106 @@ func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc {  	}  } +func unencryptedOpenSSHMarshaler(privKeyBlock []byte) ([]byte, string, string, string, error) { +	key := generateOpenSSHPadding(privKeyBlock, 8) +	return key, "none", "none", "", nil +} + +func passphraseProtectedOpenSSHMarshaler(passphrase []byte) openSSHEncryptFunc { +	return func(privKeyBlock []byte) ([]byte, string, string, string, error) { +		salt := make([]byte, 16) +		if _, err := rand.Read(salt); err != nil { +			return nil, "", "", "", err +		} + +		opts := struct { +			Salt   []byte +			Rounds uint32 +		}{salt, 16} + +		// Derive key to encrypt the private key block. +		k, err := bcrypt_pbkdf.Key(passphrase, salt, int(opts.Rounds), 32+aes.BlockSize) +		if err != nil { +			return nil, "", "", "", err +		} + +		// Add padding matching the block size of AES. +		keyBlock := generateOpenSSHPadding(privKeyBlock, aes.BlockSize) + +		// Encrypt the private key using the derived secret. + +		dst := make([]byte, len(keyBlock)) +		key, iv := k[:32], k[32:] +		block, err := aes.NewCipher(key) +		if err != nil { +			return nil, "", "", "", err +		} + +		stream := cipher.NewCTR(block, iv) +		stream.XORKeyStream(dst, keyBlock) + +		return dst, "aes256-ctr", "bcrypt", string(Marshal(opts)), nil +	} +} + +const privateKeyAuthMagic = "openssh-key-v1\x00" +  type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error) +type openSSHEncryptFunc func(PrivKeyBlock []byte) (ProtectedKeyBlock []byte, cipherName, kdfName, kdfOptions string, err error) + +type openSSHEncryptedPrivateKey struct { +	CipherName   string +	KdfName      string +	KdfOpts      string +	NumKeys      uint32 +	PubKey       []byte +	PrivKeyBlock []byte +} + +type openSSHPrivateKey struct { +	Check1  uint32 +	Check2  uint32 +	Keytype string +	Rest    []byte `ssh:"rest"` +} + +type openSSHRSAPrivateKey struct { +	N       *big.Int +	E       *big.Int +	D       *big.Int +	Iqmp    *big.Int +	P       *big.Int +	Q       *big.Int +	Comment string +	Pad     []byte `ssh:"rest"` +} + +type openSSHEd25519PrivateKey struct { +	Pub     []byte +	Priv    []byte +	Comment string +	Pad     []byte `ssh:"rest"` +} + +type openSSHECDSAPrivateKey struct { +	Curve   string +	Pub     []byte +	D       *big.Int +	Comment string +	Pad     []byte `ssh:"rest"` +}  // parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt  // function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used  // as the decrypt function to parse an unencrypted private key. See  // https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key.  func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.PrivateKey, error) { -	const magic = "openssh-key-v1\x00" -	if len(key) < len(magic) || string(key[:len(magic)]) != magic { +	if len(key) < len(privateKeyAuthMagic) || string(key[:len(privateKeyAuthMagic)]) != privateKeyAuthMagic {  		return nil, errors.New("ssh: invalid openssh private key format")  	} -	remaining := key[len(magic):] - -	var w struct { -		CipherName   string -		KdfName      string -		KdfOpts      string -		NumKeys      uint32 -		PubKey       []byte -		PrivKeyBlock []byte -	} +	remaining := key[len(privateKeyAuthMagic):] +	var w openSSHEncryptedPrivateKey  	if err := Unmarshal(remaining, &w); err != nil {  		return nil, err  	} @@ -1284,13 +1452,7 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv  		return nil, err  	} -	pk1 := struct { -		Check1  uint32 -		Check2  uint32 -		Keytype string -		Rest    []byte `ssh:"rest"` -	}{} - +	var pk1 openSSHPrivateKey  	if err := Unmarshal(privKeyBlock, &pk1); err != nil || pk1.Check1 != pk1.Check2 {  		if w.CipherName != "none" {  			return nil, x509.IncorrectPasswordError @@ -1300,18 +1462,7 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv  	switch pk1.Keytype {  	case KeyAlgoRSA: -		// https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773 -		key := struct { -			N       *big.Int -			E       *big.Int -			D       *big.Int -			Iqmp    *big.Int -			P       *big.Int -			Q       *big.Int -			Comment string -			Pad     []byte `ssh:"rest"` -		}{} - +		var key openSSHRSAPrivateKey  		if err := Unmarshal(pk1.Rest, &key); err != nil {  			return nil, err  		} @@ -1337,13 +1488,7 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv  		return pk, nil  	case KeyAlgoED25519: -		key := struct { -			Pub     []byte -			Priv    []byte -			Comment string -			Pad     []byte `ssh:"rest"` -		}{} - +		var key openSSHEd25519PrivateKey  		if err := Unmarshal(pk1.Rest, &key); err != nil {  			return nil, err  		} @@ -1360,14 +1505,7 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv  		copy(pk, key.Priv)  		return &pk, nil  	case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: -		key := struct { -			Curve   string -			Pub     []byte -			D       *big.Int -			Comment string -			Pad     []byte `ssh:"rest"` -		}{} - +		var key openSSHECDSAPrivateKey  		if err := Unmarshal(pk1.Rest, &key); err != nil {  			return nil, err  		} @@ -1415,6 +1553,131 @@ func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.Priv  	}  } +func marshalOpenSSHPrivateKey(key crypto.PrivateKey, comment string, encrypt openSSHEncryptFunc) (*pem.Block, error) { +	var w openSSHEncryptedPrivateKey +	var pk1 openSSHPrivateKey + +	// Random check bytes. +	var check uint32 +	if err := binary.Read(rand.Reader, binary.BigEndian, &check); err != nil { +		return nil, err +	} + +	pk1.Check1 = check +	pk1.Check2 = check +	w.NumKeys = 1 + +	// Use a []byte directly on ed25519 keys. +	if k, ok := key.(*ed25519.PrivateKey); ok { +		key = *k +	} + +	switch k := key.(type) { +	case *rsa.PrivateKey: +		E := new(big.Int).SetInt64(int64(k.PublicKey.E)) +		// Marshal public key: +		// E and N are in reversed order in the public and private key. +		pubKey := struct { +			KeyType string +			E       *big.Int +			N       *big.Int +		}{ +			KeyAlgoRSA, +			E, k.PublicKey.N, +		} +		w.PubKey = Marshal(pubKey) + +		// Marshal private key. +		key := openSSHRSAPrivateKey{ +			N:       k.PublicKey.N, +			E:       E, +			D:       k.D, +			Iqmp:    k.Precomputed.Qinv, +			P:       k.Primes[0], +			Q:       k.Primes[1], +			Comment: comment, +		} +		pk1.Keytype = KeyAlgoRSA +		pk1.Rest = Marshal(key) +	case ed25519.PrivateKey: +		pub := make([]byte, ed25519.PublicKeySize) +		priv := make([]byte, ed25519.PrivateKeySize) +		copy(pub, k[32:]) +		copy(priv, k) + +		// Marshal public key. +		pubKey := struct { +			KeyType string +			Pub     []byte +		}{ +			KeyAlgoED25519, pub, +		} +		w.PubKey = Marshal(pubKey) + +		// Marshal private key. +		key := openSSHEd25519PrivateKey{ +			Pub:     pub, +			Priv:    priv, +			Comment: comment, +		} +		pk1.Keytype = KeyAlgoED25519 +		pk1.Rest = Marshal(key) +	case *ecdsa.PrivateKey: +		var curve, keyType string +		switch name := k.Curve.Params().Name; name { +		case "P-256": +			curve = "nistp256" +			keyType = KeyAlgoECDSA256 +		case "P-384": +			curve = "nistp384" +			keyType = KeyAlgoECDSA384 +		case "P-521": +			curve = "nistp521" +			keyType = KeyAlgoECDSA521 +		default: +			return nil, errors.New("ssh: unhandled elliptic curve " + name) +		} + +		pub := elliptic.Marshal(k.Curve, k.PublicKey.X, k.PublicKey.Y) + +		// Marshal public key. +		pubKey := struct { +			KeyType string +			Curve   string +			Pub     []byte +		}{ +			keyType, curve, pub, +		} +		w.PubKey = Marshal(pubKey) + +		// Marshal private key. +		key := openSSHECDSAPrivateKey{ +			Curve:   curve, +			Pub:     pub, +			D:       k.D, +			Comment: comment, +		} +		pk1.Keytype = keyType +		pk1.Rest = Marshal(key) +	default: +		return nil, fmt.Errorf("ssh: unsupported key type %T", k) +	} + +	var err error +	// Add padding and encrypt the key if necessary. +	w.PrivKeyBlock, w.CipherName, w.KdfName, w.KdfOpts, err = encrypt(Marshal(pk1)) +	if err != nil { +		return nil, err +	} + +	b := Marshal(w) +	block := &pem.Block{ +		Type:  "OPENSSH PRIVATE KEY", +		Bytes: append([]byte(privateKeyAuthMagic), b...), +	} +	return block, nil +} +  func checkOpenSSHKeyPadding(pad []byte) error {  	for i, b := range pad {  		if int(b) != i+1 { @@ -1424,6 +1687,13 @@ func checkOpenSSHKeyPadding(pad []byte) error {  	return nil  } +func generateOpenSSHPadding(block []byte, blockSize int) []byte { +	for i, l := 0, len(block); (l+i)%blockSize != 0; i++ { +		block = append(block, byte(i+1)) +	} +	return block +} +  // FingerprintLegacyMD5 returns the user presentation of the key's  // fingerprint as described by RFC 4716 section 4.  func FingerprintLegacyMD5(pubKey PublicKey) string { diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go index 922032d95..b55f86056 100644 --- a/vendor/golang.org/x/crypto/ssh/messages.go +++ b/vendor/golang.org/x/crypto/ssh/messages.go @@ -349,6 +349,20 @@ type userAuthGSSAPIError struct {  	LanguageTag string  } +// Transport layer OpenSSH extension. See [PROTOCOL], section 1.9 +const msgPing = 192 + +type pingMsg struct { +	Data string `sshtype:"192"` +} + +// Transport layer OpenSSH extension. See [PROTOCOL], section 1.9 +const msgPong = 193 + +type pongMsg struct { +	Data string `sshtype:"193"` +} +  // typeTags returns the possible type bytes for the given reflect.Type, which  // should be a struct. The possible values are separated by a '|' character.  func typeTags(structType reflect.Type) (tags []byte) { diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go index 9654c0186..d2d24c635 100644 --- a/vendor/golang.org/x/crypto/ssh/mux.go +++ b/vendor/golang.org/x/crypto/ssh/mux.go @@ -231,6 +231,12 @@ func (m *mux) onePacket() error {  		return m.handleChannelOpen(packet)  	case msgGlobalRequest, msgRequestSuccess, msgRequestFailure:  		return m.handleGlobalPacket(packet) +	case msgPing: +		var msg pingMsg +		if err := Unmarshal(packet, &msg); err != nil { +			return fmt.Errorf("failed to unmarshal ping@openssh.com message: %w", err) +		} +		return m.sendMessage(pongMsg(msg))  	}  	// assume a channel packet. diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go index b21322aff..727c71b9c 100644 --- a/vendor/golang.org/x/crypto/ssh/server.go +++ b/vendor/golang.org/x/crypto/ssh/server.go @@ -576,7 +576,16 @@ userAuthLoop:  				if !ok || len(payload) > 0 {  					return nil, parseError(msgUserAuthRequest)  				} - +				// Ensure the declared public key algo is compatible with the +				// decoded one. This check will ensure we don't accept e.g. +				// 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) { +					authErr = fmt.Errorf("ssh: public key type %q not compatible with selected algorithm %q", +						pubKey.Type(), algo) +					break +				}  				// Ensure the public key algo and signature algo  				// are supported.  Compare the private key  				// algorithm name that corresponds to algo with  | 
