draft-ietf-babel-hmac-05.txt | draft-ietf-babel-hmac-06.txt | |||
---|---|---|---|---|
Network Working Group C. Do | Network Working Group C. Do | |||
Internet-Draft W. Kolodziejak | Internet-Draft W. Kolodziejak | |||
Obsoletes: 7298 (if approved) J. Chroboczek | Obsoletes: 7298 (if approved) J. Chroboczek | |||
Updates: 6126bis (if approved) IRIF, University of Paris-Diderot | Intended status: Standards Track IRIF, University of Paris-Diderot | |||
Intended status: Standards Track June 7, 2019 | Expires: December 22, 2019 June 20, 2019 | |||
Expires: December 9, 2019 | ||||
HMAC authentication for the Babel routing protocol | HMAC authentication for the Babel routing protocol | |||
draft-ietf-babel-hmac-05 | draft-ietf-babel-hmac-06 | |||
Abstract | Abstract | |||
This document describes a cryptographic authentication mechanism for | This document describes a cryptographic authentication mechanism for | |||
the Babel routing protocol that has provisions for replay avoidance. | the Babel routing protocol that has provisions for replay avoidance. | |||
This document updates RFC 6126bis and obsoletes RFC 7298. | This document updates RFC 6126bis and obsoletes RFC 7298. | |||
Status of This Memo | Status of This Memo | |||
This Internet-Draft is submitted in full conformance with the | This Internet-Draft is submitted in full conformance with the | |||
skipping to change at page 1, line 34 ¶ | skipping to change at page 1, line 33 ¶ | |||
Internet-Drafts are working documents of the Internet Engineering | Internet-Drafts are working documents of the Internet Engineering | |||
Task Force (IETF). Note that other groups may also distribute | Task Force (IETF). Note that other groups may also distribute | |||
working documents as Internet-Drafts. The list of current Internet- | working documents as Internet-Drafts. The list of current Internet- | |||
Drafts is at https://datatracker.ietf.org/drafts/current/. | Drafts is at https://datatracker.ietf.org/drafts/current/. | |||
Internet-Drafts are draft documents valid for a maximum of six months | Internet-Drafts are draft documents valid for a maximum of six months | |||
and may be updated, replaced, or obsoleted by other documents at any | and may be updated, replaced, or obsoleted by other documents at any | |||
time. It is inappropriate to use Internet-Drafts as reference | time. It is inappropriate to use Internet-Drafts as reference | |||
material or to cite them other than as "work in progress." | material or to cite them other than as "work in progress." | |||
This Internet-Draft will expire on December 9, 2019. | This Internet-Draft will expire on December 22, 2019. | |||
Copyright Notice | Copyright Notice | |||
Copyright (c) 2019 IETF Trust and the persons identified as the | Copyright (c) 2019 IETF Trust and the persons identified as the | |||
document authors. All rights reserved. | document authors. All rights reserved. | |||
This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
Provisions Relating to IETF Documents | Provisions Relating to IETF Documents | |||
(https://trustee.ietf.org/license-info) in effect on the date of | (https://trustee.ietf.org/license-info) in effect on the date of | |||
publication of this document. Please review these documents | publication of this document. Please review these documents | |||
skipping to change at page 2, line 19 ¶ | skipping to change at page 2, line 19 ¶ | |||
1.2. Assumptions and security properties . . . . . . . . . . . 3 | 1.2. Assumptions and security properties . . . . . . . . . . . 3 | |||
1.3. Specification of Requirements . . . . . . . . . . . . . . 4 | 1.3. Specification of Requirements . . . . . . . . . . . . . . 4 | |||
2. Conceptual overview of the protocol . . . . . . . . . . . . . 4 | 2. Conceptual overview of the protocol . . . . . . . . . . . . . 4 | |||
3. Data Structures . . . . . . . . . . . . . . . . . . . . . . . 6 | 3. Data Structures . . . . . . . . . . . . . . . . . . . . . . . 6 | |||
3.1. The Interface Table . . . . . . . . . . . . . . . . . . . 6 | 3.1. The Interface Table . . . . . . . . . . . . . . . . . . . 6 | |||
3.2. The Neighbour table . . . . . . . . . . . . . . . . . . . 6 | 3.2. The Neighbour table . . . . . . . . . . . . . . . . . . . 6 | |||
4. Protocol Operation . . . . . . . . . . . . . . . . . . . . . 7 | 4. Protocol Operation . . . . . . . . . . . . . . . . . . . . . 7 | |||
4.1. HMAC computation . . . . . . . . . . . . . . . . . . . . 7 | 4.1. HMAC computation . . . . . . . . . . . . . . . . . . . . 7 | |||
4.2. Packet Transmission . . . . . . . . . . . . . . . . . . . 8 | 4.2. Packet Transmission . . . . . . . . . . . . . . . . . . . 8 | |||
4.3. Packet Reception . . . . . . . . . . . . . . . . . . . . 8 | 4.3. Packet Reception . . . . . . . . . . . . . . . . . . . . 8 | |||
4.4. Expiring per-neighbour state . . . . . . . . . . . . . . 11 | 4.4. Expiring per-neighbour state . . . . . . . . . . . . . . 12 | |||
5. Packet Format . . . . . . . . . . . . . . . . . . . . . . . . 12 | 5. Packet Format . . . . . . . . . . . . . . . . . . . . . . . . 12 | |||
5.1. HMAC TLV . . . . . . . . . . . . . . . . . . . . . . . . 12 | 5.1. HMAC TLV . . . . . . . . . . . . . . . . . . . . . . . . 12 | |||
5.2. PC TLV . . . . . . . . . . . . . . . . . . . . . . . . . 12 | 5.2. PC TLV . . . . . . . . . . . . . . . . . . . . . . . . . 13 | |||
5.3. Challenge Request TLV . . . . . . . . . . . . . . . . . . 13 | 5.3. Challenge Request TLV . . . . . . . . . . . . . . . . . . 13 | |||
5.4. Challenge Reply TLV . . . . . . . . . . . . . . . . . . . 13 | 5.4. Challenge Reply TLV . . . . . . . . . . . . . . . . . . . 14 | |||
6. Security Considerations . . . . . . . . . . . . . . . . . . . 14 | 6. Security Considerations . . . . . . . . . . . . . . . . . . . 14 | |||
7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 15 | 7. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 15 | |||
8. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 15 | 8. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 16 | |||
9. References . . . . . . . . . . . . . . . . . . . . . . . . . 15 | 9. References . . . . . . . . . . . . . . . . . . . . . . . . . 16 | |||
9.1. Normative References . . . . . . . . . . . . . . . . . . 15 | 9.1. Normative References . . . . . . . . . . . . . . . . . . 16 | |||
9.2. Informational References . . . . . . . . . . . . . . . . 16 | 9.2. Informational References . . . . . . . . . . . . . . . . 17 | |||
Appendix A. Incremental deployment and key rotation . . . . . . 16 | Appendix A. Incremental deployment and key rotation . . . . . . 17 | |||
Appendix B. Changes from previous versions . . . . . . . . . . . 17 | Appendix B. Changes from previous versions . . . . . . . . . . . 18 | |||
B.1. Changes since draft-ietf-babel-hmac-00 . . . . . . . . . 17 | B.1. Changes since draft-ietf-babel-hmac-00 . . . . . . . . . 18 | |||
B.2. Changes since draft-ietf-babel-hmac-01 . . . . . . . . . 17 | B.2. Changes since draft-ietf-babel-hmac-01 . . . . . . . . . 18 | |||
B.3. Changes since draft-ietf-babel-hmac-02 . . . . . . . . . 17 | B.3. Changes since draft-ietf-babel-hmac-02 . . . . . . . . . 18 | |||
B.4. Changes since draft-ietf-babel-hmac-03 . . . . . . . . . 18 | B.4. Changes since draft-ietf-babel-hmac-03 . . . . . . . . . 18 | |||
B.5. Changes since draft-ietf-babel-hmac-04 . . . . . . . . . 18 | B.5. Changes since draft-ietf-babel-hmac-04 . . . . . . . . . 19 | |||
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 18 | B.6. Changes since draft-ietf-babel-hmac-05 . . . . . . . . . 19 | |||
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 19 | ||||
1. Introduction | 1. Introduction | |||
By default, the Babel routing protocol trusts the information | By default, the Babel routing protocol trusts the information | |||
contained in every UDP datagram that it receives on the Babel port. | contained in every UDP datagram that it receives on the Babel port. | |||
An attacker can redirect traffic to itself or to a different node in | An attacker can redirect traffic to itself or to a different node in | |||
the network, causing a variety of potential issues. In particular, | the network, causing a variety of potential issues. In particular, | |||
an attacker might: | an attacker might: | |||
o spoof a Babel packet, and redirect traffic by announcing a smaller | o spoof a Babel packet, and redirect traffic by announcing a smaller | |||
skipping to change at page 8, line 37 ¶ | skipping to change at page 8, line 37 ¶ | |||
HMAC protection is configured, the TLV aggregation logic MUST take | HMAC protection is configured, the TLV aggregation logic MUST take | |||
into account the overhead due to PC TLVs (one in each packet) and | into account the overhead due to PC TLVs (one in each packet) and | |||
HMAC TLVs (one per configured key). | HMAC TLVs (one per configured key). | |||
Before sending a packet, the following actions are performed: | Before sending a packet, the following actions are performed: | |||
o a PC TLV containing the PC and Index associated with the outgoing | o a PC TLV containing the PC and Index associated with the outgoing | |||
interface MUST be appended to the packet body; the PC MUST be | interface MUST be appended to the packet body; the PC MUST be | |||
incremented by a strictly positive amount (typically just 1); if | incremented by a strictly positive amount (typically just 1); if | |||
the PC overflows, a fresh index MUST be generated (as defined in | the PC overflows, a fresh index MUST be generated (as defined in | |||
Section 3.1); | Section 3.1); a node MUST NOT include multiple PC TLVs in a single | |||
packet; | ||||
o for each key configured on the interface, an HMAC is computed as | o for each key configured on the interface, an HMAC is computed as | |||
specified in Section 4.1 above, and stored in an HMAC TLV that | specified in Section 4.1 above, and stored in an HMAC TLV that | |||
MUST be appended to the packet trailer (see Section 4.2 of | MUST be appended to the packet trailer (see Section 4.2 of | |||
[RFC6126bis]). | [RFC6126bis]). | |||
4.3. Packet Reception | 4.3. Packet Reception | |||
When a packet is received on an interface that is configured for HMAC | When a packet is received on an interface that is configured for HMAC | |||
protection, the following steps are performed before the packet is | protection, the following steps are performed before the packet is | |||
skipping to change at page 9, line 20 ¶ | skipping to change at page 9, line 23 ¶ | |||
to avoid memory exhaustion attacks, an entry in the Neighbour | to avoid memory exhaustion attacks, an entry in the Neighbour | |||
Table MUST NOT be created before the HMAC test has passed | Table MUST NOT be created before the HMAC test has passed | |||
successfully. The HMAC of the packet MUST NOT be computed for | successfully. The HMAC of the packet MUST NOT be computed for | |||
each HMAC TLV contained in the packet, but only once for each | each HMAC TLV contained in the packet, but only once for each | |||
configured key. | configured key. | |||
o The packet body is then parsed a first time. During this | o The packet body is then parsed a first time. During this | |||
"preparse" phase, the packet body is traversed and all TLVs are | "preparse" phase, the packet body is traversed and all TLVs are | |||
ignored except PC TLVs, Challenge Requests and Challenge Replies. | ignored except PC TLVs, Challenge Requests and Challenge Replies. | |||
When a PC TLV is encountered, the enclosed PC and Index are saved | When a PC TLV is encountered, the enclosed PC and Index are saved | |||
for later processing; if multiple PCs are found, only the first | for later processing; if multiple PCs are found (which should not | |||
one is processed, the remaining ones MUST be silently ignored. If | happen, see Section 4.2 above), only the first one is processed, | |||
a Challenge Request is encountered, a Challenge Reply MUST be | the remaining ones MUST be silently ignored. If a Challenge | |||
scheduled, as described in Section 4.3.1.2. If a Challenge Reply | Request is encountered, a Challenge Reply MUST be scheduled, as | |||
is encountered, it is tested for validity as described in | described in Section 4.3.1.2. If a Challenge Reply is | |||
encountered, it is tested for validity as described in | ||||
Section 4.3.1.3 and a note is made of the result of the test. | Section 4.3.1.3 and a note is made of the result of the test. | |||
o The preparse phase above has yielded two pieces of data: the PC | o The preparse phase above has yielded two pieces of data: the PC | |||
and Index from the first PC TLV, and a bit indicating whether the | and Index from the first PC TLV, and a bit indicating whether the | |||
packet contains a successful Challenge Reply. If the packet does | packet contains a successful Challenge Reply. If the packet does | |||
not contain a PC TLV, the packet MUST be dropped and processing | not contain a PC TLV, the packet MUST be dropped and processing | |||
stops at this point. If the packet contains a successful | stops at this point. If the packet contains a successful | |||
Challenge Reply, then the PC and Index contained in the PC TLV | Challenge Reply, then the PC and Index contained in the PC TLV | |||
MUST be stored in the Neighbour Table entry corresponding to the | MUST be stored in the Neighbour Table entry corresponding to the | |||
sender (which may need to be created at this stage), and the | sender (which may need to be created at this stage), and the | |||
skipping to change at page 10, line 7 ¶ | skipping to change at page 10, line 10 ¶ | |||
and the Index contained in the PC TLV is equal to the Index in the | and the Index contained in the PC TLV is equal to the Index in the | |||
Neighbour Table entry corresponding to the sender. The receiver | Neighbour Table entry corresponding to the sender. The receiver | |||
compares the received PC with the PC contained in the Neighbour | compares the received PC with the PC contained in the Neighbour | |||
Table; if the received PC is smaller or equal than the PC | Table; if the received PC is smaller or equal than the PC | |||
contained in the Neighbour Table, the packet MUST be dropped and | contained in the Neighbour Table, the packet MUST be dropped and | |||
processing stops (no challenge is sent in this case, since the | processing stops (no challenge is sent in this case, since the | |||
mismatch might be caused by harmless packet reordering on the | mismatch might be caused by harmless packet reordering on the | |||
link). Otherwise, the PC contained in the Neighbour Table entry | link). Otherwise, the PC contained in the Neighbour Table entry | |||
is set to the received PC, and the packet is accepted. | is set to the received PC, and the packet is accepted. | |||
In the algorithm described above, challenge requests are processed | ||||
and challenges are sent before the PC/Index pair is verified against | ||||
the neighbour table. This simplifies the implementation somewhat | ||||
(the node may simply schedule outgoing requests as it walks the | ||||
packet during the preparse phase), but 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, and | ||||
it MAY ignore a challenge request in the case where it it 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 is 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 is extremely cheap (it's just a bitwise comparison of | ||||
two strings of octets), a similar optimisation for challenge replies | ||||
is not worthwile. | ||||
After the packet has been accepted, it is processed as normal, except | After the packet has been accepted, it is processed as normal, except | |||
that any PC, Challenge Request and Challenge Reply TLVs that it | that any PC, Challenge Request and Challenge Reply TLVs that it | |||
contains are silently ignored. | contains are silently ignored. | |||
4.3.1. Challenge Requests and Replies | 4.3.1. Challenge Requests and Replies | |||
During the preparse stage, the receiver might encounter a mismatched | During the preparse stage, the receiver might encounter a mismatched | |||
Index, to which it will react by scheduling a Challenge Request. It | Index, to which it will react by scheduling a Challenge Request. It | |||
might encounter a Challenge Request TLV, to which it will reply with | might encounter a Challenge Request TLV, to which it will reply with | |||
a Challenge Reply TLV. Finally, it might encounter a Challenge Reply | a Challenge Reply TLV. Finally, it might encounter a Challenge Reply | |||
skipping to change at page 13, line 7 ¶ | skipping to change at page 13, line 31 ¶ | |||
PC The Packet Counter (PC), a 32-bit (4 octet) unsigned | PC The Packet Counter (PC), a 32-bit (4 octet) unsigned | |||
integer which is increased with every packet sent over this | integer which is increased with every packet sent over this | |||
interface. A fresh index (as defined in Section 3.1) MUST | interface. A fresh index (as defined in Section 3.1) MUST | |||
be generated whenever the PC overflows. | be generated whenever the PC overflows. | |||
Index The sender's Index, an opaque string of 0 to 32 octets. | Index The sender's Index, an opaque string of 0 to 32 octets. | |||
Indices are limited to a size of 32 octets: a node MUST NOT send a | Indices are limited to a size of 32 octets: a node MUST NOT send a | |||
TLV with an index of size strictly larger than 32 octets, and a node | TLV with an index of size strictly larger than 32 octets, and a node | |||
MAY ignore a PC TLV with an index of size strictly larger than 32 | MAY ignore a PC TLV with an index of length strictly larger than 32 | |||
octets. | octets. Indices of length 0 are valid: if a node has reliable stable | |||
storage and the packet counter never overflows, then only one index | ||||
is necessary, and the value of length 0 is the canonical choice. | ||||
5.3. Challenge Request TLV | 5.3. Challenge Request TLV | |||
0 1 2 3 | 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 | 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... | | Type = 18 | Length | Nonce... | |||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- | |||
Fields : | Fields : | |||
skipping to change at page 13, line 31 ¶ | skipping to change at page 14, line 8 ¶ | |||
Length The length of the body, in octets, exclusive of the Type | Length The length of the body, in octets, exclusive of the Type | |||
and Length fields. | and Length fields. | |||
Nonce The nonce uniquely identifying the challenge, an opaque | Nonce The nonce uniquely identifying the challenge, an opaque | |||
string of 0 to 192 octets. | string of 0 to 192 octets. | |||
Nonces are limited to a size of 192 octets: a node MUST NOT send a | Nonces are limited to a size of 192 octets: a node MUST NOT send a | |||
Challenge Request TLV with a nonce of size strictly larger than 192 | Challenge Request TLV with a nonce of size strictly larger than 192 | |||
octets, and a node MAY ignore a nonce that is of size strictly larger | octets, and a node MAY ignore a nonce that is of size strictly larger | |||
than 192 octets. | than 192 octets. Nonces of length 0 are valid: if a node has | |||
reliable stable storage, then it may use a sequential counter for | ||||
generating nonces which get encoded in the minumum number of octets | ||||
required; the value 0 is then encoded as the string of length 0. | ||||
5.4. Challenge Reply TLV | 5.4. Challenge Reply TLV | |||
0 1 2 3 | 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 | 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... | | Type = 19 | Length | Nonce... | |||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- | |||
Fields : | Fields : | |||
skipping to change at page 15, line 36 ¶ | skipping to change at page 16, line 24 ¶ | |||
| 19 | Challenge Reply | this document | | | 19 | Challenge Reply | this document | | |||
+------+-------------------+---------------+ | +------+-------------------+---------------+ | |||
8. Acknowledgments | 8. Acknowledgments | |||
The protocol described in this document is based on the original HMAC | The protocol described in this document is based on the original HMAC | |||
protocol defined by Denis Ovsienko [RFC7298]. The use of a pseudo- | protocol defined by Denis Ovsienko [RFC7298]. The use of a pseudo- | |||
header was suggested by David Schinazi. The use of an index to avoid | header was suggested by David Schinazi. The use of an index to avoid | |||
replay was suggested by Markus Stenberg. The authors are also | replay was suggested by Markus Stenberg. The authors are also | |||
indebted to Donald Eastlake, Toke Hoiland-Jorgensen, Florian Horn, | indebted to Donald Eastlake, Toke Hoiland-Jorgensen, Florian Horn, | |||
and Dave Taht. | Dave Taht and Martin Vigoureux. | |||
9. References | 9. References | |||
9.1. Normative References | 9.1. Normative References | |||
[RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed- | [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed- | |||
Hashing for Message Authentication", RFC 2104, | Hashing for Message Authentication", RFC 2104, | |||
DOI 10.17487/RFC2104, February 1997, | DOI 10.17487/RFC2104, February 1997, | |||
<https://www.rfc-editor.org/info/rfc2104>. | <https://www.rfc-editor.org/info/rfc2104>. | |||
skipping to change at page 18, line 18 ¶ | skipping to change at page 19, line 7 ¶ | |||
o Fixed an issue with packets that contain a successful challenge | o Fixed an issue with packets that contain a successful challenge | |||
reply: they should be accepted before checking the PC value. | reply: they should be accepted before checking the PC value. | |||
o Clarified that keys are the exact value of the HMAC hash size, and | o Clarified that keys are the exact value of the HMAC hash size, and | |||
not subject to preprocessing; this makes management more | not subject to preprocessing; this makes management more | |||
deterministic. | deterministic. | |||
B.5. Changes since draft-ietf-babel-hmac-04 | B.5. Changes since draft-ietf-babel-hmac-04 | |||
Use normative language in more places. | o Use normative language in more places. | |||
B.6. Changes since draft-ietf-babel-hmac-05 | ||||
o Do not update RFC 6126bis. | ||||
o Clarify that indices and nonces of length 0 are valid. | ||||
o Clarify that multiple PC TLVs in a single packet are not allowed. | ||||
o Allow discarding challenge requests when they carry an old PC. | ||||
Authors' Addresses | Authors' Addresses | |||
Clara Do | Clara Do | |||
IRIF, University of Paris-Diderot | IRIF, University of Paris-Diderot | |||
75205 Paris Cedex 13 | 75205 Paris Cedex 13 | |||
France | France | |||
Email: clarado_perso@yahoo.fr | Email: clarado_perso@yahoo.fr | |||
End of changes. 15 change blocks. | ||||
30 lines changed or deleted | 67 lines changed or added | |||
This html diff was produced by rfcdiff 1.47. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |