[noise] Generic fallback handling

Rhys Weatherley rhys.weatherley at gmail.com
Thu May 26 01:44:22 PDT 2016


Alex asked me about how I extended the Noise-C API to deal with Noise
Pipes, and I thought I might share the approach with the rest of the
mailing list.  This is my contribution to how we might handle other types
of fallback protocols should we choose to do that.

The specification effectively treats the IK and XXfallback phases of Noise
Pipes as separate: the application sees the failure and then starts a
completely new handshake, hand-carrying across the static and ephemeral
keys to satisfy the XXfallback requirements.

I instead took a different approach: the HandshakeState for IK is converted
into one for XXfallback, within the same object.  At the high level, I have
a Fallback() method that does the following:

Fallback():
  - Change the pattern in the protocol name to "XXfallback".
  - Clear the remote static public key.
  - Clear the responder's ephemeral key but keep the initiator's ephemeral
key.
  - Swap the initiator/responder role of the handshake.
  - Call Initialize() again.

All other parameters (prologue, psk, cipher, dh, hash, s) remain the same.
In a previous version of Noise-C, the prologue and psk had to be provided
again as arguments to Fallback() because they had been forgotten by that
point in the handshake.  The latest Noise-C remembers those values too, but
alternative implementations don't have to.  Note: Noise-C does provide a
way to override the previous parameters before Initialize() if the
application needs to, but it usually doesn't.

With this API, the local static key and initiator's ephemeral key do not
need to be provided again because they are already in the HandshakeState.

This API doesn't provide a complete implementation of Noise Pipes - it only
provides a primitive to make the application's life easier.  There are
still the issues of packet types and framing for the application to deal
with.

This method could conceivably be extended to other kinds of fallbacks.  For
each pair of before/after patterns, the Fallback() method performs a
sequence of actions to convert one into the other while leaving the bulk of
the settings the same.

I can see two possible approaches to generalize this: fallback tokens and
pre-message analysis.

Fallback tokens would be similar to message tokens, but instead define the
primitive actions to perform for a specific before/after pattern pair.  For
example, "clear-rs", "swap-roles", "keep-init-e", ... The downside of this
is the O(n^2) nature - each potential pair needs a fallback token sequence
defined.

The other approach is pre-message analysis: look at the arguments and
pre-messages for the new pattern.  Clear any key that is no longer
required, and check that required keys are already present in the
HandshakeState.  Each requirement is dealt with separately with a
keep/clear decision for each.

Pre-message analysis would allow fallbacks between lots of existing
patterns.  For example, it is possible to fallback from IK to NN by
throwing away all keys and starting again from scratch with no identity
information.  The value of this is debatable, so we may want to restrict
fallbacks to only those patterns that start with "<- e" and have matching
static key requirements [both IK and XXfallback have (s, rs) in their
arguments].

Long story short: I think fallbacks can be made more general by introducing
a formal Fallback() method into the HandshakeState with defined semantics
as to how the implementation interprets an invocation of Fallback().

Cheers,

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


More information about the Noise mailing list