IETF-SSH archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

AEAD in ssh



denis bider <ietf-ssh3%denisbider.com@localhost> writes:

> With regard to AEAD:
>
> I think we should just make the following simple and clear statement:
>
> MAC algorithms are secondary to encryption algorithms, and are
> evaluated only if the encryption algorithm is not AEAD. If an AEAD
> encryption algorithm is negotiated, the outcome of MAC negotiation is
> irrelevant and must be ignored. If no mutual MAC algorithms are
> available, this causes key exchange to fail if, and only if, the
> negotiated encryption algorithm is not AEAD.

That's only one part of it. I think the following points need clear
specification:

1. How to negotiate use of AEAD. 

   The above would work, I think. 

   Or one could specify a "n/a" mac name, which is a bit like "none",
   except that negotiation fails if it's the output of the mac
   negotiation and the negotiated cipher isn't an aead mechanism. Maybe
   unnecessary, but it could also serve the second purpose as signalling
   support for aead, in case the negotiation rules need tweaking (see
   also next point). If defined, it should be mandatory (i.e., if the
   agreed cipher is aead, but "n/a" mac isn't offered, connection should
   fail).

2. How it interacts with first_kex_packet_follows. 

   Roughly, if everything is "guessed" correctly except the mac
   algorithm (e.g, if the mac name-list is empty so mac negotiation
   fails), and the agreed cipher is aead, the guess ought to
   nevertheless be considered successful. The details must be made
   crystal clear. 

   (And I'm open to tweaking the rules in other ways too, if new rules are
   reliably signalled via some extension or by the "n/a" atom; it's
   unclear to me if the first_kex_packet_follows logic really needs to
   depend on anything else but the agreed key exchange mechanism and
   maybe host_key_algorithm (I think I can argue that it's independent
   of host_key_algorithm: Every reasonable keyexchange algorithm needs
   input from the client, and the key exchange signature must depend on
   that data. Hence the first kex packet should be independent of the
   signature)).

3. If and how to encrypt the length field. 

   My strong opinion is that it ought to be encrypted. A spec for AEAD
   in ssh should either specify fully how to do that, or give clear
   guidelines in case some details must be left to the specification of
   each AEAD mechanism. Roughly, one should use an independent cipher
   instance (distinct key or disjoint nonce sequence or distinct ctr
   value) to encrypt the length in a ctr-like mode.

4. What the "block size" used for padding purposes (RFC 4253, Sec. 6,
   "Binary Packet Protocol") should be. 

   AEAD in the abstract doesn't expose any block size, so I'd be
   inclined to say that we should always use 8, the ssh minimum. One
   could tie it to the underlying block cipher if there is one, but it
   makes little sense to me, given that it's the length *including* the
   length field which must be a multiple of the "block size". And with
   AEAD, the length field has to be separately encrypted, so by the
   current rules, we're always going to be unaligned anyway.

5. Precisely which bytes go into the AEAD nonce, data, and plaintext,
   when processing each packet.

   Perhaps we should first take a step back and look at the binary
   packet format:

      uint32    packet_length
      byte      padding_length
      byte[n1]  payload; n1 = packet_length - padding_length - 1
      byte[n2]  random padding; n2 = padding_length
      byte[m]   mac (Message Authentication Code - MAC); m = mac_length

    For AEAD, maybe it's better to think about it as applying the
    padding to the *plaintext*. Then the plaintext input to the AEAD
    algorithm would be

      byte      padding_length
      byte[n1]  payload; n1 = packet_length - padding_length - 1
      byte[n2]  random padding; n2 = padding_length

    These n1+n2+1 = packet_length bytes of cleartext are transformed
    using AEAD into packet_length+m bytes of ciphertext including an
    authentication data.

    For simplicity, drop all requirements on the padding length except
    keeping the lower bound n2 >= 4.

    The packet length field is encrypted separately producing 4 bytes of
    encrypted length preceding the AEAD ciphertext on the wire. It can
    also be included in the associated data, before or after encryption;
    I'm not sure if there's any real benefit in doing that, but it might
    make it a little more robust.

The existing RFC 5647 on aes-gcm is unclear on (1) and (2) (and
apparently not implemented that way in openssh). I disagree with its
choice for (3), this has been argued on the secsh list recently, I'll
not repeat it here. 

I think it gets (5) right (without deep thinking about it. I note that
it departs from RFC 4253 by not including an explicit sequence number in
the authenticated data). For (4), it specifies that AEAD plaintext
*excluding* the length field must be a multiple of 16. Which makes some
sense, but (i) departs from the original rules, and (ii) is of little
benefit, since gcm doesn't require the input to be an integral number of
AES blocks.

Openssh's chacha-poly1305 is also pretty important. I don't have their
details in front of me, but at least the length *is* encrypted, using an
independent chacha instance. And it doesn't agree with the (later)
definition of chacha-poly1305 in RFC 7539.

In short, to write a good specification will require some non-trivial
amount of work. And I think it's pretty important work. Do you agree?
Are there any objections to the above direction? (I already know some
dislike encrypted lengths). What are the chances to reach rough
consensus?

Regards,
/Niels

-- 
Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26.
Internet email is subject to wholesale government surveillance.



Home | Main Index | Thread Index | Old Index