Subject: Re: additional core draft nits in need of WG attention.

From: [email-masked] (Peter Gutmann)
Date: Sat, 22 Nov 2003 15:15:41 +1300

Jeffrey Hutzelman <[email-masked]> writes:

>Based on this, it seems clear that "implicit server authentication" in this
>context means authentication where the server's identity is proved only by
>its later ability to encrypt valid messages.  This doesn't apply to the
>current diffie-hellman-group1-sha1 keyex, in which the server signs the
>exchange hash, and thus proves its identity and binds it to the algorithm
>negotiation and key exchange just completed.

Not necessarily.  My less tongue-in-cheek guess at the meaning of the text was
that the "implicit" stuff was intended to make the first post-handshake
message (service or global request or whatever the client happened to send
there) play the same role as the Finished message in SSL, where the client and
server do a mutual proof-of-possession of encryption and MAC keys via a
pipeline-stalling message that prevents any further (sensitive) data from
being exchanged until the PoP has concluded (the SSL Finished also
authenticates the handshake messages).  The signed exchange hash merely proves
to the client that the server knows the master secret, but not necessarily
that the client and server share encryption and MAC keys.  Without this mutual
PoP, the client could end up sending passwords to the server using an
incorrect (and potentially weak) key if it's messed up something and derived
the key incorrectly.

Because there's no rationale included in the spec, I don't know if the need
for mutual PoP was an SSH design requirement or not.  If not then the current
wording would be fine.  If it is, then it'd have to be changed to make the PoP
step explicit (which I guess would affect existing implementations).

Peter.

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Fri, 21 Nov 2003 22:50:17 -0500

On Saturday, November 22, 2003 15:15:41 +1300 Peter Gutmann 
<[email-masked]> wrote:

>> Based on this, it seems clear that "implicit server authentication" in
>> this context means authentication where the server's identity is proved
>> only by its later ability to encrypt valid messages.  This doesn't apply
>> to the current diffie-hellman-group1-sha1 keyex, in which the server
>> signs the exchange hash, and thus proves its identity and binds it to
>> the algorithm negotiation and key exchange just completed.
>
> Not necessarily.  My less tongue-in-cheek guess at the meaning of the
> text was that the "implicit" stuff was intended to make the first
> post-handshake message (service or global request or whatever the client
> happened to send there) play the same role as the Finished message in
> SSL, where the client and server do a mutual proof-of-possession of
> encryption and MAC keys via a pipeline-stalling message that prevents any
> further (sensitive) data from being exchanged until the PoP has concluded
> (the SSL Finished also authenticates the handshake messages).  The signed
> exchange hash merely proves to the client that the server knows the
> master secret, but not necessarily that the client and server share
> encryption and MAC keys.  Without this mutual PoP, the client could end
> up sending passwords to the server using an incorrect (and potentially
> weak) key if it's messed up something and derived the key incorrectly.
>
> Because there's no rationale included in the spec, I don't know if the
> need for mutual PoP was an SSH design requirement or not.  If not then
> the current wording would be fine.  If it is, then it'd have to be
> changed to make the PoP step explicit (which I guess would affect
> existing implementations).

At this point in the SSH protocol, we really only care about the server 
proving things to the client.  The client gets a chance to prove its 
identity, and authenticate the algorithm negotiation and key exchange, 
during user authentication, which happens only after key exchange is 
complete.

