Merge pull request #6210 from containers/renovate/golang.org-x-crypto-0.x
fix(deps): update module golang.org/x/crypto to v0.39.0
This commit is contained in:
commit
12e41eca79
6
go.mod
6
go.mod
|
@ -37,7 +37,7 @@ require (
|
|||
github.com/spf13/pflag v1.0.6
|
||||
github.com/stretchr/testify v1.10.0
|
||||
go.etcd.io/bbolt v1.4.0
|
||||
golang.org/x/crypto v0.38.0
|
||||
golang.org/x/crypto v0.39.0
|
||||
golang.org/x/sync v0.15.0
|
||||
golang.org/x/sys v0.33.0
|
||||
golang.org/x/term v0.32.0
|
||||
|
@ -147,9 +147,9 @@ require (
|
|||
go.opentelemetry.io/otel v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/mod v0.25.0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
||||
google.golang.org/grpc v1.71.0 // indirect
|
||||
|
|
16
go.sum
16
go.sum
|
@ -411,8 +411,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
|
|||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
|
@ -424,8 +424,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -500,8 +500,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -516,8 +516,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
@ -50,7 +50,7 @@ func (ih InvalidHashPrefixError) Error() string {
|
|||
type InvalidCostError int
|
||||
|
||||
func (ic InvalidCostError) Error() string {
|
||||
return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), MinCost, MaxCost)
|
||||
return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed inclusive range %d..%d", int(ic), MinCost, MaxCost)
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
|
@ -555,7 +555,7 @@ func (c *client) insertKey(s interface{}, comment string, constraints []byte) er
|
|||
})
|
||||
case *dsa.PrivateKey:
|
||||
req = ssh.Marshal(dsaKeyMsg{
|
||||
Type: ssh.KeyAlgoDSA,
|
||||
Type: ssh.InsecureKeyAlgoDSA,
|
||||
P: k.P,
|
||||
Q: k.Q,
|
||||
G: k.G,
|
||||
|
@ -803,16 +803,16 @@ var _ ssh.AlgorithmSigner = &agentKeyringSigner{}
|
|||
//
|
||||
// This map must be kept in sync with the one in certs.go.
|
||||
var certKeyAlgoNames = map[string]string{
|
||||
ssh.CertAlgoRSAv01: ssh.KeyAlgoRSA,
|
||||
ssh.CertAlgoRSASHA256v01: ssh.KeyAlgoRSASHA256,
|
||||
ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512,
|
||||
ssh.CertAlgoDSAv01: ssh.KeyAlgoDSA,
|
||||
ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256,
|
||||
ssh.CertAlgoECDSA384v01: ssh.KeyAlgoECDSA384,
|
||||
ssh.CertAlgoECDSA521v01: ssh.KeyAlgoECDSA521,
|
||||
ssh.CertAlgoSKECDSA256v01: ssh.KeyAlgoSKECDSA256,
|
||||
ssh.CertAlgoED25519v01: ssh.KeyAlgoED25519,
|
||||
ssh.CertAlgoSKED25519v01: ssh.KeyAlgoSKED25519,
|
||||
ssh.CertAlgoRSAv01: ssh.KeyAlgoRSA,
|
||||
ssh.CertAlgoRSASHA256v01: ssh.KeyAlgoRSASHA256,
|
||||
ssh.CertAlgoRSASHA512v01: ssh.KeyAlgoRSASHA512,
|
||||
ssh.InsecureCertAlgoDSAv01: ssh.InsecureKeyAlgoDSA,
|
||||
ssh.CertAlgoECDSA256v01: ssh.KeyAlgoECDSA256,
|
||||
ssh.CertAlgoECDSA384v01: ssh.KeyAlgoECDSA384,
|
||||
ssh.CertAlgoECDSA521v01: ssh.KeyAlgoECDSA521,
|
||||
ssh.CertAlgoSKECDSA256v01: ssh.KeyAlgoSKECDSA256,
|
||||
ssh.CertAlgoED25519v01: ssh.KeyAlgoED25519,
|
||||
ssh.CertAlgoSKED25519v01: ssh.KeyAlgoSKED25519,
|
||||
}
|
||||
|
||||
// underlyingAlgo returns the signature algorithm associated with algo (which is
|
||||
|
|
|
@ -506,7 +506,7 @@ func (s *server) insertIdentity(req []byte) error {
|
|||
switch record.Type {
|
||||
case ssh.KeyAlgoRSA:
|
||||
addedKey, err = parseRSAKey(req)
|
||||
case ssh.KeyAlgoDSA:
|
||||
case ssh.InsecureKeyAlgoDSA:
|
||||
addedKey, err = parseDSAKey(req)
|
||||
case ssh.KeyAlgoECDSA256, ssh.KeyAlgoECDSA384, ssh.KeyAlgoECDSA521:
|
||||
addedKey, err = parseECDSAKey(req)
|
||||
|
@ -514,7 +514,7 @@ func (s *server) insertIdentity(req []byte) error {
|
|||
addedKey, err = parseEd25519Key(req)
|
||||
case ssh.CertAlgoRSAv01:
|
||||
addedKey, err = parseRSACert(req)
|
||||
case ssh.CertAlgoDSAv01:
|
||||
case ssh.InsecureCertAlgoDSAv01:
|
||||
addedKey, err = parseDSACert(req)
|
||||
case ssh.CertAlgoECDSA256v01, ssh.CertAlgoECDSA384v01, ssh.CertAlgoECDSA521v01:
|
||||
addedKey, err = parseECDSACert(req)
|
||||
|
|
|
@ -20,14 +20,19 @@ import (
|
|||
// 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"
|
||||
CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
|
||||
CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
|
||||
CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
|
||||
CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
|
||||
CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
|
||||
CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
|
||||
CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
|
||||
// Deprecated: DSA is only supported at insecure key sizes, and was removed
|
||||
// from major implementations.
|
||||
CertAlgoDSAv01 = InsecureCertAlgoDSAv01
|
||||
// Deprecated: DSA is only supported at insecure key sizes, and was removed
|
||||
// from major implementations.
|
||||
InsecureCertAlgoDSAv01 = "ssh-dss-cert-v01@openssh.com"
|
||||
CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
|
||||
CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
|
||||
CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
|
||||
CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"
|
||||
CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com"
|
||||
CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
|
||||
|
||||
// CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a
|
||||
// Certificate.Type (or PublicKey.Type), but only in
|
||||
|
@ -485,16 +490,16 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
|
|||
//
|
||||
// This map must be kept in sync with the one in agent/client.go.
|
||||
var certKeyAlgoNames = map[string]string{
|
||||
CertAlgoRSAv01: KeyAlgoRSA,
|
||||
CertAlgoRSASHA256v01: KeyAlgoRSASHA256,
|
||||
CertAlgoRSASHA512v01: KeyAlgoRSASHA512,
|
||||
CertAlgoDSAv01: KeyAlgoDSA,
|
||||
CertAlgoECDSA256v01: KeyAlgoECDSA256,
|
||||
CertAlgoECDSA384v01: KeyAlgoECDSA384,
|
||||
CertAlgoECDSA521v01: KeyAlgoECDSA521,
|
||||
CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256,
|
||||
CertAlgoED25519v01: KeyAlgoED25519,
|
||||
CertAlgoSKED25519v01: KeyAlgoSKED25519,
|
||||
CertAlgoRSAv01: KeyAlgoRSA,
|
||||
CertAlgoRSASHA256v01: KeyAlgoRSASHA256,
|
||||
CertAlgoRSASHA512v01: KeyAlgoRSASHA512,
|
||||
InsecureCertAlgoDSAv01: InsecureKeyAlgoDSA,
|
||||
CertAlgoECDSA256v01: KeyAlgoECDSA256,
|
||||
CertAlgoECDSA384v01: KeyAlgoECDSA384,
|
||||
CertAlgoECDSA521v01: KeyAlgoECDSA521,
|
||||
CertAlgoSKECDSA256v01: KeyAlgoSKECDSA256,
|
||||
CertAlgoED25519v01: KeyAlgoED25519,
|
||||
CertAlgoSKED25519v01: KeyAlgoSKED25519,
|
||||
}
|
||||
|
||||
// underlyingAlgo returns the signature algorithm associated with algo (which is
|
||||
|
|
|
@ -58,11 +58,11 @@ func newRC4(key, iv []byte) (cipher.Stream, error) {
|
|||
type cipherMode struct {
|
||||
keySize int
|
||||
ivSize int
|
||||
create func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error)
|
||||
create func(key, iv []byte, macKey []byte, algs DirectionAlgorithms) (packetCipher, error)
|
||||
}
|
||||
|
||||
func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||
return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||
func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) {
|
||||
return func(key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) {
|
||||
stream, err := createFunc(key, iv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -98,36 +98,36 @@ func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream,
|
|||
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.
|
||||
"aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)},
|
||||
"aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)},
|
||||
"aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)},
|
||||
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.
|
||||
"arcfour128": {16, 0, streamCipherMode(1536, newRC4)},
|
||||
"arcfour256": {32, 0, streamCipherMode(1536, newRC4)},
|
||||
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.
|
||||
"arcfour": {16, 0, streamCipherMode(0, newRC4)},
|
||||
InsecureCipherRC4: {16, 0, streamCipherMode(0, newRC4)},
|
||||
|
||||
// AEAD ciphers
|
||||
gcm128CipherID: {16, 12, newGCMCipher},
|
||||
gcm256CipherID: {32, 12, newGCMCipher},
|
||||
chacha20Poly1305ID: {64, 0, newChaCha20Cipher},
|
||||
CipherAES128GCM: {16, 12, newGCMCipher},
|
||||
CipherAES256GCM: {32, 12, newGCMCipher},
|
||||
CipherChaCha20Poly1305: {64, 0, newChaCha20Cipher},
|
||||
|
||||
// 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.
|
||||
aes128cbcID: {16, aes.BlockSize, newAESCBCCipher},
|
||||
InsecureCipherAES128CBC: {16, aes.BlockSize, newAESCBCCipher},
|
||||
|
||||
// 3des-cbc is insecure and is not included in the default
|
||||
// config.
|
||||
tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher},
|
||||
InsecureCipherTripleDESCBC: {24, des.BlockSize, newTripleDESCBCCipher},
|
||||
}
|
||||
|
||||
// prefixLen is the length of the packet prefix that contains the packet length
|
||||
|
@ -307,7 +307,7 @@ type gcmCipher struct {
|
|||
buf []byte
|
||||
}
|
||||
|
||||
func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) {
|
||||
func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs DirectionAlgorithms) (packetCipher, error) {
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -429,7 +429,7 @@ type cbcCipher struct {
|
|||
oracleCamouflage uint32
|
||||
}
|
||||
|
||||
func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||
func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) {
|
||||
cbc := &cbcCipher{
|
||||
mac: macModes[algs.MAC].new(macKey),
|
||||
decrypter: cipher.NewCBCDecrypter(c, iv),
|
||||
|
@ -443,7 +443,7 @@ func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorith
|
|||
return cbc, nil
|
||||
}
|
||||
|
||||
func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||
func newAESCBCCipher(key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) {
|
||||
c, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -457,7 +457,7 @@ func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCi
|
|||
return cbc, nil
|
||||
}
|
||||
|
||||
func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {
|
||||
func newTripleDESCBCCipher(key, iv, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) {
|
||||
c, err := des.NewTripleDESCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -635,8 +635,6 @@ func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader
|
|||
return nil
|
||||
}
|
||||
|
||||
const chacha20Poly1305ID = "chacha20-poly1305@openssh.com"
|
||||
|
||||
// chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com
|
||||
// AEAD, which is described here:
|
||||
//
|
||||
|
@ -650,7 +648,7 @@ type chacha20Poly1305Cipher struct {
|
|||
buf []byte
|
||||
}
|
||||
|
||||
func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) {
|
||||
func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs DirectionAlgorithms) (packetCipher, error) {
|
||||
if len(key) != 64 {
|
||||
panic(len(key))
|
||||
}
|
||||
|
|
|
@ -110,6 +110,7 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e
|
|||
}
|
||||
|
||||
c.sessionID = c.transport.getSessionID()
|
||||
c.algorithms = c.transport.getAlgorithms()
|
||||
return c.clientAuthenticate(config)
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
_ "crypto/sha1"
|
||||
|
@ -24,69 +25,258 @@ const (
|
|||
serviceSSH = "ssh-connection"
|
||||
)
|
||||
|
||||
// supportedCiphers lists ciphers we support but might not recommend.
|
||||
var supportedCiphers = []string{
|
||||
"aes128-ctr", "aes192-ctr", "aes256-ctr",
|
||||
"aes128-gcm@openssh.com", gcm256CipherID,
|
||||
chacha20Poly1305ID,
|
||||
"arcfour256", "arcfour128", "arcfour",
|
||||
aes128cbcID,
|
||||
tripledescbcID,
|
||||
// The ciphers currently or previously implemented by this library, to use in
|
||||
// [Config.Ciphers]. For a list, see the [Algorithms.Ciphers] returned by
|
||||
// [SupportedAlgorithms] or [InsecureAlgorithms].
|
||||
const (
|
||||
CipherAES128GCM = "aes128-gcm@openssh.com"
|
||||
CipherAES256GCM = "aes256-gcm@openssh.com"
|
||||
CipherChaCha20Poly1305 = "chacha20-poly1305@openssh.com"
|
||||
CipherAES128CTR = "aes128-ctr"
|
||||
CipherAES192CTR = "aes192-ctr"
|
||||
CipherAES256CTR = "aes256-ctr"
|
||||
InsecureCipherAES128CBC = "aes128-cbc"
|
||||
InsecureCipherTripleDESCBC = "3des-cbc"
|
||||
InsecureCipherRC4 = "arcfour"
|
||||
InsecureCipherRC4128 = "arcfour128"
|
||||
InsecureCipherRC4256 = "arcfour256"
|
||||
)
|
||||
|
||||
// The key exchanges currently or previously implemented by this library, to use
|
||||
// in [Config.KeyExchanges]. For a list, see the
|
||||
// [Algorithms.KeyExchanges] returned by [SupportedAlgorithms] or
|
||||
// [InsecureAlgorithms].
|
||||
const (
|
||||
InsecureKeyExchangeDH1SHA1 = "diffie-hellman-group1-sha1"
|
||||
InsecureKeyExchangeDH14SHA1 = "diffie-hellman-group14-sha1"
|
||||
KeyExchangeDH14SHA256 = "diffie-hellman-group14-sha256"
|
||||
KeyExchangeDH16SHA512 = "diffie-hellman-group16-sha512"
|
||||
KeyExchangeECDHP256 = "ecdh-sha2-nistp256"
|
||||
KeyExchangeECDHP384 = "ecdh-sha2-nistp384"
|
||||
KeyExchangeECDHP521 = "ecdh-sha2-nistp521"
|
||||
KeyExchangeCurve25519 = "curve25519-sha256"
|
||||
InsecureKeyExchangeDHGEXSHA1 = "diffie-hellman-group-exchange-sha1"
|
||||
KeyExchangeDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
|
||||
// KeyExchangeMLKEM768X25519 is supported from Go 1.24.
|
||||
KeyExchangeMLKEM768X25519 = "mlkem768x25519-sha256"
|
||||
|
||||
// An alias for KeyExchangeCurve25519SHA256. This kex ID will be added if
|
||||
// KeyExchangeCurve25519SHA256 is requested for backward compatibility with
|
||||
// OpenSSH versions up to 7.2.
|
||||
keyExchangeCurve25519LibSSH = "curve25519-sha256@libssh.org"
|
||||
)
|
||||
|
||||
// The message authentication code (MAC) currently or previously implemented by
|
||||
// this library, to use in [Config.MACs]. For a list, see the
|
||||
// [Algorithms.MACs] returned by [SupportedAlgorithms] or
|
||||
// [InsecureAlgorithms].
|
||||
const (
|
||||
HMACSHA256ETM = "hmac-sha2-256-etm@openssh.com"
|
||||
HMACSHA512ETM = "hmac-sha2-512-etm@openssh.com"
|
||||
HMACSHA256 = "hmac-sha2-256"
|
||||
HMACSHA512 = "hmac-sha2-512"
|
||||
HMACSHA1 = "hmac-sha1"
|
||||
InsecureHMACSHA196 = "hmac-sha1-96"
|
||||
)
|
||||
|
||||
var (
|
||||
// supportedKexAlgos specifies key-exchange algorithms implemented by this
|
||||
// package in preference order, excluding those with security issues.
|
||||
supportedKexAlgos = []string{
|
||||
KeyExchangeCurve25519,
|
||||
KeyExchangeECDHP256,
|
||||
KeyExchangeECDHP384,
|
||||
KeyExchangeECDHP521,
|
||||
KeyExchangeDH14SHA256,
|
||||
KeyExchangeDH16SHA512,
|
||||
KeyExchangeDHGEXSHA256,
|
||||
}
|
||||
// defaultKexAlgos specifies the default preference for key-exchange
|
||||
// algorithms in preference order.
|
||||
defaultKexAlgos = []string{
|
||||
KeyExchangeCurve25519,
|
||||
KeyExchangeECDHP256,
|
||||
KeyExchangeECDHP384,
|
||||
KeyExchangeECDHP521,
|
||||
KeyExchangeDH14SHA256,
|
||||
InsecureKeyExchangeDH14SHA1,
|
||||
}
|
||||
// insecureKexAlgos specifies key-exchange algorithms implemented by this
|
||||
// package and which have security issues.
|
||||
insecureKexAlgos = []string{
|
||||
InsecureKeyExchangeDH14SHA1,
|
||||
InsecureKeyExchangeDH1SHA1,
|
||||
InsecureKeyExchangeDHGEXSHA1,
|
||||
}
|
||||
// supportedCiphers specifies cipher algorithms implemented by this package
|
||||
// in preference order, excluding those with security issues.
|
||||
supportedCiphers = []string{
|
||||
CipherAES128GCM,
|
||||
CipherAES256GCM,
|
||||
CipherChaCha20Poly1305,
|
||||
CipherAES128CTR,
|
||||
CipherAES192CTR,
|
||||
CipherAES256CTR,
|
||||
}
|
||||
// defaultCiphers specifies the default preference for ciphers algorithms
|
||||
// in preference order.
|
||||
defaultCiphers = supportedCiphers
|
||||
// insecureCiphers specifies cipher algorithms implemented by this
|
||||
// package and which have security issues.
|
||||
insecureCiphers = []string{
|
||||
InsecureCipherAES128CBC,
|
||||
InsecureCipherTripleDESCBC,
|
||||
InsecureCipherRC4256,
|
||||
InsecureCipherRC4128,
|
||||
InsecureCipherRC4,
|
||||
}
|
||||
// supportedMACs specifies MAC algorithms implemented by this package in
|
||||
// preference order, excluding those with security issues.
|
||||
supportedMACs = []string{
|
||||
HMACSHA256ETM,
|
||||
HMACSHA512ETM,
|
||||
HMACSHA256,
|
||||
HMACSHA512,
|
||||
HMACSHA1,
|
||||
}
|
||||
// defaultMACs specifies the default preference for MAC algorithms in
|
||||
// preference order.
|
||||
defaultMACs = []string{
|
||||
HMACSHA256ETM,
|
||||
HMACSHA512ETM,
|
||||
HMACSHA256,
|
||||
HMACSHA512,
|
||||
HMACSHA1,
|
||||
InsecureHMACSHA196,
|
||||
}
|
||||
// insecureMACs specifies MAC algorithms implemented by this
|
||||
// package and which have security issues.
|
||||
insecureMACs = []string{
|
||||
InsecureHMACSHA196,
|
||||
}
|
||||
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e.
|
||||
// methods of authenticating servers) implemented by this package in
|
||||
// preference order, excluding those with security issues.
|
||||
supportedHostKeyAlgos = []string{
|
||||
CertAlgoRSASHA256v01,
|
||||
CertAlgoRSASHA512v01,
|
||||
CertAlgoECDSA256v01,
|
||||
CertAlgoECDSA384v01,
|
||||
CertAlgoECDSA521v01,
|
||||
CertAlgoED25519v01,
|
||||
KeyAlgoRSASHA256,
|
||||
KeyAlgoRSASHA512,
|
||||
KeyAlgoECDSA256,
|
||||
KeyAlgoECDSA384,
|
||||
KeyAlgoECDSA521,
|
||||
KeyAlgoED25519,
|
||||
}
|
||||
// defaultHostKeyAlgos specifies the default preference for host-key
|
||||
// algorithms in preference order.
|
||||
defaultHostKeyAlgos = []string{
|
||||
CertAlgoRSASHA256v01,
|
||||
CertAlgoRSASHA512v01,
|
||||
CertAlgoRSAv01,
|
||||
InsecureCertAlgoDSAv01,
|
||||
CertAlgoECDSA256v01,
|
||||
CertAlgoECDSA384v01,
|
||||
CertAlgoECDSA521v01,
|
||||
CertAlgoED25519v01,
|
||||
KeyAlgoECDSA256,
|
||||
KeyAlgoECDSA384,
|
||||
KeyAlgoECDSA521,
|
||||
KeyAlgoRSASHA256,
|
||||
KeyAlgoRSASHA512,
|
||||
KeyAlgoRSA,
|
||||
InsecureKeyAlgoDSA,
|
||||
KeyAlgoED25519,
|
||||
}
|
||||
// insecureHostKeyAlgos specifies host-key algorithms implemented by this
|
||||
// package and which have security issues.
|
||||
insecureHostKeyAlgos = []string{
|
||||
KeyAlgoRSA,
|
||||
InsecureKeyAlgoDSA,
|
||||
CertAlgoRSAv01,
|
||||
InsecureCertAlgoDSAv01,
|
||||
}
|
||||
// supportedPubKeyAuthAlgos specifies the supported client public key
|
||||
// authentication algorithms. Note that this doesn't include certificate
|
||||
// types since those use the underlying algorithm. Order is irrelevant.
|
||||
supportedPubKeyAuthAlgos = []string{
|
||||
KeyAlgoED25519,
|
||||
KeyAlgoSKED25519,
|
||||
KeyAlgoSKECDSA256,
|
||||
KeyAlgoECDSA256,
|
||||
KeyAlgoECDSA384,
|
||||
KeyAlgoECDSA521,
|
||||
KeyAlgoRSASHA256,
|
||||
KeyAlgoRSASHA512,
|
||||
}
|
||||
|
||||
// defaultPubKeyAuthAlgos specifies the preferred client public key
|
||||
// authentication algorithms. This list is sent to the client if it supports
|
||||
// the server-sig-algs extension. Order is irrelevant.
|
||||
defaultPubKeyAuthAlgos = []string{
|
||||
KeyAlgoED25519,
|
||||
KeyAlgoSKED25519,
|
||||
KeyAlgoSKECDSA256,
|
||||
KeyAlgoECDSA256,
|
||||
KeyAlgoECDSA384,
|
||||
KeyAlgoECDSA521,
|
||||
KeyAlgoRSASHA256,
|
||||
KeyAlgoRSASHA512,
|
||||
KeyAlgoRSA,
|
||||
InsecureKeyAlgoDSA,
|
||||
}
|
||||
// insecurePubKeyAuthAlgos specifies client public key authentication
|
||||
// algorithms implemented by this package and which have security issues.
|
||||
insecurePubKeyAuthAlgos = []string{
|
||||
KeyAlgoRSA,
|
||||
InsecureKeyAlgoDSA,
|
||||
}
|
||||
)
|
||||
|
||||
// NegotiatedAlgorithms defines algorithms negotiated between client and server.
|
||||
type NegotiatedAlgorithms struct {
|
||||
KeyExchange string
|
||||
HostKey string
|
||||
Read DirectionAlgorithms
|
||||
Write DirectionAlgorithms
|
||||
}
|
||||
|
||||
// preferredCiphers specifies the default preference for ciphers.
|
||||
var preferredCiphers = []string{
|
||||
"aes128-gcm@openssh.com", gcm256CipherID,
|
||||
chacha20Poly1305ID,
|
||||
"aes128-ctr", "aes192-ctr", "aes256-ctr",
|
||||
// Algorithms defines a set of algorithms that can be configured in the client
|
||||
// or server config for negotiation during a handshake.
|
||||
type Algorithms struct {
|
||||
KeyExchanges []string
|
||||
Ciphers []string
|
||||
MACs []string
|
||||
HostKeys []string
|
||||
PublicKeyAuths []string
|
||||
}
|
||||
|
||||
// supportedKexAlgos specifies the supported key-exchange algorithms in
|
||||
// preference order.
|
||||
var supportedKexAlgos = []string{
|
||||
kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH,
|
||||
// P384 and P521 are not constant-time yet, but since we don't
|
||||
// reuse ephemeral keys, using them for ECDH should be OK.
|
||||
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
|
||||
kexAlgoDH14SHA256, kexAlgoDH16SHA512, kexAlgoDH14SHA1,
|
||||
kexAlgoDH1SHA1,
|
||||
// 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.
|
||||
func SupportedAlgorithms() Algorithms {
|
||||
return Algorithms{
|
||||
Ciphers: slices.Clone(supportedCiphers),
|
||||
MACs: slices.Clone(supportedMACs),
|
||||
KeyExchanges: slices.Clone(supportedKexAlgos),
|
||||
HostKeys: slices.Clone(supportedHostKeyAlgos),
|
||||
PublicKeyAuths: slices.Clone(supportedPubKeyAuthAlgos),
|
||||
}
|
||||
}
|
||||
|
||||
// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden
|
||||
// for the server half.
|
||||
var serverForbiddenKexAlgos = map[string]struct{}{
|
||||
kexAlgoDHGEXSHA1: {}, // server half implementation is only minimal to satisfy the automated tests
|
||||
kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests
|
||||
}
|
||||
|
||||
// preferredKexAlgos specifies the default preference for key-exchange
|
||||
// algorithms in preference order. The diffie-hellman-group16-sha512 algorithm
|
||||
// is disabled by default because it is a bit slower than the others.
|
||||
var preferredKexAlgos = []string{
|
||||
kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH,
|
||||
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
|
||||
kexAlgoDH14SHA256, kexAlgoDH14SHA1,
|
||||
}
|
||||
|
||||
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
|
||||
// of authenticating servers) in preference order.
|
||||
var supportedHostKeyAlgos = []string{
|
||||
CertAlgoRSASHA256v01, CertAlgoRSASHA512v01,
|
||||
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
||||
CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
|
||||
|
||||
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
|
||||
KeyAlgoRSASHA256, KeyAlgoRSASHA512,
|
||||
KeyAlgoRSA, KeyAlgoDSA,
|
||||
|
||||
KeyAlgoED25519,
|
||||
}
|
||||
|
||||
// supportedMACs specifies a default set of MAC algorithms in preference order.
|
||||
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
|
||||
// because they have reached the end of their useful life.
|
||||
var supportedMACs = []string{
|
||||
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "hmac-sha2-256", "hmac-sha2-512", "hmac-sha1", "hmac-sha1-96",
|
||||
// InsecureAlgorithms returns algorithms currently implemented by this package
|
||||
// and which have security issues.
|
||||
func InsecureAlgorithms() Algorithms {
|
||||
return Algorithms{
|
||||
KeyExchanges: slices.Clone(insecureKexAlgos),
|
||||
Ciphers: slices.Clone(insecureCiphers),
|
||||
MACs: slices.Clone(insecureMACs),
|
||||
HostKeys: slices.Clone(insecureHostKeyAlgos),
|
||||
PublicKeyAuths: slices.Clone(insecurePubKeyAuthAlgos),
|
||||
}
|
||||
}
|
||||
|
||||
var supportedCompressions = []string{compressionNone}
|
||||
|
@ -94,13 +284,13 @@ 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,
|
||||
KeyAlgoDSA: crypto.SHA1,
|
||||
KeyAlgoECDSA256: crypto.SHA256,
|
||||
KeyAlgoECDSA384: crypto.SHA384,
|
||||
KeyAlgoECDSA521: crypto.SHA512,
|
||||
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,
|
||||
|
@ -135,18 +325,6 @@ func isRSACert(algo string) bool {
|
|||
return isRSA(algo)
|
||||
}
|
||||
|
||||
// supportedPubKeyAuthAlgos specifies the supported client public key
|
||||
// authentication algorithms. Note that this doesn't include certificate types
|
||||
// since those use the underlying algorithm. This list is sent to the client if
|
||||
// it supports the server-sig-algs extension. Order is irrelevant.
|
||||
var supportedPubKeyAuthAlgos = []string{
|
||||
KeyAlgoED25519,
|
||||
KeyAlgoSKED25519, KeyAlgoSKECDSA256,
|
||||
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
|
||||
KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA,
|
||||
KeyAlgoDSA,
|
||||
}
|
||||
|
||||
// unexpectedMessageError results when the SSH message that we received didn't
|
||||
// match what we wanted.
|
||||
func unexpectedMessageError(expected, got uint8) error {
|
||||
|
@ -169,20 +347,21 @@ func findCommon(what string, client []string, server []string) (common string, e
|
|||
return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server)
|
||||
}
|
||||
|
||||
// directionAlgorithms records algorithm choices in one direction (either read or write)
|
||||
type directionAlgorithms struct {
|
||||
// DirectionAlgorithms defines the algorithms negotiated in one direction
|
||||
// (either read or write).
|
||||
type DirectionAlgorithms struct {
|
||||
Cipher string
|
||||
MAC string
|
||||
Compression string
|
||||
compression string
|
||||
}
|
||||
|
||||
// rekeyBytes returns a rekeying intervals in bytes.
|
||||
func (a *directionAlgorithms) rekeyBytes() int64 {
|
||||
func (a *DirectionAlgorithms) rekeyBytes() int64 {
|
||||
// According to RFC 4344 block ciphers should rekey after
|
||||
// 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
|
||||
// 128.
|
||||
switch a.Cipher {
|
||||
case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcm128CipherID, gcm256CipherID, aes128cbcID:
|
||||
case CipherAES128CTR, CipherAES192CTR, CipherAES256CTR, CipherAES128GCM, CipherAES256GCM, InsecureCipherAES128CBC:
|
||||
return 16 * (1 << 32)
|
||||
|
||||
}
|
||||
|
@ -192,32 +371,25 @@ func (a *directionAlgorithms) rekeyBytes() int64 {
|
|||
}
|
||||
|
||||
var aeadCiphers = map[string]bool{
|
||||
gcm128CipherID: true,
|
||||
gcm256CipherID: true,
|
||||
chacha20Poly1305ID: true,
|
||||
CipherAES128GCM: true,
|
||||
CipherAES256GCM: true,
|
||||
CipherChaCha20Poly1305: true,
|
||||
}
|
||||
|
||||
type algorithms struct {
|
||||
kex string
|
||||
hostKey string
|
||||
w directionAlgorithms
|
||||
r directionAlgorithms
|
||||
}
|
||||
func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *NegotiatedAlgorithms, err error) {
|
||||
result := &NegotiatedAlgorithms{}
|
||||
|
||||
func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) {
|
||||
result := &algorithms{}
|
||||
|
||||
result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos)
|
||||
result.KeyExchange, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
|
||||
result.HostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
stoc, ctos := &result.w, &result.r
|
||||
stoc, ctos := &result.Write, &result.Read
|
||||
if isClient {
|
||||
ctos, stoc = stoc, ctos
|
||||
}
|
||||
|
@ -246,12 +418,12 @@ func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMs
|
|||
}
|
||||
}
|
||||
|
||||
ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
|
||||
ctos.compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
stoc.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
|
||||
stoc.compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -297,7 +469,7 @@ func (c *Config) SetDefaults() {
|
|||
c.Rand = rand.Reader
|
||||
}
|
||||
if c.Ciphers == nil {
|
||||
c.Ciphers = preferredCiphers
|
||||
c.Ciphers = defaultCiphers
|
||||
}
|
||||
var ciphers []string
|
||||
for _, c := range c.Ciphers {
|
||||
|
@ -309,19 +481,22 @@ func (c *Config) SetDefaults() {
|
|||
c.Ciphers = ciphers
|
||||
|
||||
if c.KeyExchanges == nil {
|
||||
c.KeyExchanges = preferredKexAlgos
|
||||
c.KeyExchanges = defaultKexAlgos
|
||||
}
|
||||
var kexs []string
|
||||
for _, k := range c.KeyExchanges {
|
||||
if kexAlgoMap[k] != nil {
|
||||
// Ignore the KEX if we have no kexAlgoMap definition.
|
||||
kexs = append(kexs, k)
|
||||
if k == KeyExchangeCurve25519 && !contains(c.KeyExchanges, keyExchangeCurve25519LibSSH) {
|
||||
kexs = append(kexs, keyExchangeCurve25519LibSSH)
|
||||
}
|
||||
}
|
||||
}
|
||||
c.KeyExchanges = kexs
|
||||
|
||||
if c.MACs == nil {
|
||||
c.MACs = supportedMACs
|
||||
c.MACs = defaultMACs
|
||||
}
|
||||
var macs []string
|
||||
for _, m := range c.MACs {
|
||||
|
|
|
@ -74,6 +74,13 @@ type Conn interface {
|
|||
// Disconnect
|
||||
}
|
||||
|
||||
// AlgorithmsConnMetadata is a ConnMetadata that can return the algorithms
|
||||
// negotiated between client and server.
|
||||
type AlgorithmsConnMetadata interface {
|
||||
ConnMetadata
|
||||
Algorithms() NegotiatedAlgorithms
|
||||
}
|
||||
|
||||
// DiscardRequests consumes and rejects all requests from the
|
||||
// passed-in channel.
|
||||
func DiscardRequests(in <-chan *Request) {
|
||||
|
@ -106,6 +113,7 @@ type sshConn struct {
|
|||
sessionID []byte
|
||||
clientVersion []byte
|
||||
serverVersion []byte
|
||||
algorithms NegotiatedAlgorithms
|
||||
}
|
||||
|
||||
func dup(src []byte) []byte {
|
||||
|
@ -141,3 +149,7 @@ func (c *sshConn) ClientVersion() []byte {
|
|||
func (c *sshConn) ServerVersion() []byte {
|
||||
return dup(c.serverVersion)
|
||||
}
|
||||
|
||||
func (c *sshConn) Algorithms() NegotiatedAlgorithms {
|
||||
return c.algorithms
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ type keyingTransport interface {
|
|||
// prepareKeyChange sets up a key change. The key change for a
|
||||
// direction will be effected if a msgNewKeys message is sent
|
||||
// or received.
|
||||
prepareKeyChange(*algorithms, *kexResult) error
|
||||
prepareKeyChange(*NegotiatedAlgorithms, *kexResult) error
|
||||
|
||||
// setStrictMode sets the strict KEX mode, notably triggering
|
||||
// sequence number resets on sending or receiving msgNewKeys.
|
||||
|
@ -115,7 +115,7 @@ type handshakeTransport struct {
|
|||
bannerCallback BannerCallback
|
||||
|
||||
// Algorithms agreed in the last key exchange.
|
||||
algorithms *algorithms
|
||||
algorithms *NegotiatedAlgorithms
|
||||
|
||||
// Counters exclusively owned by readLoop.
|
||||
readPacketsLeft uint32
|
||||
|
@ -164,7 +164,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt
|
|||
if config.HostKeyAlgorithms != nil {
|
||||
t.hostKeyAlgorithms = config.HostKeyAlgorithms
|
||||
} else {
|
||||
t.hostKeyAlgorithms = supportedHostKeyAlgos
|
||||
t.hostKeyAlgorithms = defaultHostKeyAlgos
|
||||
}
|
||||
go t.readLoop()
|
||||
go t.kexLoop()
|
||||
|
@ -184,6 +184,10 @@ func (t *handshakeTransport) getSessionID() []byte {
|
|||
return t.sessionID
|
||||
}
|
||||
|
||||
func (t *handshakeTransport) getAlgorithms() NegotiatedAlgorithms {
|
||||
return *t.algorithms
|
||||
}
|
||||
|
||||
// waitSession waits for the session to be established. This should be
|
||||
// the first thing to call after instantiating handshakeTransport.
|
||||
func (t *handshakeTransport) waitSession() error {
|
||||
|
@ -290,7 +294,7 @@ func (t *handshakeTransport) resetWriteThresholds() {
|
|||
if t.config.RekeyThreshold > 0 {
|
||||
t.writeBytesLeft = int64(t.config.RekeyThreshold)
|
||||
} else if t.algorithms != nil {
|
||||
t.writeBytesLeft = t.algorithms.w.rekeyBytes()
|
||||
t.writeBytesLeft = t.algorithms.Write.rekeyBytes()
|
||||
} else {
|
||||
t.writeBytesLeft = 1 << 30
|
||||
}
|
||||
|
@ -407,7 +411,7 @@ func (t *handshakeTransport) resetReadThresholds() {
|
|||
if t.config.RekeyThreshold > 0 {
|
||||
t.readBytesLeft = int64(t.config.RekeyThreshold)
|
||||
} else if t.algorithms != nil {
|
||||
t.readBytesLeft = t.algorithms.r.rekeyBytes()
|
||||
t.readBytesLeft = t.algorithms.Read.rekeyBytes()
|
||||
} else {
|
||||
t.readBytesLeft = 1 << 30
|
||||
}
|
||||
|
@ -700,9 +704,9 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
|||
}
|
||||
}
|
||||
|
||||
kex, ok := kexAlgoMap[t.algorithms.kex]
|
||||
kex, ok := kexAlgoMap[t.algorithms.KeyExchange]
|
||||
if !ok {
|
||||
return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.kex)
|
||||
return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.KeyExchange)
|
||||
}
|
||||
|
||||
var result *kexResult
|
||||
|
@ -809,12 +813,12 @@ func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner {
|
|||
}
|
||||
|
||||
func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) {
|
||||
hostKey := pickHostKey(t.hostKeys, t.algorithms.hostKey)
|
||||
hostKey := pickHostKey(t.hostKeys, t.algorithms.HostKey)
|
||||
if hostKey == nil {
|
||||
return nil, errors.New("ssh: internal error: negotiated unsupported signature type")
|
||||
}
|
||||
|
||||
r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.hostKey)
|
||||
r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.HostKey)
|
||||
return r, err
|
||||
}
|
||||
|
||||
|
@ -829,7 +833,7 @@ func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := verifyHostKeySignature(hostKey, t.algorithms.hostKey, result); err != nil {
|
||||
if err := verifyHostKeySignature(hostKey, t.algorithms.HostKey, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -20,21 +20,18 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
|
||||
kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
|
||||
kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256"
|
||||
kexAlgoDH16SHA512 = "diffie-hellman-group16-sha512"
|
||||
kexAlgoECDH256 = "ecdh-sha2-nistp256"
|
||||
kexAlgoECDH384 = "ecdh-sha2-nistp384"
|
||||
kexAlgoECDH521 = "ecdh-sha2-nistp521"
|
||||
kexAlgoCurve25519SHA256LibSSH = "curve25519-sha256@libssh.org"
|
||||
kexAlgoCurve25519SHA256 = "curve25519-sha256"
|
||||
|
||||
// For the following kex only the client half contains a production
|
||||
// ready implementation. The server half only consists of a minimal
|
||||
// implementation to satisfy the automated tests.
|
||||
kexAlgoDHGEXSHA1 = "diffie-hellman-group-exchange-sha1"
|
||||
kexAlgoDHGEXSHA256 = "diffie-hellman-group-exchange-sha256"
|
||||
// This is the group called diffie-hellman-group1-sha1 in RFC 4253 and
|
||||
// Oakley Group 2 in RFC 2409.
|
||||
oakleyGroup2 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
|
||||
// This is the group called diffie-hellman-group14-sha1 in RFC 4253 and
|
||||
// Oakley Group 14 in RFC 3526.
|
||||
oakleyGroup14 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF"
|
||||
// This is the group called diffie-hellman-group15-sha512 in RFC 8268 and
|
||||
// Oakley Group 15 in RFC 3526.
|
||||
oakleyGroup15 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
|
||||
// This is the group called diffie-hellman-group16-sha512 in RFC 8268 and
|
||||
// Oakley Group 16 in RFC 3526.
|
||||
oakleyGroup16 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF"
|
||||
)
|
||||
|
||||
// kexResult captures the outcome of a key exchange.
|
||||
|
@ -402,53 +399,46 @@ func ecHash(curve elliptic.Curve) crypto.Hash {
|
|||
var kexAlgoMap = map[string]kexAlgorithm{}
|
||||
|
||||
func init() {
|
||||
// This is the group called diffie-hellman-group1-sha1 in
|
||||
// RFC 4253 and Oakley Group 2 in RFC 2409.
|
||||
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
|
||||
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
|
||||
p, _ := new(big.Int).SetString(oakleyGroup2, 16)
|
||||
kexAlgoMap[InsecureKeyExchangeDH1SHA1] = &dhGroup{
|
||||
g: new(big.Int).SetInt64(2),
|
||||
p: p,
|
||||
pMinus1: new(big.Int).Sub(p, bigOne),
|
||||
hashFunc: crypto.SHA1,
|
||||
}
|
||||
|
||||
// This are the groups called diffie-hellman-group14-sha1 and
|
||||
// diffie-hellman-group14-sha256 in RFC 4253 and RFC 8268,
|
||||
// and Oakley Group 14 in RFC 3526.
|
||||
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
|
||||
p, _ = new(big.Int).SetString(oakleyGroup14, 16)
|
||||
group14 := &dhGroup{
|
||||
g: new(big.Int).SetInt64(2),
|
||||
p: p,
|
||||
pMinus1: new(big.Int).Sub(p, bigOne),
|
||||
}
|
||||
|
||||
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
|
||||
kexAlgoMap[InsecureKeyExchangeDH14SHA1] = &dhGroup{
|
||||
g: group14.g, p: group14.p, pMinus1: group14.pMinus1,
|
||||
hashFunc: crypto.SHA1,
|
||||
}
|
||||
kexAlgoMap[kexAlgoDH14SHA256] = &dhGroup{
|
||||
kexAlgoMap[KeyExchangeDH14SHA256] = &dhGroup{
|
||||
g: group14.g, p: group14.p, pMinus1: group14.pMinus1,
|
||||
hashFunc: crypto.SHA256,
|
||||
}
|
||||
|
||||
// This is the group called diffie-hellman-group16-sha512 in RFC
|
||||
// 8268 and Oakley Group 16 in RFC 3526.
|
||||
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF", 16)
|
||||
p, _ = new(big.Int).SetString(oakleyGroup16, 16)
|
||||
|
||||
kexAlgoMap[kexAlgoDH16SHA512] = &dhGroup{
|
||||
kexAlgoMap[KeyExchangeDH16SHA512] = &dhGroup{
|
||||
g: new(big.Int).SetInt64(2),
|
||||
p: p,
|
||||
pMinus1: new(big.Int).Sub(p, bigOne),
|
||||
hashFunc: crypto.SHA512,
|
||||
}
|
||||
|
||||
kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
|
||||
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
|
||||
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
|
||||
kexAlgoMap[kexAlgoCurve25519SHA256] = &curve25519sha256{}
|
||||
kexAlgoMap[kexAlgoCurve25519SHA256LibSSH] = &curve25519sha256{}
|
||||
kexAlgoMap[kexAlgoDHGEXSHA1] = &dhGEXSHA{hashFunc: crypto.SHA1}
|
||||
kexAlgoMap[kexAlgoDHGEXSHA256] = &dhGEXSHA{hashFunc: crypto.SHA256}
|
||||
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}
|
||||
}
|
||||
|
||||
// curve25519sha256 implements the curve25519-sha256 (formerly known as
|
||||
|
@ -601,9 +591,9 @@ const (
|
|||
func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshakeMagics) (*kexResult, error) {
|
||||
// Send GexRequest
|
||||
kexDHGexRequest := kexDHGexRequestMsg{
|
||||
MinBits: dhGroupExchangeMinimumBits,
|
||||
PreferedBits: dhGroupExchangePreferredBits,
|
||||
MaxBits: dhGroupExchangeMaximumBits,
|
||||
MinBits: dhGroupExchangeMinimumBits,
|
||||
PreferredBits: dhGroupExchangePreferredBits,
|
||||
MaxBits: dhGroupExchangeMaximumBits,
|
||||
}
|
||||
if err := c.writePacket(Marshal(&kexDHGexRequest)); err != nil {
|
||||
return nil, err
|
||||
|
@ -690,9 +680,7 @@ func (gex *dhGEXSHA) Client(c packetConn, randSource io.Reader, magics *handshak
|
|||
}
|
||||
|
||||
// Server half implementation of the Diffie Hellman Key Exchange with SHA1 and SHA256.
|
||||
//
|
||||
// This is a minimal implementation to satisfy the automated tests.
|
||||
func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
|
||||
func (gex *dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshakeMagics, priv AlgorithmSigner, algo string) (result *kexResult, err error) {
|
||||
// Receive GexRequest
|
||||
packet, err := c.readPacket()
|
||||
if err != nil {
|
||||
|
@ -702,13 +690,32 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
|
|||
if err = Unmarshal(packet, &kexDHGexRequest); err != nil {
|
||||
return
|
||||
}
|
||||
// We check that the request received is valid and that the MaxBits
|
||||
// requested are at least equal to our supported minimum. This is the same
|
||||
// check done in OpenSSH:
|
||||
// https://github.com/openssh/openssh-portable/blob/80a2f64b/kexgexs.c#L94
|
||||
//
|
||||
// Furthermore, we also check that the required MinBits are less than or
|
||||
// equal to 4096 because we can use up to Oakley Group 16.
|
||||
if kexDHGexRequest.MaxBits < kexDHGexRequest.MinBits || kexDHGexRequest.PreferredBits < kexDHGexRequest.MinBits ||
|
||||
kexDHGexRequest.MaxBits < kexDHGexRequest.PreferredBits || kexDHGexRequest.MaxBits < dhGroupExchangeMinimumBits ||
|
||||
kexDHGexRequest.MinBits > 4096 {
|
||||
return nil, fmt.Errorf("ssh: DH GEX request out of range, min: %d, max: %d, preferred: %d", kexDHGexRequest.MinBits,
|
||||
kexDHGexRequest.MaxBits, kexDHGexRequest.PreferredBits)
|
||||
}
|
||||
|
||||
var p *big.Int
|
||||
// We hardcode sending Oakley Group 14 (2048 bits), Oakley Group 15 (3072
|
||||
// bits) or Oakley Group 16 (4096 bits), based on the requested max size.
|
||||
if kexDHGexRequest.MaxBits < 3072 {
|
||||
p, _ = new(big.Int).SetString(oakleyGroup14, 16)
|
||||
} else if kexDHGexRequest.MaxBits < 4096 {
|
||||
p, _ = new(big.Int).SetString(oakleyGroup15, 16)
|
||||
} else {
|
||||
p, _ = new(big.Int).SetString(oakleyGroup16, 16)
|
||||
}
|
||||
|
||||
// Send GexGroup
|
||||
// This is the group called diffie-hellman-group14-sha1 in RFC
|
||||
// 4253 and Oakley Group 14 in RFC 3526.
|
||||
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
|
||||
g := big.NewInt(2)
|
||||
|
||||
msg := &kexDHGexGroupMsg{
|
||||
P: p,
|
||||
G: g,
|
||||
|
@ -746,9 +753,9 @@ func (gex dhGEXSHA) Server(c packetConn, randSource io.Reader, magics *handshake
|
|||
h := gex.hashFunc.New()
|
||||
magics.write(h)
|
||||
writeString(h, hostKeyBytes)
|
||||
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMinimumBits))
|
||||
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangePreferredBits))
|
||||
binary.Write(h, binary.BigEndian, uint32(dhGroupExchangeMaximumBits))
|
||||
binary.Write(h, binary.BigEndian, kexDHGexRequest.MinBits)
|
||||
binary.Write(h, binary.BigEndian, kexDHGexRequest.PreferredBits)
|
||||
binary.Write(h, binary.BigEndian, kexDHGexRequest.MaxBits)
|
||||
writeInt(h, p)
|
||||
writeInt(h, g)
|
||||
writeInt(h, kexDHGexInit.X)
|
||||
|
|
|
@ -36,14 +36,19 @@ import (
|
|||
// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner
|
||||
// arguments.
|
||||
const (
|
||||
KeyAlgoRSA = "ssh-rsa"
|
||||
KeyAlgoDSA = "ssh-dss"
|
||||
KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
|
||||
KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com"
|
||||
KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
|
||||
KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
|
||||
KeyAlgoED25519 = "ssh-ed25519"
|
||||
KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"
|
||||
KeyAlgoRSA = "ssh-rsa"
|
||||
// Deprecated: DSA is only supported at insecure key sizes, and was removed
|
||||
// from major implementations.
|
||||
KeyAlgoDSA = InsecureKeyAlgoDSA
|
||||
// Deprecated: DSA is only supported at insecure key sizes, and was removed
|
||||
// from major implementations.
|
||||
InsecureKeyAlgoDSA = "ssh-dss"
|
||||
KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
|
||||
KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com"
|
||||
KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
|
||||
KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
|
||||
KeyAlgoED25519 = "ssh-ed25519"
|
||||
KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"
|
||||
|
||||
// KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not
|
||||
// public key formats, so they can't appear as a PublicKey.Type. The
|
||||
|
@ -67,7 +72,7 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
|
|||
switch algo {
|
||||
case KeyAlgoRSA:
|
||||
return parseRSA(in)
|
||||
case KeyAlgoDSA:
|
||||
case InsecureKeyAlgoDSA:
|
||||
return parseDSA(in)
|
||||
case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
|
||||
return parseECDSA(in)
|
||||
|
@ -77,7 +82,7 @@ func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
|
|||
return parseED25519(in)
|
||||
case KeyAlgoSKED25519:
|
||||
return parseSKEd25519(in)
|
||||
case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
|
||||
case CertAlgoRSAv01, InsecureCertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
|
||||
cert, err := parseCert(in, certKeyAlgoNames[algo])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
|
@ -47,22 +47,22 @@ func (t truncatingMAC) Size() int {
|
|||
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
|
||||
|
||||
var macModes = map[string]*macMode{
|
||||
"hmac-sha2-512-etm@openssh.com": {64, true, func(key []byte) hash.Hash {
|
||||
HMACSHA512ETM: {64, true, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha512.New, key)
|
||||
}},
|
||||
"hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
|
||||
HMACSHA256ETM: {32, true, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha256.New, key)
|
||||
}},
|
||||
"hmac-sha2-512": {64, false, func(key []byte) hash.Hash {
|
||||
HMACSHA512: {64, false, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha512.New, key)
|
||||
}},
|
||||
"hmac-sha2-256": {32, false, func(key []byte) hash.Hash {
|
||||
HMACSHA256: {32, false, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha256.New, key)
|
||||
}},
|
||||
"hmac-sha1": {20, false, func(key []byte) hash.Hash {
|
||||
HMACSHA1: {20, false, func(key []byte) hash.Hash {
|
||||
return hmac.New(sha1.New, key)
|
||||
}},
|
||||
"hmac-sha1-96": {20, false, func(key []byte) hash.Hash {
|
||||
InsecureHMACSHA196: {20, false, func(key []byte) hash.Hash {
|
||||
return truncatingMAC{12, hmac.New(sha1.New, key)}
|
||||
}},
|
||||
}
|
||||
|
|
|
@ -122,9 +122,9 @@ type kexDHGexReplyMsg struct {
|
|||
const msgKexDHGexRequest = 34
|
||||
|
||||
type kexDHGexRequestMsg struct {
|
||||
MinBits uint32 `sshtype:"34"`
|
||||
PreferedBits uint32
|
||||
MaxBits uint32
|
||||
MinBits uint32 `sshtype:"34"`
|
||||
PreferredBits uint32
|
||||
MaxBits uint32
|
||||
}
|
||||
|
||||
// See RFC 4253, section 10.
|
||||
|
|
|
@ -19,19 +19,15 @@ import (
|
|||
"golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
const (
|
||||
kexAlgoMLKEM768xCurve25519SHA256 = "mlkem768x25519-sha256"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// After Go 1.24rc1 mlkem swapped the order of return values of Encapsulate.
|
||||
// See #70950.
|
||||
if runtime.Version() == "go1.24rc1" {
|
||||
return
|
||||
}
|
||||
supportedKexAlgos = slices.Insert(supportedKexAlgos, 0, kexAlgoMLKEM768xCurve25519SHA256)
|
||||
preferredKexAlgos = slices.Insert(preferredKexAlgos, 0, kexAlgoMLKEM768xCurve25519SHA256)
|
||||
kexAlgoMap[kexAlgoMLKEM768xCurve25519SHA256] = &mlkem768WithCurve25519sha256{}
|
||||
supportedKexAlgos = slices.Insert(supportedKexAlgos, 0, KeyExchangeMLKEM768X25519)
|
||||
defaultKexAlgos = slices.Insert(defaultKexAlgos, 0, KeyExchangeMLKEM768X25519)
|
||||
kexAlgoMap[KeyExchangeMLKEM768X25519] = &mlkem768WithCurve25519sha256{}
|
||||
}
|
||||
|
||||
// mlkem768WithCurve25519sha256 implements the hybrid ML-KEM768 with
|
||||
|
|
|
@ -243,22 +243,15 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
|
|||
fullConf.MaxAuthTries = 6
|
||||
}
|
||||
if len(fullConf.PublicKeyAuthAlgorithms) == 0 {
|
||||
fullConf.PublicKeyAuthAlgorithms = supportedPubKeyAuthAlgos
|
||||
fullConf.PublicKeyAuthAlgorithms = defaultPubKeyAuthAlgos
|
||||
} else {
|
||||
for _, algo := range fullConf.PublicKeyAuthAlgorithms {
|
||||
if !contains(supportedPubKeyAuthAlgos, algo) {
|
||||
if !contains(SupportedAlgorithms().PublicKeyAuths, algo) && !contains(InsecureAlgorithms().PublicKeyAuths, algo) {
|
||||
c.Close()
|
||||
return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if the config contains any unsupported key exchanges
|
||||
for _, kex := range fullConf.KeyExchanges {
|
||||
if _, ok := serverForbiddenKexAlgos[kex]; ok {
|
||||
c.Close()
|
||||
return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex)
|
||||
}
|
||||
}
|
||||
|
||||
s := &connection{
|
||||
sshConn: sshConn{conn: c},
|
||||
|
@ -315,6 +308,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
|
|||
|
||||
// We just did the key change, so the session ID is established.
|
||||
s.sessionID = s.transport.getSessionID()
|
||||
s.algorithms = s.transport.getAlgorithms()
|
||||
|
||||
var packet []byte
|
||||
if packet, err = s.transport.readPacket(); err != nil {
|
||||
|
|
|
@ -16,13 +16,6 @@ import (
|
|||
// wire. No message decoding is done, to minimize the impact on timing.
|
||||
const debugTransport = false
|
||||
|
||||
const (
|
||||
gcm128CipherID = "aes128-gcm@openssh.com"
|
||||
gcm256CipherID = "aes256-gcm@openssh.com"
|
||||
aes128cbcID = "aes128-cbc"
|
||||
tripledescbcID = "3des-cbc"
|
||||
)
|
||||
|
||||
// packetConn represents a transport that implements packet based
|
||||
// operations.
|
||||
type packetConn interface {
|
||||
|
@ -92,14 +85,14 @@ func (t *transport) setInitialKEXDone() {
|
|||
// prepareKeyChange sets up key material for a keychange. The key changes in
|
||||
// both directions are triggered by reading and writing a msgNewKey packet
|
||||
// respectively.
|
||||
func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error {
|
||||
ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult)
|
||||
func (t *transport) prepareKeyChange(algs *NegotiatedAlgorithms, kexResult *kexResult) error {
|
||||
ciph, err := newPacketCipher(t.reader.dir, algs.Read, kexResult)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.reader.pendingKeyChange <- ciph
|
||||
|
||||
ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult)
|
||||
ciph, err = newPacketCipher(t.writer.dir, algs.Write, kexResult)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -259,7 +252,7 @@ var (
|
|||
// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as
|
||||
// described in RFC 4253, section 6.4. direction should either be serverKeys
|
||||
// (to setup server->client keys) or clientKeys (for client->server keys).
|
||||
func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {
|
||||
func newPacketCipher(d direction, algs DirectionAlgorithms, kex *kexResult) (packetCipher, error) {
|
||||
cipherMode := cipherModes[algs.Cipher]
|
||||
|
||||
iv := make([]byte, cipherMode.ivSize)
|
||||
|
|
|
@ -22,7 +22,10 @@
|
|||
// as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0.
|
||||
package semver
|
||||
|
||||
import "sort"
|
||||
import (
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// parsed returns the parsed form of a semantic version string.
|
||||
type parsed struct {
|
||||
|
@ -154,19 +157,22 @@ func Max(v, w string) string {
|
|||
// ByVersion implements [sort.Interface] for sorting semantic version strings.
|
||||
type ByVersion []string
|
||||
|
||||
func (vs ByVersion) Len() int { return len(vs) }
|
||||
func (vs ByVersion) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
|
||||
func (vs ByVersion) Less(i, j int) bool {
|
||||
cmp := Compare(vs[i], vs[j])
|
||||
if cmp != 0 {
|
||||
return cmp < 0
|
||||
}
|
||||
return vs[i] < vs[j]
|
||||
func (vs ByVersion) Len() int { return len(vs) }
|
||||
func (vs ByVersion) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
|
||||
func (vs ByVersion) Less(i, j int) bool { return compareVersion(vs[i], vs[j]) < 0 }
|
||||
|
||||
// Sort sorts a list of semantic version strings using [Compare] and falls back
|
||||
// to use [strings.Compare] if both versions are considered equal.
|
||||
func Sort(list []string) {
|
||||
slices.SortFunc(list, compareVersion)
|
||||
}
|
||||
|
||||
// Sort sorts a list of semantic version strings using [ByVersion].
|
||||
func Sort(list []string) {
|
||||
sort.Sort(ByVersion(list))
|
||||
func compareVersion(a, b string) int {
|
||||
cmp := Compare(a, b)
|
||||
if cmp != 0 {
|
||||
return cmp
|
||||
}
|
||||
return strings.Compare(a, b)
|
||||
}
|
||||
|
||||
func parse(v string) (p parsed, ok bool) {
|
||||
|
|
|
@ -751,7 +751,7 @@ go.opentelemetry.io/otel/metric/noop
|
|||
go.opentelemetry.io/otel/trace
|
||||
go.opentelemetry.io/otel/trace/embedded
|
||||
go.opentelemetry.io/otel/trace/noop
|
||||
# golang.org/x/crypto v0.38.0
|
||||
# golang.org/x/crypto v0.39.0
|
||||
## explicit; go 1.23.0
|
||||
golang.org/x/crypto/argon2
|
||||
golang.org/x/crypto/bcrypt
|
||||
|
@ -782,7 +782,7 @@ golang.org/x/crypto/ssh/agent
|
|||
golang.org/x/crypto/ssh/internal/bcrypt_pbkdf
|
||||
golang.org/x/crypto/twofish
|
||||
golang.org/x/crypto/xts
|
||||
# golang.org/x/mod v0.24.0
|
||||
# golang.org/x/mod v0.25.0
|
||||
## explicit; go 1.23.0
|
||||
golang.org/x/mod/semver
|
||||
# golang.org/x/net v0.39.0
|
||||
|
@ -808,7 +808,7 @@ golang.org/x/sys/windows/registry
|
|||
# golang.org/x/term v0.32.0
|
||||
## explicit; go 1.23.0
|
||||
golang.org/x/term
|
||||
# golang.org/x/text v0.25.0
|
||||
# golang.org/x/text v0.26.0
|
||||
## explicit; go 1.23.0
|
||||
golang.org/x/text/secure/bidirule
|
||||
golang.org/x/text/transform
|
||||
|
|
Loading…
Reference in New Issue