RFC 9140
Nimble Out-of-Band Authentication for EAP (EAP-NOOB)
RFC 9140: Nimble Out-of-Band Authentication for EAP (EAP-NOOB) ๐
The receipts first, bestie ๐งพ
- RFC number: 9140, Standards Track, with ISSN 2070-1721
- Date: December 2021
- Authors: T. Aura (Aalto University), M. Sethi (Ericsson), and A. Peltonen (Aalto University)
- Obsoletes / updates: the title block doesn't list anything it obsoletes or updates, so this is a standalone spec ๐ธ
Abstract โจ
okay so EAP (the Extensible Authentication Protocol) already supports a bunch of different ways to authenticate, and this doc adds a new one called EAP-NOOB ๐ฆ It's for nimble out-of-band (OOB) authentication and key derivation, and it's built for bootstrapping all kinds of Internet-of-Things (IoT) devices that come with zero preconfigured credentials. The trick is a user-assisted, one-directional OOB message sent between the peer device and the authentication server, which is how the in-band key exchange gets authenticated ๐ The device has to have a nonnetwork input or output interface, like a display, microphone, speaker, or blinking light, that can send or receive dynamically generated messages tens of bytes long ๐
Status of This Memo โจ
This is an Internet Standards Track document ๐
This document is a product of the Internet Engineering Task Force (IETF). 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 more on Internet Standards, check Section 2 of RFC 7841 ๐
Info about the current status of this document, any errata, and how to give feedback lives at https://www.rfc-editor.org/info/rfc9140 ๐
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 stood on the publication date. Please actually read these, because they spell out your rights and restrictions for this doc ๐ Code Components pulled out of this document must include Revised BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, same as the Revised BSD License says ๐ซถ
Table of Contents ๐ง
1. Introduction
2. Terminology
3. EAP-NOOB Method
3.1. Protocol Overview
3.2. Protocol Messages and Sequences
3.2.1. Common Handshake in All EAP-NOOB Exchanges
3.2.2. Initial Exchange
3.2.3. OOB Step
3.2.4. Completion Exchange
3.2.5. Waiting Exchange
3.3. Protocol Data Fields
3.3.1. Peer Identifier and NAI
3.3.2. Message Data Fields
3.4. Fast Reconnect and Rekeying
3.4.1. Persistent EAP-NOOB Association
3.4.2. Reconnect Exchange
3.4.3. User Reset
3.5. Key Derivation
3.6. Error Handling
3.6.1. Invalid Messages
3.6.2. Unwanted Peer
3.6.3. State Mismatch
3.6.4. Negotiation Failure
3.6.5. Cryptographic Verification Failure
3.6.6. Application-Specific Failure
4. ServerInfo and PeerInfo Contents
5. IANA Considerations
5.1. Cryptosuites
5.2. Message Types
5.3. Error Codes
5.4. ServerInfo Data Fields
5.5. PeerInfo Data Fields
5.6. Domain Name Reservation
5.7. Guidance for Designated Experts
6. Security Considerations
6.1. Authentication Principle
6.2. Identifying Correct Endpoints
6.3. Trusted Path Issues and Misbinding Attacks
6.4. Peer Identifiers and Attributes
6.5. Downgrading Threats
6.6. Protected Success and Failure Indications
6.7. Channel Binding
6.8. Denial of Service
6.9. Recovery from Loss of Last Message
6.10. Privacy Considerations
6.11. EAP Security Claims
7. References
7.1. Normative References
7.2. Informative References
Appendix A. Exchanges and Events per State
Appendix B. Application-Specific Parameters
Appendix C. EAP-NOOB Roaming
Appendix D. OOB Message as a URL
Acknowledgments
Authors' Addresses
1. Introduction โจ
okay bestie, this doc describes a way to do registration, authentication, and key derivation for network-connected smart devices, like the consumer and enterprise appliances that make up the Internet of Things (IoT) ๐ These devices might be off-the-shelf hardware sold with no registration or credential setup at all, or they could be recycled devices that just got a hard reset. So the device registration in a server database, who owns the device, and its credentials for both network access and application-level security all have to get sorted at deployment time ๐ฆ Also, a lot of these devices only have super limited user interfaces, usually input-only (like a camera) or output-only (like a display screen) ๐ It gets extra tricky because there can be tons of these devices, and they might need to be deployed or reconfigured nimbly based on what users need ๐
To sum up, devices can have these vibes:
- no preestablished relation with the intended server or user,
- no preprovisioned device identifier or authentication credentials, or
- an input or output interface that might only do one-directional out-of-band communication.
Lots of proprietary OOB configuration methods already exist for specific IoT devices ๐ธ This spec's goal is to give us an open standard and a generic protocol for bootstrapping security on network-connected appliances like displays, printers, speakers, and cameras ๐ The security bootstrapping here uses a user-assisted OOB channel. The device authentication depends on the user having physical access to the device, and the key exchange security assumes attackers can't observe or modify the messages going over the OOB channel ๐ We follow the usual pairing protocol approach: do a Diffie-Hellman key exchange over the insecure network, then authenticate the established key with the help of the OOB channel so impersonation attacks don't work ๐ฆ
This solution is meant for devices with a nonnetwork input or output interface, like a camera, microphone, display screen, speaker, or blinking Light Emitting Diode (LED), that can send or receive dynamically generated messages tens of bytes long โจ Honestly, this might not be right for super tiny sensors or actuators with no user interface at all, or for devices the user can't reach ๐ We also assume the OOB channel is at least partly automated (think a camera scanning a bar code), so there's no need to make the data sent through the OOB channel absolutely minimal ๐ That's different from Bluetooth pairing [Bluetooth], where it's essential to keep the manually transferred or compared codes short ๐ญ The OOB messages in this spec are dynamically generated, so static printed registration codes are a no-go ๐ซ The big reason is that receiving the OOB message is what authorizes the server to take ownership of the device ๐ Dynamic OOB messages are more secure than static printed codes, since those can leak and get misused later ๐
2. Terminology ๐
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 ๐
This doc also uses the following terms as they're defined in [RFC5216] ๐ง
- authenticator: The entity initiating EAP authentication.
- peer: The entity that responds to the authenticator. In [IEEE-802.1X], this entity is known as the supplicant. (We use the terms peer, device, and peer device interchangeably.) ๐ซถ
- server: The entity that terminates the EAP authentication method with the peer. When no backend authentication server is used, the EAP server is part of the authenticator. When the authenticator operates in pass-through mode, the EAP server is located on the backend authentication server ๐ฅ๏ธ
3. EAP-NOOB Method ๐ฆ
This section defines the EAP-NOOB method ๐ The protocol is a generalized version of the original idea presented by Sethi et al. [Sethi14] ๐
(to be continued in part 2 ๐ธ)
3.1. Protocol Overview โจ
okay so one EAP-NOOB method run is actually spread across two or more EAP conversations, and this spec calls each one an Exchange ๐ Each Exchange is made of several EAP request-response pairs. At least two separate EAP conversations are needed so the human user has time to deliver the OOB message between them ๐ซถ
The whole protocol kicks off with the Initial Exchange, which is four EAP request-response pairs ๐ธ During this part the server gives the peer an identifier, and they negotiate the protocol version and cryptosuite (aka the cryptographic algorithm suite) ๐ฅ They also swap nonces and do an Ephemeral Elliptic Curve Diffie-Hellman (ECDHE) key exchange, which is giving very secret-handshake energy ๐ฆ Then comes the user-assisted OOB Step. It only needs one out-of-band message, and it can go either from the peer to the server or from the server to the peer ๐ While the peer is waiting for that OOB Step to happen, it MAY probe the server by reconnecting with EAP-NOOB ๐ If the OOB Step already happened, the probe leads to the Completion Exchange, which finishes the mutual authentication and key confirmation ๐ If it hasn't happened yet, the probe leads to the Waiting Exchange instead, and the peer will try again after a minimum waiting time that the server decides ๐ฐ๏ธ The Initial Exchange and Waiting Exchange always end in EAP-Failure, but the Completion Exchange can end in EAP-Success โจ Once the peer and server finish a successful Completion Exchange, both sides save the created association in persistent storage, and the OOB Step never gets repeated ๐ After that, making new temporal keys, ECDHE rekeying, and updating cryptographic algorithms can all be done with the Reconnect Exchange ๐ง
OOB Output/Initial Exchange/
Waiting Exchange
.-----.
| v
.------------------. Initial .------------------.
| | Exchange | |
.->| Unregistered (0) |---------------->|Waiting for OOB(1)|
| | (ephemeral) | | (ephemeral) |
| | | | |
| '------------------' '------------------'
| | | ^
User Reset Completion | | |
| Exchange | OOB OOB
|<-------. .-------------------------' Input Reject/
| | | | Initial
| | | | Exchange
| | v v |
| .------------------. Completion .------------------.
| | | Exchange | |
| | Registered (4) |<----------------| OOB Received (2) |
| | (persistent) | | (ephemeral) |
| | | | |
| '------------------' '------------------'
| | ^
| Mobility/ |
| Timeout/ Reconnect
| Failure Exchange
| | |
| v |
| .------------------.
| | |
'--| Reconnecting (3) |
| (persistent) |
| |
'------------------'
Figure 1: EAP-NOOB Server-Peer Association State Machine
Figure 1 is the association state machine, and it's the same for the server and the peer ๐ฆ (Just a heads up: it only shows the main state transitions to keep it readable. The full table of transitions lives in Appendix A ๐) When the peer starts the EAP-NOOB method, the server picks the next message exchange based on the combo of server and peer states ๐ Both the EAP server and peer begin in the Unregistered (0) state, where no state information has to be stored ๐ซง Before a successful Completion Exchange, the server-peer association is ephemeral on both ends (ephemeral states 0..2), and if there's a timeout or error, one or both endpoints can drop back to Unregistered (0) so the Initial Exchange runs again ๐ Once the Completion Exchange ends in EAP-Success, the association becomes persistent (persistent states 3..4) ๐ Only a user reset or a memory failure can send the server or peer from the persistent states back to the ephemeral states and the Initial Exchange ๐ญ
Now the big rules, bestie ๐ The server MUST NOT repeat a successful OOB Step with the same peer, unless the association gets explicitly reset by the user or lost because the persistent storage on the server failed ๐ซ To be more specific, once the association hits the Registered (4) state, the server MUST NOT delete the association or go back to the ephemeral states 0..2 without explicit user approval ๐ โโ๏ธ Same vibe for the peer: it MUST NOT repeat the OOB Step unless the user explicitly deletes the association with the server from the peer, or resets the peer to the Unregistered (0) state ๐ The server and peer MAY implement user reset of the association by deleting the state data from that endpoint ๐งน And if an endpoint keeps storing data about the association after a user reset, its behavior MUST be equivalent to having deleted the association data ๐ซ
It can happen that the peer accidentally (or through a user reset) loses its persistent state and reconnects to the server without a peer identifier it was given before ๐ฅบ In that case, the server MUST treat the peer as a new peer ๐ The server MAY use auxiliary information, like the PeerInfo field from the Initial Exchange, to spot multiple associations with the same peer ๐ต๏ธโโ๏ธ But it MUST NOT delete or merge redundant associations without user or application approval ๐ Why? Because EAP-NOOB has no secure way to verify that two peers are actually the same physical device, and that's a whole mood ๐ค Similarly, the server might lose the association state because of a memory failure or user reset. In that case, the only way to recover is for the user to also reset the peer ๐
A special feature of EAP-NOOB is that the server is not assumed to know anything about the peer ahead of time ๐ So the peer starts out using the generic identity string "noob@eap-noob.arpa" as its Network Access Identifier (NAI) ๐ชช Then the server hands the peer a server-specific identifier. The generic NAI does two jobs: first, it tells the server that the peer supports and expects the EAP-NOOB method ๐ Second, it lets EAP-NOOB sessions get routed to a specific authentication server in an Authentication, Authorization, and Accounting (AAA) architecture ๐บ๏ธ
EAP-NOOB is kind of an unusual EAP method because the peer has to have multiple EAP conversations with the server before it can get EAP-Success ๐ฉ It's not that EAP can't handle delays between request-response pairs (it totally can, like for repeated password entry), but OOB authentication delays can be WAY longer than password retries ๐ข Plus, EAP-NOOB has to support peers with no input capability in their user interface, like LED light bulbs ๐ก Those devices can't have a user start the protocol, so they have to run the Initial Exchange opportunistically and hope the OOB Step happens within a timeout period (NoobTimeout). That's why the timeout needs to be several minutes instead of seconds โณ To support these high-latency OOB channels, the peer and server do the Initial Exchange in one EAP conversation, give time for the OOB message to get delivered, and later run the Waiting Exchange and Completion Exchange in different EAP conversations ๐
3.2. Protocol Messages and Sequences ๐
Okay, this section defines the EAP-NOOB exchanges, and each one corresponds to an EAP conversation ๐งต Every exchange starts with a common handshake, and that handshake decides what type of exchange comes next ๐ค The common handshake messages and the later messages for each exchange type are listed in the diagrams below ๐ The diagrams also say which data fields show up in each message ๐ Each exchange has multiple EAP request-response pairs and ends either in EAP-Failure, which means authentication isn't successful (yet), or in EAP-Success โจ
3.2.1. Common Handshake in All EAP-NOOB Exchanges ๐ค
okay so every EAP-NOOB exchange starts with the same little handshake, bestie ๐ It opens with the identity request and response that all EAP methods use. This part lets the AAA setup figure out where to route the convo (to the EAP server) and lets that server pick the EAP method. After that comes one EAP-NOOB request-response pair, where the server finds out the peer's identifier (PeerId) and state (PeerState) โจ
Here's the play-by-play. Each exchange begins with the authenticator sending an EAP-Request/Identity packet to the peer. From there it's just the server and the peer chatting, and the authenticator acts like a pass-through ๐ฆ The peer replies to the authenticator with an EAP-Response/Identity packet that carries its Network Access Identifier (NAI). The authenticator forwards that response and the rest of the conversation between the peer and the AAA architecture, no cap. The AAA architecture then routes it to one specific AAA server (called "EAP server" or just "server" in this spec) by looking at the realm part of the NAI. The server picks the EAP-NOOB method using the user part of the NAI, as defined in Section 3.3.1 ๐
Once the server has the EAP-Response/Identity, it sends the first EAP-NOOB request (Type=1) to the peer. The peer answers with its PeerId and its PeerState, which is somewhere in the range 0..3. Hot take: the peer SHOULD omit the PeerId from that response (Type=1) when PeerState=0 ๐ Then the server picks which EAP-NOOB exchange comes next, which is the ensuing message sequence, as explained below. The peer figures out which exchange it's in by checking the message type field (Type) of the next EAP-NOOB request from the server.
The server MUST determine the exchange type from the combo of the peer and server states. Table 14 has the summary. If either side is Unregistered (0) and the other is in one of the ephemeral states (0..2), the server goes with the Initial Exchange. If either side is OOB Received (2) and the other is Waiting for OOB (1) or OOB Received (2), the OOB Step has already happened, so the server picks the Completion Exchange. If both are Waiting for OOB (1), it's the Waiting Exchange. If the peer is Reconnecting (3) and the server is Registered (4) or Reconnecting (3), the server picks the Reconnect Exchange. Every other combo is an error situation where the user has to step in, and the server SHOULD tell the peer about it using error code 2002 (see Section 3.6.3). Also, the peer MUST NOT initiate EAP-NOOB while it's Registered (4) ๐ซ
EAP Peer Authenticator EAP Server
| | |
|<----------- EAP-Request/Identity -| |
| |
| |
|------------ EAP-Response/Identity -------------->|
| (NAI=noob@eap-noob.arpa) |
| |
| |
|<----------- EAP-Request/EAP-NOOB ----------------|
| (Type=1) |
| |
| |
|------------ EAP-Response/EAP-NOOB -------------->|
| (Type=1,[PeerId],PeerState=1) |
| |
| continuing with exchange-specific messages... |
Figure 2: Common Handshake in All EAP-NOOB Exchanges
3.2.2. Initial Exchange ๐ฑ
The Initial Exchange is the common handshake plus two more EAP-NOOB request-response pairs. One pair handles version, cryptosuite, and parameter negotiation, and the other handles the ECDHE key exchange. The server's first EAP-NOOB request (Type=2) carries a newly allocated PeerId for the peer, plus an optional NewNAI for giving the peer a new NAI. The server allocates a new PeerId during the Initial Exchange no matter what old PeerId showed up in the previous response (Type=1) โจ That request also lists the protocol versions (Vers) and cryptosuites (Cryptosuites) the server supports, an indicator of the OOB channel directions it supports (Dirs), and a ServerInfo object. The peer picks one version and one cryptosuite, then sends back a response (Type=2) with the selected protocol version (Verp), the received PeerId, the selected cryptosuite (Cryptosuitep), an indicator of the OOB channel direction(s) it picked (Dirp), and a PeerInfo object.
In the second EAP-NOOB request and response (Type=3), the server and peer swap the public parts of their ECDHE keys and their nonces (PKs, Ns, PKp, and Np). The ECDHE keys MUST be based on the negotiated cryptosuite, which is Cryptosuitep ๐ The Initial Exchange always finishes with an EAP-Failure from the server, because the authentication can't be completed yet. Plot twist, but it's by design ๐ญ
EAP Peer EAP Server
| ...continuing from common handshake |
| |
|<----------- EAP-Request/EAP-NOOB ----------------|
| (Type=2,Vers,PeerId,[NewNAI], |
| Cryptosuites,Dirs,ServerInfo) |
| |
| |
|------------ EAP-Response/EAP-NOOB -------------->|
| (Type=2,Verp,PeerId,Cryptosuitep, |
| Dirp,PeerInfo) |
| |
| |
|<----------- EAP-Request/EAP-NOOB ----------------|
| (Type=3,PeerId,PKs,Ns,[SleepTime]) |
| |
| |
|------------ EAP-Response/EAP-NOOB -------------->|
| (Type=3,PeerId,PKp,Np) |
| |
| |
|<----------- EAP-Failure -------------------------|
| |
Figure 3: Initial Exchange
Once the Initial Exchange wraps up, both the server and the peer land in Waiting for OOB (1) ๐
3.2.3. OOB Step ๐
The OOB Step (labeled OOB Output and OOB Input in Figure 1) happens right after the Initial Exchange. Which side sends the OOB message depends on the negotiated OOB channel direction. The peer or the server outputs it, as shown in Figure 4 or Figure 5 respectively. The data fields are the PeerId, the secret nonce Noob, and the cryptographic fingerprint Hoob. What's actually in those fields is defined in Section 3.3.2. The OOB message gets delivered to the other endpoint through a user-assisted OOB channel, so yes, a human is in the loop ๐
To keep things short, we'll use OOB sender and OOB receiver on top of the EAP server and EAP peer names we already know. If the OOB message goes server-to-peer, the server is the OOB sender and the peer is the OOB receiver. If it goes peer-to-server, the peer is the OOB sender and the server is the OOB receiver ๐
EAP Peer EAP Server
| |
|=================OOB=============================>|
| (PeerId,Noob,Hoob) |
| |
Figure 4: OOB Step, from Peer to EAP Server
EAP Peer EAP Server
| |
|<================OOB==============================|
| (PeerId,Noob,Hoob) |
| |
Figure 5: OOB Step, from EAP Server to Peer
The OOB receiver MUST compare the fingerprint Hoob it received (see Section 3.3.2) with a value it computed locally for the PeerID it received. This integrity check is how the endpoints make sure they agree on what's in the Initial Exchange ๐ If the values match, the receiver moves to OOB Received (2). If they don't, the receiver MUST reject the OOB message. For usability, the OOB receiver SHOULD tell the user whether the OOB message was accepted or rejected. The receiver SHOULD reject invalid OOB messages without changing its state in the association state machine, until an application-specific number of invalid messages (OobRetries) has been reached. After that, the receiver SHOULD treat it as an error and go back to Unregistered (0) ๐ค
The server or the peer MAY send several OOB messages with different Noob values while in Waiting for OOB (1). The OOB sender SHOULD remember those Noob values until they expire, and accept any one of them in the following Completion Exchange. The Noob values the server sends expire after an application-dependent timeout (NoobTimeout), and the server MUST NOT accept Noob values older than that in the Completion Exchange โฐ The RECOMMENDED value for NoobTimeout is 3600 seconds, unless there's an application-specific reason to make it shorter or longer. The Noob values the peer sends expire as defined in Section 3.2.5.
The OOB receiver doesn't accept more OOB messages once it has accepted one and moved to OOB Received (2). But the receiver MAY buffer redundant OOB messages, just in case an OOB message expiry or similar error shows up in the Completion Exchange and sends it back to Waiting for OOB (1). It is RECOMMENDED that the OOB receiver tells the user about redundant OOB messages, but it MAY discard them silently instead ๐ซถ
The sender will usually generate a new Noob, and therefore a new OOB message, at constant time intervals (NoobInterval). The RECOMMENDED interval is:
NoobInterval = NoobTimeout / 2
With that setup, the receiver of the OOB will at any given time accept either of the two latest Noob values, which is very neat ๐ง Timing can also depend on user interaction or on implementation considerations, though.
Even though it's not recommended (see Section 3.3), this specification does allow both directions to be negotiated for the OOB channel (Dirp=3). In that case, both sides SHOULD output the OOB message, and it's up to the user to deliver at least one of them ๐
The details of the OOB channel, including the message encoding, are left to the application. Appendix D has an example of how the OOB message can be encoded as a URL that can be embedded in a dynamic QR code or an NFC (Near Field Communication) tag ๐ฑ
3.2.4. Completion Exchange โจ
okay bestie, after the Initial Exchange, if the peer picked the peer-to-server direction for the OOB channel, the peer SHOULD start the EAP-NOOB method again after an applications-specific waiting time ๐ฐ๏ธ to check if the OOB Step is finished. and if the peer picked server-to-peer and actually gets the OOB message, it SHOULD kick off EAP-NOOB right away โก. depending on the peer and server states, the server either does the Completion Exchange or the Waiting Exchange (see Section 3.2.1 for how it decides ๐ ).
the Completion Exchange is the common handshake plus one or two more EAP-NOOB request-response pairs ๐. if the peer is in the Waiting for OOB (1) state, the OOB message went peer-to-server, so there's only one pair (Type=6) ๐ธ. the server sends the NoobId (see Section 3.3.2) in the request, and the peer uses it to figure out exactly which OOB message the server got ๐. if the peer is in the OOB Received (2) state, the OOB message went server-to-peer, so you need two pairs (Type=5 and Type=6) ๐ฆ. the first pair (Type=5) is how the server finds out the NoobId, which tells it exactly which OOB message the peer got. then the server sends that same NoobId back to the peer in the latter request ๐.
in the last pair (Type=6) of the Completion Exchange, the server and peer swap message authentication codes ๐. both sides MUST compute the keys Kms and Kmp (as defined in Section 3.5), plus the message authentication codes MACs and MACp (as defined in Section 3.3.2) ๐งฎ. both sides MUST also compare the code they received with their own locally computed value ๐. if the peer finds the correct MACs and the server finds the correct MACp, the Completion Exchange ends in EAP-Success ๐. if not, the endpoint where the comparison fails sends an error message (error code 4001, see Section 3.6.5), and the Completion Exchange ends in EAP-Failure ๐.
after a successful Completion Exchange, both the server and the peer move to the Registered (4) state ๐. they also derive the output keying material and store the persistent EAP-NOOB association state, as defined in Sections 3.4 and 3.5 โจ.
the OOB message can expire before it's received โณ. when that happens, the sender no longer recognizes the NoobId it gets in the Completion Exchange. another reason the OOB sender might not recognize the NoobId is if the OOB message was spoofed and had an attacker-generated Noob value ๐ค. the recipient of an unrecognized NoobId sends an error message (error code 2003, see Section 3.6.1), and the Completion Exchange ends in EAP-Failure ๐ โโ๏ธ. the recipient of error message 2003 goes back to the Waiting for OOB (1) state. this transition is called OOB Reject in Figure 1 (even though it's really just a specific kind of failed Completion Exchange) ๐ฅฒ. the sender of the error message stays in its previous state.
it's not expected to happen in practice, but bad user interface design could lead to two OOB messages getting delivered at the same time, one from the peer to the server and one from the server to the peer ๐. the server spots this at the very start of the Completion Exchange by noticing that both the server and the peer are in the OOB Received (2) state. in that case, as a tiebreaker, the server MUST behave as if only the server-to-peer message had been delivered ๐ซถ.
EAP Peer EAP Server
| ...continuing from common handshake |
| |
|<----------- [ EAP-Request/EAP-NOOB ] ------------|
| (Type=5,PeerId) |
| |
| |
|------------ [ EAP-Response/EAP-NOOB ] ---------->|
| (Type=5,PeerId,NoobId) |
| |
| |
|<----------- EAP-Request/EAP-NOOB ----------------|
| (Type=6,PeerId,NoobId,MACs) |
| |
| |
|------------ EAP-Response/EAP-NOOB -------------->|
| (Type=6,PeerId,MACp) |
| |
| |
|<----------- EAP-Success -------------------------|
| |
Figure 6: Completion Exchange
3.2.5. Waiting Exchange ๐
as we talked about in Section 3.2.4, the peer SHOULD probe the server for completion of the OOB Step ๐. when the peer and server states show that the OOB message hasn't been delivered yet, the server picks the Waiting Exchange (see Section 3.2.1 for how it decides ๐ ). the Waiting Exchange is the common handshake plus one more request-response pair, and it always ends in EAP-Failure ๐.
to keep peers from probing the server too often ๐, the server MAY send a minimum time to wait before probing again, either in the Initial Exchange or in the Waiting Exchange โฑ๏ธ. a peer that hasn't received an OOB message SHOULD wait at least the server-specified minimum waiting time in seconds (SleepTime) before starting EAP again with the same server ๐. the peer uses the latest SleepTime value it received in or after the Initial Exchange ๐ฌ. if the server never sent a SleepTime value, the peer MUST wait for an application-specified minimum time (SleepTimeDefault) ๐ซ .
after the Waiting Exchange, the peer MUST discard (from its local ephemeral storage) the Noob values it sent to the server in OOB messages that are older than the application-defined timeout NoobTimeout (see Section 3.2.3) ๐๏ธ. the peer SHOULD discard these expired Noob values even if probing failed because of, e.g., failing to connect to the EAP server or an incorrect message authentication code ๐. this timeout for peer-generated Noob values is set up this way so the peer can probe the server once after waiting out the server-specified SleepTime โจ.
if the server and peer negotiated to use only the server-to-peer direction for the OOB channel (Dirp=2), the peer SHOULD still probe the server ๐ซฃ. the reason is to keep the server up to date on which peers are still waiting for OOB messages ๐. the server MAY set SleepTime to a high number (e.g., 3600) so the peer doesn't probe the server often ๐ด.
EAP Peer EAP Server
| ...continuing from common handshake |
| |
|<----------- EAP-Request/EAP-NOOB ----------------|
| (Type=4,PeerId,[SleepTime]) |
| |
| |
|------------ EAP-Response/EAP-NOOB -------------->|
| (Type=4,PeerId) |
| |
| |
|<----------- EAP-Failure -------------------------|
| |
Figure 7: Waiting Exchange
3.3. Protocol Data Fields ๐
okay, this section is where we define all the identifiers and data fields the EAP-NOOB method uses ๐ง the bones of the whole thing, bestie ๐.
3.3.1. Peer Identifier and NAI โจ
okay bestie, this is the naming section ๐ The server hands the peer a brand new peer identifier (PeerId) during the Initial Exchange. That PeerId MUST follow the syntax of the utf8-username from [RFC7542] ๐
The server MUST generate these so they never repeat and so the peer or some random third party can't guess them before the server actually sends them over. One option is to grab a random 16-byte value and base64url encode it without padding [RFC4648], which gives you a 22-character ASCII string ๐ฆ Another option is a random 22-character alphanumeric ASCII string. It's RECOMMENDED to not go longer than that, because longer IDs make the OOB messages longer too ๐
Now the peer uses that PeerId to introduce itself in every exchange after. The peer MUST copy the PeerId byte by byte from the message where it was given out, and the server MUST do a byte-by-byte comparison between what it receives and the PeerID it previously allocated. Here's how the peer fills in PeerId in response type 1 ๐ธ As mentioned in Section 3.2.1, when the peer is in the Unregistered (0) state, it SHOULD leave the PeerId out of response type 1. When the peer is in one of the states 1..2, it MUST use the PeerId the server assigned in the latest Initial Exchange. When the peer is in one of the persistent states 3..4, it MUST use the PeerId from its persistent EAP-NOOB association. (The PeerId gets saved into the association when the peer moves to the Registered (4) state after a Completion Exchange ๐ง)
Next up, the NAI ๐ The default NAI for the peer is "noob@eap-noob.arpa". The peer implementation MAY let the user or an application configure a different NAI, and that configured one beats the default. The server MAY also assign a brand new NAI during the Initial Exchange or Reconnect Exchange, using the NewNAI field in request types 2 and 7, and that overrides whatever NAI was there before ๐ฅ Here's who uses what:
- When the peer is in the Unregistered (0) state, or it's in one of the states 1..2 and the server didn't send a
NewNAIin the latest Initial Exchange, the peer MUST use the configured NAI or, if there isn't one, the default NAI. - When the peer is in one of the states 1..2 and the server DID send a
NewNAIin the latest Initial Exchange, the peer MUST use that server-assigned NAI. - When the peer moves to the Registered (4) state after the Completion Exchange, it saves the same NAI value it used in the Completion Exchange into the persistent EAP-NOOB association.
- When the peer is in the Reconnecting (3) or Registered (4) state, it MUST use the NAI from its persistent EAP-NOOB association.
- When the server sends
NewNAIin the Reconnect Exchange, the peer writes that value to the persistent EAP-NOOB association when it goes from the Reconnecting (3) state to the Registered (4) state.
Every NAI value MUST follow the syntax in [RFC7542] ๐ซถ
Why do we care about the server-assigned NAI? It makes routing EAP sessions over the AAA infrastructure way more flexible, including roaming situations (see Appendix C) ๐ Some authenticators or AAA servers look at the realm part of the assigned NAI to decide peer-specific connection settings, like sticking the peer on a specific VLAN ๐ Meanwhile the user- or app-configured NAI is what lets brand new devices register while they're roaming. It also lets manufacturers run their own AAA servers to bootstrap new peer devices ๐
Last bit of this section: the PeerId and server-assigned NAI are only ephemeral until a successful Completion Exchange happens. After that they become part of the persistent EAP-NOOB association, and they stick around until the user resets the peer and server, or until a new NAI gets assigned in the Reconnect Exchange ๐ญโจ
3.3.2. Message Data Fields ๐
Okay, so Table 1 spells out every data field in the protocol messages ๐ The in-band messages are JSON objects [RFC8259] encoded in UTF-8, and the JSON member names are listed in the left-hand column of the table ๐ฆ
Okay bestie, this is the ultimate cheat sheet of every message field ๐ Literally every single one lives here, so screenshot it ๐ธ
+===============+=================================================+
| Data Field | Description |
+===============+=================================================+
| Vers, Verp | EAP-NOOB protocol versions supported by the EAP |
| | server and the protocol version chosen by the |
| | peer. Vers is a JSON array of unsigned |
| | integers, and Verp is an unsigned integer. |
| | Example values are "[1]" and "1", respectively. |
+---------------+-------------------------------------------------+
| PeerId | Peer identifier, as defined in Section 3.3.1. |
+---------------+-------------------------------------------------+
| NAI, NewNAI | Peer NAI and server-assigned new peer NAI, as |
| | defined in Section 3.3.1. |
+---------------+-------------------------------------------------+
| Type | EAP-NOOB message type. The type is an integer |
| | in the range 0..9. EAP-NOOB requests and the |
| | corresponding responses share the same type |
| | value. |
+---------------+-------------------------------------------------+
| PeerState | Peer state is an integer in the range 0..4 (see |
| | Figure 1). However, only values 0..3 are ever |
| | sent in the protocol messages. |
+---------------+-------------------------------------------------+
| PKs, PKp | The public components of the ECDHE keys of the |
| | server and peer. PKs and PKp are sent in the |
| | JSON Web Key (JWK) format [RFC7517]. The |
| | detailed format of the JWK object is defined by |
| | the cryptosuite. |
+---------------+-------------------------------------------------+
| Cryptosuites, | The identifiers of cryptosuites supported by |
| Cryptosuitep | the server and of the cryptosuite selected by |
| | the peer. The server-supported cryptosuites in |
| | Cryptosuites are formatted as a JSON array of |
| | the identifier integers. The server MUST send |
| | a nonempty array with no repeating elements, |
| | ordered by decreasing priority. The peer MUST |
| | respond with exactly one suite in the |
| | Cryptosuitep value, formatted as an identifier |
| | integer. Mandatory-to-implement cryptosuites |
| | and the registration procedure for new |
| | cryptosuites are specified in Section 5.1. |
| | Example values are "[1]" and "1", respectively. |
+---------------+-------------------------------------------------+
| Dirs, Dirp | An integer indicating the OOB channel |
| | directions supported by the server and the |
| | directions selected by the peer. The possible |
| | values are 1=peer-to-server, 2=server-to-peer, |
| | and 3=both directions. |
+---------------+-------------------------------------------------+
| Dir | The actual direction of the OOB message |
| | (1=peer-to-server, 2=server-to-peer). This |
| | value is not sent over any communication |
| | channel, but it is included in the computation |
| | of the cryptographic fingerprint Hoob. |
+---------------+-------------------------------------------------+
| Ns, Np | 32-byte nonces for the Initial Exchange. |
+---------------+-------------------------------------------------+
| ServerInfo | This field contains information about the |
| | server to be passed from the EAP method to the |
| | application layer in the peer. The information |
| | is specific to the application or to the OOB |
| | channel, and it is encoded as a JSON object of |
| | at most 500 bytes. It could include, for |
| | example, the access-network name and server |
| | name, a Uniform Resource Locator (URL) |
| | [RFC3986], or some other information that helps |
| | the user deliver the OOB message to the server |
| | through the out-of-band channel. |
+---------------+-------------------------------------------------+
| PeerInfo | This field contains information about the peer |
| | to be passed from the EAP method to the |
| | application layer in the server. The |
| | information is specific to the application or |
| | to the OOB channel, and it is encoded as a JSON |
| | object of at most 500 bytes. It could include, |
| | for example, the peer brand, model, and serial |
| | number, which help the user distinguish between |
| | devices and deliver the OOB message to the |
| | correct peer through the out-of-band channel. |
+---------------+-------------------------------------------------+
| SleepTime | The number of seconds for which the peer MUST |
| | NOT start a new execution of the EAP-NOOB |
| | method with the authenticator, unless the peer |
| | receives the OOB message or the sending is |
| | triggered by an application-specific user |
| | action. The server can use this field to limit |
| | the rate at which peers probe it. SleepTime is |
| | an unsigned integer in the range 0..3600. |
+---------------+-------------------------------------------------+
| Noob | 16-byte secret nonce sent through the OOB |
| | channel and used for the session key |
| | derivation. The endpoint that received the OOB |
| | message uses this secret in the Completion |
| | Exchange to authenticate the exchanged key to |
| | the endpoint that sent the OOB message. |
+---------------+-------------------------------------------------+
| Hoob | 16-byte cryptographic fingerprint (i.e., hash |
| | value) computed from all the parameters |
| | exchanged in the Initial Exchange and in the |
| | OOB message. Receiving this fingerprint over |
| | the OOB channel guarantees the integrity of the |
| | key exchange and parameter negotiation. Hence, |
| | it authenticates the exchanged key to the |
| | endpoint that receives the OOB message. |
+---------------+-------------------------------------------------+
| NoobId | 16-byte identifier for the OOB message, |
| | computed with a one-way function from the nonce |
| | Noob in the message. |
+---------------+-------------------------------------------------+
| MACs, MACp | Message authentication codes (HMAC) for mutual |
| | authentication, key confirmation, and integrity |
| | check on the exchanged information. The input |
| | to the HMAC is defined below, and the key for |
| | the HMAC is defined in Section 3.5. |
+---------------+-------------------------------------------------+
| Ns2, Np2 | 32-byte nonces for the Reconnect Exchange. |
+---------------+-------------------------------------------------+
| KeyingMode | Integer indicating the key derivation method. 0 |
| | in the Completion Exchange, and 1..3 in the |
| | Reconnect Exchange. |
+---------------+-------------------------------------------------+
| PKs2, PKp2 | The public components of the ECDHE keys of the |
| | server and peer for the Reconnect Exchange. |
| | PKp2 and PKs2 are sent in the JSON Web Key |
| | (JWK) format [RFC7517]. The detailed format of |
| | the JWK object is defined by the cryptosuite. |
+---------------+-------------------------------------------------+
| MACs2, MACp2 | Message authentication codes (HMAC) for mutual |
| | authentication, key confirmation, and integrity |
| | check on the Reconnect Exchange. The input to |
| | the HMAC is defined below, and the key for the |
| | HMAC is defined in Section 3.5. |
+---------------+-------------------------------------------------+
| ErrorCode | Integer indicating an error condition. Defined |
| | in Section 5.3. |
+---------------+-------------------------------------------------+
| ErrorInfo | Textual error message for logging and debugging |
| | purposes. A UTF-8 string of at most 500 bytes. |
+---------------+-------------------------------------------------+
Table 1: Message Data Fields ๐
It is RECOMMENDED for servers to support both OOB channel directions (Dirs=3) unless the type of the OOB channel limits them to one direction (Dirs=1 or Dirs=2). ๐ฆ On the other hand, it is RECOMMENDED that the peer selects only one direction (Dirp=1 or Dirp=2) even when both directions (Dirp=3) would be technically possible. The reason? If value 3 gets negotiated, the user could be shown two OOB messages, one for each direction, even though only one of them actually needs to be delivered. Confusing, right? ๐ Nevertheless, the EAP-NOOB protocol is designed to also cope with the value 3. In that case, it uses the first delivered OOB message. And in the unlikely case of simultaneously delivered OOB messages, the protocol prioritizes the server-to-peer direction. โจ
Every in-band nonce (Ns, Np, Ns2, Np2) is a 32-byte fresh random byte string, and the secret nonce Noob is a 16-byte fresh random byte string. ๐ฒ Every single nonce is generated by whichever endpoint sends the message, so no sneaky borrowing ๐
The fingerprint Hoob and the identifier NoobId are computed with the cryptographic hash function H, which is specified in the negotiated cryptosuite and truncated to the 16 leftmost bytes of the output. Then the message authentication codes (MACs, MACp, MACs2, MACp2) are computed with the function HMAC. That's the hashed message authentication code [RFC2104] built on top of H, truncated to the 32 leftmost bytes of the output. Main character energy ๐๐
The inputs to the hash function for Hoob and to the HMAC for MACs, MACp, MACs2, and MACp2 are JSON arrays with a fixed number (17) of elements. The array elements MUST be copied to the array verbatim from the sent and received in-band messages ๐ง. When an element is a JSON object, its members MUST NOT be reordered or reencoded. White space MUST NOT be added anywhere in the JSON structure. Implementers should check that their JSON library copies the elements as UTF-8 strings, doesn't modify them in any way, and doesn't add white space to the HMAC input ๐ซถ.
The inputs for computing the fingerprint and message authentication codes are these:
Hoob = H(Dir,Vers,Verp,PeerId,Cryptosuites,Dirs,ServerInfo,
Cryptosuitep,Dirp,NAI,PeerInfo,0,PKs,Ns,PKp,Np,Noob).
NoobId = H("NoobId",Noob).
MACs = HMAC(Kms; 2,Vers,Verp,PeerId,Cryptosuites,Dirs,ServerInfo,
Cryptosuitep,Dirp,NAI,PeerInfo,0,PKs,Ns,PKp,Np,Noob).
MACp = HMAC(Kmp; 1,Vers,Verp,PeerId,Cryptosuites,Dirs,ServerInfo,
Cryptosuitep,Dirp,NAI,PeerInfo,0,PKs,Ns,PKp,Np,Noob).
MACs2 = HMAC(Kms2; 2,Vers,Verp,PeerId,Cryptosuites,"",[ServerInfo],
Cryptosuitep,"",NAI,[PeerInfo],KeyingMode,[PKs2],Ns2,[PKp2],Np2,"")
MACp2 = HMAC(Kmp2; 1,Vers,Verp,PeerId,Cryptosuites,"",[ServerInfo],
Cryptosuitep,"",NAI,[PeerInfo],KeyingMode,[PKs2],Ns2,[PKp2],Np2,"")
Anything marked with "" isn't there at all, and the stuff in [] brackets is optional ๐. Either way, the missing bits get stood in for by empty strings "" inside the HMAC input JSON array. The NAI in these inputs is whatever NAI value will be sitting in the persistent EAP-NOOB association if the Completion Exchange or Reconnect Exchange succeeds ๐
. For the Completion Exchange, that's the NewNAI the server assigned in the Initial Exchange before it, or if no NewNAI got sent, the NAI the client used in the Initial Exchange. For the Reconnect Exchange, it's the NewNAI the server assigned in that same Reconnect Exchange, or if none got sent, the unchanged NAI from the persistent EAP-NOOB association. Each bracketed value for computing Macs2 and Macp2 MUST be included if it was sent or received in the same Reconnect Exchange. Otherwise it gets swapped out for an empty string "". Iconic behaviour, honestly โจ.
The parameter Dir tells you which direction the OOB message carrying the Noob value is heading (1=peer-to-server, 2=server-to-peer). It's in the Hoob input so the user can't accidentally bounce the OOB message back to whoever sent it, which only really matters in the rare cases where both OOB directions have been negotiated ๐. The keys (Kms, Kmp, Kms2, and Kmp2) for the HMACs are defined in Section 3.5 ๐.
The nonces (Ns, Np, Ns2, Np2, and Noob) and the hash value (NoobId) MUST be base64url encoded [RFC4648] when they're used as input to the cryptographic functions H or HMAC ๐ธ. These values, plus the message authentication codes (MACs, MACp, MACs2, and MACp2), MUST also be base64url encoded when they're sent as JSON strings in the in-band messages. The values Noob and Hoob in the OOB channel MAY be base64url encoded if that's appropriate for the application and the OOB channel ๐ฆ. All base64url encoding is done without padding. The encoded values end up taking up more space than the byte counts above, so, for example, a 16-byte nonce becomes a 22-character string and a 32-byte nonce or message authentication code becomes a 43-character string ๐. Meanwhile, in the key derivation in Section 3.5, the unencoded nonces (raw bytes) are what get fed into the key derivation function ๐ง .
The ServerInfo and PeerInfo are JSON objects with UTF-8 encoding. The length of either encoded object as a byte array MUST NOT exceed 500 bytes ๐ซ. The format and semantics of these objects MUST be defined by the application that uses the EAP-NOOB method ๐.
3.4. Fast Reconnect and Rekeying
EAP-NOOB implements fast reconnect ([RFC3748], Section 7.2.1), which avoids repeatedly using the user-assisted OOB channel ๐โโ๏ธ๐จ. Iykyk, the OOB step is the annoying part, so skipping it is a whole mood.
The rekeying and the Reconnect Exchange may be needed for several reasons ๐. New EAP output values, Main Session Key (MSK) and Extended Main Session Key (EMSK), may be needed because of mobility or a timeout of session keys ๐. Software or hardware failure, or user action, may also cause the authenticator, EAP server, or peer to lose its nonpersistent state data ๐. The failure would typically get noticed by the peer or authenticator once session keys stop being accepted by the other endpoint. Changes in the supported cryptosuites in the EAP server or peer may also cause the need for a new key exchange ๐. When the EAP server or peer detects any one of these events, it MUST change from the Registered (4) state to the Reconnecting (3) state ๐ฆ. These state transitions are labeled Mobility/Timeout/Failure in Figure 1. After that, the EAP-NOOB method will perform the Reconnect Exchange the next time EAP is triggered ๐.
3.4.1. Persistent EAP-NOOB Association
To enable rekeying, the EAP server and peer store the session state in persistent memory after a successful Completion Exchange ๐พ. This state data, called "persistent EAP-NOOB association", MUST include at least the data fields shown in Table 2. These fields are what get used to identify and authenticate the peer in the Reconnect Exchange ๐ชช. When a persistent EAP-NOOB association exists, the EAP server and peer are in the Registered (4) state or the Reconnecting (3) state, as shown in Figure 1 ๐.
+==================+==========================+===================+
| Data Field | Value | Type |
+==================+==========================+===================+
| PeerId | Peer identifier | UTF-8 string |
| | allocated by server | (typically 22 |
| | | ASCII characters) |
+------------------+--------------------------+-------------------+
| Verp | Negotiated protocol | integer |
| | version | |
+------------------+--------------------------+-------------------+
| Cryptosuitep | Negotiated cryptosuite | integer |
+------------------+--------------------------+-------------------+
| CryptosuitepPrev | Previous cryptosuite | integer |
| (at peer only) | | |
+------------------+--------------------------+-------------------+
| NAI | NAI assigned by the | UTF-8 string |
| | server or configured by | |
| | the user or the default | |
| | NAI "noob@eap-noob.arpa" | |
+------------------+--------------------------+-------------------+
| Kz | Persistent key material | 32 bytes |
+------------------+--------------------------+-------------------+
| KzPrev (at peer | Previous Kz value | 32 bytes |
| only) | | |
+------------------+--------------------------+-------------------+
Table 2: Persistent EAP-NOOB Association
3.4.2. Reconnect Exchange โจ
okay so the server picks the Reconnect Exchange when both the peer and the server are in a persistent state AND fast reconnection is needed ๐ฅ (check Section 3.2.1 for the deets ๐ ).
The Reconnect Exchange is the common handshake plus three more EAP-NOOB request-response pairs ๐. The first one is for cryptosuite and parameter negotiation, the second is for the nonce and ECDHE key exchange, and the last one is for swapping message authentication codes ๐ฆ. In the first request and response (Type=7), the server and peer negotiate a protocol version and cryptosuite exactly the same way they do in the Initial Exchange ๐. The server SHOULD NOT offer and the peer MUST NOT accept protocol versions or cryptosuites that it knows to be weaker than the one currently in the Cryptosuitep field of the persistent EAP-NOOB association ๐ โโ๏ธ. The server SHOULD NOT needlessly change the cryptosuites it offers to the same peer, because peer devices may have limited ability to update their persistent storage ๐. However, if the peer has different values in the Cryptosuitep and CryptosuitepPrev fields, it SHOULD also accept offers that are not weaker than CryptosuitepPrev ๐ธ. Note that Cryptosuitep and CryptosuitePrev from the persistent EAP-NOOB association are only used to support the negotiation I just described ๐ง. All the actual cryptographic operations use the newly negotiated cryptosuite โจ. The request and response (Type=7) MAY additionally contain PeerInfo and ServerInfo objects ๐.
Next up, the server works out the KeyingMode (defined in Section 3.5) based on changes in the negotiated cryptosuite and on whether it wants forward secrecy or not ๐. The server SHOULD only select KeyingMode 3 when the negotiated cryptosuite differs from the Cryptosuitep in the server's persistent EAP-NOOB association, even though it is technically possible to pick this value without changing the cryptosuite ๐. In the second request and response (Type=8), the server tells the peer about the KeyingMode, and the two of them swap nonces (Ns2, Np2) ๐. When KeyingMode is 2 or 3 (rekeying with ECDHE), they also swap public components of their ECDHE keys (PKs2, PKp2) ๐. The server ECDHE key MUST be fresh, meaning it was not previously used with the same peer ๐ฅ. The peer ECDHE key SHOULD be fresh, meaning it was not previously used โจ.
In the third and final request and response (Type=9), the server and peer swap message authentication codes ๐ซถ. Both sides MUST compute the keys Kms2 and Kmp2, as defined in Section 3.5, and the message authentication codes MACs2 and MACp2, as defined in Section 3.3.2 ๐ . Both sides MUST compare the received message authentication code with a locally computed value ๐ญ.
Now the peer's rules for comparing the received MACs2 are kinda tricky, bestie ๐. That's because MACs2 does two jobs: it authenticates the current exchange, and it may also confirm whether a recent cryptosuite upgrade worked or flopped ๐ฆ. Here's how the peer handles the final request (Type=9):
- First, the peer compares the received MACs2 value with one it computed using the Kz stored in the persistent EAP-NOOB association. If the received and computed values match, the peer deletes any data stored in the CryptosuitepPrev and KzPrev fields of the persistent EAP-NOOB association ๐งน. It does this because the received MACs2 confirms that the peer and server share the same Cryptosuitep and Kz, so any previous values must no longer be accepted ๐ .
- On the flip side, if the received MACs2 value does NOT match the one the peer computed locally with Kz, the peer checks whether the KzPrev field in the persistent EAP-NOOB association stores a key ๐. If it does, the peer repeats the key derivation (Section 3.5) and the local MACs2 computation (Section 3.3.2) using KzPrev in place of Kz ๐. If this second computed MACs2 matches the received value, that match means there was a synchronization failure caused by losing the last response (Type=9) in a previously attempted cryptosuite upgrade ๐ฑ. In this case, the peer rolls that upgrade back by overwriting Cryptosuitep with CryptosuitepPrev and Kz with KzPrev in the persistent EAP-NOOB association โช. It also clears the CryptosuitepPrev and KzPrev fields ๐งฝ.
- If the received MACs2 matched one of the locally computed values, the peer sends the final response (Type=9) ๐ฉ. The peer also moves to the Registered (4) state ๐. When KeyingMode is 1 or 2, the peer stops right there ๐. When KeyingMode is 3, the peer also updates the persistent EAP-NOOB association with the negotiated Cryptosuitep and the newly derived Kz value ๐. To prepare for a possible synchronization failure caused by losing the final response (Type=9) during a cryptosuite upgrade, the peer copies the old Cryptosuitep and Kz values in the persistent EAP-NOOB association into the CryptosuitepPrev and KzPrev fields ๐.
- Finally, if the received MACs2 matches neither of the two values the peer computed locally (or the only value, if no KzPrev was stored), the peer sends an error message (error code 4001, see Section 3.6.5) ๐จ. That makes the Reconnect Exchange end in EAP-Failure ๐.
The server's rules for the final message are a lot simpler, because the server doesn't store previous keys and it never rolls back a cryptosuite upgrade ๐. When the server receives the final response (Type=9), it compares the received value of MACp2 with one it computes locally ๐. If the values match, the Reconnect Exchange ends in EAP-Success ๐ฅณ. When KeyingMode is 3, the server also updates Cryptosuitep and Kz in the persistent EAP-NOOB association ๐. On the other hand, if the values don't match, the server sends an error message (error code 4001), and the Reconnect Exchange ends in EAP-Failure ๐ญ.
The endpoints MAY send updated NewNAI, ServerInfo, and PeerInfo objects in the Reconnect Exchange ๐. When nothing has changed, they SHOULD omit that information from the messages ๐. If the NewNAI was sent, each side updates NAI in the persistent EAP-NOOB association when it moves to the Registered (4) state ๐.
Here's the whole exchange as a picture, bestie ๐ผ๏ธ:
EAP Peer EAP Server
| ...continuing from common handshake |
| |
|<----------- EAP-Request/EAP-NOOB ----------------|
| (Type=7,Vers,PeerId,Cryptosuites, |
| [NewNAI],[ServerInfo]) |
| |
| |
|------------ EAP-Response/EAP-NOOB -------------->|
| (Type=7,Verp,PeerId,Cryptosuitep,[PeerInfo])|
| |
| |
|<----------- EAP-Request/EAP-NOOB ----------------|
| (Type=8,PeerId,KeyingMode,[PKs2],Ns2) |
| |
| |
|------------ EAP-Response/EAP-NOOB -------------->|
| (Type=8,PeerId,[PKp2],Np2) |
| |
| |
|<----------- EAP-Request/EAP-NOOB ----------------|
| (Type=9,PeerId,MACs2) |
| |
| |
|------------ EAP-Response/EAP-NOOB -------------->|
| (Type=9,PeerId,MACp2) |
| |
| |
|<----------- EAP-Success -------------------------|
| |
Figure 8: Reconnect Exchange
3.4.3. User Reset โจ
okay so, as the association state machine in Figure 1 shows, the ONLY specified way for the association to go from the Registered (4) state back to the Unregistered (0) state is a user-initiated reset ๐. After the reset, a fresh OOB message will be needed to set up a new association between the EAP server and peer ๐จ. Typical situations where a user reset is required are when the other side has accidentally lost the persistent EAP-NOOB association data, or when the peer device is decommissioned ๐๏ธ.
The server could detect that the peer is in the Registered or Reconnecting state, while the server itself is in one of the ephemeral states 0..2 (this includes situations where the server doesn't recognize the PeerId) ๐ค. In this case, effort should be made to recover the persistent server state, for example from backup storage, especially if lots of peer devices are similarly affected ๐. If that's not possible, the EAP server SHOULD log the error or notify an administrator ๐ฃ. The only way to continue from a situation like this is having the user reset the peer device ๐ง.
On the other hand, if the peer is in any of the ephemeral states 0..2, including the Unregistered state, the server will treat the peer as a new peer device and allocate a new PeerId to it ๐. The PeerInfo can be used by the user as a clue about which physical device lost its state ๐ต๏ธโโ๏ธ. However, there's no secure way to match the "new" peer with the old PeerId without repeating the OOB Step ๐ โโ๏ธ. This gets resolved when the user performs the OOB Step and thereby identifies the physical peer device ๐ซถ. The server user interface MAY support situations where the "new" peer is actually a previously registered peer that a user reset or that otherwise lost its persistent data ๐งฉ. In those cases, the user could choose to merge the new peer identity with the old one on the server ๐. The alternative is to treat the device just like a new peer ๐.
3.5. Key Derivation โจ
okay so bestie, this is where EAP-NOOB makes its secret keys ๐โจ The server and peer both get the EAP output values MSK and EMSK, plus other secret keying material, from the output of an Ephemeral Elliptic Curve Diffie-Hellman (ECDHE) algorithm, following the NIST specification [NIST-DH]. In NIST's language, this is a C(2e, 0s, ECC CDH) scheme, which means two ephemeral keys and no static keys ๐
In the Initial Exchange and the Reconnect Exchange, the server and peer compute the ECDHE shared secret Z, as defined in Section 6.1.2 of the NIST specification [NIST-DH]. Then, in the Completion Exchange and the Reconnect Exchange, they use that Z to compute the secret keying material with the one-step key derivation function (KDF) defined in Section 5.8.2.1 of the NIST specification. The auxiliary function H is a hash function, and it comes from the negotiated cryptosuite ๐
The key derivation has four different modes (KeyingMode), listed in Table 3. Table 4 shows what goes into the KDF in each KeyingMode.
+============+============================================+
| KeyingMode | Description |
+============+============================================+
| 0 | Completion Exchange (always with ECDHE) |
+------------+--------------------------------------------+
| 1 | Reconnect Exchange, rekeying without ECDHE |
+------------+--------------------------------------------+
| 2 | Reconnect Exchange, rekeying with ECHDE, |
| | no change in cryptosuite |
+------------+--------------------------------------------+
| 3 | Reconnect Exchange, rekeying with ECDHE, |
| | new cryptosuite negotiated |
+------------+--------------------------------------------+
Table 3: Keying Modes
Now let's go mode by mode ๐ฆ
In the Completion Exchange (KeyingMode=0), the input Z comes from the Initial Exchange that came before it. The KDF also takes some extra inputs called FixedInfo, and for those we use the concatenation format from Section 5.8.2.1.1 of the NIST specification [NIST-DH]. FixedInfo is made of the AlgorithmId, PartyUInfo, PartyVInfo, and SuppPrivInfo fields. The first three are fixed-length bit strings. SuppPrivInfo is a variable-length string that starts with a one-byte Datalength counter. AlgorithmId is the fixed-length, 8-byte ASCII string "EAP-NOOB". The other inputs are the server and peer nonces, and in the Completion Exchange, the secret nonce Noob from the OOB message gets thrown in too ๐ง
In the simplest form of the Reconnect Exchange (KeyingMode=1), fresh nonces get swapped but no ECDHE keys are sent at all ๐ธ Here, the input Z to the KDF is replaced by the shared key Kz from the persistent EAP-NOOB association. You get rekeying without the computational cost of the ECDHE exchange, but also without forward secrecy, so it's a tradeoff ๐
When forward secrecy is wanted in the Reconnect Exchange (KeyingMode=2 or KeyingMode=3), both nonces and ECDHE keys get exchanged. The input Z is the fresh shared secret from the ECDHE exchange using PKs2 and PKp2. The inputs also include the shared secret Kz from the persistent EAP-NOOB association, which binds the rekeying output to the previously authenticated keys ๐
Here's Table 4, the full list of KDF inputs:
+=========================+==============+===============+==========+
| KeyingMode | KDF input | Value | Length |
| | field | | (bytes) |
+=========================+==============+===============+==========+
| 0 Completion | Z | ECDHE shared | variable |
| | | secret from | |
| | | PKs and PKp | |
| +--------------+---------------+----------+
| | AlgorithmId | "EAP-NOOB" | 8 |
| +--------------+---------------+----------+
| | PartyUInfo | Np | 32 |
| +--------------+---------------+----------+
| | PartyVInfo | Ns | 32 |
| +--------------+---------------+----------+
| | SuppPubInfo | (not | |
| | | allowed) | |
| +--------------+---------------+----------+
| | SuppPrivInfo | Noob | 16 |
+-------------------------+--------------+---------------+----------+
| 1 Reconnect, rekeying | Z | Kz | 32 |
| without ECDHE +--------------+---------------+----------+
| | AlgorithmId | "EAP-NOOB" | 8 |
| +--------------+---------------+----------+
| | PartyUInfo | Np2 | 32 |
| +--------------+---------------+----------+
| | PartyVInfo | Ns2 | 32 |
| +--------------+---------------+----------+
| | SuppPubInfo | (not | |
| | | allowed) | |
| +--------------+---------------+----------+
| | SuppPrivInfo | (null) | 0 |
+-------------------------+--------------+---------------+----------+
| 2 or 3 Reconnect, | Z | ECDHE shared | variable |
| rekeying, with ECDHE, | | secret from | |
| same or new cryptosuite | | PKs2 and | |
| | | PKp2 | |
| +--------------+---------------+----------+
| | AlgorithmId | "EAP-NOOB" | 8 |
| +--------------+---------------+----------+
| | PartyUInfo | Np2 | 32 |
| +--------------+---------------+----------+
| | PartyVInfo | Ns2 | 32 |
| +--------------+---------------+----------+
| | SuppPubInfo | (not | |
| | | allowed) | |
| +--------------+---------------+----------+
| | SuppPrivInfo | Kz | 32 |
+-------------------------+--------------+---------------+----------+
Table 4: Key Derivation Input
Next up is Table 5, which says how the bytes the KDF spits out get used ๐ Along with the EAP output values MSK and EMSK, the server and peer also derive another shared secret key called AMSK (Application Main Session Key), which MAY be used for application-layer security. The leftover output bytes are used internally by EAP-NOOB for its message authentication keys (Kms, Kmp, Kms2, and Kmp2).
The Completion Exchange (KeyingMode=0) makes the shared secret Kz, and the server and peer store it in the persistent EAP-NOOB association. If a new cryptosuite gets negotiated in the Reconnect Exchange (KeyingMode=3), that also makes a new Kz. In that case, the server and peer update both the cryptosuite and Kz in the persistent EAP-NOOB association. The peer also keeps the previous Cryptosuitep and Kz values, stored in the CryptosuitepPrev and KzPrev fields of the persistent EAP-NOOB association ๐
โ ๏ธ Heads up: Table 5 is where the byte ranges get sliced up, so double-check your offsets when you implement this ๐ซถ
+==============================+============+==========+=========+
| KeyingMode | KDF output | Used as | Length |
| | bytes | | (bytes) |
+==============================+============+==========+=========+
| 0 Completion | 0..63 | MSK | 64 |
| +------------+----------+---------+
| | 64..127 | EMSK | 64 |
| +------------+----------+---------+
| | 128..191 | AMSK | 64 |
| +------------+----------+---------+
| | 192..223 | MethodId | 32 |
| +------------+----------+---------+
| | 224..255 | Kms | 32 |
| +------------+----------+---------+
| | 256..287 | Kmp | 32 |
| +------------+----------+---------+
| | 288..319 | Kz | 32 |
+------------------------------+------------+----------+---------+
| 1 or 2 Reconnect, rekeying | 0..63 | MSK | 64 |
| without ECDHE, or with ECDHE +------------+----------+---------+
| and unchanged cryptosuite | 64..127 | EMSK | 64 |
| +------------+----------+---------+
| | 128..191 | AMSK | 64 |
| +------------+----------+---------+
| | 192..223 | MethodId | 32 |
| +------------+----------+---------+
| | 224..255 | Kms2 | 32 |
| +------------+----------+---------+
| | 256..287 | Kmp2 | 32 |
+------------------------------+------------+----------+---------+
| 3 Reconnect, rekeying with | 0..63 | MSK | 64 |
| ECDHE, new cryptosuite +------------+----------+---------+
| | 64..127 | EMSK | 64 |
| +------------+----------+---------+
| | 128..191 | AMSK | 64 |
| +------------+----------+---------+
| | 192..223 | MethodId | 32 |
| +------------+----------+---------+
| | 224..255 | Kms2 | 32 |
| +------------+----------+---------+
| | 256..287 | Kmp2 | 32 |
| +------------+----------+---------+
| | 288..319 | Kz | 32 |
+------------------------------+------------+----------+---------+
Table 5: Key Derivation Output
Last but definitely not least ๐ every EAP method has to export a Server-Id, Peer-Id, and Session-Id [RFC5247]. In EAP-NOOB, the exported Peer-Id is the PeerId that the server assigned to the peer. The exported Server-Id is a zero-length string (aka the null string), because EAP-NOOB neither knows nor assigns any server identifier. The exported Session-Id is made by sticking the one-byte Type-Code 0x38 (decimal value 56) together with the MethodId, which comes from the KDF output as shown in Table 5. It's giving main character energy ๐โจ
3.6. Error Handling ๐
Okay bestie, when something goes sideways in EAP-NOOB, we don't just keep chatting like nothing happened ๐ We send an error notification message (Type=0) instead of the next EAP request or response. Both the EAP server and the peer can send one, as shown in Figures 9 and 10 below ๐ฆ. After sending or receiving an error notification, the server MUST send an EAP-Failure (as required by [RFC3748], Section 4.2). Non-negotiable, periodt ๐ . The notification MAY contain an ErrorInfo field, which is a UTF-8-encoded text string with a maximum length of 500 bytes. It's just for descriptive info for logging and debugging, so future-you can figure out what went wrong ๐ง
EAP Peer EAP Server
... ...
| |
|<----------- EAP-Request/EAP-NOOB ----------------|
| (Type=0,[PeerId],ErrorCode,[ErrorInfo]) |
| |
| |
|<----------- EAP-Failure -------------------------|
| |
Figure 9: Error Notification from Server to Peer ๐ธ
EAP Peer EAP Server
... ...
| |
|------------ EAP-Response/EAP-NOOB -------------->|
| (Type=0,[PeerId],ErrorCode,[ErrorInfo]) |
| |
| |
|<----------- EAP-Failure -------------------------|
| |
Figure 10: Error Notification from Peer to Server ๐ธ
After the exchange fails because of an error notification, the server and peer set their association state like this ๐. In the Initial Exchange, both the sender and the recipient of the error notification MUST set the association state to the Unregistered (0) state. In the Waiting Exchange and Completion Exchange, each side MUST stay in its old state, as if the failed exchange never happened. The one exception is the recipient of error code 2003, who processes it as specified in Section 3.2.4 โจ. In the Reconnect Exchange, both sides MUST set the association state to the Reconnecting (3) state.
Errors that happen in the OOB channel are not explicitly notified in-band. That one's on the OOB channel, no in-band drama needed ๐ โโ๏ธ
3.6.1. Invalid Messages ๐
If the NAI structure is invalid, the server SHOULD send the error code 1001 to the peer. The recipient of an EAP-NOOB request or response SHOULD send the following error codes back to the sender: 1002 if it cannot parse the message as a JSON object, or if the top-level JSON object has missing or unrecognized members; 1003 if a data field has an invalid value, such as an integer out of range, and there's no more specific error code available; 1004 if the received message type was unexpected in the current state; 2004 if the PeerId has an unexpected value; 2003 if the NoobId is not recognized; and 1005 if the ECDHE key is invalid. Lots of codes, bestie, but each one is so specific ๐ค๐
3.6.2. Unwanted Peer ๐ซ
The preferred way for the EAP server to rate limit EAP-NOOB connections from a peer is to use the SleepTime parameter in the Waiting Exchange ๐ข. However, if the EAP server receives repeated EAP-NOOB connections from a peer that apparently should not connect to this server, the server MAY indicate that the connections are unwanted by sending the error code 2001. After getting this error message, the peer MAY refrain from reconnecting to the same EAP server. If possible, both the EAP server and peer SHOULD indicate this error condition to the user or server administrator. Also, to avoid persistent denial of service, peer devices that can't alert a user SHOULD keep trying to reconnect infrequently (for example, approximately every 3600 seconds) โฐ๐ฅน
3.6.3. State Mismatch ๐งฉ
In the states marked with "-" in Table 14 in Appendix A, user action is required to reset the association state or to recover it, for example from backup storage ๐ญ. In those cases, the server sends the error code 2002 to the peer. If possible, both the EAP server and peer SHOULD indicate this error condition to the user or server administrator.
3.6.4. Negotiation Failure ๐
If there's no matching protocol version, the peer sends the error code 3001 to the server. If there's no matching cryptosuite, the peer sends the error code 3002 to the server. If there's no matching OOB direction, the peer sends the error code 3003 to the server.
In practice, there's no way to recover from these errors without software or hardware changes ๐. If possible, both the EAP server and peer SHOULD indicate these error conditions to the user.
3.6.5. Cryptographic Verification Failure ๐
If the receiver of the OOB message detects an unrecognized PeerId or an incorrect fingerprint (Hoob) in the OOB message, the receiver MUST remain in the Waiting for OOB (1) state, as if no OOB message was received. The receiver SHOULD indicate the failure to accept the OOB message to the user. No in-band error message is sent.
Note that if the OOB message was delivered from the server to the peer and the peer does not recognize the PeerId, the likely cause is that the user accidentally delivered the OOB message to the wrong peer device ๐. If possible, the peer SHOULD indicate this to the user. However, the peer device may not have the capability for many different error indications to the user, so it MAY use the same indication as for an incorrect fingerprint.
The reason for all this is that the invalid OOB message could have been presented to the receiver by mistake, or on purpose by a malicious party ๐. So it should be ignored, in the hope that the honest user soon delivers a correct OOB message ๐ซถ.
If the EAP server or peer detects an incorrect message authentication code (MACs, MACp, MACs2, or MACp2), it sends the error code 4001 to the other side. As specified at the beginning of Section 3.6, a failed Completion Exchange does not result in server or peer state changes, while an error in the Reconnect Exchange puts both sides into the Reconnecting (3) state, which leads to another reconnect attempt ๐.
The reason for this is that the invalid cryptographic message may have been spoofed by a malicious party, so it should be ignored ๐ต๏ธโโ๏ธ. In particular, a spoofed message on the in-band channel should not force the honest user to perform the OOB Step again. In practice, though, the error may come from other failures, such as a software bug ๐. For this reason, the EAP server MAY limit the rate of peer connections with SleepTime after the above error. Also, there SHOULD be a way for the user to reset the peer to the Unregistered (0) state, so the OOB Step can be repeated as the last resort ๐.
3.6.6. Application-Specific Failure ๐
Applications MAY define new error messages for failures that are specific to the application or to one type of OOB channel ๐ง. They MAY also use the generic application-specific error code 5001, or the error codes 5002 and 5004, which have been reserved for indicating invalid data in the ServerInfo and PeerInfo fields, respectively. And since OOB channels that use a URL are anticipated, the error code 5003 has been reserved for indicating an invalid server URL ๐โจ
4. ServerInfo and PeerInfo Contents โจ
okay bestie, so ServerInfo and PeerInfo are the fields in the Initial Exchange and Reconnect Exchange where the server and the peer get to spill the tea about themselves ๐ to the other side. They're JSON objects, and their structure can be specified separately for each application and each type of OOB channel ๐. ServerInfo and PeerInfo MAY carry extra auxiliary data needed for the OOB channel messaging and for EAP channel binding (see Section 6.7) ๐ซถ. This section covers the optional starter fields that this spec registers for ServerInfo and PeerInfo. Further specs can ask IANA for their own app-specific ServerInfo and PeerInfo fields too (see Sections 5.4 and 5.5) ๐
+================+=================================================+
| Data Field | Description |
+================+=================================================+
| Type | Type-tag string that can be used by the peer as |
| | a hint for how to interpret the ServerInfo |
| | contents. |
+----------------+-------------------------------------------------+
| ServerName | String that may be used to aid human |
| | identification of the server. |
+----------------+-------------------------------------------------+
| ServerURL | Prefix string when the OOB message is formatted |
| | as a URL, as suggested in Appendix D. |
+----------------+-------------------------------------------------+
| SSIDList | List of IEEE 802.11 wireless network service |
| | set identifier (SSID) strings used for roaming |
| | support, as suggested in Appendix C. JSON |
| | array of ASCII-encoded SSID strings. |
+----------------+-------------------------------------------------+
| Base64SSIDList | List of IEEE 802.11 wireless network identifier |
| | (SSID) strings used for roaming support, as |
| | suggested in Appendix C. JSON array of SSIDs, |
| | each of which is base64url-encoded without |
| | padding. Peers SHOULD send at most one of the |
| | fields SSIDList and Base64SSIDList in PeerInfo, |
| | and the server SHOULD ignore SSIDList if |
| | Base64SSIDList is included. |
+----------------+-------------------------------------------------+
Table 6: ServerInfo Data Fields
+==============+===================================================+
| Data Field | Description |
+==============+===================================================+
| Type | Type-tag string that can be used by the server as |
| | a hint for how to interpret the PeerInfo |
| | contents. |
+--------------+---------------------------------------------------+
| PeerName | String that may be used to aid human |
| | identification of the peer. |
+--------------+---------------------------------------------------+
| Manufacturer | Manufacturer or brand string. |
+--------------+---------------------------------------------------+
| Model | Manufacturer-specified model string. |
+--------------+---------------------------------------------------+
| SerialNumber | Manufacturer-assigned serial number. |
+--------------+---------------------------------------------------+
| MACAddress | Peer link-layer 48-bit extended unique identifier |
| | (EUI-48) in the 12-digit base-16 form [EUI-48]. |
| | The string MAY be in upper or lower case and MAY |
| | include additional colon ':' or dash '-' |
| | characters that MUST be ignored by the server. |
+--------------+---------------------------------------------------+
| SSID | IEEE 802.11 network SSID for channel binding. |
| | The SSID is an ASCII string. |
+--------------+---------------------------------------------------+
| Base64SSID | IEEE 802.11 network SSID for channel binding. |
| | The SSID is base64url encoded. Peer SHOULD send |
| | at most one of the fields SSID and Base64SSID in |
| | PeerInfo, and the server SHOULD ignore SSID if |
| | Base64SSID is included. |
+--------------+---------------------------------------------------+
| BSSID | Wireless network basic service set identifier |
| | (BSSID) (EUI-48) in the 12-digit base-16 form |
| | [EUI-48] for channel binding. The string MAY be |
| | in upper or lower case and MAY include additional |
| | colon ':' or dash '-' characters that MUST be |
| | ignored by the server. |
+--------------+---------------------------------------------------+
Table 7: PeerInfo Data Fields
5. IANA Considerations ๐ฆ
okay so this section is all about registering EAP-NOOB values with IANA, following [RFC8126] ๐
The EAP Method Type for EAP-NOOB (value 56) has been assigned in the "Method Types" subregistry of the "Extensible Authentication Protocol (EAP) Registry" ๐
Per this memo, IANA has created and will maintain a brand-new registry called "Nimble Out-of-Band Authentication for EAP Parameters (EAP-NOOB)" in the Extensible Authentication Protocol (EAP) category. IANA has also created and will maintain the subregistries described in the subsections below ๐
5.1. Cryptosuites โจ
IANA has created and will maintain a new subregistry called "EAP-NOOB Cryptosuites" inside the "Nimble Out-of-Band Authentication for EAP Parameters (EAP-NOOB)" registry. Cryptosuites are identified by an integer. Each cryptosuite MUST specify an ECDHE curve for the key exchange, the encoding of the ECDHE public key as a JWK object, and a cryptographic hash function for the fingerprint and HMAC computation and key derivation. The hash value output by that cryptographic hash function MUST be at least 32 bytes in length. The initial values for this registry are:
+=============+===============================================+
| Cryptosuite | Algorithms |
+=============+===============================================+
| 0 | Reserved |
+-------------+-----------------------------------------------+
| 1 | ECDHE curve Curve25519 [RFC7748], public-key |
| | format [RFC7517], hash function SHA-256 |
| | [RFC6234]. The JWK encoding of Curve25519 |
| | public key is defined in [RFC8037]. For |
| | clarity, the "crv" parameter is "X25519", the |
| | "kty" parameter is "OKP", and the public-key |
| | encoding contains only an x-coordinate. |
+-------------+-----------------------------------------------+
| 2 | ECDHE curve NIST P-256 [FIPS186-4], public- |
| | key format [RFC7517], hash function SHA-256 |
| | [RFC6234]. The JWK encoding of NIST P-256 |
| | public key is defined in [RFC7518]. For |
| | clarity, the "crv" parameter is "P-256", the |
| | "kty" parameter is "EC", and the public-key |
| | encoding has both an x and y coordinate, as |
| | defined in Section 6.2.1 of [RFC7518]. |
+-------------+-----------------------------------------------+
Table 8: EAP-NOOB Cryptosuites
EAP-NOOB implementations MUST support Cryptosuite 1. Support for Cryptosuite 2 is RECOMMENDED. Here's an example of a Cryptosuite 1 public key encoded as a JWK object ๐ (the line breaks are just for readability, not part of the value):
"jwk":{"kty":"OKP","crv":"X25519","x":"3p7bfXt9wbTTW2HC7OQ1Nz-
DQ8hbeGdNrfx-FG-IK08"}
Assignment of new values for new cryptosuites MUST be done through IANA with "Specification Required", as defined in [RFC8126] ๐
5.2. Message Types ๐
IANA has created and will maintain a new subregistry called "EAP-NOOB Message Types" inside the "Nimble Out-of-Band Authentication for EAP Parameters (EAP-NOOB)" registry. EAP-NOOB request and response pairs are identified by an integer Message Type. The initial values for this registry are:
+=========+============+========================================+
| Message | Used in | Purpose |
| Type | Exchange | |
+=========+============+========================================+
| 0 | Error | Error notification |
+---------+------------+----------------------------------------+
| 1 | All | PeerId and PeerState discovery |
| | exchanges | |
+---------+------------+----------------------------------------+
| 2 | Initial | Version, cryptosuite, and parameter |
| | | negotiation |
+---------+------------+----------------------------------------+
| 3 | Initial | Exchange of ECDHE keys and nonces |
+---------+------------+----------------------------------------+
| 4 | Waiting | Indication to the peer that the server |
| | | has not yet received an OOB message |
+---------+------------+----------------------------------------+
| 5 | Completion | NoobId discovery |
+---------+------------+----------------------------------------+
| 6 | Completion | Authentication and key confirmation |
| | | with HMAC |
+---------+------------+----------------------------------------+
| 7 | Reconnect | Version, cryptosuite, and parameter |
| | | negotiation |
+---------+------------+----------------------------------------+
| 8 | Reconnect | Exchange of ECDHE keys and nonces |
+---------+------------+----------------------------------------+
| 9 | Reconnect | Authentication and key confirmation |
| | | with HMAC |
+---------+------------+----------------------------------------+
Table 9: EAP-NOOB Message Types
Assignment of new values for new Message Types MUST be done through IANA with "Specification Required", as defined in [RFC8126] ๐ซถ
5.3. Error Codes ๐จ
okay bestie, IANA is creating and looking after a brand new subregistry called "EAP-NOOB Error codes" inside the "Nimble Out-of-Band Authentication for EAP Parameters (EAP-NOOB)" registry ๐ . Cryptosuites are identified by an integer. The starting values are in this table:
+============+===========================================+
| Error code | Purpose |
+============+===========================================+
| 1001 | Invalid NAI |
+------------+-------------------------------------------+
| 1002 | Invalid message structure |
+------------+-------------------------------------------+
| 1003 | Invalid data |
+------------+-------------------------------------------+
| 1004 | Unexpected message type |
+------------+-------------------------------------------+
| 1005 | Invalid ECDHE key |
+------------+-------------------------------------------+
| 2001 | Unwanted peer |
+------------+-------------------------------------------+
| 2002 | State mismatch, user action required |
+------------+-------------------------------------------+
| 2003 | Unrecognized OOB message identifier |
+------------+-------------------------------------------+
| 2004 | Unexpected peer identifier |
+------------+-------------------------------------------+
| 3001 | No mutually supported protocol version |
+------------+-------------------------------------------+
| 3002 | No mutually supported cryptosuite |
+------------+-------------------------------------------+
| 3003 | No mutually supported OOB direction |
+------------+-------------------------------------------+
| 4001 | HMAC verification failure |
+------------+-------------------------------------------+
| 5001 | Application-specific error |
+------------+-------------------------------------------+
| 5002 | Invalid server info |
+------------+-------------------------------------------+
| 5003 | Invalid server URL |
+------------+-------------------------------------------+
| 5004 | Invalid peer info |
+------------+-------------------------------------------+
| 6001-6999 | Reserved for Private and Experimental Use |
+------------+-------------------------------------------+
Table 10: EAP-NOOB Error Codes
Adding new error codes MUST go through IANA with "Specification Required" (that's [RFC8126]), except for 6001-6999. That range is reserved for "Private Use" and "Experimental Use", both locally and on the open Internet ๐.
5.4. ServerInfo Data Fields ๐งพ
IANA is making another subregistry, this one called "EAP-NOOB ServerInfo Data Fields", inside that same "Nimble Out-of-Band Authentication for EAP Parameters (EAP-NOOB)" registry โจ. The starting values look like this:
+================+=====================+
| Data Field | Specification |
+================+=====================+
| Type | RFC 9140, Section 4 |
+----------------+---------------------+
| ServerName | RFC 9140, Section 4 |
+----------------+---------------------+
| ServerURL | RFC 9140, Section 4 |
+----------------+---------------------+
| SSIDList | RFC 9140, Section 4 |
+----------------+---------------------+
| Base64SSIDList | RFC 9140, Section 4 |
+----------------+---------------------+
Table 11: ServerInfo Data Fields
New values for new ServerInfo data fields MUST be assigned through IANA with "Specification Required", as defined in [RFC8126] ๐.
5.5. PeerInfo Data Fields ๐ฑ
IANA has been asked to create and maintain a new subregistry called "EAP-NOOB PeerInfo Data Fields", inside the "Nimble Out-of-Band Authentication for EAP Parameters (EAP-NOOB)" registry ๐ฆ. The starting values are:
+==============+=====================+
| Data Field | Specification |
+==============+=====================+
| Type | RFC 9140, Section 4 |
+--------------+---------------------+
| PeerName | RFC 9140, Section 4 |
+--------------+---------------------+
| Manufacturer | RFC 9140, Section 4 |
+--------------+---------------------+
| Model | RFC 9140, Section 4 |
+--------------+---------------------+
| SerialNumber | RFC 9140, Section 4 |
+--------------+---------------------+
| MACAddress | RFC 9140, Section 4 |
+--------------+---------------------+
| SSID | RFC 9140, Section 4 |
+--------------+---------------------+
| Base64SSID | RFC 9140, Section 4 |
+--------------+---------------------+
| BSSID | RFC 9140, Section 4 |
+--------------+---------------------+
Table 12: PeerInfo Data Fields
New values for new PeerInfo data fields MUST be assigned through IANA with "Specification Required", as defined in [RFC8126] ๐.
5.6. Domain Name Reservation ๐
The special-use domain eap-noob.arpa has been registered in the .arpa registry (https://www.iana.org/domains/arpa) and in the "Special-Use Domain Names" registry (https://www.iana.org/assignments/special-use-domain-names) ๐.
5.7. Guidance for Designated Experts ๐
Experts SHOULD be conservative about handing out new Cryptosuites ๐. Experts MUST check that the requested values line up with the current Crypto Forum Research Group (CFRG) guidance on cryptographic algorithm security ๐. Experts MUST make sure that any new Cryptosuites fully specify how the ECDHE public key is encoded, and should include details such as the value of the "kty" (key type) parameter when JWK [RFC7517] encoding is used.
Experts SHOULD be conservative with new Message Types too ๐ . Experts SHOULD check that a well-defined specification for the new Message Type is permanently and publicly available ๐.
Experts SHOULD be conservative with new Error codes as well, since 6001-6999 is already set aside for private and experimental use ๐งช.
Experts MAY be liberal when handing out new ServerInfo and PeerInfo data fields ๐ฅฐ. Experts MUST make sure the requested data field has a unique name that isn't easily confused with existing registrations. For example, a request for a new PeerInfo data field "ssid" should be rejected even though it's unique, because it can be confused with the existing registration of "SSID" ๐
โโ๏ธ. Experts MUST also make sure that a suitable Description for the data field is available.
6. Security Considerations ๐
okay, this part is serious bestie ๐ญ. EAP-NOOB is an authentication and key derivation protocol, so you'll find security considerations in most sections of this spec ๐ซถ. Down below, we walk through the protocol design and call out some other special considerations that you really don't want to skip ๐.
6.1. Authentication Principle โจ
okay bestie, so EAP-NOOB sets up a shared secret with an authenticated ECDHE key exchange ๐. The mutual authentication is built on two separate features, and both ride along in the OOB message ๐. Feature one is the secret nonce Noob. The peer and server use it in the Completion Exchange to mutually authenticate the session key they made with ECDHE ๐ซถ. The message authentication codes computed with Noob are alone enough to authenticate the key exchange, no cap ๐ . Feature two is the integrity-protecting fingerprint Hoob ๐ฆ. Its whole purpose is to prevent impersonation attacks, even when an attacker can eavesdrop on the OOB channel and Noob has been compromised ๐ญ. In human-assisted OOB channels like human-perceptible audio or a user-typed URL, it can be easier to spot tampering than to spot disclosure of the OOB message, so those apps really benefit from feature two ๐.
The fingerprint Hoob is kinda intricate, ngl ๐. The endpoint that receives the OOB message uses Hoob to verify the integrity of the ECDHE exchange, so the OOB receiver can catch impersonation attacks that might have happened on the in-band channel โจ. The other endpoint isn't equally protected, though, because the OOB message and fingerprint only go one direction ๐. The OOB sender gets some protection from the fact that the user may notice the association failing at the OOB receiver and then reset the OOB sender ๐ธ. Other device-pairing protocols have fixed similar situations by making the user confirm to the OOB sender that the receiver accepted it, e.g., with a button press on the sender side ๐. Applications MAY implement EAP-NOOB this way ๐. Still, EAP-NOOB was designed to work with strictly one-directional OOB communication, and the fingerprint is only the second feature, so the spec does not mandate that explicit confirmation to the OOB sender ๐.
Here's the summary ๐. EAP-NOOB uses the combined protection of Noob and Hoob, both conveyed in the OOB message ๐. Noob alone is sufficient for mutual authentication unless the attacker can eavesdrop on it from the OOB channel ๐ง. Even if an attacker eavesdrops on Noob, they still can't pull off a full impersonation attack on the in-band channel, because a mismatching fingerprint would alert the OOB receiver, which would reject the OOB message ๐ก๏ธ. The attacker who eavesdropped on Noob can impersonate the OOB receiver to the OOB sender. If they do, the association only looks complete on the OOB sender side, and the user has to fix that by resetting the OOB sender to the initial state ๐ค.
The expected use cases are ones where EAP-NOOB replaces a user-entered access credential in IoT appliances ๐ . In wireless network access without EAP, that user-entered credential is often a passphrase shared by all the network stations ๐ถ. The advantage of an EAP-based solution, EAP-NOOB included, is that it establishes a different shared secret for each peer device, which makes the system more resilient against device compromise ๐ช. Another perk is that you can revoke the security association for an individual device on the server side ๐ซ.
Forward secrecy during fast reconnect in EAP-NOOB is optional ๐. The Reconnect Exchange only provides forward secrecy if both the server and peer send their fresh ECDHE keys. That lets both of them limit how often the costly computation for forward secrecy happens ๐งฎ. The server MAY adjust how often it attempts ECDHE rekeying, based on what it knows about the peer's computational capabilities ๐ฏ.
Another way some servers control their computational load is to reuse the same ECDHE key for all peers over a short server-specific time window ๐ฐ๏ธ. In that case, forward secrecy is only achieved after the server updates its ECDHE key, which may be a reasonable trade-off between security and performance โ๏ธ. However, the server MUST NOT reuse the same ECDHE key with the same peer when rekeying with ECDHE (KeyingMode=2 or KeyingMode=3) ๐จ. Instead, it can simply not send an ECDHE key (KeyingMode=1) โจ.
The users delivering OOB messages will often authenticate themselves to the EAP server, e.g., by logging into a secure web page or API ๐. In that case, the server can associate the peer device with the user account ๐ค. Applications that use EAP-NOOB can use this info to configure the initial owner of the freshly registered device ๐.
6.2. Identifying Correct Endpoints ๐ต๏ธโโ๏ธ
okay so the potential weaknesses in EAP-NOOB come from the fact that the user has to physically identify the correct peer device ๐. If the user accidentally delivers the OOB message from the wrong peer device to the server, the server may create an association with the wrong peer ๐ฌ. Relying on the user to identify the correct endpoints is an inherent property of user-assisted, out-of-band authentication ๐ง . To understand what a user mistake could lead to, we need to check out a few different scenarios ๐.
In the first scenario, there's no malicious party. The user just makes an accidental mistake between two out-of-the-box devices that are both ready to be registered to a server ๐คทโโ๏ธ. If the user delivers the OOB message from the wrong device to the server, confusion may arise, but usually no security issues ๐. In the second scenario, an attacker intentionally tricks the user, for example by substituting the original peer device with a compromised one ๐. That's essentially a supply chain attack where the user accepts a compromised physical device ๐ฆ.
There's also a third scenario, where an opportunistic attacker tries to take advantage of the user's accidental mistake ๐ฆนโโ๏ธ. For example, the user could play an audio or a blinking LED message to a device that isn't expecting to receive it ๐ก. In simple security bootstrapping solutions that transfer a primary key to the device via the OOB channel, the device could misuse or leak the accidentally received primary key ๐. EAP-NOOB isn't vulnerable to these opportunistic attackers, because the OOB message has no value to anyone who did not take part in the corresponding Initial Exchange ๐ โโ๏ธโจ.
One mechanism that can mitigate user mistakes is certification of peer devices ๐ . A certificate or an attestation token (e.g., [TLS-CWT] and [RATS-EAT]) can convey authentic identifiers and attributes of the peer device to the server, such as model and serial number ๐. Compared to fully certificate-based authentication, though, EAP-NOOB can be used without trusted third parties, and it doesn't require the user to know any identifier of the peer device. Physical access to the device is sufficient for bootstrapping with EAP-NOOB ๐ซถ.
Similarly, the attacker can try to trick the user into delivering the OOB message to the wrong server, so that the peer device becomes associated with the wrong server ๐ญ. If the EAP server is accessed through a web user interface, the attack is akin to phishing, where the user is tricked into accessing the wrong URL and wrong web page ๐ฃ. OOB implementation with a dedicated app on a mobile device, which communicates with a server API at a preconfigured URL, can protect against such attacks ๐ฑ๐ก๏ธ.
After device registration, an attacker could clone the device identity by copying the keys from the persistent EAP-NOOB association into another device ๐ฏโโ๏ธ. The attacker can be an outsider who gains access to the keys, or the device owner who wants to have two devices matching the same registration ๐. The cloning threats can be mitigated by creating the cryptographic keys and storing the persistent EAP-NOOB association on the peer device in a secure hardware component, such as a trusted execution environment (TEE) ๐. Furthermore, remote attestation on the application level could give the server assurance that the device has not been cloned ๐งพ. A Reconnect Exchange with a new cryptosuite (KeyingMode=3) will also disconnect all but the first clone that performs the update ๐.
6.3. Trusted Path Issues and Misbinding Attacks ๐ช
another potential threat is spoofed user input or output on the peer device ๐ป. When the user is delivering the OOB message to or from the correct peer device, a trusted path between the user and the peer device is needed ๐ค๏ธ. That means the user must communicate directly with an authentic operating system and EAP-NOOB implementation in the peer device, not with a spoofed user interface ๐ โโ๏ธ. Otherwise, a registered device under the control of the attacker could emulate the behavior of an unregistered device ๐ฑ. The secure path can be implemented, for example, by having the user press a reset button to return the device to the Unregistered (0) state and to invoke a trusted UI ๐. The problem is that these trusted paths aren't standardized across devices ๐ค.
Another potential consequence of a spoofed UI is the misbinding attack ๐ฏ. This is where the user tries to register a correct but compromised device, which tricks the user into registering another (uncompromised) device instead ๐ฅด. For example, the compromised device might have a malicious, full-screen app running that shows the user QR codes copied, in real time, from another device's screen ๐ฑ๐. If the unwitting user scans the QR code and delivers the OOB message in it to the server, the wrong device may become registered in the server ๐. These misbinding vulnerabilities arise because the user has no secure way to verify that the in-band cryptographic handshake and the out-of-band physical access terminate at the same physical device ๐. Sethi et al. [Sethi19] analyze the misbinding threat against device-pairing protocols and also EAP-NOOB ๐. Essentially, all protocols where authentication relies on the user's physical access to the device are vulnerable to misbinding, including EAP-NOOB ๐งจ.
A standardized trusted path for communicating directly with the trusted computing base in a physical device would mitigate the misbinding threat, but such paths rarely exist in practice ๐ฅบ. Careful asset tracking on the server side can also prevent most misbinding attacks, if the peer device sends its identifiers or attributes in the PeerInfo field and the server compares them with the expected values ๐โจ. The wrong but uncompromised device's PeerInfo will not match the expected values, so it gets caught ๐จ. Device certification by the manufacturer can further strengthen the asset tracking ๐ญ๐.
6.4. Peer Identifiers and Attributes โจ
Okay so the PeerId is the server's own little nametag for its association with a peer ๐ It SHOULD NOT be shown to the user, because its value starts out ephemeral (temporary, not forever) ๐ฆ
Since the server is the one handing out the PeerId, and it only has to mean something inside that one server, the so-called identifier squatting attacks (where a sneaky peer grabs somebody else's identifier) are literally not possible in EAP-NOOB ๐ The server SHOULD assign a random or pseudorandom PeerId to each new peer. It SHOULD NOT pick the PeerId based on any peer characteristics it might happen to know, like the peer's link-layer network address ๐
Now the messy part ๐ญ User reset or failure in the OOB Step can make the peer do a bunch of Initial Exchanges with the server. Each one gets a new PeerId and stores ephemeral protocol state, so the server ends up holding lots of them. The peer will typically only remember the latest ones. EAP-NOOB leaves it up to the implementation to decide when to delete these ephemeral associations. There is no security reason to delete them early, and the server has no way to verify that the peers are actually the same one. So the safest move is to store the ephemeral states on the server for at least one day โญ If the OOB messages are sent only in the server-to-peer direction, the server SHOULD NOT delete the ephemeral state before all the related Noob values have expired. Keep those values alive ๐ง
After EAP-NOOB is done, the server may store the PeerInfo data, and the user may use it to identify the peer and its attributes, like the make and model or serial number ๐ But a compromised peer could lie in the PeerInfo it sends, so if the server stores anything about the peer, the user needs to approve it during or after the OOB Step ๐ Without that user verification or authentication at the application level, the PeerInfo is not authenticated information and should not be relied on. One possible use for the PeerInfo field is EAP channel binding (see Section 6.7) ๐ฆ
6.5. Downgrading Threats ๐
The fingerprint Hoob protects all the information exchanged in the Initial Exchange, including the cryptosuite negotiation. The message authentication codes MACs and MACp also protect that same info. The message authentication codes MACs2 and MACp2 protect information exchanged during key renegotiation in the Reconnect Exchange. This prevents downgrading attacks to weaker cryptosuites, as long as the possible attacks take more time than the maximum time allowed for EAP-NOOB completion. That's typically the case for recently discovered cryptanalytic attacks, so we're safe-ish ๐
As an extra precaution, the EAP server and peer MUST check for downgrading attacks in the Reconnect Exchange like this. As long as the server or peer saves any information about the other endpoint, it MUST also remember the previously negotiated cryptosuite, and it MUST NOT accept renegotiation of any cryptosuite that is known to be weaker than the previous one, such as a deprecated cryptosuite. Figuring out how strong each cryptosuite is counts as out of scope for this spec. Implementations or local policies at the peer and server may manage that instead ๐ฅ
Now the direction negotiation, which is its own vibe ๐ญ Its integrity can't be verified the same way the cryptosuite negotiation's can. So if the OOB channel used in an application is critically insecure in one direction, an on-path attacker could modify the negotiation messages and force that direction to be used. Applications that support OOB messages in both directions SHOULD, therefore, ensure that the OOB channel has sufficiently strong security in both directions. It's a theoretical vulnerability, but it could show up in practice if EAP-NOOB gets deployed in new applications. Right now, most peer devices are expected to support only one OOB direction, so messing with the direction negotiation can only stop the protocol from finishing ๐ซถ
Last bit: the long-term shared key material Kz in the persistent EAP-NOOB association is set up with an ECDHE key exchange when the peer and server first associate. It's a weaker secret than a manually configured random shared key, because advances in cryptanalysis against the ECDHE curve in use could eventually let an attacker recover Kz. EAP-NOOB protects against that by allowing cryptosuite upgrades in the Reconnect Exchange, and by updating the shared key material Kz whenever the cryptosuite gets upgraded. Upgrades aren't expected to happen often, but when one is needed, it can happen without a manual reset and reassociation of the peer devices โจ
6.6. Protected Success and Failure Indications ๐
Section 7.16 of [RFC3748] lets EAP methods specify protected result indications, because EAP-Success and EAP-Failure packets are neither acknowledged nor integrity protected. [RFC3748] notes that these indications may be explicit or implicit ๐ฆ
EAP-NOOB relies on implicit, protected success indicators in the Completion Exchange and the Reconnect Exchange. Successful verification of MACs and MACs2 in the EAP-Request message from the server (message type 6 and message type 9, respectively) acts as an implicit, protected success indication to the peer. Similarly, successful verification of MACp and MACp2 in the EAP-Response message from the peer (message type 6 and message type 9, respectively) acts as an implicit, protected success indication to the server ๐
EAP-NOOB failure messages are not protected. Protected failure result indications wouldn't meaningfully improve availability, since EAP-NOOB reacts to most malformed data by ending the current EAP conversation in EAP-Failure. Also, because EAP-NOOB spans multiple conversations, a failure in one conversation usually means no state change at the level of the EAP-NOOB state machine ๐
6.7. Channel Binding ๐ฆ
EAP channel binding, defined in [RFC6677], means the endpoints compare their perceptions of network properties, like lower-layer identifiers, over the secure channel that EAP authentication set up. Section 4.1 of [RFC6677] defines two approaches to channel binding. EAP-NOOB follows the first one, where the peer and server exchange plaintext information about the network over a channel that is integrity protected with keys derived during the EAP execution. More specifically, channel information gets exchanged in the plaintext PeerInfo and ServerInfo objects, and is later verified with message authentication codes (MACp, MACs, MACp2, and MACs2). This allows policy-based comparison with locally perceived network properties on either side, plus logging for debugging purposes ๐
The peer MAY include in PeerInfo any data items that it wants to bind to the EAP-NOOB association and to the exported keys. These can be properties of the authenticator or the access link, like the SSID and BSSID of the wireless network (see Table 6). As noted in Section 4.3 of [RFC6677], the scope of channel binding varies between deployments. For example, the server may have less link-layer information available from roaming networks than from a local enterprise network, and it may be unable to verify all the network properties received in PeerInfo. There are also privacy considerations related to exchanging the ServerInfo and PeerInfo while roaming (see Section 6.10) ๐
Channel binding to secure channels, defined in [RFC5056], binds authentication at a higher protocol layer to a secure channel at a lower layer. Like most EAP methods, EAP-NOOB exports the session keys MSK and EMSK, and an outer tunnel or a higher-layer protocol can bind its authentication to these keys. EAP-NOOB also exports the key AMSK, which may be used to bind application-layer authentication to the secure channel created by EAP-NOOB and to the session keys MSK and EMSK โจ
6.8. Denial of Service ๐
Denial-of-service (DoS) attacks by on-link attackers can't be fully prevented, but the design goal in EAP-NOOB is to void long-lasting failure caused by an attacker who is only present temporarily or intermittently. The main defense is the persistent EAP-NOOB association, which is never deleted automatically due to in-band messages or error indications. So the endpoints can always use the persistent association to reconnect after the DoS attacker leaves the network. In this sense, the persistent association does the same job in EAP-NOOB as a permanent primary key or certificate does in other authentication protocols. Logical attacks against updates of the persistent association are discussed in Section 6.9 ๐ก๏ธ
Besides logical DoS attacks, resource exhaustion attacks against the EAP server also need to be considered. The number of persistent EAP-NOOB associations created in the server is limited by the need for a user to help deliver the OOB message. The users can be authenticated for the input or output of the OOB message at the EAP server, and any users who create excessive numbers of persistent associations can be held accountable, with their associations deleted by the server administrator. What an attacker can do without user authentication is perform the Initial Exchange repeatedly and create a large number of ephemeral associations (server in Waiting for OOB (1) state) without ever delivering the OOB message. Section 6.4 suggested that the server should store the ephemeral states for at least a day. This may require off-loading the state storage from memory to disk during a DoS attack. However, if the server implementation can't keep up with the rate of Initial Exchanges from a DoS attacker and needs to drop some ephemeral states, no damage is done to already-created persistent associations, and honest users can resume registering new peers once the DoS attacker leaves the network ๐ธ
There are some trade-offs in the protocol design between politely backing off and giving way to DoS attackers. An on-link DoS attacker could spoof the SleepTime value in the Initial Exchange or Waiting Exchange to cause denial of service against a specific peer device. There is an upper limit on the SleepTime (3600 seconds) to mitigate that spoofing threat. This means that, with an on-link DoS attacker spoofing the SleepTime, it could take up to one hour after the OOB message is delivered before the device performs the Completion Exchange and becomes functional ๐ญ Similarly, the Unwanted peer error (error code 2001) could cause the peer to stop connecting to the network. If the peer device can alert the user about the error condition, it can safely stop connecting to the server and wait for the user to trigger a reconnection attempt, e.g., by resetting the device. As mentioned in Section 3.6.2, peer devices that can't alert the user should keep retrying the Initial Exchange infrequently to avoid a permanent DoS condition โ ๏ธ
We believe a maximum backoff time of 3600 seconds is reasonable for a new protocol, because malfunctioning or misconfigured peer implementations are at least as big a concern as DoS attacks. Politely backing off within some reasonable limits will also help the protocol get accepted. The maximum backoff times could be shortened as the protocol implementations mature ๐
6.9. Recovery from Loss of Last Message โจ
okay so the EAP-NOOB Completion Exchange AND the Reconnect Exchange with cryptosuite update both cause a persistent state change, and that change has to happen on both endpoints or on neither ๐ซถ. If only one side changes, you get a state mismatch, and then the user has to step in and fix it ๐ญ. The mismatch can happen if the final EAP response from either exchange gets lost. In the Completion Exchange, losing the final response (Type=6) means the peer jumps to Registered (4) and creates a persistent EAP-NOOB association, but the server is stuck in an ephemeral state (1 or 2) ๐. In the Reconnect Exchange, losing the final response (Type=9) means the peer goes to Registered (4) and updates its persistent key material Kz, while the server is still in Reconnecting (3) holding onto the old key material ๐.
This is literally an unavoidable problem in distributed systems, bestie ๐. It's theoretically impossible to guarantee that state changes happen at the same time on endpoints that talk asynchronously. So every protocol has one critical message that might get lost, and then one side commits while the other doesn't. In EAP, that critical message is the final response from the peer to the server. Normally the final response is followed by EAP-Success, but [RFC3748], Section 4.2 says the peer MAY assume that the EAP-Success was lost and the authentication was successful ๐ฆ. Also, EAP method implementations on the peer never get notified about EAP-Success from the parent EAP state machine [RFC4137]. So for all these reasons, EAP-NOOB on the peer side commits to the state change as soon as it sends the final response, no waiting around ๐ .
The best available fix for a lost critical message is to keep trying ๐. The EAP retransmission behavior in Section 4.3 of [RFC3748] suggests 3-5 retransmissions. If there's no attacker, that's enough to make the chance of failure acceptable. But a determined attacker on the in-band channel can drop the final EAP-Response message and every retransmission after it ๐ค. In the Completion Exchange (KeyingMode=0) and the Reconnect Exchange with cryptosuite upgrade (KeyingMode=3), that could cause a state mismatch and a persistent denial of service until the user resets the peer state. Not me getting DoS'd by a villain ๐.
EAP-NOOB has its own recovery mechanism that lets the Reconnect Exchange be retried an unlimited number of times ๐. Once the DoS attacker stops dropping packets on the in-band channel, the protocol recovers. The logic for this is specified in Section 3.4.2.
EAP-NOOB does NOT do the same kind of retry thing in the Completion Exchange, and here's why ๐ง. A user is always involved in the initial association process, so the user can just repeat the OOB Step to finish the association after the DoS attacker is gone. The Reconnect Exchange, on the other hand, has to work without any user involvement, so it needs the retry logic ๐.
Main character energy is protecting your state machine, periodt ๐
6.10. Privacy Considerations ๐ธ
okay privacy time, and this one's a lot ๐. There are privacy issues when you do the Reconnect Exchange while roaming. The peer and server might send updated PeerInfo and ServerInfo fields during the Reconnect Exchange. That data goes unencrypted between the peer and the EAP authenticator, like a wireless access point ๐ฌ. So both random outsiders and the access network can see it. The PeerInfo field has identifiers and other info about the peer device (check Table 6). It's about the device, not directly about the user, but it can still leak stuff about the user to the access network and to outside observers ๐ซฃ. ServerInfo can leak whether the peer is affiliated with the home network. So for this reason, the optional PeerInfo and ServerInfo in the Reconnect Exchange SHOULD be omitted unless some critical data has changed and it can't be updated at the application layer ๐.
Peer devices that randomize their Layer 2 address to avoid being tracked can do that whenever the user resets the EAP-NOOB association โจ. During the association's lifetime, the PeerId is a unique identifier that can be used to track the peer on the access network, which is kinda sus ๐ต๏ธโโ๏ธ. Later versions of this spec might think about updating the PeerId at each Reconnect Exchange. If that happens, they'd need to figure out how the authenticator and access-network admins can spot misbehaving peer devices and add them to a deny list. They'd also need to avoid losing sync between the server and the peer if messages get dropped during the identifier update ๐งฉ.
To get stronger identity protection in later EAP-NOOB versions, the optional server-assigned NAI (NewNAI) SHOULD have a constant username part. The RECOMMENDED username is "noob" ๐ฅฐ. The server MAY, however, send a different username in NewNAI to avoid username collisions within its realm or to follow local username policy ๐.
6.11. EAP Security Claims ๐
EAP security claims are defined in Section 7.2.1 of [RFC3748] ๐. Here's what EAP-NOOB claims, in Table 13 (it's giving checklist energy โ ):
+=================+=================================================+
| Security | EAP-NOOB Claim |
| Property | |
+=================+=================================================+
| Authentication | ECDHE key exchange with out-of-band |
| mechanism | authentication |
+-----------------+-------------------------------------------------+
| Protected | yes |
| cryptosuite | |
| negotiation | |
+-----------------+-------------------------------------------------+
| Mutual | yes |
| authentication | |
+-----------------+-------------------------------------------------+
| Integrity | yes |
| protection | |
+-----------------+-------------------------------------------------+
| Replay | yes |
| protection | |
+-----------------+-------------------------------------------------+
| Confidentiality | no |
+-----------------+-------------------------------------------------+
| Key derivation | yes |
+-----------------+-------------------------------------------------+
| Key strength | The specified cryptosuites provide |
| | key strength of at least 128 bits. |
+-----------------+-------------------------------------------------+
| Dictionary | yes |
| attack | |
| protection | |
+-----------------+-------------------------------------------------+
| Fast reconnect | yes |
+-----------------+-------------------------------------------------+
| Cryptographic | not applicable |
| binding | |
+-----------------+-------------------------------------------------+
| Session | yes |
| independence | |
+-----------------+-------------------------------------------------+
| Fragmentation | no |
+-----------------+-------------------------------------------------+
| Channel binding | yes (The ServerInfo and PeerInfo can |
| | be used to convey integrity-protected |
| | channel properties, such as network |
| | SSID or peer MAC address.) |
+-----------------+-------------------------------------------------+
Table 13: EAP Security Claims
Honestly the channel binding row is my fave, the ServerInfo and PeerInfo can carry integrity-protected stuff like the network SSID or peer MAC address ๐ฆ
7. References ๐
7.1. Normative References ๐
okay so these are the must-read foundations the whole spec leans on, bestie ๐ if you skip them, the rest of the doc is gonna feel like a plot with missing episodes ๐ญ
- [EUI-48] IEEE, "IEEE Standard for Local and Metropolitan Area Networks: Overview and Architecture", DOI 10.1109/IEEESTD.2014.6847097, IEEE Standard 802-2014, June 2014,
<https://doi.org/10.1109/IEEESTD.2014.6847097>. - [FIPS186-4] National Institute of Standards and Technology (NIST), "Digital Signature Standard (DSS)", DOI 10.6028/NIST.FIPS.186-4, FIPS 186-4, July 2013,
<https://doi.org/10.6028/NIST.FIPS.186-4>. - [NIST-DH] Barker, E., Chen, L., Roginsky, A., Vassilev, A., and R. Davis, "Recommendation for Pair-Wise Key-Establishment Schemes Using Discrete Logarithm Cryptography", DOI 10.6028/NIST.SP.800-56Ar3, NIST Special Publication 800-56A Revision 3, April 2018,
<https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf>. - [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>. - [RFC3748] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and H. Levkowetz, Ed., "Extensible Authentication Protocol (EAP)", RFC 3748, DOI 10.17487/RFC3748, June 2004,
<https://www.rfc-editor.org/info/rfc3748>. - [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
<https://www.rfc-editor.org/info/rfc4648>. - [RFC5247] Aboba, B., Simon, D., and P. Eronen, "Extensible Authentication Protocol (EAP) Key Management Framework", RFC 5247, DOI 10.17487/RFC5247, August 2008,
<https://www.rfc-editor.org/info/rfc5247>. - [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>. - [RFC7517] Jones, M., "JSON Web Key (JWK)", RFC 7517, DOI 10.17487/RFC7517, May 2015,
<https://www.rfc-editor.org/info/rfc7517>. - [RFC7518] Jones, M., "JSON Web Algorithms (JWA)", RFC 7518, DOI 10.17487/RFC7518, May 2015,
<https://www.rfc-editor.org/info/rfc7518>. - [RFC7542] DeKok, A., "The Network Access Identifier", RFC 7542, DOI 10.17487/RFC7542, May 2015,
<https://www.rfc-editor.org/info/rfc7542>. - [RFC7748] Langley, A., Hamburg, M., and S. Turner, "Elliptic Curves for Security", RFC 7748, DOI 10.17487/RFC7748, January 2016,
<https://www.rfc-editor.org/info/rfc7748>. - [RFC8037] Liusvaara, I., "CFRG Elliptic Curve Diffie-Hellman (ECDH) and Signatures in JSON Object Signing and Encryption (JOSE)", RFC 8037, DOI 10.17487/RFC8037, January 2017,
<https://www.rfc-editor.org/info/rfc8037>. - [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017,
<https://www.rfc-editor.org/info/rfc8126>. - [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>. - [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, December 2017,
<https://www.rfc-editor.org/info/rfc8259>.
7.2. Informative References ๐ฆ
these ones are the extra reading, the "ooh, tell me more" pile ๐ธ not required to build the thing, but SO worth a look if you're curious about the backstory
- [Bluetooth] Bluetooth Special Interest Group, "Bluetooth Core Specification Version 5.3", July 2021,
<https://www.bluetooth.com/specifications/bluetooth-core-specification>. - [IEEE-802.1X] IEEE, "IEEE Standard for Local and Metropolitan Area Networks--Port-Based Network Access Control", IEEE Standard 802.1X-2020, February 2020.
- [RATS-EAT] Lundblade, L., Mandyam, G., and J. O'Donoghue, "The Entity Attestation Token (EAT)", Work in Progress, Internet-Draft, draft-ietf-rats-eat-11, 24 October 2021,
<https://datatracker.ietf.org/doc/html/draft-ietf-rats-eat-11>. - [RFC2904] Vollbrecht, J., Calhoun, P., Farrell, S., Gommans, L., Gross, G., de Bruijn, B., de Laat, C., Holdrege, M., and D. Spence, "AAA Authorization Framework", RFC 2904, DOI 10.17487/RFC2904, August 2000,
<https://www.rfc-editor.org/info/rfc2904>. - [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, DOI 10.17487/RFC3986, January 2005,
<https://www.rfc-editor.org/info/rfc3986>. - [RFC4137] Vollbrecht, J., Eronen, P., Petroni, N., and Y. Ohba, "State Machines for Extensible Authentication Protocol (EAP) Peer and Authenticator", RFC 4137, DOI 10.17487/RFC4137, August 2005,
<https://www.rfc-editor.org/info/rfc4137>. - [RFC5056] Williams, N., "On the Use of Channel Bindings to Secure Channels", RFC 5056, DOI 10.17487/RFC5056, November 2007,
<https://www.rfc-editor.org/info/rfc5056>. - [RFC5216] Simon, D., Aboba, B., and R. Hurst, "The EAP-TLS Authentication Protocol", RFC 5216, DOI 10.17487/RFC5216, March 2008,
<https://www.rfc-editor.org/info/rfc5216>. - [RFC6677] Hartman, S., Ed., Clancy, T., and K. Hoeper, "Channel-Binding Support for Extensible Authentication Protocol (EAP) Methods", RFC 6677, DOI 10.17487/RFC6677, July 2012,
<https://www.rfc-editor.org/info/rfc6677>. - [Sethi14] Sethi, M., Oat, E., Di Francesco, M., and T. Aura, "Secure bootstrapping of cloud-managed ubiquitous displays", Proceedings of ACM International Joint Conference on Pervasive and Ubiquitous Computing (UbiComp 2014), pp. 739-750, Seattle, USA, DOI 10.1145/2632048.2632049, September 2014,
<http://dx.doi.org/10.1145/2632048.2632049>. - [Sethi19] Sethi, M., Peltonen, A., and T. Aura, "Misbinding Attacks on Secure Device Pairing and Bootstrapping", DOI 10.1145/3321705.3329813, February 2019,
<https://arxiv.org/abs/1902.07550>. - [TLS-CWT] Tschofenig, H. and M. Brossard, "Using CBOR Web Tokens (CWTs) in Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)", Work in Progress, Internet-Draft, draft-tschofenig-tls-cwt-02, 13 July 2020,
<https://datatracker.ietf.org/doc/html/draft-tschofenig-tls-cwt-02>.
Appendix A. Exchanges and Events per State โจ
okay so Table 14 is literally the server's decision cheat sheet ๐ฅ it shows how the EAP server picks the exchange type based on the server state AND the peer state. in the combos marked with a hyphen "-", there's no possible exchange and the user has to do something before anything can move forward ๐ peer state 4 is left out of the table bc the peer never connects to the server while it's in that state ๐ the table also shows how errors get handled in each exchange, and the big highlight is that whoever gets error code 2003 drops back to state 1 ๐
+=============+===============================+==================+
| Peer States | Exchange Chosen by the Server | Next Peer and |
| | | Server States |
+=============+===============================+==================+
| Server State: Unregistered (0) |
+-------------+-------------------------------+------------------+
| 0..2 | Initial Exchange | both 1 (0 on |
| | | error) |
+-------------+-------------------------------+------------------+
| 3 | - | no change, |
| | | notify user |
+-------------+-------------------------------+------------------+
| Server State: Waiting for OOB (1) |
+-------------+-------------------------------+------------------+
| 0 | Initial Exchange | both 1 (0 on |
| | | error) |
+-------------+-------------------------------+------------------+
| 1 | Waiting Exchange | both 1 (no |
| | | change on error) |
+-------------+-------------------------------+------------------+
| 2 | Completion Exchange | both 4 (A) |
+-------------+-------------------------------+------------------+
| 3 | - | no change, |
| | | notify user |
+-------------+-------------------------------+------------------+
| Server State: OOB Received (2) |
+-------------+-------------------------------+------------------+
| 0 | Initial Exchange | both 1 (0 on |
| | | error) |
+-------------+-------------------------------+------------------+
| 1 | Completion Exchange | both 4 (B) |
+-------------+-------------------------------+------------------+
| 2 | Completion Exchange | both 4 (A) |
+-------------+-------------------------------+------------------+
| 3 | - | no change, |
| | | notify user |
+-------------+-------------------------------+------------------+
| Server State: Reconnecting (3) or Registered (4) |
+-------------+-------------------------------+------------------+
| 0..2 | - | no change, |
| | | notify user |
+-------------+-------------------------------+------------------+
| 3 | Reconnect Exchange | both 4 (3 on |
| | | error) |
+-------------+-------------------------------+------------------+
Table 14: How the Server Chooses the Exchange Type
(A) peer to 1 on error 2003; no other changes on error
(B) server to 1 on error 2003; no other changes on error
Table 15 is the list of local events that can happen in the server or the peer ๐ฆ both of them output and accept OOB messages in association state 1, which pushes the receiver to state 2 ๐ธ communication errors and timeouts in states 0..2 send things back to state 0, while similar errors in states 3..4 send things to state 3 โจ rekeying requests (like refreshing session keys or upgrading the cryptosuite) also take the association from state 3..4 to state 3 ๐ the user can always reset the association to state 0, and recovering association data (like from a backup) lands you in state 3 ๐ซถ
+===================+========================+=========+
| Server/Peer State | Possible Local Events | Next |
| | in the Server and Peer | State |
+===================+========================+=========+
| 1 | OOB Output | 1 |
+-------------------+------------------------+---------+
| 1 | OOB Input | 2 (1 on |
| | | error) |
+-------------------+------------------------+---------+
| 0..2 | Mobility/timeout/ | 0 |
| | network failure | |
+-------------------+------------------------+---------+
| 3..4 | Mobility/timeout/ | 3 |
| | network failure | |
+-------------------+------------------------+---------+
| 3..4 | Rekeying request | 3 |
+-------------------+------------------------+---------+
| 0..4 | User resets | 0 |
| | association | |
+-------------------+------------------------+---------+
| 0..4 | Association state | 3 |
| | recovery | |
+-------------------+------------------------+---------+
Table 15: Local Events in the Server and Peer
Appendix B. Application-Specific Parameters ๐
Table 16 is the list of OOB channel parameters that every application using EAP-NOOB has to specify ๐ it's not exhaustive and it's only here as a handy reference for implementers ๐ง
+====================+=========================================+
| Parameter | Description |
+====================+=========================================+
| OobDirs | Allowed directions of the OOB channel. |
+--------------------+-----------------------------------------+
| OobMessageEncoding | How the OOB message data fields are |
| | encoded for the OOB channel. |
+--------------------+-----------------------------------------+
| SleepTimeDefault | Default minimum time in seconds that |
| | the peer should sleep before the next |
| | Waiting Exchange. |
+--------------------+-----------------------------------------+
| OobRetries | Number of received OOB messages with |
| | invalid Hoob, after which the receiver |
| | moves to Unregistered (0) state. When |
| | the OOB channel has error detection or |
| | correction, the RECOMMENDED value is 5. |
+--------------------+-----------------------------------------+
| NoobTimeout | How many seconds the sender of the OOB |
| | message remembers the sent Noob value. |
| | The RECOMMENDED value is 3600 seconds. |
+--------------------+-----------------------------------------+
| ServerInfoType | The value of the Type field and the |
| | other required fields in ServerInfo. |
+--------------------+-----------------------------------------+
| PeerInfoType | The value of the Type field and the |
| | other required fields in PeerInfo. |
+--------------------+-----------------------------------------+
Table 16: OOB Channel Characteristics
Appendix C. EAP-NOOB Roaming ๐
AAA architectures [RFC2904] let network-connected appliances that are authenticated over EAP go roaming ๐งณ while the peer is roaming in a visited network, authentication still happens between the peer and an authentication server back at its home network ๐ EAP-NOOB makes this work by letting the server assign a NAI to the peer โจ once the NAI is assigned, the visited network can route the EAP session over to the peer's home AAA server ๐
a peer device that's brand new or has been through a hard reset should be connected first to the home network and set up an EAP-NOOB association with its home AAA server before it can roam ๐ after that, it can do the Reconnect Exchange from the visited network ๐ฆ
the device may also give the user a way to configure the NAI of the home network yourself ๐ง this is the user or application-configured NAI mentioned in Section 3.3.1 ๐ in that case, the EAP-NOOB association can be created while roaming, and the configured NAI makes sure the EAP messages get routed to the home AAA server correctly ๐
while roaming, the device needs to figure out which networks it can use the EAP-NOOB association on for network access ๐บ๏ธ for 802.11 access networks, the server MAY send a list of SSID strings in the ServerInfo field, called either SSIDList or Base64SSIDList ๐ the list is formatted as explained in Table 6 ๐ง if it's there, the peer MAY use this list as a hint for which networks the EAP-NOOB association can be used for access authorization, on top of the access network where the Initial Exchange happened ๐ซถ
Appendix D. OOB Message as a URL ๐
EAP-NOOB doesn't mandate any particular OOB communication channel, but typical ones include graphical displays and emulated NFC tags ๐ฑ in the peer-to-server direction, it can be convenient to encode the OOB message as a URL ๐ that URL then gets encoded as a QR code for displays and printers, or as an NFC Data Exchange Format (NDEF) record for dynamic NFC tags ๐ง the user just scans the QR code or NFC tag and opens the URL, which delivers the OOB message to the authentication server โจ
the URL MUST specify https or another server-authenticated scheme, so there's a secure connection to the server and the on-path attacker can't read or modify the OOB message ๐ญ
the ServerInfo in this case includes a field called ServerURL, in this format, with a RECOMMENDED length of at most 60 characters ๐
https://<host>[:<port>]/[<path>]
then the peer appends the OOB message fields (PeerId, Noob, and Hoob) as a query string ๐ PeerId is provided to the peer by the server and might be a 22-character ASCII string ๐ธ the peer base64url encodes the 16-byte values Noob and Hoob, without padding, into 22-character ASCII strings ๐ซง the query parameters MAY be in any order ๐ฆ the resulting URL looks like this:
https://<host>[:<port>]/[<path>]?P=<PeerId>&N=<Noob>&H=<Hoob>
here's an example of a well-formed URL encoding the OOB message (without line breaks) ๐
https://aaa.example.com/eapnoob?P=mcm5BSCDZ45cYPlAr1ghNw&N=rMinS0-F4E
fCU8D9ljxX_A&H=QvnMp4UGxuQVFaXPW_14UW
Acknowledgments ๐ซถโจ
Okay bestie, the people who made this happen deserve a whole shoutout! ๐ Max Crone, Shiva Prasad TP, and Raghavendra MS implemented parts of this protocol with wpa_supplicant and hostapd, which is literally so impressive ๐ฅ. Eduardo Inglรฉs and Dan Garcia-Carrillo worked on implementing it on Contiki ๐ง. Their input helped make the spec better, and we are so grateful ๐ธ.
The authors want to thank Rhys Smith and Josh Howlett for valuable feedback, plus new use cases and requirements for the protocol ๐ . Huge thanks also to Eric Rescorla, Alan Dekok, Darshak Thakore, Stefan Winter, Hannes Tschofenig, Daniel Migault, Roman Danyliw, Benjamin Kaduk, Francesca Palombini, Steve Hanna, Lars Eggert, and รric Vyncke for their comments and reviews ๐ฆ. The main character energy of this whole review squad is unmatched ๐.
We also want to give a massive, sincere thank-you to Dave Thaler for his thorough review of the document ๐๐.
Authors' Addresses ๐
Meet the authors! ๐
Tuomas Aura
Aalto University
FI-00076 Aalto
Finland
Email: tuomas.aura@aalto.fi
Mohit Sethi
Ericsson
FI-02420 Jorvas
Finland
Email: mohit@iki.fi
Aleksi Peltonen
Aalto University
FI-00076 Aalto
Finland
Email: aleksi.peltonen@aalto.fi
๐ฆ where this page comes from
- ietf: rfc9140 2021-12
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms