Bladeren bron

vendor: golang.org/x/crypto v0.9.0

full diff: https://github.com/golang/crypto/compare/v0.3.0...v0.9.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 1 jaar geleden
bovenliggende
commit
9670db3904

+ 1 - 1
vendor.mod

@@ -200,7 +200,7 @@ require (
 	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/multierr v1.8.0 // indirect
 	go.uber.org/zap v1.21.0 // indirect
-	golang.org/x/crypto v0.3.0 // indirect
+	golang.org/x/crypto v0.9.0 // indirect
 	golang.org/x/oauth2 v0.6.0 // indirect
 	golang.org/x/tools v0.6.0 // indirect
 	google.golang.org/api v0.110.0 // indirect

+ 2 - 2
vendor.sum

@@ -1550,8 +1550,8 @@ golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWP
 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
-golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
+golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
+golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=

+ 49 - 34
vendor/golang.org/x/crypto/cryptobyte/asn1.go

@@ -264,36 +264,35 @@ func (s *String) ReadASN1Boolean(out *bool) bool {
 	return true
 }
 
-var bigIntType = reflect.TypeOf((*big.Int)(nil)).Elem()
-
 // ReadASN1Integer decodes an ASN.1 INTEGER into out and advances. If out does
-// not point to an integer or to a big.Int, it panics. It reports whether the
-// read was successful.
+// not point to an integer, to a big.Int, or to a []byte it panics. Only
+// positive and zero values can be decoded into []byte, and they are returned as
+// big-endian binary values that share memory with s. Positive values will have
+// no leading zeroes, and zero will be returned as a single zero byte.
+// ReadASN1Integer reports whether the read was successful.
 func (s *String) ReadASN1Integer(out interface{}) bool {
-	if reflect.TypeOf(out).Kind() != reflect.Ptr {
-		panic("out is not a pointer")
-	}
-	switch reflect.ValueOf(out).Elem().Kind() {
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+	switch out := out.(type) {
+	case *int, *int8, *int16, *int32, *int64:
 		var i int64
 		if !s.readASN1Int64(&i) || reflect.ValueOf(out).Elem().OverflowInt(i) {
 			return false
 		}
 		reflect.ValueOf(out).Elem().SetInt(i)
 		return true
-	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+	case *uint, *uint8, *uint16, *uint32, *uint64:
 		var u uint64
 		if !s.readASN1Uint64(&u) || reflect.ValueOf(out).Elem().OverflowUint(u) {
 			return false
 		}
 		reflect.ValueOf(out).Elem().SetUint(u)
 		return true
-	case reflect.Struct:
-		if reflect.TypeOf(out).Elem() == bigIntType {
-			return s.readASN1BigInt(out.(*big.Int))
-		}
+	case *big.Int:
+		return s.readASN1BigInt(out)
+	case *[]byte:
+		return s.readASN1Bytes(out)
+	default:
+		panic("out does not point to an integer type")
 	}
-	panic("out does not point to an integer type")
 }
 
 func checkASN1Integer(bytes []byte) bool {
@@ -333,6 +332,21 @@ func (s *String) readASN1BigInt(out *big.Int) bool {
 	return true
 }
 
+func (s *String) readASN1Bytes(out *[]byte) bool {
+	var bytes String
+	if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) {
+		return false
+	}
+	if bytes[0]&0x80 == 0x80 {
+		return false
+	}
+	for len(bytes) > 1 && bytes[0] == 0 {
+		bytes = bytes[1:]
+	}
+	*out = bytes
+	return true
+}
+
 func (s *String) readASN1Int64(out *int64) bool {
 	var bytes String
 	if !s.ReadASN1(&bytes, asn1.INTEGER) || !checkASN1Integer(bytes) || !asn1Signed(out, bytes) {
@@ -417,6 +431,14 @@ func (s *String) readBase128Int(out *int) bool {
 		}
 		ret <<= 7
 		b := s.read(1)[0]
+
+		// ITU-T X.690, section 8.19.2:
+		// The subidentifier shall be encoded in the fewest possible octets,
+		// that is, the leading octet of the subidentifier shall not have the value 0x80.
+		if i == 0 && b == 0x80 {
+			return false
+		}
+
 		ret |= int(b & 0x7f)
 		if b&0x80 == 0 {
 			*out = ret
@@ -545,7 +567,7 @@ func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool {
 	return true
 }
 
-// ReadASN1BitString decodes an ASN.1 BIT STRING into out and advances. It is
+// ReadASN1BitStringAsBytes decodes an ASN.1 BIT STRING into out and advances. It is
 // an error if the BIT STRING is not a whole number of bytes. It reports
 // whether the read was successful.
 func (s *String) ReadASN1BitStringAsBytes(out *[]byte) bool {
@@ -654,34 +676,27 @@ func (s *String) SkipOptionalASN1(tag asn1.Tag) bool {
 	return s.ReadASN1(&unused, tag)
 }
 
-// ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER
-// explicitly tagged with tag into out and advances. If no element with a
-// matching tag is present, it writes defaultValue into out instead. If out
-// does not point to an integer or to a big.Int, it panics. It reports
-// whether the read was successful.
+// ReadOptionalASN1Integer attempts to read an optional ASN.1 INTEGER explicitly
+// tagged with tag into out and advances. If no element with a matching tag is
+// present, it writes defaultValue into out instead. Otherwise, it behaves like
+// ReadASN1Integer.
 func (s *String) ReadOptionalASN1Integer(out interface{}, tag asn1.Tag, defaultValue interface{}) bool {
-	if reflect.TypeOf(out).Kind() != reflect.Ptr {
-		panic("out is not a pointer")
-	}
 	var present bool
 	var i String
 	if !s.ReadOptionalASN1(&i, &present, tag) {
 		return false
 	}
 	if !present {
-		switch reflect.ValueOf(out).Elem().Kind() {
-		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
-			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+		switch out.(type) {
+		case *int, *int8, *int16, *int32, *int64,
+			*uint, *uint8, *uint16, *uint32, *uint64, *[]byte:
 			reflect.ValueOf(out).Elem().Set(reflect.ValueOf(defaultValue))
-		case reflect.Struct:
-			if reflect.TypeOf(out).Elem() != bigIntType {
-				panic("invalid integer type")
-			}
-			if reflect.TypeOf(defaultValue).Kind() != reflect.Ptr ||
-				reflect.TypeOf(defaultValue).Elem() != bigIntType {
+		case *big.Int:
+			if defaultValue, ok := defaultValue.(*big.Int); ok {
+				out.(*big.Int).Set(defaultValue)
+			} else {
 				panic("out points to big.Int, but defaultValue does not")
 			}
-			out.(*big.Int).Set(defaultValue.(*big.Int))
 		default:
 			panic("invalid integer type")
 		}

+ 6 - 3
vendor/golang.org/x/crypto/cryptobyte/builder.go

@@ -303,9 +303,9 @@ func (b *Builder) add(bytes ...byte) {
 	b.result = append(b.result, bytes...)
 }
 
-// Unwrite rolls back n bytes written directly to the Builder. An attempt by a
-// child builder passed to a continuation to unwrite bytes from its parent will
-// panic.
+// Unwrite rolls back non-negative n bytes written directly to the Builder.
+// An attempt by a child builder passed to a continuation to unwrite bytes
+// from its parent will panic.
 func (b *Builder) Unwrite(n int) {
 	if b.err != nil {
 		return
@@ -317,6 +317,9 @@ func (b *Builder) Unwrite(n int) {
 	if length < 0 {
 		panic("cryptobyte: internal error")
 	}
+	if n < 0 {
+		panic("cryptobyte: attempted to unwrite negative number of bytes")
+	}
 	if n > length {
 		panic("cryptobyte: attempted to unwrite more than was written")
 	}

+ 6 - 93
vendor/golang.org/x/crypto/curve25519/curve25519.go

@@ -5,71 +5,18 @@
 // Package curve25519 provides an implementation of the X25519 function, which
 // performs scalar multiplication on the elliptic curve known as Curve25519.
 // See RFC 7748.
+//
+// Starting in Go 1.20, this package is a wrapper for the X25519 implementation
+// in the crypto/ecdh package.
 package curve25519 // import "golang.org/x/crypto/curve25519"
 
-import (
-	"crypto/subtle"
-	"errors"
-	"strconv"
-
-	"golang.org/x/crypto/curve25519/internal/field"
-)
-
 // ScalarMult sets dst to the product scalar * point.
 //
 // Deprecated: when provided a low-order point, ScalarMult will set dst to all
 // zeroes, irrespective of the scalar. Instead, use the X25519 function, which
 // will return an error.
 func ScalarMult(dst, scalar, point *[32]byte) {
-	var e [32]byte
-
-	copy(e[:], scalar[:])
-	e[0] &= 248
-	e[31] &= 127
-	e[31] |= 64
-
-	var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element
-	x1.SetBytes(point[:])
-	x2.One()
-	x3.Set(&x1)
-	z3.One()
-
-	swap := 0
-	for pos := 254; pos >= 0; pos-- {
-		b := e[pos/8] >> uint(pos&7)
-		b &= 1
-		swap ^= int(b)
-		x2.Swap(&x3, swap)
-		z2.Swap(&z3, swap)
-		swap = int(b)
-
-		tmp0.Subtract(&x3, &z3)
-		tmp1.Subtract(&x2, &z2)
-		x2.Add(&x2, &z2)
-		z2.Add(&x3, &z3)
-		z3.Multiply(&tmp0, &x2)
-		z2.Multiply(&z2, &tmp1)
-		tmp0.Square(&tmp1)
-		tmp1.Square(&x2)
-		x3.Add(&z3, &z2)
-		z2.Subtract(&z3, &z2)
-		x2.Multiply(&tmp1, &tmp0)
-		tmp1.Subtract(&tmp1, &tmp0)
-		z2.Square(&z2)
-
-		z3.Mult32(&tmp1, 121666)
-		x3.Square(&x3)
-		tmp0.Add(&tmp0, &z3)
-		z3.Multiply(&x1, &z2)
-		z2.Multiply(&tmp1, &tmp0)
-	}
-
-	x2.Swap(&x3, swap)
-	z2.Swap(&z3, swap)
-
-	z2.Invert(&z2)
-	x2.Multiply(&x2, &z2)
-	copy(dst[:], x2.Bytes())
+	scalarMult(dst, scalar, point)
 }
 
 // ScalarBaseMult sets dst to the product scalar * base where base is the
@@ -78,7 +25,7 @@ func ScalarMult(dst, scalar, point *[32]byte) {
 // It is recommended to use the X25519 function with Basepoint instead, as
 // copying into fixed size arrays can lead to unexpected bugs.
 func ScalarBaseMult(dst, scalar *[32]byte) {
-	ScalarMult(dst, scalar, &basePoint)
+	scalarBaseMult(dst, scalar)
 }
 
 const (
@@ -91,21 +38,10 @@ const (
 // Basepoint is the canonical Curve25519 generator.
 var Basepoint []byte
 
-var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+var basePoint = [32]byte{9}
 
 func init() { Basepoint = basePoint[:] }
 
-func checkBasepoint() {
-	if subtle.ConstantTimeCompare(Basepoint, []byte{
-		0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	}) != 1 {
-		panic("curve25519: global Basepoint value was modified")
-	}
-}
-
 // X25519 returns the result of the scalar multiplication (scalar * point),
 // according to RFC 7748, Section 5. scalar, point and the return value are
 // slices of 32 bytes.
@@ -121,26 +57,3 @@ func X25519(scalar, point []byte) ([]byte, error) {
 	var dst [32]byte
 	return x25519(&dst, scalar, point)
 }
-
-func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
-	var in [32]byte
-	if l := len(scalar); l != 32 {
-		return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32")
-	}
-	if l := len(point); l != 32 {
-		return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32")
-	}
-	copy(in[:], scalar)
-	if &point[0] == &Basepoint[0] {
-		checkBasepoint()
-		ScalarBaseMult(dst, &in)
-	} else {
-		var base, zero [32]byte
-		copy(base[:], point)
-		ScalarMult(dst, &in, &base)
-		if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
-			return nil, errors.New("bad input point: low order point")
-		}
-	}
-	return dst[:], nil
-}

+ 105 - 0
vendor/golang.org/x/crypto/curve25519/curve25519_compat.go

@@ -0,0 +1,105 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !go1.20
+
+package curve25519
+
+import (
+	"crypto/subtle"
+	"errors"
+	"strconv"
+
+	"golang.org/x/crypto/curve25519/internal/field"
+)
+
+func scalarMult(dst, scalar, point *[32]byte) {
+	var e [32]byte
+
+	copy(e[:], scalar[:])
+	e[0] &= 248
+	e[31] &= 127
+	e[31] |= 64
+
+	var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element
+	x1.SetBytes(point[:])
+	x2.One()
+	x3.Set(&x1)
+	z3.One()
+
+	swap := 0
+	for pos := 254; pos >= 0; pos-- {
+		b := e[pos/8] >> uint(pos&7)
+		b &= 1
+		swap ^= int(b)
+		x2.Swap(&x3, swap)
+		z2.Swap(&z3, swap)
+		swap = int(b)
+
+		tmp0.Subtract(&x3, &z3)
+		tmp1.Subtract(&x2, &z2)
+		x2.Add(&x2, &z2)
+		z2.Add(&x3, &z3)
+		z3.Multiply(&tmp0, &x2)
+		z2.Multiply(&z2, &tmp1)
+		tmp0.Square(&tmp1)
+		tmp1.Square(&x2)
+		x3.Add(&z3, &z2)
+		z2.Subtract(&z3, &z2)
+		x2.Multiply(&tmp1, &tmp0)
+		tmp1.Subtract(&tmp1, &tmp0)
+		z2.Square(&z2)
+
+		z3.Mult32(&tmp1, 121666)
+		x3.Square(&x3)
+		tmp0.Add(&tmp0, &z3)
+		z3.Multiply(&x1, &z2)
+		z2.Multiply(&tmp1, &tmp0)
+	}
+
+	x2.Swap(&x3, swap)
+	z2.Swap(&z3, swap)
+
+	z2.Invert(&z2)
+	x2.Multiply(&x2, &z2)
+	copy(dst[:], x2.Bytes())
+}
+
+func scalarBaseMult(dst, scalar *[32]byte) {
+	checkBasepoint()
+	scalarMult(dst, scalar, &basePoint)
+}
+
+func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
+	var in [32]byte
+	if l := len(scalar); l != 32 {
+		return nil, errors.New("bad scalar length: " + strconv.Itoa(l) + ", expected 32")
+	}
+	if l := len(point); l != 32 {
+		return nil, errors.New("bad point length: " + strconv.Itoa(l) + ", expected 32")
+	}
+	copy(in[:], scalar)
+	if &point[0] == &Basepoint[0] {
+		scalarBaseMult(dst, &in)
+	} else {
+		var base, zero [32]byte
+		copy(base[:], point)
+		scalarMult(dst, &in, &base)
+		if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
+			return nil, errors.New("bad input point: low order point")
+		}
+	}
+	return dst[:], nil
+}
+
+func checkBasepoint() {
+	if subtle.ConstantTimeCompare(Basepoint, []byte{
+		0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	}) != 1 {
+		panic("curve25519: global Basepoint value was modified")
+	}
+}

+ 46 - 0
vendor/golang.org/x/crypto/curve25519/curve25519_go120.go

@@ -0,0 +1,46 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build go1.20
+
+package curve25519
+
+import "crypto/ecdh"
+
+func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
+	curve := ecdh.X25519()
+	pub, err := curve.NewPublicKey(point)
+	if err != nil {
+		return nil, err
+	}
+	priv, err := curve.NewPrivateKey(scalar)
+	if err != nil {
+		return nil, err
+	}
+	out, err := priv.ECDH(pub)
+	if err != nil {
+		return nil, err
+	}
+	copy(dst[:], out)
+	return dst[:], nil
+}
+
+func scalarMult(dst, scalar, point *[32]byte) {
+	if _, err := x25519(dst, scalar[:], point[:]); err != nil {
+		// The only error condition for x25519 when the inputs are 32 bytes long
+		// is if the output would have been the all-zero value.
+		for i := range dst {
+			dst[i] = 0
+		}
+	}
+}
+
+func scalarBaseMult(dst, scalar *[32]byte) {
+	curve := ecdh.X25519()
+	priv, err := curve.NewPrivateKey(scalar[:])
+	if err != nil {
+		panic("curve25519: internal error: scalarBaseMult was not 32 bytes")
+	}
+	copy(dst[:], priv.PublicKey().Bytes())
+}

+ 1 - 1
vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go

@@ -245,7 +245,7 @@ func feSquareGeneric(v, a *Element) {
 	v.carryPropagate()
 }
 
-// carryPropagate brings the limbs below 52 bits by applying the reduction
+// carryPropagateGeneric brings the limbs below 52 bits by applying the reduction
 // identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. TODO inline
 func (v *Element) carryPropagateGeneric() *Element {
 	c0 := v.l0 >> 51

+ 2 - 1
vendor/golang.org/x/crypto/ssh/cipher.go

@@ -114,7 +114,8 @@ var cipherModes = map[string]*cipherMode{
 	"arcfour": {16, 0, streamCipherMode(0, newRC4)},
 
 	// AEAD ciphers
-	gcmCipherID:        {16, 12, newGCMCipher},
+	gcm128CipherID:     {16, 12, newGCMCipher},
+	gcm256CipherID:     {32, 12, newGCMCipher},
 	chacha20Poly1305ID: {64, 0, newChaCha20Cipher},
 
 	// CBC mode is insecure and so is not included in the default config.

+ 5 - 4
vendor/golang.org/x/crypto/ssh/common.go

@@ -28,7 +28,7 @@ const (
 // supportedCiphers lists ciphers we support but might not recommend.
 var supportedCiphers = []string{
 	"aes128-ctr", "aes192-ctr", "aes256-ctr",
-	"aes128-gcm@openssh.com",
+	"aes128-gcm@openssh.com", gcm256CipherID,
 	chacha20Poly1305ID,
 	"arcfour256", "arcfour128", "arcfour",
 	aes128cbcID,
@@ -37,7 +37,7 @@ var supportedCiphers = []string{
 
 // preferredCiphers specifies the default preference for ciphers.
 var preferredCiphers = []string{
-	"aes128-gcm@openssh.com",
+	"aes128-gcm@openssh.com", gcm256CipherID,
 	chacha20Poly1305ID,
 	"aes128-ctr", "aes192-ctr", "aes256-ctr",
 }
@@ -168,7 +168,7 @@ func (a *directionAlgorithms) rekeyBytes() int64 {
 	// 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
 	// 128.
 	switch a.Cipher {
-	case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID:
+	case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcm128CipherID, gcm256CipherID, aes128cbcID:
 		return 16 * (1 << 32)
 
 	}
@@ -178,7 +178,8 @@ func (a *directionAlgorithms) rekeyBytes() int64 {
 }
 
 var aeadCiphers = map[string]bool{
-	gcmCipherID:        true,
+	gcm128CipherID:     true,
+	gcm256CipherID:     true,
 	chacha20Poly1305ID: true,
 }
 

+ 1 - 1
vendor/golang.org/x/crypto/ssh/connection.go

@@ -97,7 +97,7 @@ func (c *connection) Close() error {
 	return c.sshConn.conn.Close()
 }
 
-// sshconn provides net.Conn metadata, but disallows direct reads and
+// sshConn provides net.Conn metadata, but disallows direct reads and
 // writes.
 type sshConn struct {
 	conn net.Conn

+ 30 - 18
vendor/golang.org/x/crypto/ssh/handshake.go

@@ -58,11 +58,13 @@ type handshakeTransport struct {
 	incoming  chan []byte
 	readError error
 
-	mu             sync.Mutex
-	writeError     error
-	sentInitPacket []byte
-	sentInitMsg    *kexInitMsg
-	pendingPackets [][]byte // Used when a key exchange is in progress.
+	mu               sync.Mutex
+	writeError       error
+	sentInitPacket   []byte
+	sentInitMsg      *kexInitMsg
+	pendingPackets   [][]byte // Used when a key exchange is in progress.
+	writePacketsLeft uint32
+	writeBytesLeft   int64
 
 	// If the read loop wants to schedule a kex, it pings this
 	// channel, and the write loop will send out a kex
@@ -71,7 +73,8 @@ type handshakeTransport struct {
 
 	// If the other side requests or confirms a kex, its kexInit
 	// packet is sent here for the write loop to find it.
-	startKex chan *pendingKex
+	startKex    chan *pendingKex
+	kexLoopDone chan struct{} // closed (with writeError non-nil) when kexLoop exits
 
 	// data for host key checking
 	hostKeyCallback HostKeyCallback
@@ -86,12 +89,10 @@ type handshakeTransport struct {
 	// Algorithms agreed in the last key exchange.
 	algorithms *algorithms
 
+	// Counters exclusively owned by readLoop.
 	readPacketsLeft uint32
 	readBytesLeft   int64
 
-	writePacketsLeft uint32
-	writeBytesLeft   int64
-
 	// The session ID or nil if first kex did not complete yet.
 	sessionID []byte
 }
@@ -108,7 +109,8 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
 		clientVersion: clientVersion,
 		incoming:      make(chan []byte, chanSize),
 		requestKex:    make(chan struct{}, 1),
-		startKex:      make(chan *pendingKex, 1),
+		startKex:      make(chan *pendingKex),
+		kexLoopDone:   make(chan struct{}),
 
 		config: config,
 	}
@@ -340,16 +342,17 @@ write:
 		t.mu.Unlock()
 	}
 
+	// Unblock reader.
+	t.conn.Close()
+
 	// drain startKex channel. We don't service t.requestKex
 	// because nobody does blocking sends there.
-	go func() {
-		for init := range t.startKex {
-			init.done <- t.writeError
-		}
-	}()
+	for request := range t.startKex {
+		request.done <- t.getWriteError()
+	}
 
-	// Unblock reader.
-	t.conn.Close()
+	// Mark that the loop is done so that Close can return.
+	close(t.kexLoopDone)
 }
 
 // The protocol uses uint32 for packet counters, so we can't let them
@@ -545,7 +548,16 @@ func (t *handshakeTransport) writePacket(p []byte) error {
 }
 
 func (t *handshakeTransport) Close() error {
-	return t.conn.Close()
+	// Close the connection. This should cause the readLoop goroutine to wake up
+	// and close t.startKex, which will shut down kexLoop if running.
+	err := t.conn.Close()
+
+	// Wait for the kexLoop goroutine to complete.
+	// At that point we know that the readLoop goroutine is complete too,
+	// because kexLoop itself waits for readLoop to close the startKex channel.
+	<-t.kexLoopDone
+
+	return err
 }
 
 func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {

+ 3 - 3
vendor/golang.org/x/crypto/ssh/keys.go

@@ -1087,9 +1087,9 @@ func (*PassphraseMissingError) Error() string {
 	return "ssh: this private key is passphrase protected"
 }
 
-// ParseRawPrivateKey returns a private key from a PEM encoded private key. It
-// supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. If the
-// private key is encrypted, it will return a PassphraseMissingError.
+// ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports
+// RSA, DSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, OpenSSL, and OpenSSH
+// formats. If the private key is encrypted, it will return a PassphraseMissingError.
 func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
 	block, _ := pem.Decode(pemBytes)
 	if block == nil {

+ 2 - 1
vendor/golang.org/x/crypto/ssh/transport.go

@@ -17,7 +17,8 @@ import (
 const debugTransport = false
 
 const (
-	gcmCipherID    = "aes128-gcm@openssh.com"
+	gcm128CipherID = "aes128-gcm@openssh.com"
+	gcm256CipherID = "aes256-gcm@openssh.com"
 	aes128cbcID    = "aes128-cbc"
 	tripledescbcID = "3des-cbc"
 )

+ 1 - 1
vendor/modules.txt

@@ -1162,7 +1162,7 @@ go.uber.org/zap/internal/bufferpool
 go.uber.org/zap/internal/color
 go.uber.org/zap/internal/exit
 go.uber.org/zap/zapcore
-# golang.org/x/crypto v0.3.0
+# golang.org/x/crypto v0.9.0
 ## explicit; go 1.17
 golang.org/x/crypto/blowfish
 golang.org/x/crypto/chacha20