Subject: Re: Data transfer during key re-exchange

From: Jacob Nevins <[email-masked]>
Date: Tue, 20 Jul 2004 23:50:43 +0100

Joseph Galbraith writes:
> Jacob Nevins wrote:
> > What happens to "application data" (connection protocol etc) during a
> > key re-exchange is still not specified by the current transport draft
> > (transport-18).
    [snip my suggestion]
> > If anyone has objections, this issue should at least go in the issue
> > tracker, so it doesn't get lost again.
> 
> Every time this discussion has come up before I've looked for
> the language that I knew was there in section 7.1, and then
> found it in section 7.3 (which really is quite clear, if misplaced)
  [snip]
> And in section 9,
  [snip]
> I've never quite understood the confusion on this issue... however,
> I don't object to the new text.  I do object to it's proposed
> location though... I think it should go in Section 7.1 and section
> 7.3 could be condensed a little bit to remove redunancy.

Fair enough.

> If a re-enforcing sentance is needed in section 9 (processed identically
> including valid packet restrictions) I wouldn't mind that.
> 
> I would strike the final paragraph of section 9-- it is wrong (key
> exchanges _does_ affect the protocols because we stop sending their
> data for the duration) and only introduces confusion about an issue that
> is pretty well specified otherwise.  I guess we could reword it as our
> re-enforcing sentance:
  [snip]

OK. How about this for a proposed change to transport-18?:

At the end of Section 7.1, add the following two paragraphs:

   Once a party has sent a KEXINIT message for key exchange or
   re-exchange, it MUST NOT send any messages other than key exchange
   method specific messages (message numbers 30 to 49); NEWKEYS; and
   DISCONNECT, IGNORE, and DEBUG; until it has sent a NEWKEYS message
   (Section 7.3).  Implementations MUST NOT accept messages other than
   these between receiving KEXINIT and NEWKEYS messages.

   Note however that during a key re-exchange, after sending a KEXINIT
   message, each party MUST be prepared to process an arbitrary number
   of received messages that may be "in flight" before seeing a
   KEXINIT from the other party.

