Subject: [babel] Reworked implementation of HMAC authentication

From: Juliusz Chroboczek <[email-masked]>
Date: Sat, 09 Mar 2019 00:59:53 +0100

Hi,

I've finally gotten my act together, and reworked Clara's and Weronika's
implementation of Babel-HMAC.  You can get the code by doing

    git clone -b hmac --recurse-submodules https://github.com/jech/babeld

While this code is almost completely untested, it is meant to eventually
implement the protocol described in

    https://tools.ietf.org/html/draft-ietf-babel-hmac

Known issues:

  - no interop testing has been done yet;
  - we create a neighbour entry too early, which makes us vulnerable to DoS;
  - we compute HMAC for each TLV, rather than just once for the whole
    packet, which, again, makes us vulnerable to DoS;
  - we don't timeout neighbours properly, which makes us vulnerable to
    delayed packets;
  - we only support sending one HMAC (receiving multiple HMACs should
    work, but for obvious reasons it's untested);
  - we don't support key rotation.

You can test this code by saying something like:

    babeld -C 'key id test type sha256 value ebf49e6fbc6414aa567e30891846e96963cdda73289b9cd245d67ff9d281abc0' -C 'interface eth0 hmac test'

The "key" stanza defines a key of type sha256, with the value given as
a 32 byte-long hex key. The "interface" stanza enables the key on the
interface eth0.

In addition to "type sha256", we support "type blake2s", which requires
a 16 byte-long key.

-- Juliusz

---

From: Dave Taht <[email-masked]>
Date: Fri, 8 Mar 2019 16:07:13 -0800

>     git clone -b hmac --recurse-submodules https://github.com/jech/babeld

Yea! I'll try to clear some time to play with this before ietf. No
promises though, I'm frantically busy on other stuff.

>     packet, which, again, makes us vulnerable to DoS;

ugh.

>   - we don't support key rotation.

Sigh.

Still, happy to see it! Thanks very much!

> _______________________________________________
> Babel-users mailing list
> [email-masked]
> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/babel-users

-- 

Dave Täht
CTO, TekLibre, LLC
http://www.teklibre.com
Tel: 1-831-205-9740

---

From: Juliusz Chroboczek <[email-masked]>
Date: Sat, 09 Mar 2019 02:37:45 +0100

> ugh.

Don't worry, it's an easy fix.

> Sigh.

The data structures are designed so it'll be easy, the problem is
designing an understandable user interface.  Given the following interface
declaration:

    interface eth0 hmac key1

what does the following mean?

    interface eth0 hmac key2

Does it add key2 to the set of keys associated with eth0, or does it
override the current value?  I'm afraid that either will cause confusion.

I'm considering keeping the set of keys associated with an interface
static, and allowing key rotation by redefining existing keys.  So you'd
say

    interface eth0 hmac key1 hmac key2
    key id key1 type sha256 value ...
    key id key2 type none

and do key rotation by saying

    key id key2 type sha256 value ...
    key id key1 type none

I'll look at Barbara's information model, the must be some insights there.

-- Juliusz

---

From: "STARK, BARBARA H" <[email-masked]>
Date: Mon, 11 Mar 2019 13:13:37 +0000

> The data structures are designed so it'll be easy, the problem is designing an
> understandable user interface.  Given the following interface
> declaration:
> 
>     interface eth0 hmac key1
> 
> Does it add key2 to the set of keys associated with eth0, or does it override
> the current value?  I'm afraid that either will cause confusion.
> 
> I'm considering keeping the set of keys associated with an interface static,
> and allowing key rotation by redefining existing keys.  So you'd say
> 

Oh, no. That doesn't sound good. I try to stay out-of-sight and not in sight. I don't want to incite rebellion.

The info model has the flags that say whether or not a key is used for signing (or validating). A key can be "disabled" by setting the flags to "false" to indicate it's not used for anything. And keys can be added/deleted.
There is still an open question about design of the hmac and dtls parts of the model, as to whether an interface can be listed in multiple instances and keys would be additive for an interface across all such instances. Which is to say, some change is still possible.
Barbara

---

From: Juliusz Chroboczek <[email-masked]>
Date: Tue, 12 Mar 2019 01:34:26 +0100

> The info model has the flags that say whether or not a key is used for
> signing (or validating). A key can be "disabled" by setting the flags to
> "false" to indicate it's not used for anything. And keys can be added/deleted.

There's a number of indirections in the information model, and I'm not
sure whether I should be mirrorring that in the config file format:

  interface -> security-obj -> credential-obj -> cred

The model used by babeld's config file is way simpler:

  interface -> key

There are two questions that I need to think about (and any contributions
from y'all will be considered carefully before they are discarded):

  1. How much flexibility am I giving up by having just one level of
     indirection instead of three ?

  2. What's the right syntax for dynamically updating the credentials that
     is both powerful and understandable by the smart but overworked system
     administrator?

Concerning point (1), there are no further constraints.  Concerning point (2),
I insist on (a) the syntax being LL(1), and (b) any statement used for
dynamic reconfiguration is also valid in the static configuration file
(but not necessarily the other way around).

I shall grok further, until fullness comes.

-- Juliusz

---

From: Toke Høiland-Jørgensen <[email-masked]>
Date: Tue, 12 Mar 2019 10:00:24 +0100

>      indirection instead of three ?

FWIW, Bird will also use the simpler mechanism (a key is part of the
iface config). But the Bird reload semantics is only "re-read the entire
config", so doesn't have the same dynamic reconfig issues...

-Toke

---

From: Juliusz Chroboczek <[email-masked]>
Date: Tue, 12 Mar 2019 13:20:26 +0100

> iface config).

How do you share a key between interfaces?

---

From: Toke Høiland-Jørgensen <[email-masked]>
Date: Tue, 12 Mar 2019 13:45:43 +0100

> How do you share a key between interfaces?

You can set them globally or per-interface (interface options in general
are just overrides of the global per-protocol options). I'm not sure
what happens if you set both, actually.

If you want to, say, use the same key on two interfaces, but not a
third, you'd have to copy the config line to both interface configs.

There are also a bunch of per-key options, such as active times and an
ID. See the 'password' entry here:
https://bird.network.cz/?get_doc&v=20&f=bird-3.html#ss3.3

I haven't played around with this extensively, but am planning to do
that once I get around to updating the implementation to the latest
version of the draft...

-Toke

---

From: Mahesh Jethanandani <[email-masked]>
Date: Tue, 12 Mar 2019 15:44:54 -0700

I believe I had brought this up before. There is a YANG keychain model (RFC 8177) that might help provide some guidance here.

But before we get there, there is one clarification. There is no babel-security-obj any more. The current tree diagram for babel is as follows ...

   +-- babel-information
      +-- babel-implementation-version
      +-- babel-enable
      +-- router-id
      +-- babel-supported-link-types
      +-- self-seqno
      +-- babel-metric-comp-algorithms
      +-- babel-security-supported
      +-- babel-hmac-enable
      +-- babel-hmac-algorithms
      +-- babel-dtls-enable
      +-- babel-dtls-cert-types
      +-- babel-stats-enable
      +-- babel-stats-reset
      +-- babel-constants

… with security configured by whether HMAC is enabled or not, and whether DTLS is enabled or not. And there is no reference to a per-interface configuration. So, currently, as defined, both HMAC and DTLS are global. Based on what I am reading here, it appears that is not what was intended. So I will join Barbara in saying we do not want to cause a rebellion by suggesting something totally radical here :-)