If proof of possession of the derived keys was a design goal, the protocol 
as it exists today already does not meet the goal, since there is obviously 
_some_ case in which the requirement is not meant to apply (otherwise it 
wouldn't be conditional!).  I would think that if this was a goal, it would 
have been called out by an explicit pipeline-stall, in the form of a pair 
of messages which behave like SSH_NEWKEYS (before you can proceed, you MUST 
both send your message and receive your peer's).  Finally, note that in 
diffie-hellman-group1-sha1, the version and algorithm negotation as well as 
the key exchange itself (together, the equivalent of the TLS handshake) are 
authenticated by the signature at the end of the key exchange.

I believe it is clear from the original text and from the nature of the 
change that the requirement at that time WAS intended to apply to 
double-encrypting-sha1, and WAS NOT intended to apply to diffie-hellman.

I believe we can make any decision we want about how clients have to behave 
wrt this requirement, and it won't affect interoperability with existing 
servers or have any implementation effect on servers -- there is no way a 
server can observe whether the client waited, so I can't see any way for a 
client's behaviour in this regard to affect interoperability.

That said, I don't think there is any good security reason to require this 
behaviour with any well-behaved mechanism, and doing so will certainly 
render some mechanisms noncompliant, apparently including yours.  It may be 
easy to fix, but what is the justification for making people do so?

-- Jeff

PS: In researching this, I had reason to go over section 5.3, which defines 
the various encryption algorithms.  It contains the following text, which I 
believe may be inconsistent with RFC2026:

> RC4 is a registered trademark of RSA Data Security Inc.

---

From: Joseph Galbraith <[email-masked]>
Date: Mon, 24 Nov 2003 09:00:09 -0700

> If proof of possession of the derived keys was a design goal, the 
> protocol as it exists today already does not meet the goal, since there 
> is obviously _some_ case in which the requirement is not meant to apply 
> (otherwise it wouldn't be conditional!).  I would think that if this was 
> a goal, it would have been called out by an explicit pipeline-stall, in 
> the form of a pair of messages which behave like SSH_NEWKEYS (before you 
> can proceed, you MUST both send your message and receive your peer's).  
> Finally, note that in diffie-hellman-group1-sha1, the version and 
> algorithm negotation as well as the key exchange itself (together, the 
> equivalent of the TLS handshake) are authenticated by the signature at 
> the end of the key exchange.

Note that in practice, we do have proof of possession, since
in order to do anything, the client must successfully send
a service request and the server must successfully respond.

(There really isn't much that is useful that you can do
with the transport layer alone.)

The only case where you could run into trouble is if the
client assumes it's service request was going to succeed
and sent the first userauth packet at the same time.

I would claim that doing this would violate at least the
spirit of the protocol if not the letter.  And if someone
ever introduced a different service (which could easily be
done in an extension draft or even using a proprietary
@dns.domain extension) such a client would fail to interoperate
or to fail in a gracefully manner.

- Joseph

---

From: [email-masked] (Niels Möller)
Date: 24 Nov 2003 19:38:05 +0100

> and sent the first userauth packet at the same time.

I think clients are supposed to be able to do exactly that. Peter
complained earlier about the chattyness of the userauth protocol, but
it doesn't have to be chatty. The client can send a password or public
userauth key + signature immediately after the SERVICE_REQUEST packet,
perhaps in the same IP packet. That way, one can connect and login
using a fairly small number of roundtrips, which I believe was one of
the original design goals.

> And if someone ever introduced a different service (which could
> easily be done in an extension draft or even using a proprietary
> @dns.domain extension) such a client would fail to interoperate or
> to fail in a gracefully manner.

Sorry, that's not how the protocol is specified. Section 9 in the
transport draft says clearly

   If the server rejects the service request, it SHOULD send an
   appropriate SSH_MSG_DISCONNECT message and MUST disconnect.

A client will not get a second chance if the service request fails,
because then the server MUST disconnect. [2]

And I also think it's appropriate for a client to expect that if it
sends a service request and a userauth request immediately after each
other, and the server rejects the service request, then the userauth
request will be ignored with no interesting side effects on the
server.

And that's why the "implicit server authentication" is dangerous, if
ever implemented: If you end up in a situation where you share your
session key with the attacker, but not with the server, then you can
end up sending your password in a packet the attacker can read, and
discover too late that you don't share a session key with the server.

I think the simplest resolution of this issue is to keep the current
text, "Note that after a key exchange with implicit server
authentication, the client MUST wait for response to its service
request message before sending any further data.", and clarify the
definition of "implicit server authentication".

So I propose the following change to the final paragraph of section 6,
Key Exchange:

Before:

   Server authentication in the key exchange MAY be implicit.  After a
   key exchange with implicit server authentication, the client MUST
   wait for response to its service request message before sending any
   further data.

After:

   A key exchange method uses "explicit server authentication" if the
   keyexchange messages include a signature or other proof of the
   server's authenticity.  A key exchange method uses "implicit server
   authentication" if, in order to prove its autenticity, the server
   also has to prove that it knows the shared secret K, by sending a
   message and a corresponding MAC which the client can verify. [1]

   All currently defined key exchange methods use explicit server
   authentication.  However, key exchange methods with implicit server
   authentication MAY be used with this protocol.  After a key exchange
   with implicit server authentication, the client MUST wait for
   response to its service request message before sending any further
   data.

I don't feel to strongly about this issue, and the proposal to just
delete all text about implicit server authentication. But I don't
think we really should start to strike out features from the protocol
at this stage. So I hope the above clarification is good enough, or if
not, that somebody else is willing to improve it shortly. Then we can
put this issue at rest.

[1] It seems like the server being able to decrypt and verify the
client's SERVICE_REQUEST message might also be important. Perhaps one
could end up with server and client sharing keys properly in the
server->client direction, but not client->server.

But I don't think this can happen, due to the way session keys are
derived (section 6.2). A proof of knowledge of K should be sufficient
for the client to establish the server's autenticity. If this
verification succeeds, and the client still does not have the right
keys for the client->server direction, then that's a serious security
hole, but it's a hole somewhere in the keyexchange and session key
generation, and I think it's fair to say that it's not server
authentication in particular that is broken.

[2] If you want to try several new fancy services, I think a more
interoperable way to do that is to first ask for the userauth service,
and then try several userauth requests with the "none" method and
varying service names.

Regards,
/Niels