Replace the last paragraph of Section 7.3 ("This message is [...]
receiving SSH_MSG_NEWKEYS.") with the following paragraph:

   The purpose of this message is to ensure that a party is able to
   respond with a SSH_MSG_DISCONNECT message that the other party can
   understand if something goes wrong with the key exchange.

Replace the last paragraph of Section 9 ("More application data [...]
SSH_MSG_NEWKEYS is sent") with the following paragraph:

   Key exchange does not affect the protocols that lie above the SSH
   transport layer, except that such protocol data MUST NOT be sent
   after a SSH_MSG_KEXINIT is sent but before a SSH_MSG_NEWKEYS is
   sent.

(For convenience I've put a marked-up copy of transport-18 at
<http://www.chiark.greenend.org.uk/~jacobn/2004/07/ssh2-kex-data-diff.html>.)

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Tue, 20 Jul 2004 21:38:16 -0400

>    these between receiving KEXINIT and NEWKEYS messages.

Uh, what's wrong with SSH_MSG_UNINPLEMENTED?
And what's wrong with other (not yet defined) messages in the 20-29 range?
Without these, it will become difficult to extend algorithm negotiation, 
which I know we've discussed in the past.

For that matter, I'm not convinced that the not-yet-defined messages in the 
1-19 range should be excluded either.  All of the defined messages in this 
range have meaning at the lowest layer, independent of key exchange state. 
Why do we think any future messages in this range won't have the same 
property?

I'd say permit any messages in the 1-49 range, with the possible exception 
of SSH_MSG_KEXINIT itself.  Note that this must be handled carefully - once 
you send a KEXINIT, you're not allowed to _send_ another one, but you 
certainly are allowed to _receive_ one if you haven't seen it yet.  The 
text you propose seems clear enough to me in this regard; an implementation 
that gets this wrong won't be able to rekey at all!

>    after a SSH_MSG_KEXINIT is sent but before a SSH_MSG_NEWKEYS is

It occurs to me that what we're really trying to say is "key exchange does 
not affect the STATE OF protocols that lie above the SSH transport 
layer...".  It can introduce arbitrary delay, but that's it.

-- Jeff

---

From: Jacob Nevins <[email-masked]>
Date: Wed, 21 Jul 2004 12:26:06 +0100

> Uh, what's wrong with SSH_MSG_UNINPLEMENTED?

OK, now this is a whole new discussion, opening issues with the original
draft. Can we get consensus and/or raise a ticket for the app-data-
during-rekey issue so that it doesn't get lost yet again in this
discussion?

That said, I can't see a reason not to include UNIMPLEMENTED, given its
status alongside the others in section 11 as being able to be sent by
either party at any time.

> which I know we've discussed in the past.

In principle yes, but at this point I'd be inclined to defer resolving
this to such time as such extensions are actually defined.
(I admit that this is partly due to the IESG's apparent paranoia about
over-extensibility; I don't want to see the drafts being held up again
on my account if there's some gremlin we haven't thought of.)

> range have meaning at the lowest layer, independent of key exchange state.

Are you really suggesting that SERVICE_REQUEST and SERVICE_ACCEPT should
be permitted during key exchange?

> Why do we think any future messages in this range won't have the same

If we're unhappy with SERVICE_REQUEST and _ACCEPT (as I think I am),
then future messages in this range may have the same undesirable
properties as them.

---

From: Jeffrey Hutzelman <[email-masked]>
Date: Wed, 21 Jul 2004 11:32:20 -0400

>> And what's wrong with other (not yet defined) messages in the 20-29
>> range? Without these, it will become difficult to extend algorithm
>> negotiation, which I know we've discussed in the past.
>

That doesn't help.  The issue is that in order to extend the exchange in 
the future, an new peer needs to be able to send a not-yet-defined message 
to an old peer and get SSH_MSG_UNIMPLEMENTED back.  In order for that to 
work, old peers must accept the not-yet-defined message and return 
SSH_MSG_UNIMPLEMENTED, rather than ignoring the not-yet-defined message or 
deciding to disconnect (either of which would appear to be OK -- we don't 
define what happens if you get a message that you MUST NOT accept).

>> For that matter, I'm not convinced that the not-yet-defined messages in
>> the 1-19 range should be excluded either.  All of the defined messages
>> in this range have meaning at the lowest layer, independent of key
>> exchange state.
>

No.  Those don't fall in the realm of not-yet-defined, and clearly should 
be excluded.

> then future messages in this range may have the same undesirable

Well, it's expected that current implementations MUST NOT send 
not-yet-defined messages at all, until they are defined.

The issue is with what current impleentations do when they receive a 
not-yet-defined message.  If we ever want to extend the protocol cleanly, 
they need to respond with SSH_MSG_UNIMPLEMENTED and otherwise do nothing, 
just as they would at any other time.  This isn't a general-purpose 
extension mechanism to be used by anyone who wants to, but it _is_ key to 
making it possible to define a future rev of the protocol which 
interoperates with this one but includes new messages (sadly, we can't just 
bump the protocol version, because we failed to define a way to indicate 
support for any version beyond 2.0 while also supporting the 1.x protocol).

Again, if we decide in the future that message 17 should be permitted 
during rekey, a new implementation won't be able to discover if its peer 
support message 17 unless implementations that don't know what that is are 
expected to send SSH_MSG_UNIMPLEMENTED.

On the other hand, if we decide that message 17 should _not_ be permitted 
during rekey, all we have to do is say that when we define message 17. 
Then new implementations will not send message 17 during rekey, and will 
not accept it if they see it then.  Old implementations will continue to 
send SSH_MSG_UNIMPLEMENTED, but that shouldn't be a problem.

-- Jeff

---

From: Derek Fawcus <[email-masked]>
Date: Thu, 22 Jul 2004 10:05:28 +0100

> >> >    these between receiving KEXINIT and NEWKEYS messages.

Well I'd have to object to the above,  as I'd want to be able to send other
transport messages (1 - 49).  Moreover the original message from Bill actually
said "must suspend transport of user data while rekey negotiation is in progress"
not "non-rekey-related traffic should be suspended for the duration of the rekey".

As to the response to receiving any such transport message,  that can be discussed...

> >> Uh, what's wrong with SSH_MSG_UNINPLEMENTED?

I agree to the point about needing to be able to send the above during the rekey.

> No.  Those don't fall in the realm of not-yet-defined, and clearly should 

Well I'd suggest one treat those as protocol errors,  and send a DISCONNECT in
response.  However if someone did a non blocking rekey implementation
(say a subsequent enhancement),  then we may well want to accept these during
a rekey.

I'd say it's a quality of implementation issue,  in the absense of any extension
for non blocking rekey,  I'd make receipt of the above send a DISCCONECT.

I don't know that it actually needs anything in the document.  I suppose we could
explicity say that behaviour upon receipt of those two during rekey is unspecified.

> send SSH_MSG_UNIMPLEMENTED, but that shouldn't be a problem.

Agreed.

DF

---

From: Bill Sommerfeld <[email-masked]>
Date: Thu, 22 Jul 2004 19:24:53 -0400

> Well I'd have to object to the above, as I'd want to be able to send
> other transport messages (1 - 49).  Moreover the original message
> from Bill actually said "must suspend transport of user data while
> rekey negotiation is in progress" not "non-rekey-related traffic
> should be suspended for the duration of the rekey".

Don't view my words as gospel. 

The intent was twofold:

 - capturing and documenting what you have to do or not do during
rekey interoperate with the least common denominator sshv2 installed
base..

 - prompt the folks looking for better-than-current-practice/seamless
rekey to go off and code and then document a negotiable extension.

						- Bill

---

From: Jacob Nevins <[email-masked]>
Date: Fri, 23 Jul 2004 14:23:34 +0100

> define what happens if you get a message that you MUST NOT accept).
  [snip other explanation]

OK, you've convinced me. How does the following replacement Section 7.1
paragraph for my proposal sound?:

   Once a party has sent a KEXINIT message for key exchange or
   re-exchange, until is has sent a NEWKEYS message (Section 7.3), it
   MUST NOT send any messages other than:
   o  Transport layer generic messages (1 to 19) (but SERVICE_REQUEST
      and SERVICE_ACCEPT MUST NOT be sent);
   o  Algorithm negotiation messages (20 to 29) (but further KEXINITs
      MUST NOT be sent);
   o  Key exchange method specific messages (30 to 49).
   The provisions of Section 11 apply for unrecognised messages, etc.

(the rest of my proposal is unchanged; see it in full at
<http://www.chiark.greenend.org.uk/ucgi/~jacobn/cvsweb/ssh2-kex-data.d/draft-ietf-secsh-transport-18-plus-kex-data.txt.diff?r1=1.1&r2=1.4&f=H>
or <http://tinyurl.com/4hdge>

To attempt to address Derek Fawcus' comments elsewhere: I don't believe
this precludes the future implementation of a non-blocking rekey
extension. (I'd have thought the obvious way to do that would be to
substitute a new KEXINIT_NONBLOCK in the 20-29 range for the KEXINIT
used for a re-exchange.) I don't think there's a need to leave responses
to any messages formally unspecified given the UNIMPLEMENTED mechanism.