RFC 8967
MAC Authentication for the Babel Routing Protocol
RFC 8967: MAC Authentication for the Babel Routing Protocol ๐
okay bestie, this one is an IETF document (the Internet Engineering Task Force, the crew that writes the rules for how the Internet talks to itself ๐ธ). It's RFC 8967, and it's a Standards Track doc, so it's an official spec, not just a vibe. It came out in January 2021 and was written by C. Dรด, W. Kolodziejak and J. Chroboczek, all from IRIF at University of Paris-Diderot ๐. The ISSN is 2070-1721. The title block says it obsoletes RFC 7298, which means the old version is retired and this one takes over ๐ซถ. It doesn't name anything it updates.
Abstract ๐
Okay so the big idea is that this doc describes a cryptographic authentication mechanism for the Babel routing protocol, and it has special features for avoiding replay attacks ๐. It also obsoletes RFC 7298, which we already covered, so no need to repeat ourselves ๐ .
Status of This Memo โจ
This is an Internet Standards Track document ๐.
It's a product of the Internet Engineering Task Force (IETF), so it represents the consensus of the IETF community ๐ซถ. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG) ๐. If you want the deets on Internet Standards, check out Section 2 of RFC 7841 ๐ง.
For the current status, any errata, and how to give feedback, go to https://www.rfc-editor.org/info/rfc8967 ๐.
Copyright Notice ๐ธ
Copyright (c) 2021 IETF Trust and the persons identified as the document authors. All rights reserved ๐.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the publication date. Please actually read these, bestie, because they explain your rights and restrictions for this doc ๐. Code Components pulled out of this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions. They also come without warranty, as described in the Simplified BSD License ๐.
Table of Contents ๐ฆ
1. Introduction
1.1. Applicability
1.2. Assumptions and Security Properties
1.3. Specification of Requirements
2. Conceptual Overview of the Protocol
3. Data Structures
3.1. The Interface Table
3.2. The Neighbour Table
4. Protocol Operation
4.1. MAC Computation
4.2. Packet Transmission
4.3. Packet Reception
4.4. Expiring Per-Neighbour State
5. Incremental Deployment and Key Rotation
6. Packet Format
6.1. MAC TLV
6.2. PC TLV
6.3. Challenge Request TLV
6.4. Challenge Reply TLV
7. Security Considerations
8. IANA Considerations
9. References
9.1. Normative References
9.2. Informational References
Acknowledgments
Authors' Addresses
1. Introduction โจ
Okay so by default, the Babel routing protocol [RFC8966] just trusts whatever info shows up in every UDP datagram it receives on the Babel port ๐ฌ. That's a big problem, because an attacker can redirect traffic to itself or to some other node in the network, and that causes all kinds of chaos ๐. Specifically, an attacker might:
- spoof a Babel packet and redirect traffic by announcing a route with a smaller metric, a larger sequence number, or a longer prefix ๐;
- spoof a malformed packet, which could make an implementation that isn't robust enough crash or mess with the rest of the network ๐;
- replay a Babel packet it captured earlier, which could redirect traffic or otherwise mess up the network ๐ญ.
Protecting a Babel network is tricky because Babel uses both unicast and multicast communication ๐. One approach, used notably by Babel over Datagram Transport Layer Security (DTLS) [RFC8968], is to use unicast for all the semantically significant communication, then wrap it in a standard unicast security protocol ๐. This doc goes the opposite way! We define a cryptographic extension to Babel that can protect both unicast and multicast traffic, so it needs very few changes to the core protocol ๐ฆ. And yes, this document obsoletes [RFC7298] ๐ .
1.1. Applicability
The protocol in this doc assumes that all interfaces on a given link are equally trusted and share a small set of symmetric keys (usually just one, and two during key rotation) ๐. It's inapplicable when asymmetric keying is needed, when the trust relationship is only partial, or when lots of trusted keys get provisioned on a single link at the same time ๐ซ.
It supports incremental deployment, which means an insecure Babel network can be made secure with no service interruption ๐ฑ. It also supports graceful key rotation, where the set of keys changes with no service interruption either ๐.
Also, this protocol doesn't need synchronised clocks, doesn't need persistently monotonic clocks, and doesn't need persistent storage beyond whatever is needed to store cryptographic keys ๐ง.
1.2. Assumptions and Security Properties
The protocol's correctness depends on these assumptions:
- the Message Authentication Code (MAC) in use is invulnerable to forgery, meaning an attacker can't produce a packet with a correct MAC without the secret key ๐;
- a node never generates the same index or nonce twice over the lifetime of a key ๐ โโ๏ธ.
The first assumption is about the MAC being used. The second one can be met by using a robust random number generator [RFC4086] and sufficiently large indices and nonces, by using a reliable hardware clock, or by rekeying often enough that collisions are unlikely ๐.
If those assumptions hold, the protocol in this document has these properties:
- it's invulnerable to spoofing: any Babel packet accepted as authentic is an exact copy of a packet originally sent by an authorised node ๐;
- locally to a single node, it's invulnerable to replay: if a node has already accepted a given packet, it will never again accept a copy of that packet or an earlier packet from the same sender ๐ก๏ธ;
- among different nodes, it's only vulnerable to immediate replay: if node A has accepted an authentic packet from C, then node B will only accept a copy of that packet if B has accepted an older packet from C, and B has received no later packet from C ๐.
Even though this protocol tries to soften the effects of a denial of service attack, it does not fully protect against those attacks ๐ค.
1.3. Specification of Requirements ๐
This is the part where the official rules live, so pay attention bestie ๐ง. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
2. Conceptual Overview of the Protocol ๐ฆ
Here's the vibe. When node B sends a Babel packet out through an interface that's configured for MAC cryptographic protection, it computes one or more MACs (one per key) and appends them to the packet ๐. When node A gets a packet over an interface that needs MAC cryptographic protection, it independently computes its own set of MACs and compares them to the ones appended to the packet. If nothing matches, the packet gets thrown out ๐๏ธ.
To guard against replay, B keeps a per-interface 32-bit integer called the "packet counter" (PC) ๐ข. Every time B sends a packet through the interface, it puts the current PC value inside the part of the packet that's protected by the MACs, then increases the PC by at least one โจ. When A gets the packet, it compares the PC value with the one in the previous packet it got from B. Unless the new one is strictly greater, the packet is discarded ๐ โโ๏ธ.
The PC mechanism alone isn't enough to stop replay, though. Picture a peer A that has no info about a peer B (maybe because it just rebooted) ๐. Say A gets a packet that's supposedly from B, carrying some PC. Since A knows nothing about B, it can't tell whether the packet is freshly made or a replay of an old one ๐ค.
So in that situation, peer A throws out the packet and challenges B to prove it knows the MAC key ๐ฅ. It sends a "Challenge Request", which is a TLV holding a unique nonce, a value that has never been used before and never will be again ๐ฒ. Peer B answers with a "Challenge Reply", a TLV containing a copy of the nonce A picked, inside a packet protected by MAC and carrying B's new PC value ๐. Since the nonce has never been used before, B's reply proves that B knows the MAC key and that the PC is fresh ๐.
This mechanism is safe against replay as long as B never resets its PC. In real life though, that's hard to guarantee, because persistent storage can fail, and hardware clocks, even when they exist, sometimes get reset ๐ฌ. Suppose B resets its PC to an earlier value and sends a packet with a previously used PC n. Peer A challenges B, B answers the challenge successfully, and A accepts the PC equal to n + 1. At that point, an attacker C can send a replayed packet with PC equal to n + 2, and A will accept it ๐.
So we need another mechanism to protect against this attack ๐ก๏ธ. In this protocol, every PC gets tagged with an "index", which is an arbitrary string of octets. Whenever B resets its PC, or whenever B doesn't know whether its PC has been reset, it picks an index it has never used before (either by drawing it randomly or by using a reliable hardware clock), and starts sending PCs with that index ๐. Whenever A notices that B has changed its index, A challenges B again ๐ฅฐ.
With this extra mechanism in place, the protocol is invulnerable to replay attacks (see Section 1.2) ๐.
3. Data Structures ๐ง
Every Babel node maintains a set of conceptual data structures, described in Section 3.2 of [RFC8966]. This protocol extends those data structures as follows ๐.
3.1. The Interface Table ๐
Every Babel node maintains an interface table, as described in Section 3.2.3 of [RFC8966]. Implementations of this protocol MUST allow each interface to be provisioned with a set of one or more MAC keys and the associated MAC algorithms (see Section 4.1 for suggested algorithms and Section 7 for suggested methods for key generation) ๐. To allow incremental deployment of this protocol (see Section 5), implementations SHOULD allow an interface to be configured in a mode where it takes part in the MAC authentication protocol but still accepts packets that aren't authenticated ๐ฑ.
This protocol adds two new pieces of data to each table entry for an interface where MAC authentication has been configured ๐ :
- a set of one or more MAC keys, each associated with a given MAC algorithm;
- a pair
(Index, PC), whereIndexis an arbitrary string of 0 to 32 octets, andPCis a 32-bit (4-octet) integer.
We say an index is fresh when it has never been used before with any of the keys currently configured on the interface ๐ธ. The Index field gets initialised to a fresh index, for example by drawing a random string of sufficient length (see Section 7 for suggested sizes), and the PC gets initialised to an arbitrary value (typically 0) โจ.
3.2. The Neighbour Table โจ
Every Babel node keeps a neighbour table, the one described in Section 3.2.4 of [RFC8966] ๐. This protocol adds two new goodies to each entry:
- a pair (Index, PC), where Index is a string of 0 to 32 octets, and PC is a 32-bit (4-octet) integer;
- a Nonce, which is an arbitrary string of 0 to 192 octets, and an associated challenge expiry timer.
The Index and PC start out undefined, and they're managed as described in Section 4.3 ๐. The Nonce and challenge expiry timer also start out undefined, and they get used as described in Section 4.3.1.1 ๐ฆ.
4. Protocol Operation ๐
4.1. MAC Computation ๐
A Babel node computes the MAC of a Babel packet like this. First it builds a pseudo-header that joins the MAC computation but never actually gets sent. If the packet is carried over IPv6, the pseudo-header looks like this:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| |
+ Src address +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Src port | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| |
+ +
| Dest address |
+ +
| |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Dest port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
If the packet is carried over IPv4, the pseudo-header looks like this instead ๐ธ:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Src address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Src port | Dest address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Dest port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Here's what each field means:
Src address: The source IP address of the packet.Src port: The source UDP port number of the packet.Dest address: The destination IP address of the packet.Src port: The destination UDP port number of the packet.
๐ Heads up: the original labels both of the port linesSrc port. I've kept that exactly as written, so the last entry is the destination port even though it saysSrc port.
Next, the node takes the pseudo-header and glues it onto the Babel packet. That means the packet header is included but the packet trailer isn't (from octet 0 inclusive up to (Body Length + 4) exclusive). Then it computes a MAC with one of the algorithms it implements. Every implementation MUST implement HMAC-SHA256 as defined in [RFC6234] and Section 2 of [RFC2104], SHOULD implement keyed BLAKE2s [RFC7693] with 128-bit (16-octet) digests, and MAY implement other MAC algorithms ๐ฅ.
4.2. Packet Transmission ๐งณ
A Babel node might hold onto TLVs for a small moment before sending them, so it can cram several into one packet, as long as it fits under the interface MTU (Section 4 of [RFC8966]) โจ. For an interface with MAC protection configured, the TLV aggregation logic MUST take into account the overhead due to PC TLVs (one in each packet) and MAC TLVs (one per configured key) ๐ .
Before sending a packet, do the following:
- a PC TLV containing the PC and Index associated with the outgoing interface MUST be appended to the packet body;
- the PC MUST be incremented by a strictly positive amount (typically just 1);
- if the PC overflows, a fresh index MUST be generated (as defined in Section 3.1);
- a node MUST NOT include multiple PC TLVs in a single packet;
- for each key configured on the interface, a MAC is computed as specified in Section 4.1 and stored in a MAC TLV that MUST be appended to the packet trailer (see Section 4.2 of [RFC8966]) ๐ซถ.
4.3. Packet Reception ๐ฌ
When a packet arrives on an interface that's set up for MAC protection, these steps run before the packet goes to normal processing:
- First, the receiver checks whether the trailer of the received packet carries at least one MAC TLV. If it doesn't, the packet MUST be immediately dropped and processing stops. Then, for each key configured on the receiving interface, the receiver computes the MAC of the packet. It then compares every generated MAC against every MAC included in the packet. If there's at least one match, the packet passes the MAC test. If there's none, the packet MUST be silently dropped and processing stops at this point ๐ญ. To avoid memory exhaustion attacks, an entry in the neighbour table MUST NOT be created before the MAC test has passed successfully. The MAC of the packet MUST NOT be computed for each MAC TLV contained in the packet, but only once for each configured key ๐.
- If an entry for the sender doesn't exist in the neighbour table, it MAY be created at this point. Or, alternatively, its creation can be delayed until a challenge needs to be sent (see below) ๐ง.
- The packet body then gets parsed a first time. This is the "preparse" phase, where the packet body is traversed and all TLVs are ignored except PC, Challenge Request, and Challenge Reply TLVs. When a PC TLV is found, the enclosed PC and Index get saved for later processing. If multiple PCs are found (which should not happen, see Section 4.2), only the first one is processed, and the remaining ones MUST be silently ignored. If a Challenge Request is encountered, a Challenge Reply MUST be scheduled, as described in Section 4.3.1.2. If a Challenge Reply is encountered, it's tested for validity as described in Section 4.3.1.3, and a note is made of the result of the test ๐.
- The preparse phase yields two pieces of data: the PC and Index from the first PC TLV, and a bit indicating whether the packet contains a successful Challenge Reply. If the packet doesn't contain a PC TLV, the packet MUST be dropped, and processing stops at this point ๐. If the packet contains a successful Challenge Reply, then the PC and Index contained in the PC TLV MUST be stored in the neighbour table entry corresponding to the sender (which already exists in this case), and the packet is accepted โ .
- Otherwise, if there's no entry in the neighbour table corresponding to the sender, or if such an entry exists but contains no Index, or if the Index it contains is different from the Index contained in the PC TLV, then a challenge MUST be sent as described in Section 4.3.1.1. The packet MUST be dropped, and processing stops at this stage ๐ซ.
- At this stage, the packet contains no successful Challenge Reply, and the Index contained in the PC TLV is equal to the Index in the neighbour table entry corresponding to the sender. The receiver compares the received PC with the PC contained in the neighbour table. If the received PC is smaller or equal than the PC contained in the neighbour table, the packet MUST be dropped and processing stops (no challenge is sent in this case, since the mismatch might be caused by harmless packet reordering on the link) ๐. Otherwise, the PC contained in the neighbour table entry is set to the received PC, and the packet is accepted ๐.
Here's the fun bit ๐ง . In the algorithm above, Challenge Requests are processed and challenges are sent before the (Index, PC) pair is verified against the neighbour table. That keeps the implementation simpler, since the node can just schedule outgoing requests as it walks the packet during the preparse phase. The catch is that it relies on the rate limiting described in Section 4.3.1.1 to avoid sending too many challenges in response to replayed packets. As an optimisation, a node MAY ignore all Challenge Requests contained in a packet except the last one. It MAY also ignore a Challenge Request when it's contained in a packet with an Index that matches the one in the neighbour table and a PC that is smaller or equal to the one contained in the neighbour table. Since it's still possible to replay a packet with an obsolete Index, the rate limiting described in Section 4.3.1.1 is required even if this optimisation is implemented ๐ค.
The same is true of Challenge Replies. However, since validating a Challenge Reply has minimal additional cost (it's just a bitwise comparison of two strings of octets), a similar optimisation for Challenge Replies is not worthwhile ๐ โโ๏ธ.
After the packet has been accepted, it's processed as normal, except that any PC, Challenge Request, and Challenge Reply TLVs it contains are silently ignored ๐.
4.3.1. Challenge Requests and Replies ๐ฆ
During the preparse stage, the receiver might encounter a mismatched Index, and it'll react by scheduling a Challenge Request. It might encounter a Challenge Request TLV, and it'll reply with a Challenge Reply TLV. Finally, it might encounter a Challenge Reply TLV, which it will attempt to match with a previously sent Challenge Request TLV, so it can update the neighbour table entry corresponding to the sender of the packet (this one's giving detective energy ๐ต๏ธโโ๏ธ).
4.3.1.1. Sending Challenges
Okay so, when a node runs into a mismatched Index during the preparse phase, it picks a nonce it has never used with any of the keys currently configured on the relevant interface ๐ . You can get one by drawing a sufficiently large random string of bytes, or by consulting a strictly monotonic hardware clock โฐ. Then it MUST store that nonce in the entry of the neighbour table for that neighbour (the entry might need to be created right then ๐), set the neighbour's challenge expiry timer to 30 seconds โจ, and send a Challenge Request TLV to the unicast address for that neighbour ๐ฆ.
A node MAY aggregate a Challenge Request with other TLVs. So if it's already got buffered TLVs headed to that neighbour's unicast address, it MAY tuck them into the same packet as the Challenge Request ๐. BUT, bestie, it MUST get the Challenge Request sent in a timely manner, because any packets received from that neighbour will be silently ignored until the challenge completes ๐.
A node MUST impose a rate limitation on the challenges it sends. The limit SHOULD default to one Challenge Request every 300 ms, and it MAY be configurable ๐ธ. This rate limiting does two jobs. First, a challenge might get triggered by a packet an attacker replayed, so this stops an attacker from making a node send a pile of challenges ๐ค. Second, it limits how many challenges get sent when there are multiple packets in flight from a single neighbour ๐ง.
4.3.1.2. Replying to Challenges
When a node encounters a Challenge Request during the preparse phase, it builds a Challenge Reply TLV by copying the Nonce from the Challenge Request into the Challenge Reply ๐. It MUST then send the Challenge Reply to the unicast address the Challenge Request came from. A challenge sent to a multicast address MUST be silently ignored, no exceptions ๐ โโ๏ธ.
Same energy as before: a node MAY aggregate a Challenge Reply with other TLVs. If it already has buffered TLVs for the unicast address of the Challenge Request's sender, it MAY send them in the same packet as the Challenge Reply ๐. However, it MUST arrange for the Challenge Reply to be sent in a timely manner (within a few seconds), and it SHOULD NOT send any other packets over the same interface before the Challenge Reply goes out. Those would just get dropped by the challenger, and nobody wants that ๐ญ.
Since a Challenge Reply might be caused by a replayed Challenge Request, a node MUST impose a rate limitation on the Challenge Replies it sends. The limit SHOULD default to one Challenge Reply for each peer every 300 ms, and it MAY be configurable ๐.
4.3.1.3. Receiving Challenge Replies
When a node encounters a Challenge Reply during the preparse phase, it checks the neighbour table entry for the neighbour that sent the Challenge Reply ๐. If no challenge is in progress (i.e., there's no Nonce stored in the neighbour table entry, or the challenge timer has expired), the Challenge Reply MUST be silently ignored, and the challenge has failed ๐.
Otherwise, the node compares the Nonce in the Challenge Reply with the Nonce stored in the neighbour table entry. If the two are equal (same length and same content), the challenge has succeeded, and the nonce stored in the neighbour table for this neighbour SHOULD be discarded ๐. If they don't match, the challenge has failed, and the nonce is NOT discarded. Wait, sorry, the nonce is not discarded, so keep it around ๐ซถ.
4.4. Expiring Per-Neighbour State
Okay, this one's a big deal. The per-neighbour (Index, PC) pair lives in the neighbour table, and it's normally thrown out when the neighbour table entry expires ๐๏ธ. Implementations MUST make sure an (Index, PC) pair gets discarded within a finite time since the last time a packet was accepted. In particular, unsuccessful challenges MUST NOT stop an (Index, PC) pair from being discarded for unbounded periods of time. Nobody gets to be a forever-stuck main character ๐.
There's a possible strategy for implementations that use a Hello history (Appendix A of [RFC8966]). You can discard the (Index, PC) pair whenever the Hello history becomes empty ๐. Another strategy is to use a timer that resets whenever a packet is accepted, and to discard the (Index, PC) pair whenever that timer expires โณ. If you go with the timer strategy, the timer SHOULD default to 5 minutes, and it MAY be configurable โฑ๏ธ.
5. Incremental Deployment and Key Rotation
Let's talk rollout, bestie ๐. For incremental deployment, the nodes in the network are first configured in a mode where packets are sent with authentication but not checked on reception. Once every node is configured to send authenticated packets, the nodes get reconfigured to reject unauthenticated packets ๐.
For key rotation, the new key gets added to all the nodes first ๐. Once that's done, both the old and the new key are sent in all packets, and packets are accepted if they're properly signed by either key. At that point, the old key gets removed ๐.
To support the procedures above, implementations of this protocol SHOULD support an interface configuration where packets are sent authenticated but received packets are accepted without verification. They SHOULD also let you change the set of keys tied to an interface without a restart ๐.
6. Packet Format
6.1. MAC TLV
Here's the MAC TLV, the one that carries the MAC of your packet ๐:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 16 | Length | MAC...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
The fields, bestie:
Type: set to 16 to indicate a MAC TLV.Length: the length of the body, in octets, not counting the Type and Length fields. It depends on the MAC algorithm being used ๐งฎ.MAC: the body holds the MAC of the packet, computed as described in Section 4.1.
This TLV is allowed in the packet trailer (see Section 4.2 of [RFC8966]), and it MUST be ignored if it shows up in the packet body ๐ โโ๏ธ.
6.2. PC TLV
The PC TLV is giving packet counter energy ๐ข:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 17 | Length | PC |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Index...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
The fields:
Type: set to 17 to indicate a PC TLV.Length: the length of the body, in octets, not counting the Type and Length fields.PC: the Packet Counter (PC), a 32-bit (4-octet) unsigned integer that goes up with every packet sent over this interface ๐. A fresh index (as defined in Section 3.1) MUST be generated whenever the PC overflows ๐.Index: the sender's Index, an opaque string of 0 to 32 octets ๐ชช.
Indices are limited to 32 octets. A node MUST NOT send a TLV with an index strictly larger than 32 octets, and a node MAY ignore a PC TLV whose index is strictly larger than 32 octets ๐ซ. Indices of length 0 are valid! If a node has reliable stable storage and the packet counter never overflows, then one index is all you need, and the length-0 value is the canonical choice ๐.
6.3. Challenge Request TLV
Next up, the Challenge Request TLV, where the nonce gets its moment โจ:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 18 | Length | Nonce...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
The fields:
Type: set to 18 to indicate a Challenge Request TLV.Length: the length of the body, in octets, not counting the Type and Length fields.Nonce: the nonce uniquely identifying the challenge, an opaque string of 0 to 192 octets ๐ฒ.
Nonces are limited to 192 octets. A node MUST NOT send a Challenge Request TLV with a nonce strictly larger than 192 octets, and a node MAY ignore a nonce strictly larger than 192 octets ๐. Nonces of length 0 are valid too. If a node has reliable stable storage, it may use a sequential counter for generating nonces, encoded in the minimum number of octets required, and the value 0 is then encoded as the string of length 0 ๐ง .
6.4. Challenge Reply TLV
Last but not least, the Challenge Reply TLV, the echo of the nonce ๐:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type = 19 | Length | Nonce...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
The fields:
Type: set to 19 to indicate a Challenge Reply TLV.Length: the length of the body, in octets, not counting the Type and Length fields.Nonce: a copy of the nonce contained in the corresponding Challenge Request ๐ช.
7. Security Considerations ๐โจ
okay bestie, this section is the serious one ๐ญ but I promise it's still iconic. This mechanism gives Babel some basic security. The scope is strictly limited, though: it only does authentication (we're assuming routing info isn't confidential, fr), it only supports symmetric keying, and it only lets every link use a small number of symmetric keys. If you need more, like confidentiality or asymmetric keying, go for a more feature-rich mechanism such as the one in [RFC8968] ๐
This mechanism leans on two assumptions, as covered in Section 1.2. The first is that the MAC is invulnerable to forgery (Section 1.1 of [RFC6039]). At the time of writing, HMAC-SHA256, which is mandatory to implement (Section 4.1), is believed to be safe against practical attacks ๐ก๏ธ
The second assumption is that indices and nonces are generated uniquely over the lifetime of a key used for MAC computation. To be precise, indices must be unique for a given (key, source) pair, and nonces must be unique for a given (key, source, destination) triple. You can get this in one of two ways: a cryptographically secure random number generator that makes indices and nonces with enough entropy (64-bit values are believed to be big enough for all practical applications), or a reliably monotonic hardware clock. If uniqueness can't be guaranteed, say because a hardware clock got reset, then rekeying is necessary ๐
The expiry mechanism mandated in Section 4.4 is required to stop an attacker from delaying an authentic packet forever ๐ซ If an attacker can delay delivery of a packet (for example, because it's sitting in a Layer 2 switch), the packet will still be accepted as long as the matching (Index, PC) pair is present at the receiver. And if the attacker can make that (Index, PC) pair stick around for arbitrary amounts of time (say, by repeatedly causing failed challenges), they can delay the packet by arbitrary amounts of time, even after the sender has left the network. That could let them redirect or blackhole traffic to destinations the sender previously advertised. Yikes, not a vibe ๐
This protocol exposes large numbers of packets and their MACs to an attacker who can capture packets, which makes it vulnerable to brute-force attacks. So keys must be chosen in a way that makes them hard to guess. Ideally they should be 32 octets long (for both HMAC-SHA256 and BLAKE2s) and chosen randomly. If, for some reason, you have to derive keys from a human-readable passphrase, it is recommended to use a key derivation function that hampers dictionary attacks, such as PBKDF2 [RFC8018], bcrypt [BCRYPT], or scrypt [RFC7914]. In that case, only the derived keys should be sent to the routers. The original passphrase itself should stay on the host used to generate the keys, like an administrator's secure laptop ๐งโ๐ป๐
It's probably not possible to be totally immune to denial of service (DoS) attacks in general, but this protocol has a bunch of mechanisms designed to mitigate them ๐ก๏ธโจ Specifically, receiving a packet with no correct MAC creates no local Babel state (Section 4.3). Receiving a replayed packet with a correct MAC, on the other hand, causes a challenge to be sent. That's somewhat mitigated by requiring that challenges be rate limited (Section 4.3.1.1) ๐ข
Receiving a replayed packet with an obsolete index causes an entry to be created in the neighbour table. At first sight, that makes the protocol susceptible to resource exhaustion attacks, similar to the familiar "TCP SYN Flooding" attack [RFC4987] ๐ฌ BUT the MAC computation includes the sender address (Section 4.1), so the amount of storage an attacker can force a node to use is limited by the number of distinct source addresses used with a single MAC key. See also Section 4 of [RFC8966], which mandates that the source address is a link-local IPv6 address or a local IPv4 address ๐
To make these resource exhaustion attacks less effective, implementations may use a separate table of uncompleted challenges, one that's separate from the neighbour table used by the core protocol. (The data structures described in Section 3.2 of [RFC8966] are conceptual, so any data structure that yields the same result may be used ๐ง ) Implementers might also consider the fact that the nonces included in Challenge Requests and Replies can be fairly large (up to 192 octets). In principle, that should allow encoding the per-challenge state as a secure "cookie" within the nonce itself ๐ช Just note that any such scheme will need to prevent cookie replay. No replay era ๐ โโ๏ธ
8. IANA Considerations ๐ธ
IANA has allocated the following values in the Babel TLV Types registry, and they're giving organized ๐๏ธ
+======+===================+===========+
| Type | Name | Reference |
+======+===================+===========+
| 16 | MAC | RFC 8967 |
+------+-------------------+-----------+
| 17 | PC | RFC 8967 |
+------+-------------------+-----------+
| 18 | Challenge Request | RFC 8967 |
+------+-------------------+-----------+
| 19 | Challenge Reply | RFC 8967 |
+------+-------------------+-----------+
Table 1
9. References ๐
9.1. Normative References
[RFC2104]Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, DOI 10.17487/RFC2104, February 1997, <https://www.rfc-editor.org/info/rfc2104>.[RFC2119]Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.[RFC6234]Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, May 2011, <https://www.rfc-editor.org/info/rfc6234>.[RFC7693]Saarinen, M-J., Ed. and J-P. Aumasson, "The BLAKE2 Cryptographic Hash and Message Authentication Code (MAC)", RFC 7693, DOI 10.17487/RFC7693, November 2015, <https://www.rfc-editor.org/info/rfc7693>.[RFC8174]Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.[RFC8966]Chroboczek, J. and D. Schinazi, "The Babel Routing Protocol", RFC 8966, DOI 10.17487/RFC8966, January 2021, <https://www.rfc-editor.org/info/rfc8966>.
9.2. Informational References
[BCRYPT]Niels, P. and D. Maziรจres, "A Future-Adaptable Password Scheme", Proceedings of the FREENIX Track: 1999 USENIX Annual Technical Conference, June 1999.[RFC4086]Eastlake 3rd, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, DOI 10.17487/RFC4086, June 2005, <https://www.rfc-editor.org/info/rfc4086>.[RFC4987]Eddy, W., "TCP SYN Flooding Attacks and Common Mitigations", RFC 4987, DOI 10.17487/RFC4987, August 2007, <https://www.rfc-editor.org/info/rfc4987>.[RFC6039]Manral, V., Bhatia, M., Jaeggli, J., and R. White, "Issues with Existing Cryptographic Protection Methods for Routing Protocols", RFC 6039, DOI 10.17487/RFC6039, October 2010, <https://www.rfc-editor.org/info/rfc6039>.[RFC7298]Ovsienko, D., "Babel Hashed Message Authentication Code (HMAC) Cryptographic Authentication", RFC 7298, DOI 10.17487/RFC7298, July 2014, <https://www.rfc-editor.org/info/rfc7298>.[RFC7914]Percival, C. and S. Josefsson, "The scrypt Password-Based Key Derivation Function", RFC 7914, DOI 10.17487/RFC7914, August 2016, <https://www.rfc-editor.org/info/rfc7914>.[RFC8018]Moriarty, K., Ed., Kaliski, B., and A. Rusch, "PKCS #5: Password-Based Cryptography Specification Version 2.1", RFC 8018, DOI 10.17487/RFC8018, January 2017, <https://www.rfc-editor.org/info/rfc8018>.[RFC8968]Dรฉcimo, A., Schinazi, D., and J. Chroboczek, "Babel Routing Protocol over Datagram Transport Layer Security", RFC 8968, DOI 10.17487/RFC8968, January 2021, <https://www.rfc-editor.org/info/rfc8968>.
Acknowledgments ๐
The protocol described in this document is based on the original HMAC protocol defined by Denis Ovsienko [RFC7298]. The use of a pseudo-header was suggested by David Schinazi. The use of an index to avoid replay was suggested by Markus Stenberg. The authors are also indebted to Antonin Dรฉcimo, Donald Eastlake, Toke Hรธiland-Jรธrgensen, Florian Horn, Benjamin Kaduk, Dave Taht, and Martin Vigoureux. Thank you all, you're literally the reason this works ๐ซถ
Authors' Addresses ๐บ๏ธ
Clara Dรด
IRIF, University of Paris-Diderot
75205 Paris CEDEX 13
France
Email: clarado_perso@yahoo.fr
Weronika Kolodziejak
IRIF, University of Paris-Diderot
75205 Paris CEDEX 13
France
Email: weronika.kolodziejak@gmail.com
Juliusz Chroboczek
IRIF, University of Paris-Diderot
Case 7014
75205 Paris CEDEX 13
France
Email: jch@irif.fr
๐ฆ where this page comes from
- ietf: rfc8967 2021-01
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms