[noise] Hidden fallback

Rhys Weatherley rhys.weatherley at gmail.com
Sat Apr 23 16:43:23 PDT 2016


Apologies if this idea was already raised before and shot down ...

For most of the handshake patterns, the API between the application and the
Noise protocol library is pretty simple.  On the sending side, the
application hands a payload to the library and the library hands back a
sequence of bytes ready to transmit.  On the receiving side, the
application hands a sequence of bytes to the library and the library hands
back a payload (or an error).

The odd one out is Noise Pipes.  The application now has to perform an
additional dance with packet types and a potential change of protocol
half-way through the process.  During this, the initiator and responder may
be reversed, adding more complexity to the application to figure out which
CipherState is which for data transport.

Another concern I have is that the protocol reveals if a fallback has
occurred or not in the sequence of packets that are exchanged.  Some
systems may not want to reveal to passive surveillance that a key change
has occurred, or that the initiator is currently ignorant of the
responder's key and thus a ripe target for an active MITM.

I was wondering if it was possible to create a "hidden fallback" pattern
that encompasses IK, XX, and XXfallback in one pattern.

Here's a quick attempt at such a thing (which I haven't completely analysed
for security).  There are two new token codes "dhes-fallback" and
"dhee-fallback" which I'll define below.

Noise_XXhiddenfallback(s, rs):
    <- s (optional)
    ...
    -> e, dhes-fallback
    <- e, dhee-fallback, s, dhse
    -> s, dhse, dhss

There are three cases of interest:

1. "s" is already known to the initiator and it is correct.
2. "s" is already known to the initiator and it is incorrect.
3. "s" is not known to the initiator (and is therefore incorrect).

I'll handle cases 1 and 2 first.

WriteMessage() is modified to include:

* For "dhes-fallback":
  - Save the current chaining key.
  - Call MixKey(DH(e, rs))
  - Appends EncryptAndHash(empty) to the buffer.
  - Do not perform EncryptAndHash(payload).  The payload must be empty.
* For "dhee-fallback":
  - Call MixKey(DH(e, re))
  - Appends EncryptAndHash(empty) to the buffer.

ReadMessage() is modified to include:

* For "dhes-fallback":
  - Save the current chaining key.
  - Call MixKey(DH(s, re))
  - Call DecryptAndHash() on an empty sequence (MAC value only).
  - If the MAC check fails, then restore the previous chaining key.
  - Whether the MAC check succeeds or not, the MixHash() part of
DecryptAndHash() must still be done.
  - Do not perform DecryptAndHash(payload).  The message must end here.
* For "dhee-fallback":
  - Call MixKey(e, re).
  - Call DecryptAndHash() on an empty sequence (MAC value only).
  - If the MAC check is successful, then the initiator had the correct key
and the handshake proceeds normally.
  - If the MAC check failed, then restore the previously saved chaining key
and call MixKey(DH(e, re)) again.
  - Whether the MAC check succeeds or not, the MixHash() part of
DecryptAndHash() must still be done.

Essentially, the effect of "dhes-fallback" on the chaining key is undone if
the initiator has the wrong "s" value for the responder.  However, the
incorrect MAC values are still mixed into the handshake hash to prevent the
fallback from being spoofed by a MITM.

For pattern correctness, "dhes-fallback" must be the last token in its
sequence and the corresponding message payload must be empty.  Any
initiator certificates that need to be sent can be added to the final
packet when the initiator's "s" value is sent.

To make the fallback truly hidden, ReadMessage() must take care to process
the "dhes-fallback" and "dhee-fallback" tokens in constant time.  It should
be possible to use constant-time conditional swaps to take care of this.

The above deals with cases 1 and 2.  Case 3 is where the initiator did not
have a saved public key for the responder.  In this case, the initiator
generates a random keypair and uses that public key as the stand-in for the
responder's "s" during the first packet.  Essentially, the initiator
manufactures an incorrect key and then case 3 is identical to case 2.

One last thing: "XXhiddenfallback" is a bit of a mouthful.  "XF"?  "XH"?

Any thoughts?

Cheers,

Rhys.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://moderncrypto.org/mail-archive/noise/attachments/20160424/f725ba29/attachment.html>


More information about the Noise mailing list