Commit Graph
18 Commits
Author SHA1 Message Date
Filippo Valsorda 1baeb1ce4c ssh: don't advertise rsa-sha2 algorithms if we can't use them
The server implementation looks at the HostKeys to advertise and
negotiate host key signature algorithms. A fundamental issue of the
Signer and AlgorithmSigner interfaces is that they don't expose the
supported signature algorithms, so really the server has to guess.

Currently, it would guess exclusively based on the PublicKey.Type,
regardless of whether the host key implemented AlgorithmSigner. This
means that a legacy Signer that only supports ssh-rsa still led the
server to negotiate rsa-sha2 algorithms. The server would then fail to
find a suitable host key to make the signature and crash.

This won't happen if only Signers from this package are used, but if a
custom Signer that doesn't support SignWithAlgorithm() but returns
"ssh-rsa" from PublicKey().Type() is used as a HostKey, the server is
vulnerable to DoS.

The only workable rules to determine what to advertise seems to be:

   1. a pure Signer will always Sign with the PublicKey.Type

   2. an AlgorithmSigner supports all algorithms associated with the
      PublicKey.Type

Rule number two means that we can't add new supported algorithms in the
future, which is not great, but it's too late to fix that.

rsaSigner was breaking rule number one, and although it would have been
fine where it's used, I didn't want to break our own interface contract.

It's unclear why we had separate test key entries for rsa-sha2
algorithms, since we can use the ssh-rsa key for those. The only test
that used them, TestCertTypes, seemed broken: the init was actually
failing at making the corresponding signers rsaSigners, and indeed the
test for the SHA-256 signer expected and checked a SHA-512 signature.

Pending CVE
For golang/go#49952

Change-Id: Ie658eefcadd87906e63fc7faae8249376aa96c79
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/392355
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-03-14 23:46:59 +00:00
Filippo Valsorda 4d399097f0 ssh: fix diffie-hellman-group-exchange g and K bounds checks
The previous code

	if gex.g.Cmp(one) != 1 && gex.g.Cmp(pMinusOne) != -1 {

deobfuscates to the classic mistake

    if g <= 1 && g >= p - 1 {

which is never true.

What the code actually intended to do is

	if gex.g.Cmp(one) != 1 || gex.g.Cmp(pMinusOne) != -1 {

or more readably and consistently with the diffieHellman method

	if gex.g.Cmp(one) <= 0 || gex.g.Cmp(pMinusOne) >= 0 {

Now, is this a security issue? The incorrect checks apply to g and k,
but not what we call Y and the spec calls f. RFC 4419 says:

   Either side MUST NOT send or accept e or f values that are not in the
   range [1, p-1].  If this condition is violated, the key exchange
   fails.  To prevent confinement attacks, they MUST accept the shared
   secret K only if 1 < K < p - 1.

Note that RFC 8268, Section 4 updates the equivalent RFC 4253 statement
(although not the RFC 4419 one) about e and f, but we are already doing
the correct full check there.

      DH Public Key values MUST be checked and both conditions:

         1 < e < p-1

         1 < f < p-1

      MUST be true.  Values not within these bounds MUST NOT be sent or
      accepted by either side.  If either one of these conditions is
      violated, then the key exchange fails.

   This simple check ensures that:

   o  The remote peer behaves properly.

   o  The local system is not forced into the two-element subgroup.

The check on K seems like a proxy for checking a number of ways to fix
the DH output (for example by manipulating g) to one of 0, 1, or -1.
This should not be meaningful to security for two reasons:

   - all parameters end up in the "transcript" hash that will get signed
     by the server's host key, and if the attacker controls the host
     key's signature, they have the ability to MitM without resorting to
     confinement attacks

   - the client secret is ephemeral, so leaking bits of it by forcing it
     into small sub-groups does not gain the attacker anything, as the
     secret does not get reused

Indeed, this is the same explanation of why it's ok not to check that p
is indeed a (safe) prime, which even OpenSSH omits. Building an
equivalent attack by manipulating p instead of g is left as an exercise
to the reader.

For the future, this is a case study in why we should not add complexity
even when it looks easy enough to do. CL 174257 added the
diffie-hellman-group-exchange kex. That introduced a data race (arguably
a security issue), which was fixed in CL 222078. Then it was too slow,
which led to CL 252337 that removed the primalty check, which required a
full analysis of whether it's safe to skip it, and checking against
other implementations. Now we find there's a bug and we have to do
another security analysis that not even the RFC bothered to do in order
to decide if it's a security issue. My decision in
https://github.com/golang/go/issues/17230#issuecomment-489163656
does not look like the right one in hindsight.

While at it, clean up the code some

   - drop useless bit size bounds logic in the server stub that get
     ignored by the rest of the function

   - make p and g local variables instead of method fields, since they
     are not persistent state (this was originally a data race which was
     fixed in CL 222078 by making Client not a pointer receiver)

Updates golang/go#17230

Change-Id: I4b1c68537109f627ccd75ec381dcfab57ce1768c
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/392015
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-03-14 23:46:39 +00:00
Filippo ValsordaandNicola Murino e4b3678e5f ssh: add diffie-hellman-group14-sha256 kex
RFC 9142 made diffie-hellman-group14-sha256 from RFC 8268 a MUST, and
it's strictly better than diffie-hellman-group14-sha1, which we already
have, and trivial to add.

> The method of key exchange used for the name "diffie-hellman-
> group14-sha256" is the same as that for "diffie-hellman-group14-sha1"
> except that the SHA256 hash algorithm is used.

Ignore the bigger groups which have a meaningful performance cost, and
don't share the same interoperability benefit.

Adapted from CL 387994.

Fixes golang/go#31731

Co-authored-by: Nicola Murino <nicola.murino@gmail.com>
Change-Id: Id4ce345a2065840f193986739ea890f105a1e929
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/392014
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
2022-03-14 23:46:33 +00:00
Михаил ПатинandFilippo Valsorda 9b076918e3 ssh: support new curve25519-sha256 kex name
RFC 8731 standardized curve25519-sha256@libssh.org as curve25519-sha256,
and some systems only advertise support for the new name.

Fixes golang/go#48756

Change-Id: Ice35874cd8c07ad48752686ac368bf11ab793f77
Co-authored-by: Filippo Valsorda <filippo@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/385394
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Trust: Matt Layher <mdlayher@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
2022-03-14 23:46:23 +00:00
Daniel Cohen afb6bcd081 ssh: remove slow unnecessary diffie-hellman-group-exchange primality check
The existing implementation validates that the prime returned by the server is, in fact, prime, which is extremely slow, especially for large key sizes.

As other implementations, including OpenSSH, do not verify the primality of the provided parameters, this change removes that check.

Fixes golang/go#41151

Change-Id: I7539714c690f08b5792a0c540cbf46c3e81f13ba
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/252337
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Roland Shoemaker <roland@golang.org>
2020-09-30 16:06:38 +00:00
Lucas Bremgartner 1b76d66859 ssh: fix data race in dh group exchange sha256
Fixes golang/go#37607

Change-Id: Iedf6522ec9b9a676ac51c054407a6aef894885f5
GitHub-Last-Rev: 8cb2460c59d2e32bc3f0480bcd7867a113361c67
GitHub-Pull-Request: golang/crypto#126
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/222078
Reviewed-by: Han-Wen Nienhuys <hanwen@google.com>
Run-TryBot: Han-Wen Nienhuys <hanwen@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2020-03-17 14:21:12 +00:00
Lars Lehtonen 6e5058baad ssh: fix dropped error
This fixes an error variable that was being dropped
prior to the return of dhGroup.Server().

Change-Id: I8ddef1832cd7a62a69b61bb1c98bc1ceb561f985
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/205420
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
2019-11-08 23:12:17 +00:00
Lucas Bremgartner 57b3e21c3d ssh: add diffie-hellman-group-exchange-sha256
Add the diffie-hellman-group-exchange-sha256 defined in RFC 4419 to
the list of supported key exchange algorithms for ssh.
The server half is only a minimal implementation to satisfy the automated tests.

Fixes golang/go#17230

Change-Id: I25880a564347fd9b4738dd2ed1e347cd5d2e21bb
GitHub-Last-Rev: 9f0b8d02c0c96e9baf00cdf1cf063ff834245443
GitHub-Pull-Request: golang/crypto#87
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/174257
Run-TryBot: Han-Wen Nienhuys <hanwen@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Han-Wen Nienhuys <hanwen@google.com>
2019-06-17 13:33:40 +00:00
Kevin Burke e8f229864d all: fix errors reported by vet, golint
None are "wrong" per se, but there are a lot of good suggestions and
in one case a docstring that was not present in godoc due to the
presence of an extra newline.

Changed "Id" in struct properties to "ID" in some non-exported
structs. Removed a trailing period from some error messages; I believe
the exact contents of error strings are not covered by the Go
compatibility promise.

Change-Id: I7c620582dc247396f72c52d38c909ccc0ec87b83
Reviewed-on: https://go-review.googlesource.com/80145
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2017-11-28 17:48:09 +00:00
Dave Cheney adbae1b6b6 all: gofmt ./...
Change-Id: I8ffee4dc712091e424b83a9f5a3cc2a6724abefc
Reviewed-on: https://go-review.googlesource.com/46050
Reviewed-by: Matt Layher <mdlayher@gmail.com>
2017-06-19 20:42:22 +00:00
Adam Langley dc7f3af03e ssh: bound DH public values to [2, p-2].
Previously this code bounded the values to [1, p-1]. This protects
against invalid values that could take lots of CPU time to calculate
with. But the standard bounding is [2, p-2] so mirror that.

Since the DH exchange is signed anyway, this is not a security fix.

Change-Id: Ibef01805a596a433b0699d7a09c076344fa8c070
Reviewed-on: https://go-review.googlesource.com/30590
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-10-10 21:14:46 +00:00
Han-Wen Nienhuys d68c3ecb62 x/crypto/ssh: make sure the initial key exchange happens once.
This is done by running the key exchange and setting the session ID
under mutex. If the first exchange encounters an already set session
ID, then do nothing.

This fixes a race condition:

On setting up the connection, both sides sent a kexInit to initiate
the first (mandatory) key exchange.  If one side was faster, the
faster side might have completed the key exchange, before the slow
side had a chance to send a kexInit.  The slow side would send a
kexInit which would trigger a second key exchange. The resulting
confirmation message (msgNewKeys) would confuse the authentication
loop.

This fix removes sessionID from the transport struct.

This fix also deletes the unused interface rekeyingTransport.

Fixes #15066

Change-Id: I7f303bce5d3214c9bdd58f52d21178a185871d90
Reviewed-on: https://go-review.googlesource.com/21606
Reviewed-by: Adam Langley <agl@golang.org>
Reviewed-by: Han-Wen Nienhuys <hanwen@google.com>
2016-04-12 17:14:56 +00:00
Carl Jackson 7b85b097bf x/crypto/ssh: run go fmt
Change-Id: Ibb071aa550ca7392543c2d1eba8f8a69ba1d86fa
Reviewed-on: https://go-review.googlesource.com/17270
Reviewed-by: Dave Cheney <dave@cheney.net>
2015-12-01 00:25:08 +00:00
hanwen aca188fab6 x/crypto/ssh: implement curve25519-sha256@libssh.org key agreement.
Fixes golang/go#11004.

Change-Id: Ic37cf9d620e3397b7ad769ae16abdaee63a7733b
Reviewed-on: https://go-review.googlesource.com/13592
Reviewed-by: Adam Langley <agl@golang.org>
2015-08-17 22:16:34 +00:00
Adam Langley fa50e7408b go.crypto/ssh: import gosshnew.
See https://groups.google.com/d/msg/Golang-nuts/AoVxQ4bB5XQ/i8kpMxdbVlEJ

R=hanwen
CC=golang-codereviews
https://golang.org/cl/86190043
2014-04-09 13:57:52 -07:00
Jonathan Pittman 44256fa2df go.crypto/ssh: cosmetic only spelling fixes
R=agl, hanwen
CC=dave, golang-dev, jpsugar
https://golang.org/cl/14430055
2013-10-10 11:35:15 -04:00
Han-Wen Nienhuys 4147256c9c go.crypto/ssh: move interpretation of msgNewKeys into
transport.

Sending the msgNewKeys packet and setting up the key material
now happen under a lock, preventing races with concurrent
writers.

R=kardianos, agl, jpsugar, hanwenn
CC=golang-dev
https://golang.org/cl/14476043
2013-10-08 15:47:04 -04:00
Han-Wen Nienhuys 73e99326fb go.crypto/ssh: separate kex algorithms into kexAlgorithm class.
Adds readPacket() to conn, and renames conn to packetConn.
Key exchanges operate on packetConn, so they can be
unittested.

R=agl, jpsugar, dave
CC=golang-dev
https://golang.org/cl/13352055
2013-09-24 12:26:29 -04:00