BTW, do we want to maintain the ability to have a global config for security such that it applies to all interfaces? 

Back to the question at hand, and the guidance that the keychain model provides for symmetric keys used by routing protocols. Again this is the YANG tree diagram for keychains.

   +--rw key-chains
      +--rw key-chain* [name]
      |  +--rw name                       string
      |  +--rw description?               string
      |  +--rw accept-tolerance {accept-tolerance}?
      |  |  +--rw duration?   uint32
      |  +--ro last-modified-timestamp?   yang:date-and-time
      |  +--rw key* [key-id]
      |     +--rw key-id                    uint64
      |     +--rw lifetime
      |     |  +--rw (lifetime)?
      |     |     +--:(send-and-accept-lifetime)
      |     |     |  +--rw send-accept-lifetime
      |     |     |     +--rw (lifetime)?
      |     |     |        +--:(always)
      |     |     |        |  +--rw always?            empty
      |     |     |        +--:(start-end-time)
      |     |     |           +--rw start-date-time?
      |     |     |           |       yang:date-and-time
      |     |     |           +--rw (end-time)?
      |     |     |              +--:(infinite)
      |     |     |              |  +--rw no-end-time?       empty
      |     |     |              +--:(duration)
      |     |     |              |  +--rw duration?          uint32
      |     |     |              +--:(end-date-time)
      |     |     |                 +--rw end-date-time?
      |     |     |                         yang:date-and-time

What this implies is that key-chains are declared globally, and each key-chain, indexed by a name, defines a bunch of keys, referenced by a key-id, each of which have their own lifetime, both on the send and receive side.

If the desire is to have a key per interface, that interface would then have a reference to one of the key-chains. Ideally, a separate key rotation protocol decides which key is used out of the chain. But since we never quite got around to defining that protocol in KARP, each implementation is left to decide how to pick the key. Sharing of keys between interfaces can be had by having both interfaces refer to the same keychain. 

Few things would have to happen to the existing documents in Babel. The IM should be updated to provide a reference from the interface to the babel-hmac-obj/babel-dtls-obj, and add a reference to a keychain instead of a key itself. If a global security configuration is desired, where every flag gets the same security configuration, then we will need a global flag to state so. Secondly, in the YANG model for Babel, we augment the keychain model to support ability to add/delete/rotate/synchronize keys separately, and update the data model to mirror any changes we make to the IM.

Cheers.

> On Mar 12, 2019, at 5:45 AM, Toke Høiland-Jørgensen <toke=[email-masked]> wrote:
> 
> babel mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/babel

Mahesh Jethanandani
[email-masked]

---

From: Juliusz Chroboczek <[email-masked]>
Date: Wed, 13 Mar 2019 00:10:23 +0100

> So, currently, as defined, both HMAC and DTLS are global.  Based on what
> I am reading here, it appears that is not what was intended. So I will
> join Barbara in saying we do not want to cause a rebellion by suggesting
> something totally radical here :-)

> such that it applies to all interfaces?

What happens when a new interface is added to an existing configuration?
With a global configuration, it is automatically and hopefully atomically
configured with the global configuration.  Without a global configuration,
the new interface might be created with a default security configuration,
which might (or might not) constitute a security hole.

Both of our security protocols have two properties:

 1. the ability to have multiple credentials configured on a single
    interface at the same time;
 2. the ability to have different sets of credentials on different
    interfaces.

The first property is what allows incremental key rotation (add the new
key, which might involve climbing trees, then remove the old key, which,
again, might involve visiting your local hospital's emergency room after
you fell off from a ladder).

The second property is what enables interconnection of routing domains
managed by different administrative entities -- you probably don't want to
share your domain's private keys, so the peering link would most probably
use a different set of credentials.  This is particularly critical for
HMAC, which only supports symmetric keying.

I think that these are important properties, and they should be reflected
in the YANG model.

-- Juliusz

---

From: Mahesh Jethanandani <[email-masked]>
Date: Wed, 13 Mar 2019 16:26:37 -0700

> On Mar 12, 2019, at 4:10 PM, Juliusz Chroboczek <[email-masked]> wrote:
> 

Agree. Will keep the global configuration option. Requires an update to the IM and DM.

> you fell off from a ladder).

This capability is supported by the keychain model.

> HMAC, which only supports symmetric keying.

Hmm. Can the two domains use certs/asymmetric keys to send the symmetric key obtained by one end, in a secure fashion to the partner domain? 

Mahesh Jethanandani
[email-masked]

---

From: Juliusz Chroboczek <[email-masked]>
Date: Tue, 19 Mar 2019 19:58:02 +0100

> Hmm. Can the two domains use certs/asymmetric keys to send the symmetric
> key obtained by one end, in a secure fashion to the partner domain?

Sure.  One could for example copy the key over ssh, or use a dedicated
key agreement protocol.

But that's obviously outside the scope of the Babel protocol.

-- Juliusz