RFC 9528

Ephemeral Diffie-Hellman Over COSE (EDHOC)

๐Ÿ“… published March 2024, from ietf

RFC 9528: Ephemeral Diffie-Hellman Over COSE (EDHOC) โœจ

Okay so bestie, this is the RFC for EDHOC, which is short for Ephemeral Diffie-Hellman Over COSE ๐Ÿฆ‹. It was written by G. Selander, J. PreuรŸ Mattsson, and F. Palombini, all at Ericsson ๐Ÿ’…. It's a Standards Track document, which means it's an official Internet standard, and it came out in March 2024 ๐ŸŒธ. It's marked ISSN 2070-1721, and this RFC doesn't obsolete or update any earlier RFCs, so it's a brand new standard, no cap ๐Ÿ”ฅ.

Quick vibe check: the whole thing is about a super lightweight, authenticated key exchange that gives you mutual authentication, forward secrecy, and identity protection ๐Ÿ”. It was built for tiny IoT devices that have limited memory, storage, and power, and its main job is to set up an OSCORE security context ๐Ÿงš.


Status of This Memo

This is an Internet Standards Track document ๐Ÿ’–.

It's a product of the Internet Engineering Task Force (IETF) and 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 info on Internet Standards, check out 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/rfc9528 โœจ.

Copyright (c) 2024 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. Read those carefully, because they spell out your rights and restrictions ๐Ÿ“œ. 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 without warranty as described in that license ๐Ÿ’œ.


Table of Contents ๐ŸŒˆ

  1. Introduction
    • 1.1. Motivation
    • 1.2. Message Size Examples
    • 1.3. Document Structure
    • 1.4. Terminology and Requirements Language
  2. EDHOC Outline
  3. Protocol Elements
    • 3.1. General
    • 3.2. Method
    • 3.3. Connection Identifiers
    • 3.4. Transport
    • 3.5. Authentication Parameters
    • 3.6. Cipher Suites
    • 3.7. Ephemeral Public Keys
    • 3.8. External Authorization Data (EAD)
    • 3.9. Application Profile
  4. Key Derivation
    • 4.1. Keys for EDHOC Message Processing
    • 4.2. Keys for EDHOC Applications
  5. Message Formatting and Processing
    • 5.1. EDHOC Message Processing Outline
    • 5.2. EDHOC Message 1
    • 5.3. EDHOC Message 2
    • 5.4. EDHOC Message 3
    • 5.5. EDHOC Message 4
  6. Error Handling
    • 6.1. Success
    • 6.2. Unspecified Error
    • 6.3. Wrong Selected Cipher Suite
    • 6.4. Unknown Credential Referenced
  7. EDHOC Message Deduplication
  8. Compliance Requirements
  9. Security Considerations
    • 9.1. Security Properties
    • 9.2. Cryptographic Considerations
    • 9.3. Cipher Suites and Cryptographic Algorithms
    • 9.4. Post-Quantum Considerations
    • 9.5. Unprotected Data and Privacy
    • 9.6. Updated Internet Threat Model Considerations
    • 9.7. Denial of Service
    • 9.8. Implementation Considerations
  10. IANA Considerations
    • 10.1. EDHOC Exporter Label Registry
    • 10.2. EDHOC Cipher Suites Registry
    • 10.3. EDHOC Method Type Registry
    • 10.4. EDHOC Error Codes Registry
    • 10.5. EDHOC External Authorization Data Registry
    • 10.6. COSE Header Parameters Registry
    • 10.7. Well-Known URI Registry
    • 10.8. Media Types Registry
    • 10.9. CoAP Content-Formats Registry
    • 10.10. Resource Type (rt=) Link Target Attribute Values Registry
    • 10.11. Expert Review Instructions
  11. References
    • 11.1. Normative References
    • 11.2. Informative References
  • Appendix A. Use with OSCORE and Transfer over CoAP
    • A.1. Deriving the OSCORE Security Context
    • A.2. Transferring EDHOC over CoAP
  • Appendix B. Compact Representation
  • Appendix C. Use of CBOR, CDDL, and COSE in EDHOC
    • C.1. CBOR and CDDL
    • C.2. CDDL Definitions
    • C.3. COSE
  • Appendix D. Authentication-Related Verifications
    • D.1. Validating the Authentication Credential
    • D.2. Identities
    • D.3. Certification Path and Trust Anchors
    • D.4. Revocation Status
    • D.5. Unauthenticated Operation
  • Appendix E. Use of External Authorization Data
  • Appendix F. Application Profile Example
  • Appendix G. Long PLAINTEXT_2
  • Appendix H. EDHOC_KeyUpdate
  • Appendix I. Example Protocol State Machine
    • I.1. Initiator State Machine
    • I.2. Responder State Machine
  • Acknowledgments
  • Authors' Addresses

1. Introduction ๐Ÿฆ‹

1.1. Motivation ๐Ÿ’…

Okay, so a ton of Internet of Things (IoT) deployments need tech that's super performant even when resources are tight [RFC7228] ๐Ÿ˜ญ. IoT devices can be constrained in all sorts of ways: memory, storage, processing power, and battery ๐Ÿ”‹. Their connections can be rough too, with unreliable and lossy channels, very limited bandwidth, and a topology that keeps changing ๐ŸŒช๏ธ. The IETF has noticed and standardized a bunch of lightweight protocols for IoT, like CoAP [RFC7252], CBOR [RFC8949], and Static Context Header Compression (SCHC) [RFC8724] ๐ŸŒธ.

Security needs the same treatment. The need for special protocols for constrained IoT extends to the security domain too [LAKE-REQS] ๐Ÿ”. What really matters here is how many round trips you need and how big your protocol messages are. Keep those low and you get good performance, since messages fit in a small number of radio frames, and you cut down on latency from fragmentation, duty cycles, and so on โœจ. Code size matters a lot too. It can be way too big for some deployments, whether because of the device's capabilities or the network load during firmware updates ๐Ÿ’€. Some IoT deployments also have to support a bunch of different transport technologies, maybe even over a single connection ๐Ÿงš.

Some security solutions already exist for this. COSE [RFC9052] offers basic application-layer security services, efficiently encoded in CBOR ๐Ÿ’œ. Then there's OSCORE [RFC8613], a lightweight communication security extension to CoAP that uses CBOR and COSE ๐ŸŽ€. To set up good quality cryptographic keys for things like COSE and OSCORE, the two endpoints can run an authenticated Diffie-Hellman key exchange, and then derive shared secret keying material from it ๐Ÿ”‘. That key exchange should also be lightweight, so it doesn't hurt performance when it gets used again and again. That could happen after a device reboots, during frequent rekeying for security reasons, or when lots of devices authenticate at the same time during network formation ๐Ÿ“.

This document specifies Ephemeral Diffie-Hellman Over COSE (EDHOC) ๐Ÿฆ‹. It's a lightweight authenticated key exchange protocol with strong security properties, including forward secrecy, identity protection, and cipher suite negotiation ๐Ÿ’–. Authentication can be based on raw public keys (RPKs) or public key certificates, and the application has to tell EDHOC how to verify that endpoints are trusted ๐Ÿซถ. EDHOC lets you reference credentials to cut down on message overhead, but credentials can also be embedded in the messages instead ๐Ÿ“ฆ. EDHOC does not currently support Pre-Shared Key (PSK) authentication. The reason is that authentication with static Diffie-Hellman (DH) public keys by reference gives you equally small messages, with much simpler key distribution and identity protection ๐Ÿ™ˆ.

EDHOC is built on known protocol constructions: SIGn-and-MAc [SIGMA], the Noise XX pattern [Noise], and Extract-and-Expand [RFC5869] ๐Ÿง . It uses COSE for cryptography and for identifying credentials, including COSE_Key, CBOR Web Token (CWT), CWT Claims Set (CCS), X.509, and CBOR-encoded X.509 (C509) certificates (see Section 3.5.2) ๐ŸŒˆ. COSE gives you crypto agility, so future algorithms and credential types aimed at IoT can slot right in ๐Ÿ‘‘.

EDHOC is designed for highly constrained settings, which makes it great for low-power networks [RFC8376] like Cellular IoT, IPv6 over the TSCH mode of IEEE 802.15.4e (6TiSCH), and LoRaWAN ๐Ÿ“ก. The main goal is to be a lightweight authenticated key exchange for OSCORE, so it can provide authentication and session key establishment for IoT use cases built on CoAP [RFC7252], involving "things" with embedded microcontrollers, sensors, and actuators ๐Ÿค–. Since it reuses the same lightweight primitives as OSCORE (CBOR, COSE, and CoAP), the extra code size stays very low โญ. Note that even though CBOR and COSE primitives are built into the protocol messages, EDHOC isn't tied to any particular transport ๐Ÿฆ‹.

A typical setup has one endpoint that's constrained, or sitting in a constrained network, and another endpoint that's a node on the Internet, like a mobile phone ๐Ÿ“ฑ. Thing-to-thing interactions over constrained networks matter too, because both endpoints get to enjoy the lightweight properties ๐Ÿ’…. EDHOC could be run when a device connects for the first time, or to set up fresh keys that aren't exposed if the long-term keys get compromised later ๐Ÿ”ฅ.

1.2. Message Size Examples ๐ŸŽ€

Table 1 shows some example EDHOC message sizes ๐Ÿ“Š. They use different kinds of authentication keys and COSE header parameters for identification. That includes static Diffie-Hellman keys or signature keys, either in CWT/CCS [RFC8392] identified by a key identifier using 'kid' [RFC9052], or in X.509 certificates identified by a hash value using 'x5t' [RFC9360] ๐Ÿ”. EDHOC always uses ephemeral-ephemeral key exchange ๐Ÿ’œ. For comparison, with RPK authentication and transfer over CoAP, the EDHOC message size can be less than 1/7 of the DTLS 1.3 handshake [RFC9147] using Ephemeral Elliptic Curve Diffie-Hellman (ECDHE) and a connection ID. See [CoAP-SEC-PROT] for more ๐Ÿ˜ญ.

          +===========+================+================+
          |           | Static DH Keys | Signature Keys |
          +===========+==========+=====+==========+=====+
          |           |      kid | x5t |      kid | x5t |
          +===========+==========+=====+==========+=====+
          | message_1 |       37 |  37 |       37 |  37 |
          +-----------+----------+-----+----------+-----+
          | message_2 |       45 |  58 |      102 | 115 |
          +-----------+----------+-----+----------+-----+
          | message_3 |       19 |  33 |       77 |  90 |
          +-----------+----------+-----+----------+-----+
          | Total     |      101 | 128 |      216 | 242 |
          +-----------+----------+-----+----------+-----+

Table 1: Examples of EDHOC Message Sizes in Bytes ๐ŸŒธ


Part 1 of 21. Next up: Section 1.3, Document Structure, and the rest of the Introduction โœจ๐Ÿ’–

1.3. Document Structure ๐Ÿงš

okay so the rest of the doc is laid out like this ๐Ÿ—บ๏ธ Section 2 gives you the EDHOC outline for signature keys, Section 3 covers the protocol elements (including how the ephemeral public keys get formatted) ๐Ÿ”‘, Section 4 handles key derivation, and Section 5 is the message processing for signature keys or static Diffie-Hellman keys ๐Ÿ’…. Section 6 is all about error messages, Section 7 explains EDHOC over a transport that doesn't handle message duplication ๐Ÿซถ, and Section 8 is the compliance requirements checklist โœ…. Also, normative text shows up in the appendices too, especially Appendix A, so don't skip those bestie ๐Ÿ™ˆ

1.4. Terminology and Requirements Language

the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this doc are read as described in BCP 14 [RFC2119] [RFC8174], but ONLY when they show up in all capitals like this ๐Ÿ’– no caps, no special meaning โœจ

you're expected to already know the vibe of CBOR [RFC8949], CBOR Sequences [RFC8742], COSE Structures and Processing [RFC9052], COSE Algorithms [RFC9053], CWT and CCS [RFC8392], and the Concise Data Definition Language (CDDL) [RFC8610], which is what's used to describe CBOR data structures ๐ŸŽ€ Examples of CBOR and CDDL are in Appendix C.1. When this spec says CBOR, it always means Deterministically Encoded CBOR, as specified in Sections 4.2.1 and 4.2.2 of [RFC8949] ๐Ÿฆ‹ And the single output from authenticated encryption (the authentication tag included) gets called "ciphertext", following [RFC5116] ๐Ÿ’œ

2. EDHOC Outline

EDHOC supports different authentication methods for the ephemeral-ephemeral Diffie-Hellman key exchange ๐ŸŒˆ This doc specifies methods based on signature keys and static Diffie-Hellman keys. This section is just the signature-key version. The rest of the doc has the details for the protocol elements and the other methods โœจ

SIGn-and-MAc (SIGMA) is a whole family of theoretical protocols with a bunch of variants [SIGMA] ๐Ÿค“ Like Internet Key Exchange Protocol Version 2 (IKEv2) [RFC7296] and (D)TLS 1.3 [RFC8446] [RFC9147], EDHOC with signature keys is built on a SIGMA variant called SIGMA-I, which gives identity protection against active attacks on the party that starts the protocol ๐Ÿ”ฅ Also like IKEv2, EDHOC uses the MAC-then-Sign variant of SIGMA-I ๐Ÿ’… The message flow (not counting the optional fourth message) is in Figure 1 ๐Ÿ‘€

Initiator                                                   Responder
|                                G_X                                |
+------------------------------------------------------------------>|
|                                                                   |
|      G_Y, Enc( ID_CRED_R, Sig( R; MAC( CRED_R, G_X, G_Y ) ) )     |
|<------------------------------------------------------------------+
|                                                                   |
|        AEAD( ID_CRED_I, Sig( I; MAC( CRED_I, G_Y, G_X ) ) )       |
+------------------------------------------------------------------>|
|                                                                   |

Figure 1: MAC-then-Sign Variant of the SIGMA-I Protocol Used by the EDHOC Method 0

The two parties in an EDHOC session are the Initiator (I) and the Responder (R), and the Initiator is the one who sends message_1 (see Section 3) ๐Ÿงš They swap ephemeral public keys, work out a shared secret session key called PRK_out, and derive the symmetric application keys that protect the app data ๐Ÿ”

  • G_X and G_Y are the Elliptic Curve Diffie-Hellman (ECDH) ephemeral public keys of I and R, respectively. ๐ŸŒธ
  • CRED_I and CRED_R are the authentication credentials holding the public authentication keys of I and R, respectively. ๐Ÿ—๏ธ
  • ID_CRED_I and ID_CRED_R are used to identify and optionally transport the credentials of I and R, respectively. ๐ŸŽŸ๏ธ
  • Sig(I; . ) and Sig(R; . ) denote signatures made with the private authentication key of I and R, respectively. โœ๏ธ
  • Enc(), AEAD(), and MAC() denote encryption, Authenticated Encryption with Associated Data, and Message Authentication Code -- crypto algorithms applied with keys derived from one or more shared secrets calculated during the protocol. ๐Ÿ“

To make it a "full-fledged" protocol, a few more elements are needed, so this spec adds:

  • transcript hashes (hashes of message data), TH_2, TH_3, and TH_4, used for key derivation and as additional authenticated data, ๐Ÿ“œ
  • computationally independent keys derived from the ECDH shared secret and used for authenticated encryption of different messages, ๐Ÿ”‘
  • an optional fourth message giving key confirmation to I in deployments where no protected application data is sent from R to I, ๐Ÿ’Œ
  • a keying material exporter and a key update function with forward secrecy, ๐Ÿ”„
  • secure negotiation of the cipher suite, ๐Ÿ›ก๏ธ
  • method types, error handling, and padding, ๐Ÿงฉ
  • the selection of connection identifiers, C_I and C_R, which may be used in EDHOC to identify the protocol state, and ๐Ÿ†”
  • transport of external authorization data. ๐ŸŽซ

EDHOC is designed to encrypt and integrity protect as much info as possible ๐Ÿซง Symmetric keys and random material are derived with EDHOC_KDF using as much previous info as possible, see Figure 6 ๐Ÿ’– It's also built to be as compact and lightweight as possible, in terms of message sizes, processing, and being able to reuse existing CBOR, COSE, and CoAP libraries ๐Ÿฆ‹ Like (D)TLS, authentication is the application's job ๐Ÿ™Œ EDHOC identifies (and can optionally transport) authentication credentials and provides proof-of-possession of the private authentication key ๐Ÿ”

To make life easier for implementors, the use of CBOR, CDDL, and COSE in EDHOC is summarized in Appendix C ๐Ÿ“š Test vectors, including CBOR diagnostic notation, are in [RFC9529] ๐Ÿงช

3. Protocol Elements

3.1. General

The EDHOC protocol has three mandatory messages (message_1, message_2, and message_3), an optional fourth message (message_4), and an error message, all passed between an Initiator (I) and a Responder (R) ๐Ÿ’ซ The odd-numbered messages come from I and the even ones come from R. Both I and R can send error messages ๐Ÿšจ The roles have slightly different security properties that should be thought about when you assign them, see Section 9.1 โš ๏ธ Every EDHOC message is a CBOR Sequence [RFC8742] and is defined as deterministically encoded CBOR as specified in Section 4.2.1 of [RFC8949] ๐ŸŽ€ Figure 2 shows an EDHOC message flow with the optional fourth message plus what's inside each message. The protocol elements in the figure are introduced in Sections 3 and 5, and message formatting and processing are specified in Sections 5 and 6 ๐Ÿ—‚๏ธ

Application data can be protected with the agreed application algorithms (AEAD, hash) from the selected cipher suite (see Section 3.6), and the app can use the established connection identifiers C_I and C_R (see Section 3.3) ๐ŸŒŸ Media types that can be used for EDHOC are defined in Section 10.8 ๐Ÿ“Ž

The Initiator can derive symmetric application keys after creating EDHOC message_3, see Section 4.2.1 ๐Ÿ—๏ธ So protected application data can be sent in parallel with or together with EDHOC message_3 ๐Ÿƒโ€โ™€๏ธ EDHOC message_4 is typically not sent ๐Ÿ™ƒ

Initiator                                                   Responder
|                 METHOD, SUITES_I, G_X, C_I, EAD_1                 |
+------------------------------------------------------------------>|
|                             message_1                             |
|                                                                   |
|       G_Y, Enc( C_R, ID_CRED_R, Signature_or_MAC_2, EAD_2 )       |
|<------------------------------------------------------------------+
|                             message_2                             |
|                                                                   |
|            AEAD( ID_CRED_I, Signature_or_MAC_3, EAD_3 )           |
+------------------------------------------------------------------>|
|                             message_3                             |
|                                                                   |
|                           AEAD( EAD_4 )                           |
|<- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                             message_4                             |

Figure 2: EDHOC Message Flow Including the Optional Fourth Message

3.2. Method

The METHOD data item in message_1 (see Section 5.2.1) is an integer that picks the authentication method ๐ŸŽฏ EDHOC currently supports authentication with signature or static Diffie-Hellman keys through four authentication methods: 0, 1, 2, and 3, see Table 2 ๐Ÿ’… When a static Diffie-Hellman key is used, the authentication comes from a Message Authentication Code (MAC) computed from an ephemeral-static ECDH shared secret, and that brings big savings in message sizes ๐Ÿคฉ Also, even in the static Diffie-Hellman-based methods, there's still an ephemeral-ephemeral Diffie-Hellman key exchange ๐Ÿ’œ

The Initiator and Responder have to agree on a single method for EDHOC, see Section 3.9 ๐Ÿค

   +===================+====================+====================+
   | Method Type Value | Initiator          | Responder          |
   |                   | Authentication Key | Authentication Key |
   +===================+====================+====================+
   |                 0 | Signature Key      | Signature Key      |
   +-------------------+--------------------+--------------------+
   |                 1 | Signature Key      | Static DH Key      |
   +-------------------+--------------------+--------------------+
   |                 2 | Static DH Key      | Signature Key      |
   +-------------------+--------------------+--------------------+
   |                 3 | Static DH Key      | Static DH Key      |
   +-------------------+--------------------+--------------------+
   |                23 | Reserved           | Reserved           |
   +-------------------+--------------------+--------------------+

Table 2: Authentication Keys for Method Types

EDHOC doesn't have a dedicated message field for the protocol version ๐Ÿ™ˆ So breaking changes to EDHOC can be introduced by specifying and registering new methods ๐Ÿฆ‹

3.3. Connection Identifiers ๐ŸŽ€

okay so EDHOC has to pick connection identifiers, C_I and C_R ๐Ÿฆ‹. They basically label the connection that the keys are being agreed for โœจ

These IDs can help line up EDHOC messages and fetch the protocol state during a session (see Section 3.4). Or apps running on top of EDHOC can use them too, like OSCORE (see Section 3.3.3). ngl they have zero cryptographic job in EDHOC ๐Ÿ’…. They just help find the right security data.

Connection identifiers in EDHOC are always byte strings ๐Ÿงš. Lots of constrained devices only have a few connections, so short IDs are usually enough. Sometimes you need the shortest possible IDs to meet overhead requirements ๐Ÿ™ˆ. Here's the catch: CBOR byte strings take at least two bytes, with one exception, the empty byte string h'', which encodes as one byte (0x40). So to get one-byte encodings for certain strings while staying valid CBOR, EDHOC puts certain IDs on the wire as CBOR integers. More on that in Section 3.3.2 ๐Ÿ’–.

3.3.1. Selection of Connection Identifiers

C_I and C_R are picked by I and R, respectively ๐ŸŒธ. The Initiator picks C_I and sends it in message_1 so the Responder can use it to refer to the connection when talking to the Initiator. The Responder picks C_R and sends it in message_2 so the Initiator can refer to the connection when talking to the Responder.

If an application protocol that runs on keys EDHOC established uses connection identifiers, then the selected connection identifiers SHALL adhere to that protocol's requirements. Section 3.3.3 has an example ๐Ÿ“.

3.3.2. Representation of Byte String Identifiers

so, to keep identifiers tiny on the wire, certain byte strings used in connection identifiers and credential identifiers (see Section 3.5.3) get integer representations ๐Ÿฆ‹.

The integers with one-byte CBOR encoding are -24, ..., 23. See Figure 3 ๐Ÿ‘‘.

Integer:  -24  -23  ... -11  ...  -2   -1    0    1  ...  15  ...  23
Encoding:  37   36  ...  2A  ...  21   20   00   01  ...  0F  ...  17

Figure 3: One-Byte CBOR-Encoded Integers

Any byte string that matches a one-byte CBOR encoding of an integer MUST be represented as the CBOR encoding of that integer ๐Ÿ”ฅ. Everything else is just encoded as a regular CBOR byte string.

For example:

  • 0x21 is represented by 0x21 (CBOR encoding of the integer -2), not by 0x4121 (CBOR encoding of the byte string 0x21). ๐Ÿ’œ
  • 0x0D is represented by 0x0D (CBOR encoding of the integer 13), not by 0x410D (CBOR encoding of the byte string 0x0D). ๐ŸŒˆ
  • 0x18 is represented by 0x4118 (CBOR encoding of the byte string 0x18). ๐Ÿ™ˆ
  • 0x38 is represented by 0x4138 (CBOR encoding of the byte string 0x38). ๐Ÿ’€
  • 0xABCD is represented by 0x42ABCD (CBOR encoding of the byte string 0xABCD). โœจ

You can think of this as a transport encoding ๐Ÿงš. A byte string that parses as the one-byte CBOR encoding of an integer (so, an integer in the range -24, ..., 23) gets copied straight into the message. A byte string that doesn't get encoded as a CBOR byte string for transport.

Implementation note, bestie ๐Ÿซถ: when you implement byte string identifier representation, it can help in some programming languages to define a new type or other data structure. In its user-facing API it acts like a byte string, but when it serializes to CBOR it produces either a CBOR byte string or a CBOR integer, depending on its value.

3.3.3. Use of Connection Identifiers with OSCORE

For OSCORE, picking a connection identifier means the endpoint is picking its Recipient ID (see Section 3.1 of [RFC8613]) ๐Ÿ”. Recipient IDs have uniqueness requirements (see Section 3.3 of [RFC8613]), so the Initiator and Responder MUST NOT pick connection identifiers that end up as the same OSCORE Recipient ID ๐Ÿšซ. Since a connection identifier is a byte string, it turns into an OSCORE Recipient ID that equals that byte string.

Examples:

  • A connection identifier 0xFF (represented in the EDHOC message as 0x41FF; see Section 3.3.2) is converted to the OSCORE Recipient ID 0xFF. ๐Ÿฆ‹
  • A connection identifier 0x21 (represented in the EDHOC message as 0x21; see Section 3.3.2) is converted to the OSCORE Recipient ID 0x21. ๐Ÿ’–

3.4. Transport ๐ŸšŒ

cryptographically, EDHOC doesn't put any requirements on the layers underneath it ๐Ÿซง. Received messages get processed as whatever message is expected next based on the protocol state (see Section 5). If processing fails for any reason, usually an error message gets sent and the EDHOC session is aborted ๐Ÿ’€.

EDHOC isn't tied to any particular transport layer, and it can even run in environments without IP ๐ŸŒธ. The application gets to choose how EDHOC messages (errors included) are transported ๐Ÿ’…. To avoid pointless message processing or protocol termination, it is RECOMMENDED to use reliable transport, like CoAP in reliable mode, which is the default transport (see Appendix A.2). In general, the transport SHOULD handle:

  • message loss,
  • message duplication (see Section 7 for an alternative),
  • flow control,
  • congestion control,
  • fragmentation and reassembly,
  • demultiplexing EDHOC messages from other types of messages,
  • denial-of-service mitigation, and
  • message correlation (see Section 3.4.1).

EDHOC doesn't need error-free transport, because a change in message content gets caught by the transcript hashes in a later integrity verification (see Section 5) ๐Ÿ”. The transport doesn't need extra stuff to deal with message reordering, because EDHOC processes things in lockstep ๐Ÿงš.

EDHOC is built for authenticated key exchange with small messages ๐ŸŽ€. The minimum message sizes are roughly what you see in the first column of Table 1. The protocol doesn't set a maximum message size. For example, it depends on how big the authentication credentials are (if they get transported, see Section 3.5) ๐Ÿ“ฆ. Encrypting very large content in message_2 with certain hash algorithms is covered in Appendix G.

The transport gets specified in the application profile, which can set limits on message sizes (see Section 3.9) ๐Ÿ’œ.

3.4.1. EDHOC Message Correlation

Correlating EDHOC messages is needed to fetch the protocol state and security context during a session ๐Ÿ”—. It also helps the Responder tell that an incoming EDHOC message starts a brand new session, so it doesn't have to fetch any existing protocol state or security context ๐ŸŒˆ.

Correlation can use mechanisms that already exist in the transport protocol. For example, the CoAP Token can correlate EDHOC messages in a CoAP response and its matching CoAP request ๐Ÿฆ‹. Connection identifiers can also do the job.

If consecutive messages can't be correlated some other way, then the transport binding SHOULD mandate prepending an appropriate connection identifier (when the EDHOC protocol has one available) to the EDHOC message ๐Ÿท๏ธ. If message_1 indication isn't provided some other way, then the transport binding SHOULD mandate prepending message_1 with the CBOR simple value true (0xf5) โœจ.

Transporting EDHOC in CoAP payloads is described in Appendix A.2, including how to use connection identifiers and message_1 indication with CoAP ๐ŸŒธ. A similar construction works for other client-server protocols too. Protocols that don't provide any correlation at all can prescribe prepending the peer's connection identifier to every message ๐Ÿซถ.

Note that correlation between EDHOC messages can happen without transport support or connection identifiers. For example, if the endpoints only accept one protocol instance at a time and only run when messages arrive in the correct sequence ๐Ÿง .

3.5. Authentication Parameters ๐Ÿ”‘

EDHOC supports different settings for how the other endpoint's public key for authentication gets transported, identified, and trusted ๐Ÿ’ซ. We'll use the term "authentication key" to mean a key used for authentication in general, or specifically the public key, when there's no risk of confusion.

EDHOC does the following authentication-related operations:

  • EDHOC transports information about credentials in ID_CRED_I and ID_CRED_R (described in Section 3.5.3) ๐Ÿชช. Based on this information, the authentication credentials CRED_I and CRED_R (described in Section 3.5.2) can be obtained. EDHOC may also transport certain authentication-related information as external authorization data (see Section 3.8).
  • EDHOC uses the authentication credentials in two ways (see Sections 5.3.2 and 5.4.2):
    • The authentication credential is input to the integrity verification using the MAC fields. ๐Ÿงฉ
    • The authentication key of the authentication credential is used with the Signature_or_MAC field to verify proof-of-possession of the private key. ๐Ÿ”

Other authentication-related verifications are out of scope for EDHOC and are the application's responsibility ๐Ÿ™Œ. In particular, the authentication credential needs to be validated in the context of the connection that EDHOC is used for (see Appendix D). EDHOC MUST allow the application to read received information about credentials in ID_CRED_R and ID_CRED_I ๐Ÿ“–. EDHOC MUST have access to the authentication key and the authentication credential ๐Ÿ—๏ธ.

Heads up, the type of authentication key, the type of authentication credential, and how the credential is identified all have a huge impact on message size ๐Ÿ“. For example, the Signature_or_MAC field is much smaller with a static DH key than with a signature key. A CWT Claims Set (CCS) is much smaller than a self-signed certificate / CWT. But if you can reference the credential with a COSE header like 'kid', that's even smaller than a CCS ๐Ÿ’–.

3.5.1. Authentication Keys ๐Ÿ”‘

okay so the authentication key MUST be a signature key or a static Diffie-Hellman key ๐Ÿ’… The Initiator and Responder MAY use different types of authentication keys, e.g., one uses a signature key and the other uses a static Diffie-Hellman key. mix and match is totally allowed bestie ๐Ÿฆ‹

the authentication key algorithm needs to play nice with the method and the selected cipher suite (see Section 3.6) ๐Ÿซถ it also needs to be compatible with the EDHOC key exchange algorithm when static Diffie-Hellman authentication is used, and compatible with the EDHOC signature algorithm when signature authentication is used.

ngl, for most signature algorithms the signature gets decided jointly by the signature algorithm and the authentication key algorithm, so they're kind of a power couple โœจ when we use static Diffie-Hellman keys, the Initiator's and the Responder's private authentication keys are called I and R, and their public authentication keys are called G_I and G_R, respectively ๐ŸŒธ

for X.509 certificates, the authentication key shows up as a SubjectPublicKeyInfo field, which also tells you what authentication key algorithm it is ๐ŸŽ€ for CWT and CCS (see Section 3.5.2), the authentication key lives in a 'cnf' claim [RFC8747] holding a COSE_Key [RFC9052], and that COSE_Key tells you the algorithm too. in EDHOC, a raw public key (RPK) is an authentication key encoded as a COSE_Key wrapped in a CCS. Figure 4 has an example, so go peek ๐Ÿ‘€

3.5.2. Authentication Credentials ๐Ÿ’–

the authentication credentials, CRED_I and CRED_R, hold the public authentication key of the Initiator and Responder, respectively. we use the notation CRED_x to mean CRED_I or CRED_R, and whatever requirements apply to CRED_x apply to both of them ๐Ÿงš the credential usually has other parameters that the application needs to verify (see Appendix D), and especially info about the identity ("subject") of the endpoint, so nobody gets misbound (see Appendix D.2). that's giving security vibes ๐Ÿ”’

EDHOC leans on COSE to identify credentials (see Section 3.5.3), so you can use X.509 certificates [RFC9360], C509 certificates [C509-CERTS], CWTs [RFC8392], and CCSs [RFC8392], for example. when the identified credential is a chain or a bag, CRED_x is just the end entity X.509 or C509 certificate / CWT. when you're choosing between a chain and a bag, it is RECOMMENDED to use a chain ๐Ÿ’… bags are unordered and can contain self-signed and extra certificates, which makes finding the end entity certificate way messier. the Initiator and Responder MAY use different types of authentication credentials, e.g., one uses an RPK and the other uses a public key certificate. mix and match again, iykyk ๐ŸŒˆ

okay this part is lowkey important. CRED_R gets used in the integrity verification (see Section 5.3.2), so it has to be specified so that it's identical whether the Initiator or the Responder is using it. same deal for CRED_I, see Section 5.4.2 ๐Ÿซถ the Initiator and Responder are expected to agree on the specific encoding of the authentication credentials; see Section 3.9. it is RECOMMENDED that the COSE 'kid' parameter, when it's used to identify the authentication credential, points at that specific encoding ๐Ÿ“ the Initiator and Responder SHOULD use an available authentication credential without re-encoding it. so a credential sent by value in EDHOC, or provisioned some other way, SHOULD be used as is ๐Ÿ’œ if for some reason a credential passed by reference might get re-encoded, a potential common encoding for CBOR-based credentials is deterministically encoded CBOR, as specified in Sections 4.2.1 and 4.2.2 of [RFC8949] โœจ

here's the breakdown by credential type:

  • When the authentication credential is an X.509 certificate, CRED_x SHALL be the DER-encoded certificate, encoded as a bstr [RFC9360].
  • When the authentication credential is a C509 certificate, CRED_x SHALL be the C509 certificate [C509-CERTS].
  • When the authentication credential is a CWT including a COSE_Key, CRED_x SHALL be the untagged CWT.
  • When the authentication credential includes a COSE_Key but is not in a CWT, CRED_x SHALL be an untagged CCS. This is how RPKs are encoded, see Figure 4 for an example.
    • Naked COSE_Keys get dressed up as CCS when used in EDHOC ๐Ÿ’… in its simplest form, you prefix the COSE_Key with 0xA108A101 (a map with a 'cnf' claim). in that case the resulting authentication credential has no other identity than the public key itself, see Appendix D.2 ๐Ÿ™ˆ

an example of CRED_x looks like this:

{                                              /CCS/
  2 : "42-50-31-FF-EF-37-32-39",               /sub/
  8 : {                                        /cnf/
    1 : {                                      /COSE_Key/
      1 : 1,                                   /kty/
      2 : h'00',                               /kid/
     -1 : 4,                                   /crv/
     -2 : h'b1a3e89460e88d3a8d54211dc95f0b90   /x/
            3ff205eb71912d6db8f4af980d2db83a'
    }
  }
}
   Figure 4: CCS Containing an X25519 Static Diffie-Hellman Key and
                          an EUI-64 Identity

3.5.3. Identification of Credentials ๐Ÿฆ‹

the ID_CRED fields, ID_CRED_R and ID_CRED_I, get sent in message_2 and message_3, respectively (see Sections 5.3.2 and 5.4.2). we use ID_CRED_x to mean ID_CRED_I or ID_CRED_R, and the requirements on ID_CRED_x apply to both ๐ŸŒท these fields are used to identify and optionally transport credentials:

  • ID_CRED_R is intended to help the Initiator retrieve the authentication credential CRED_R and the authentication key of R.
  • ID_CRED_I is intended to help the Responder retrieve the authentication credential CRED_I and the authentication key of I.

ID_CRED_x may contain the authentication credential CRED_x, for x = I or R, but in lots of settings it's not necessary to transport the credential within EDHOC ๐Ÿงš it might be pre-provisioned, or acquired out-of-band over less constrained links. ID_CRED_I and ID_CRED_R don't have any cryptographic purpose in EDHOC, since the authentication credentials are already integrity protected by the Signature_or_MAC field ๐Ÿ”

EDHOC relies on COSE for identification of credentials and supports all credential types that have COSE header parameters defined. that includes X.509 certificates [RFC9360], C509 certificates [C509-CERTS], CWTs (Section 3.5.3.1), and CCSs (Section 3.5.3.1) ๐Ÿ’–

ID_CRED_I and ID_CRED_R are of type COSE header_map, as defined in Section 3 of [RFC9052], and contain one or more COSE header parameters. if a map has several header parameters, the labels don't need to be sorted in bytewise lexicographic order. ID_CRED_I and ID_CRED_R MAY contain different header parameters. the header parameters usually give you some info about the format of the credential ๐ŸŽ€

example time: X.509 certificates can be identified by a hash value using the 'x5t' parameter (see Section 2 of [RFC9360]):

  • ID_CRED_x = { 34 : COSE_CertHash }, for x = I or R

another example: a CWT or CCS can be identified by a key identifier using the 'kid' parameter (see Section 3.1 of [RFC9052]):

  • ID_CRED_x = { 4 : kid_x }, where kid_x : kid, for x = I or R

note that COSE header parameters in ID_CRED_x are used to identify the message sender's credential ๐Ÿ’… so there's no reason to use the "-sender" header parameters, like x5t-sender, defined in Section 3 of [RFC9360]. instead, the corresponding parameter without "-sender", such as x5t, SHOULD be used ๐ŸŒธ

as Section 3.1 of [RFC9052] says, applications MUST NOT assume that 'kid' values are unique, and several keys associated with a 'kid' may need to be checked before finding the right one ๐Ÿ˜ญ applications might use extra info like 'kid context' or lower layers to decide which key to try first. applications should strive to make ID_CRED_x as unique as possible, since otherwise the recipient might have to try several keys ๐Ÿ’€

see Appendix C.3 for more examples ๐Ÿงš

3.5.3.1. COSE Header Parameters for CWT and CWT Claims Set ๐Ÿ‘‘

this document registers two new COSE header parameters, 'kcwt' and 'kccs', for use with CBOR Web Token (CWT) [RFC8392] and CWT Claims Set (CCS) [RFC8392], respectively. the CWT/CCS MUST contain a COSE_Key in a 'cnf' claim [RFC8747]. there may be any number of additional claims in the CWT/CCS ๐ŸŒˆ

CWTs sent in 'kcwt' are protected using a MAC or a signature, so they're kind of like a certificate (with public key crypto) or a Kerberos ticket (with symmetric key crypto) ๐Ÿฆ‹ CCSs sent in 'kccs' are not protected, so they're similar to raw public keys or self-signed certificates.

security considerations for 'kcwt' and 'kccs' are covered in Section 9.8. read it, it's serious ๐Ÿ˜ญ๐Ÿ”ฅ

3.5.3.2. Compact Encoding of ID_CRED Fields for 'kid' โœจ

to comply with the Lightweight Authenticated Key Exchange (LAKE) message size requirements (see [LAKE-REQS]), there are two optimizations for the case when ID_CRED_x, for x = I or R, contains a single 'kid' parameter. size matters, bestie ๐Ÿ“

  1. The CBOR map { 4 : kid_x } is replaced by the byte string kid_x.
  2. The representation of identifiers specified in Section 3.3.2 is applied to kid_x.

these optimizations MUST be applied if and only if ID_CRED_x = { 4 : kid_x } and ID_CRED_x is in PLAINTEXT_y of message_y, y = 2 or 3 (see Sections 5.3.2 and 5.4.2) ๐Ÿซถ note that the optimizations are not applied to instances of ID_CRED_x that have no impact on message size, e.g., context_y, or the COSE protected header. for example:

  • For ID_CRED_x = { 4 : h'FF' }, the encoding in PLAINTEXT_y is not the CBOR map 0xA10441FF but the CBOR byte string h'FF', i.e., 0x41FF.
  • For ID_CRED_x = { 4 : h'21' }, the encoding in PLAINTEXT_y is neither the CBOR map 0xA1044121 nor the CBOR byte string h'21', i.e., 0x4121, but the CBOR integer 0x21 ๐Ÿฆ‹๐Ÿ’…

3.6. Cipher Suites ๐Ÿ’–

okay so a cipher suite is basically a bundle of algorithms, and it's giving full toolkit ๐Ÿงฐ. It's an ordered set of algorithms from the "COSE Algorithms" and "COSE Elliptic Curves" registries, plus the EDHOC MAC length. All the algorithm names and definitions follow COSE Algorithms [RFC9053]. COSE has some very particular names, like ES256 for Elliptic Curve Digital Signature Algorithm (ECDSA) with SHA-256, A128 for AES-128, and Ed25519 for the curve edwards25519 ๐Ÿค“. Algorithms need enough parameters to be completely determined, so there's no guessing ๐Ÿ”. The EDHOC MAC length MUST be at least 8 bytes ๐Ÿ”’. Any cryptographic algorithm used in the COSE header parameters in ID_CRED fields is picked independently of the selected cipher suite, so those two choices don't have to match ๐Ÿซถ.

EDHOC is currently only specified for key exchange algorithms of type ECDH curves. But any Key Encapsulation Mechanism (KEM), including Post-Quantum Cryptography (PQC) KEMs, can be used in method 0; see Section 9.4 โœจ๐Ÿฆ‹. Using other types of key exchange algorithms to replace static DH authentication (methods 1, 2, and 3) would likely require a specification updating EDHOC with new methods, so that's a whole separate glow-up ๐Ÿ’….

EDHOC supports all signature algorithms defined by COSE ๐ŸŒˆ. Just like in (D)TLS 1.3 [RFC8446] [RFC9147] and IKEv2 [RFC7296], a signature in COSE is determined jointly by the signature algorithm and the authentication key algorithm; see Section 3.5.1 ๐ŸŽ€. The exact details of the authentication key algorithm depend on the type of authentication credential. COSE supports different formats for storing public authentication keys, including COSE_Key and X.509, and they use different names and ways to represent the authentication key and the authentication key algorithm ๐Ÿ“.

An EDHOC cipher suite consists of the following parameters:

  • EDHOC AEAD algorithm,
  • EDHOC hash algorithm,
  • EDHOC MAC length in bytes (Static DH),
  • EDHOC key exchange algorithm (ECDH curve),
  • EDHOC signature algorithm,
  • application AEAD algorithm, and
  • application hash algorithm.

Each cipher suite is identified with a predefined integer label ๐Ÿ”ข.

EDHOC can be used with all algorithms and curves defined for COSE ๐ŸŒธ. Implementations can either use any combination of COSE algorithms and parameters to define their own private cipher suite, or use one of the predefined cipher suites. Private cipher suites can be identified with any of the four values: -24, -23, -22, and -21 ๐Ÿงš. The predefined cipher suites are listed in the IANA registry (Section 10.2) with the initial content outlined here ๐Ÿ“‹:

  • Cipher suites 0-3, based on AES-CCM, are intended for constrained IoT where message overhead is a very important factor ๐Ÿค. Note that AES-CCM-16-64-128 and AES-CCM-16-128-128 are compatible with the IEEE AES-CCM* mode of operation defined in Annex B of [IEEE.802.15.4-2015] ๐Ÿฆ‹.
    • Cipher suites 1 and 3 use a larger tag length (128 bits) in EDHOC than in the application AEAD algorithm (64 bits) ๐Ÿ’œ.
  • Cipher suites 4 and 5, based on ChaCha20, are intended for less constrained applications and only use 128-bit tag lengths ๐ŸŒŠ.
  • Cipher suite 6, based on AES-GCM, is for general non-constrained applications. It consists of high-performance algorithms that are widely used in non-constrained applications ๐Ÿš€.
  • Cipher suites 24 and 25 are intended for high security applications such as government use and financial applications ๐Ÿ‘‘. These cipher suites do not share any algorithms. Cipher suite 24 consists of algorithms from the Commercial National Security Algorithm (CNSA) 1.0 suite [CNSA] ๐Ÿ”.

The different methods (Section 3.2) use the same cipher suites, but some algorithms are not used in some methods ๐Ÿ™ˆ. The EDHOC signature algorithm is not used in methods without signature authentication.

The Initiator needs to have a list of cipher suites it supports, in order of preference ๐Ÿ“. The Responder needs to have a list of cipher suites it supports. SUITES_I contains cipher suites supported by the Initiator, and it's formatted and processed as detailed in Section 5.2.1 so the cipher suite negotiation is secured ๐Ÿ”’โœจ. Examples of cipher suite negotiation are given in Section 6.3.2 ๐Ÿ’….


3.7. Ephemeral Public Keys ๐Ÿฆ‹

The ephemeral public keys in EDHOC (G_X and G_Y) use a compact representation of elliptic curve points; see Appendix B ๐ŸŒ™. In COSE, compact representation is achieved by formatting the ECDH ephemeral public keys as COSE_Keys of type EC2 or Octet Key Pair (OKP), according to Sections 7.1 and 7.2 of [RFC9053]. The trick is that you only include the x parameter in G_X and G_Y ๐Ÿคโœจ.

For Elliptic Curve Keys of type EC2, compact representation MAY be used also in the COSE_Key ๐Ÿ’ซ. COSE always uses compact output for Elliptic Curve Keys of type EC2 ๐Ÿ’œ. If the COSE implementation requires a y parameter, the value y = false or a calculated y-coordinate can be used; see Appendix B ๐ŸŒธ.


3.8. External Authorization Data (EAD) ๐ŸŽ€

okay so in order to reduce round trips and the number of messages, or to simplify processing, external security applications can be plugged into EDHOC by carrying authorization-related data inside the messages ๐Ÿš€๐Ÿ’….

EDHOC allows processing of external authorization data (EAD) to be defined in a separate specification, and it's sent in dedicated fields of the four EDHOC messages: EAD_1, EAD_2, EAD_3, and EAD_4 ๐Ÿงš. EAD is opaque data to EDHOC, so EDHOC doesn't look inside it ๐Ÿ™ˆ.

Each EAD field, EAD_x, for x = 1, 2, 3, or 4, is a CBOR sequence (see Appendix C.1) made of one or more EAD items. An EAD item ead is a CBOR sequence of an ead_label and an optional ead_value; see Figure 5 and Appendix C.2 for the CDDL definitions ๐Ÿ“‹.

ead = (
  ead_label : int,
  ? ead_value : bstr,
)

Figure 5: EAD Item ๐Ÿ–ผ๏ธ

A security application may register one or more EAD labels (see Section 10.5) and specify the associated processing and security considerations ๐Ÿ“. The IANA registry contains the absolute value of the ead_label, |ead_label|. The same ead_value applies independently of the sign of the ead_label ๐Ÿ”.

An EAD item can be either critical or non-critical, and that's determined by the sign of the ead_label in the EAD item transported in the EAD field. A negative value means the EAD item is critical, and a nonnegative value means it's non-critical โšก๐ŸŒˆ.

If an endpoint receives a critical EAD item it doesn't recognize, or a critical EAD item that contains information it cannot process, then the endpoint MUST send an EDHOC error message back as defined in Section 6, and the EDHOC session MUST be aborted ๐Ÿ›‘๐Ÿ˜ญ. The EAD item specification defines the error processing. A non-critical EAD item can be ignored ๐Ÿซถ.

The security application registering a new EAD item needs to describe under what conditions the EAD item is critical or non-critical, and therefore whether the ead_label is used with a negative or positive sign ๐Ÿง . ead_label = 0 is used for padding; see Section 3.8.1 ๐Ÿ“.

The security application may define multiple uses of certain EAD items. For example, the same EAD item may be used in different EDHOC messages ๐Ÿ”. Multiple occurrences of an EAD item in one EAD field may also be specified, but the criticality of the repeated EAD item is expected to be the same ๐Ÿ’œ.

The EAD fields of EDHOC MUST only be used with registered EAD items; see Section 10.5 ๐Ÿ”๐Ÿšจ. Examples of the use of EAD are provided in Appendix E โœจ.


3.8.1. Padding ๐ŸŒธ

EDHOC message_1 and the plaintext of message_2, message_3, and message_4 can be padded using the corresponding EAD_x field, for x = 1, 2, 3, or 4 ๐ŸŽ€. Padding in EAD_1 mitigates amplification attacks (see Section 9.7), and padding in EAD_2, EAD_3, and EAD_4 hides the true length of the plaintext (see Section 9.6) ๐Ÿฆ‹. Padding MUST be ignored and discarded by the receiving application ๐Ÿ—‘๏ธ.

Padding is obtained by using an EAD item with ead_label = 0 and a (pseudo)randomly generated byte string of appropriate length as ead_value. Just note that the ead_label and the CBOR encoding of ead_value also add bytes ๐Ÿงฎ. For example:

  • One-byte padding (optional ead_value omitted):
    • EAD_x = 0x00
  • Two-byte padding, using the empty byte string (0x40) as ead_value:
    • EAD_x = 0x0040
  • Three-byte padding, constructed from the pseudorandomly generated ead_value 0xe9 encoded as byte string:
    • EAD_x = 0x0041e9

Multiple occurrences of EAD items with ead_label = 0 are allowed. Certain padding lengths require the use of at least two such EAD items ๐Ÿงฉ.

Note that padding is non-critical, because the intended behavior when receiving is to ignore it ๐Ÿ™ˆ๐Ÿ’–.

3.9. Application Profile โœจ

okay so EDHOC needs a few parameters agreed on between the Initiator and the Responder ๐ŸŽ€ Some of them can be negotiated during the protocol run (the cipher suite, see Section 3.6, slay ๐Ÿ’…), but others are only communicated and can't be negotiated, like which authentication method gets used (see Section 3.2) ๐Ÿ™ˆ. Then there are parameters that have to be known out-of-band so everything actually finishes, e.g., whether message_4 is used or not ๐Ÿซถ. The application is the one that decides which endpoint is the Initiator and which is the Responder ๐Ÿ‘‘.

The whole point of an application profile is to describe the intended use of EDHOC so the right processing and verifications can happen. That includes things like:

  1. How the endpoint detects that an EDHOC message is received. This includes how EDHOC messages get transported, for example, in the payload of a CoAP message with a certain Uri-Path or Content-Format; see Appendix A.2.

The transport method can also describe extra data carried along with the messages that the transport needs in order to satisfy the requirements of Section 3.4, e.g., connection identifiers used with certain messages; see Appendix A.2. ๐Ÿฆ‹

  1. Authentication method (METHOD; see Section 3.2).
  2. Profile for authentication credentials (CRED_I and CRED_R; see Section 3.5.2), e.g., profile for certificate or CCS, including supported authentication key algorithms (subject public key algorithm in X.509 or C509 certificate). ๐ŸŒธ
  3. Type used to identify credentials (ID_CRED_I and ID_CRED_R; see Section 3.5.3).
  4. Use and type of external authorization data (EAD_1, EAD_2, EAD_3, and EAD_4; see Section 3.8).
  5. Identifier used as the identity of the endpoint; see Appendix D.2.
  6. If message_4 shall be sent/expected, and if not, how to ensure a protected application message is sent from the Responder to the Initiator; see Section 5.5. ๐Ÿงš

The application profile may also contain info about supported cipher suites. The procedure for selecting and verifying a cipher suite is still done the way Sections 5.2.1 and 6.3 describe it, but knowing this stuff ahead of time can make it simpler โœจ Also, EDHOC messages can be processed without the application profile, because the EDHOC messages include info about the type and length of all fields ๐Ÿ’–

An example of an application profile is shown in Appendix F. ๐Ÿ“

For some parameters, like METHOD, the type of the ID_CRED field, or EAD, the receiver of an EDHOC message can verify compliance with the application profile. If it has to fail because of a lack of compliance, it can infer the reason the EDHOC session failed ๐Ÿ”ฅ

For other encodings, like the profiling of CRED_x in the case where it is not transported, it may not be possible to verify that the lack of compliance with the application profile was the reason for failure. For example, integrity verification in message_2 or message_3 may fail for reasons other than a wrong credential. Say the Initiator uses a public key certificate by reference (i.e., not transported within the protocol). Then both endpoints need to use an identical data structure as CRED_I, or else the integrity verification will fail ๐Ÿ˜ญ

Note that it is not necessary for the endpoints to specify a single transport for the EDHOC messages. For example, a mix of CoAP and HTTP may be used along the path, and this may still allow correlation between messages. ๐ŸŒˆ

The application profile may depend on the identity of the other endpoint or on other info carried in an EDHOC message, but then it only applies to the later phases of the protocol, when that info is known. (The Initiator does not know the identity of the Responder before having verified message_2, and the Responder does not know the identity of the Initiator before having verified message_3.) ๐Ÿ™ˆ

Other conditions can be part of the application profile too, such as what the target application or use is (if there is more than one application/use), to the extent that EDHOC can distinguish between them. If multiple application profiles are used, the receiver needs to be able to determine which one applies to a given EDHOC session, for example, based on the URI the EDHOC message is sent to, or the external authorization data type. ๐Ÿ’œ


4. Key Derivation โœจ

4.1. Keys for EDHOC Message Processing

EDHOC uses Extract-and-Expand [RFC5869] with the EDHOC hash algorithm in the selected cipher suite to derive the keys used in message processing ๐Ÿ”‘ This section defines EDHOC_Extract (Section 4.1.1) and EDHOC_Expand (Section 4.1.2), and explains how to use them to derive PRK_out (Section 4.1.3), which is the shared secret session key that comes out of a completed EDHOC session ๐ŸŽ€

EDHOC_Extract is used to derive fixed-length uniformly pseudorandom keys (PRKs) from ECDH shared secrets. EDHOC_Expand is used to define EDHOC_KDF for generating MACs and for deriving output keying material (OKM) from PRKs. ๐Ÿฆ‹

In EDHOC, a specific message is protected with a certain PRK, but how the key is derived depends on the authentication method (Section 3.2), as detailed in Section 5. โœจ

4.1.1. EDHOC_Extract

The pseudorandom keys (PRKs) used for EDHOC message processing are derived using EDHOC_Extract:

PRK = EDHOC_Extract( salt, IKM )

where the input keying material (IKM) and salt are defined for each PRK below.

The definition of EDHOC_Extract depends on the EDHOC hash algorithm of the selected cipher suite:

  • If the EDHOC hash algorithm is SHA-2, then EDHOC_Extract( salt, IKM ) = HKDF-Extract( salt, IKM ) [RFC5869].
  • If the EDHOC hash algorithm is SHAKE128, then EDHOC_Extract( salt, IKM ) = KMAC128( salt, IKM, 256, "" ).
  • If the EDHOC hash algorithm is SHAKE256, then EDHOC_Extract( salt, IKM ) = KMAC256( salt, IKM, 512, "" ).

where the Keccak Message Authentication Code (KMAC) is specified in [SP800-185]. ๐ŸŒธ

The rest of the section defines the pseudorandom keys PRK_2e, PRK_3e2m, and PRK_4e3m. Their use is shown in Figure 6. The index of a PRK tells you its use, or which message protection operation it is involved in. For example, PRK_3e2m is involved in the encryption of message 3 and in calculating the MAC of message 2. ๐Ÿงš

4.1.1.1. PRK_2e

The pseudorandom key PRK_2e is derived with the following input:

  • The salt SHALL be TH_2.
  • The IKM SHALL be the ephemeral-ephemeral ECDH shared secret G_XY (calculated from G_X and Y or G_Y and X) as defined in Section 6.3.1 of [RFC9053]. The use of G_XY gives forward secrecy, in the sense that compromise of the private authentication keys does not compromise past session keys. ๐Ÿ”ฅ

Example: Assuming the use of curve25519, the ECDH shared secret G_XY is the output of the X25519 function [RFC7748]:

G_XY = X25519( Y, G_X ) = X25519( X, G_Y )

Example: Assuming the use of SHA-256, the extract phase of the key derivation function is HKDF-Extract, which produces PRK_2e as follows:

PRK_2e = HMAC-SHA-256( TH_2, G_XY )

4.1.1.2. PRK_3e2m

The pseudorandom key PRK_3e2m is derived as follows:

If the Responder authenticates with a static Diffie-Hellman key, then PRK_3e2m = EDHOC_Extract( SALT_3e2m, G_RX ), where

  • SALT_3e2m is derived from PRK_2e (see Section 4.1.2), and
  • G_RX is the ECDH shared secret calculated from G_R and X, or G_X and R (the Responder's private authentication key; see Section 3.5.1),

else PRK_3e2m = PRK_2e. ๐Ÿ’–

4.1.1.3. PRK_4e3m

The pseudorandom key PRK_4e3m is derived as follows:

If the Initiator authenticates with a static Diffie-Hellman key, then PRK_4e3m = EDHOC_Extract( SALT_4e3m, G_IY ), where

  • SALT_4e3m is derived from PRK_3e2m (see Section 4.1.2), and
  • G_IY is the ECDH shared secret calculated from G_I and Y, or G_Y and I (the Initiator's private authentication key; see Section 3.5.1),

else PRK_4e3m = PRK_3e2m. ๐ŸŒˆ

4.1.2. EDHOC_Expand and EDHOC_KDF

The output keying material (OKM), including keys, initialization vectors (IVs), and salts, is derived from the PRKs using EDHOC_KDF, which is defined through EDHOC_Expand:

OKM = EDHOC_KDF( PRK, info_label, context, length )
    = EDHOC_Expand( PRK, info, length )

where info is encoded as the CBOR sequence:

info = (
  info_label : int,
  context : bstr,
  length : uint,
)

where:

  • info_label is an int,
  • context is a bstr, and
  • length is the length of OKM in bytes. ๐ŸŽ€

When EDHOC_KDF is used to derive OKM for EDHOC message processing, the context includes one of the transcript hashes, TH_2, TH_3, or TH_4, defined in Sections 5.3.2 and 5.4.2. โœจ

The definition of EDHOC_Expand depends on the EDHOC hash algorithm of the selected cipher suite:

  • If the EDHOC hash algorithm is SHA-2, then EDHOC_Expand( PRK, info, length ) = HKDF-Expand( PRK, info, length ) [RFC5869].
  • If the EDHOC hash algorithm is SHAKE128, then EDHOC_Expand( PRK, info, length ) = KMAC128( PRK, info, L, "" ).
  • If the EDHOC hash algorithm is SHAKE256, then EDHOC_Expand( PRK, info, length ) = KMAC256( PRK, info, L, "" ).

where L = 8 โ‹… length, the output length in bits. ๐Ÿงฎ

Figure 6 lists the derivations made with EDHOC_KDF, where:

  • hash_length is the length of the output size of the EDHOC hash algorithm of the selected cipher suite,
  • key_length is the length of the encryption key of the EDHOC AEAD algorithm of the selected cipher suite, and
  • iv_length is the length of the initialization vector of the EDHOC AEAD algorithm of the selected cipher suite.

Further details of the key derivation, and how the output keying material is used, are specified in Section 5. ๐Ÿ’œ

KEYSTREAM_2   = EDHOC_KDF( PRK_2e,   0, TH_2,      plaintext_length )
SALT_3e2m     = EDHOC_KDF( PRK_2e,   1, TH_2,      hash_length )
MAC_2         = EDHOC_KDF( PRK_3e2m, 2, context_2, mac_length_2 )
K_3           = EDHOC_KDF( PRK_3e2m, 3, TH_3,      key_length )
IV_3          = EDHOC_KDF( PRK_3e2m, 4, TH_3,      iv_length )
SALT_4e3m     = EDHOC_KDF( PRK_3e2m, 5, TH_3,      hash_length )
MAC_3         = EDHOC_KDF( PRK_4e3m, 6, context_3, mac_length_3 )
PRK_out       = EDHOC_KDF( PRK_4e3m, 7, TH_4,      hash_length )
K_4           = EDHOC_KDF( PRK_4e3m, 8, TH_4,      key_length )
IV_4          = EDHOC_KDF( PRK_4e3m, 9, TH_4,      iv_length )
PRK_exporter  = EDHOC_KDF( PRK_out, 10, h'',       hash_length )

              Figure 6: Key Derivations Using EDHOC_KDF

h'' is CBOR diagnostic notation for the empty byte string, 0x40. ๐Ÿ“

4.1.3. PRK_out

The pseudorandom key PRK_out, derived as shown in Figure 6, is the output session key of a completed EDHOC session. ๐Ÿ‘‘

Keys for applications are derived using EDHOC_Exporter (see Section 4.2.1) from PRK_exporter, which in turn is derived from PRK_out as shown in Figure 6. For the purpose of generating application keys, it is sufficient to store PRK_out or PRK_exporter. ๐Ÿ”‘

(Note that the word "store" used here does not imply that the application has access to the plaintext PRK_out, since that may be reserved for code within a Trusted Execution Environment (TEE); see Section 9.8.) ๐Ÿ›ก๏ธ

4.2. Keys for EDHOC Applications

This section defines EDHOC_Exporter in terms of EDHOC_KDF and PRK_exporter. A key update function is defined in Appendix H. ๐Ÿฆ‹

4.2.1. EDHOC_Exporter โœจ

okay so bestie, this is the bit where you get keying material for your application ๐Ÿ”‘๐Ÿ’– You use the EDHOC_Exporter interface, and it's basically a wrapper around EDHOC_KDF that feeds in PRK_exporter:

EDHOC_Exporter(exporter_label, context, length)
  = EDHOC_KDF(PRK_exporter, exporter_label, context, length)

where:

  • exporter_label is a registered uint from the "EDHOC Exporter Labels" registry (Section 10.1),
  • context is a bstr defined by the application, and
  • length is a uint defined by the application.

Now the main rule ๐Ÿšจ: the (exporter_label, context) pair MUST be unique, so an (exporter_label, context) MUST NOT be used for two different purposes. No mixing them up, periodt ๐Ÿ’… BUT you're totally allowed to re-derive the same key several times, as long as you do it securely ๐Ÿฆ‹ Like, most encryption algorithms are fine reusing the same key with different nonces. And context can just be the empty CBOR byte string if you want, no drama ๐ŸŒธ

Examples of how to use EDHOC_Exporter are in Appendix A ๐Ÿงš


5. Message Formatting and Processing ๐ŸŽ€

this section is where the actual messages get formatted and processed ๐Ÿ’Œ Error messages are covered in Section 6, and annotated traces of EDHOC sessions are over in [RFC9529] ๐Ÿ“–โœจ

an EDHOC message is encoded as a sequence of CBOR data items (CBOR Sequence [RFC8742]), and there are some extra optimizations to keep the overhead nice and small ๐Ÿ“

EDHOC uses the COSE_Key, COSE_Sign1, and COSE_Encrypt0 structures, but only a subset of the parameters actually goes into the messages (see Appendix C.3) ๐Ÿซถ So the recipient might need to add parameters back into the COSE headers to rebuild the COSE object, like the 'alg' parameter for COSE_Sign1 or COSE_Encrypt0. iykyk ๐Ÿ˜ญ


5.1. EDHOC Message Processing Outline ๐Ÿฆ‹

for every new or ongoing EDHOC session, the endpoints keep a protocol state with identifiers, keying material, and so on ๐Ÿ—‚๏ธ That state is tied to an application profile (Section 3.9), which tells you how messages get transported, identified, and processed ๐ŸŒˆ

EDHOC messages SHALL be processed according to the current protocol state. when a message comes in, these steps happen:

  1. Detect that an EDHOC message has been received, for example by a port number, URI, or media type (Section 3.9). ๐Ÿ‘€
  2. Retrieve the protocol state using the message correlation (see Section 3.4.1). If there's no protocol state and it's message_1, make a new one. The Responder also needs to use whatever denial-of-service mitigation is available (Section 9.7) ๐Ÿ›ก๏ธ
  3. If the message is an error message, process it according to Section 6. Otherwise, process it as the next expected message for the protocol state. โœ…

The message processing steps SHALL be processed in order, unless otherwise stated ๐Ÿ”ข If processing fails, an error message is typically sent, the EDHOC session gets aborted, and the protocol state is erased ๐Ÿ’€ Once you've composed and sent a message and before the next one arrives, error messages SHALL NOT be sent ๐Ÿ™…โ€โ™€๏ธ

after the last message is processed successfully (message_3 or message_4, depending on the application profile), the EDHOC session is complete โœจ After that, no error messages are sent, and the EDHOC session output MAY be kept even if error messages come in later ๐ŸŽ€ More details are in the next subsections and Section 6 ๐Ÿ’–

โš ๏ธ different instances of the same message MUST NOT be processed in one EDHOC session. If the same message shows up again, processing fails, because the protocol state has already moved on and is expecting something else ๐Ÿ™ˆ Message deduplication MUST be done by the transport protocol (see Section 3.4) or, if the transport doesn't support it, as described in Section 7 ๐Ÿซถ

5.2. EDHOC Message 1 ๐ŸŒธ

5.2.1. Formatting of Message 1 ๐Ÿงš

message_1 SHALL be a CBOR Sequence (see Appendix C.1), defined like this:

message_1 = (
  METHOD : int,
  SUITES_I : suites,
  G_X : bstr,
  C_I : bstr / -24..23,
  ? EAD_1,
)

suites = [ 2* int ] / int
EAD_1 = 1* ead

where:

  • METHOD is an authentication method; see Section 3.2,
  • SUITES_I is an array of cipher suites that the Initiator supports, built as specified in Section 5.2.2,
  • G_X is the ephemeral public key of the Initiator, and
  • C_I is a variable-length connection identifier (connection identifiers are byte strings, but certain values are shown as integers in the message; see Section 3.3.2), and
  • EAD_1 is external authorization data; see Section 3.8.

5.2.2. Initiator Composition of Message 1 ๐Ÿ’…

the processing steps are below and in Section 6.3 โœจ

The Initiator SHALL compose message_1 like this:

  • Build SUITES_I as an array of the cipher suites the Initiator supports, in order of preference. The first one is the most preferred, and the last one is the one the Initiator selected for this EDHOC session ๐Ÿ‘‘ If the most preferred suite is the one selected, then SUITES_I has just that suite and is encoded as an int. Every suite preferred over the selected one MUST be included. (See also Section 6.3.) ๐Ÿ’–
    • The selected suite should be based on what the Initiator can assume the Responder supports. If the Initiator earlier got an error message with error code 2 containing SUITES_R (see Section 6.3) listing the Responder's supported suites, then the Initiator SHOULD pick its most preferred supported suite from those, bearing in mind error messages can be forged ๐Ÿ™ˆ
    • The Initiator MUST NOT change its order of preference for cipher suites, and MUST NOT leave out a suite it prefers over the selected one just because of earlier error messages from the Responder. ๐Ÿšซ
  • Generate an ephemeral ECDH key pair using the curve in the selected cipher suite, and format it as a COSE_Key. Let G_X be the 'x' parameter of the COSE_Key. ๐Ÿ”‘
  • Choose a connection identifier C_I and store it during the EDHOC session. ๐ŸŽ€
  • Encode message_1 as a sequence of CBOR-encoded data items, as specified in Section 5.2.1. ๐Ÿง

5.2.3. Responder Processing of Message 1 ๐Ÿฆ‹

The Responder SHALL process message_1 in this order:

  1. Decode message_1 (see Appendix C.1). ๐Ÿ“ฆ
  2. Process message_1. In particular, verify that the selected cipher suite is supported, and that no prior suite in SUITES_I is supported. ๐Ÿ”
  3. If all processing completes successfully and EAD_1 is present, make it available to the application for EAD processing. ๐ŸŒˆ

If any processing step fails, the Responder MUST send an EDHOC error message back as defined in Section 6, and the EDHOC session MUST be aborted. ๐Ÿšจ


5.3. EDHOC Message 2 ๐ŸŒท

5.3.1. Formatting of Message 2 ๐Ÿ’–

message_2 SHALL be a CBOR Sequence (see Appendix C.1), defined like this:

message_2 = (
  G_Y_CIPHERTEXT_2 : bstr,
)

where:

  • G_Y_CIPHERTEXT_2 is the concatenation of G_Y (the ephemeral public key of the Responder) and CIPHERTEXT_2. ๐Ÿซถ

5.3.2. Responder Composition of Message 2 โœจ

The Responder SHALL compose message_2 like this:

  • Generate an ephemeral ECDH key pair using the curve in the selected cipher suite, and format it as a COSE_Key. Let G_Y be the 'x' parameter of the COSE_Key. ๐Ÿ”‘
  • Choose a connection identifier C_R and store it for the length of the EDHOC session. ๐ŸŽ€
  • Compute the transcript hash TH_2 = H( G_Y, H(message_1) ), where H() is the EDHOC hash algorithm of the selected cipher suite. The input to the hash function is a CBOR Sequence. Note that H(message_1) can be computed and cached already while processing message_1. ๐Ÿง 
  • Compute MAC_2 as in Section 4.1.2 with context_2 = << C_R, ID_CRED_R, TH_2, CRED_R, ? EAD_2 >> (see Appendix C.1 for notation). ๐Ÿ”
    • If the Responder authenticates with a static Diffie-Hellman key (method equals 1 or 3), then mac_length_2 is the EDHOC MAC length of the selected cipher suite. If the Responder authenticates with a signature key (method equals 0 or 2), then mac_length_2 is equal to hash_length. ๐Ÿ“
    • C_R is a variable-length connection identifier. Connection identifiers are byte strings, but certain values are represented as integers in the message; see Section 3.3.2. ๐Ÿฆ‹
    • ID_CRED_R is an identifier that helps retrieve CRED_R; see Section 3.5.3. ๐Ÿ”Ž
    • CRED_R is a CBOR item containing the authentication credential of the Responder; see Section 3.5.2. ๐Ÿชช
    • EAD_2 is external authorization data; see Section 3.8. ๐ŸŒธ
  • If the Responder authenticates with a static Diffie-Hellman key (method equals 1 or 3), then Signature_or_MAC_2 is MAC_2. If the Responder authenticates with a signature key (method equals 0 or 2), then Signature_or_MAC_2 is the 'signature' field of a COSE_Sign1 object. That's computed as specified in Section 4.4 of [RFC9052], using the signature algorithm of the selected cipher suite, the Responder's private authentication key, and these parameters as input (see Appendix C.3 for an overview of COSE and Appendix C.1 for notation): โœ๏ธ
    • protected = << ID_CRED_R >>
    • external_aad = << TH_2, CRED_R, ? EAD_2 >>
    • payload = MAC_2
  • CIPHERTEXT_2 is calculated with a binary additive stream cipher, using a keystream generated with EDHOC_Expand and this plaintext: ๐ŸŒŠ
    • PLAINTEXT_2 = ( C_R, ID_CRED_R / bstr / -24..23, Signature_or_MAC_2, ? EAD_2 )
      • If ID_CRED_R contains a single 'kid' parameter, i.e., ID_CRED_R = { 4 : kid_R }, then the compact encoding is applied; see Section 3.5.3.2. ๐Ÿฌ
      • C_R is the variable-length connection identifier. Connection identifiers are byte strings, but certain values are represented as integers in the message; see Section 3.3.2. ๐ŸŽ€
    • Compute KEYSTREAM_2 as in Section 4.1.2, where plaintext_length is the length of PLAINTEXT_2. For the case where plaintext_length exceeds the EDHOC_KDF output size, see Appendix G. ๐Ÿงฎ
    • CIPHERTEXT_2 = PLAINTEXT_2 XOR KEYSTREAM_2 ๐Ÿ’ซ
  • Encode message_2 as a sequence of CBOR-encoded data items, as specified in Section 5.3.1. ๐ŸŽ

5.3.3. Initiator Processing of Message 2 โœจ

okay so this is where the Initiator gets message_2 and actually does the work ๐Ÿ’… and it has to do it in this exact order, bestie, no skipping ๐ŸŽ€

The Initiator SHALL process message_2 in the following order:

  1. Decode message_2 (see Appendix C.1). ๐Ÿงš
  2. Retrieve the protocol state using available message correlation (e.g., the CoAP Token, the 5-tuple, or the prepended C_I; see Section 3.4.1). It's giving "find the right conversation" energy ๐Ÿ’œ
  3. Decrypt CIPHERTEXT_2; see Section 5.3.2. ๐Ÿ”“
  4. If all processing is completed successfully, then make ID_CRED_R and (if present) EAD_2 available to the application for authentication and EAD processing. When and how to perform authentication is up to the application. The app gets to decide the vibe here ๐Ÿ‘‘
  5. Obtain the authentication credential (CRED_R) and the authentication key of R from the application (or by other means). ๐Ÿ”‘
  6. Verify Signature_or_MAC_2 using the algorithm in the selected cipher suite. The verification process depends on the method; see Section 5.3.2. Make the result of the verification available to the application. โœ…

If any processing step fails, then the Initiator MUST send an EDHOC error message back as defined in Section 6, and the EDHOC session MUST be aborted. ๐Ÿ’€ no cap this part is serious, bestie ๐Ÿซถ

5.4. EDHOC Message 3 ๐Ÿฆ‹

5.4.1. Formatting of Message 3 ๐ŸŽ€

message_3 SHALL be a CBOR Sequence (see Appendix C.1), as defined below. ๐Ÿงš

message_3 = (
  CIPHERTEXT_3 : bstr,
)

5.4.2. Initiator Composition of Message 3 ๐Ÿ’…

The Initiator SHALL compose message_3 as follows: literally the main character moment of the whole handshake ๐Ÿ”ฅ

  • Compute the transcript hash TH_3 = H(TH_2, PLAINTEXT_2, CRED_R), where H() is the EDHOC hash algorithm of the selected cipher suite. The input to the hash function is a CBOR Sequence. Note that TH_3 can be computed and cached already in the processing of message_2. โœจ
  • Compute MAC_3 as in Section 4.1.2, with context_3 = << ID_CRED_I, TH_3, CRED_I, ? EAD_3 >>
    • If the Initiator authenticates with a static Diffie-Hellman key (method equals 2 or 3), then mac_length_3 is the EDHOC MAC length of the selected cipher suite. If the Initiator authenticates with a signature key (method equals 0 or 1), then mac_length_3 is equal to hash_length. ๐ŸŒธ
    • ID_CRED_I is an identifier to facilitate the retrieval of CRED_I; see Section 3.5.3. ๐Ÿ”
    • CRED_I is a CBOR item containing the authentication credential of the Initiator; see Section 3.5.2. ๐Ÿชช
    • EAD_3 is external authorization data; see Section 3.8. ๐ŸŒˆ
  • If the Initiator authenticates with a static Diffie-Hellman key (method equals 2 or 3), then Signature_or_MAC_3 is MAC_3. If the Initiator authenticates with a signature key (method equals 0 or 1), then Signature_or_MAC_3 is the 'signature' field of a COSE_Sign1 object, computed as specified in Section 4.4 of [RFC9052] using the signature algorithm of the selected cipher suite, the private authentication key of the Initiator, and the following parameters as input (see Appendix C.3):
    • protected = << ID_CRED_I >>
    • external_aad = << TH_3, CRED_I, ? EAD_3 >>
    • payload = MAC_3
  • Compute a COSE_Encrypt0 object as defined in Sections 5.2 and 5.3 of [RFC9052], with the EDHOC AEAD algorithm of the selected cipher suite, using the encryption key K_3, the initialization vector IV_3 (if used by the AEAD algorithm), the plaintext PLAINTEXT_3, and the following parameters as input (see Appendix C.3):
    • protected = h''
    • external_aad = TH_3
    • K_3 and IV_3 are defined in Section 4.1.2
    • PLAINTEXT_3 = ( ID_CRED_I / bstr / -24..23, Signature_or_MAC_3, ? EAD_3 )
      • If ID_CRED_I contains a single 'kid' parameter, i.e., ID_CRED_I = { 4 : kid_I }, then the compact encoding is applied; see Section 3.5.3.2. ๐Ÿค

CIPHERTEXT_3 is the 'ciphertext' of COSE_Encrypt0.

  • Compute the transcript hash TH_4 = H(TH_3, PLAINTEXT_3, CRED_I), where H() is the EDHOC hash algorithm of the selected cipher suite. The input to the hash function is a CBOR Sequence. ๐Ÿงฎ
  • Calculate PRK_out as defined in Figure 6. The Initiator can now derive application keys using the EDHOC_Exporter interface; see Section 4.2.1. ๐Ÿ—๏ธ
  • Encode message_3 as a CBOR data item as specified in Section 5.4.1. ๐Ÿ“ฆ
  • Make the connection identifiers (C_I and C_R) and the application algorithms in the selected cipher suite available to the application. ๐ŸŽ

After creating message_3, the Initiator can compute PRK_out (see Section 4.1.3) and derive application keys using the EDHOC_Exporter interface (see Section 4.2.1). The Initiator SHOULD NOT persistently store PRK_out or application keys until the Initiator has verified message_4 or a message protected with a derived application key, such as an OSCORE message, from the Responder and the application has authenticated the Responder. This is similar to waiting for an acknowledgment (ACK) in a transport protocol. The Initiator SHOULD NOT send protected application data until the application has authenticated the Responder. โณ patience is a whole skill, bestie

5.4.3. Responder Processing of Message 3 ๐ŸŒท

The Responder SHALL process message_3 in the following order:

  1. Decode message_3 (see Appendix C.1). ๐Ÿงš
  2. Retrieve the protocol state using available message correlation (e.g., the CoAP Token, the 5-tuple, or the prepended C_R; see Section 3.4.1). ๐Ÿ’œ
  3. Decrypt and verify the COSE_Encrypt0 as defined in Sections 5.2 and 5.3 of [RFC9052], with the EDHOC AEAD algorithm in the selected cipher suite and the parameters defined in Section 5.4.2. ๐Ÿ”“
  4. If all processing completed successfully, then make ID_CRED_I and (if present) EAD_3 available to the application for authentication and EAD processing. When and how to perform authentication is up to the application. ๐Ÿ‘‘
  5. Obtain the authentication credential (CRED_I) and the authentication key of I from the application (or by other means). ๐Ÿ”‘
  6. Verify Signature_or_MAC_3 using the algorithm in the selected cipher suite. The verification process depends on the method; see Section 5.4.2. Make the result of the verification available to the application. โœ…
  7. Make the connection identifiers (C_I and C_R) and the application algorithms in the selected cipher suite available to the application. ๐ŸŽ

After processing message_3, the Responder can compute PRK_out (see Section 4.1.3) and derive application keys using the EDHOC_Exporter interface (see Section 4.2.1). The Responder SHOULD NOT persistently store PRK_out or application keys until the application has authenticated the Initiator. The Responder SHOULD NOT send protected application data until the application has authenticated the Initiator.

If any processing step fails, then the Responder MUST send an EDHOC error message back as defined in Section 6, and the EDHOC session MUST be aborted. ๐Ÿ’€ same energy as before, no skipping

5.5. EDHOC Message 4 ๐ŸŒˆ

This section specifies message_4, which is OPTIONAL to support. Key confirmation is normally provided by sending an application message from the Responder to the Initiator protected with a key derived with the EDHOC_Exporter, e.g., using OSCORE (see Appendix A). In deployments where no protected application message is sent from the Responder to the Initiator, message_4 MUST be supported and MUST be used. Two examples of such deployments are: ๐Ÿซถ

  1. when EDHOC is only used for authentication and no application data is sent and
  2. when application data is only sent from the Initiator to the Responder.

Further considerations about when to use message_4 are provided in Sections 3.9 and 9.1. ๐Ÿ“š

5.5.1. Formatting of Message 4 ๐ŸŽ€

message_4 SHALL be a CBOR Sequence (see Appendix C.1), as defined below. ๐Ÿงš

message_4 = (
  CIPHERTEXT_4 : bstr,

)

5.5.2. Responder Composition of Message 4 ๐Ÿ’…

The Responder SHALL compose message_4 as follows:

  • Compute a COSE_Encrypt0 as defined in Sections 5.2 and 5.3 of [RFC9052], with the EDHOC AEAD algorithm of the selected cipher suite, using the encryption key K_4, the initialization vector IV_4 (if used by the AEAD algorithm), the plaintext PLAINTEXT_4, and the following parameters as input (see Appendix C.3):
    • protected = h''
    • external_aad = TH_4
    • K_4 and IV_4 are defined in Section 4.1.2
    • PLAINTEXT_4 = ( ? EAD_4 )
      • EAD_4 is external authorization data; see Section 3.8.

CIPHERTEXT_4 is the 'ciphertext' of COSE_Encrypt0.

  • Encode message_4 as a CBOR data item as specified in Section 5.5.1. ๐Ÿ“ฆ

5.5.3. Initiator Processing of Message 4 ๐Ÿฆ‹

The Initiator SHALL process message_4 as follows:

  • Decode message_4 (see Appendix C.1).
  • Retrieve the protocol state using available message correlation (e.g., the CoAP Token, the 5-tuple, or the prepended C_I; see Section 3.4.1).
  • Decrypt and verify the COSE_Encrypt0 as defined in Sections 5.2 and 5.3 of [RFC9052], with the EDHOC AEAD algorithm in the selected cipher suite and the parameters defined in Section 5.5.2.
  • Make (if present) EAD_4 available to the application for EAD processing.

If any processing step fails, then the Initiator MUST send an EDHOC error message back as defined in Section 6, and the EDHOC session MUST be aborted.

After verifying message_4, the Initiator is assured that the Responder has calculated the key PRK_out (key confirmation) and that no other party can derive the key. ๐Ÿ”โœจ that's the payoff, bestie, we did it ๐Ÿฅน

6. Error Handling โœจ

okay bestie, this section is all about error messages ๐Ÿ™ˆ it covers the format they have to use and what to do with each error code we've got right now. more codes can get registered later too, see Section 10.4 ๐Ÿ’…

so, lots of things can go wrong during EDHOC processing ๐Ÿ˜ญ like in CoAP, an error can come from something wrong in the message you received, or from something going wrong inside the endpoint that's receiving it. except for processing and formatting errors, it's up to the application to decide when to send an error message ๐Ÿฆ‹ error messages are super important for debugging, but they MAY be skipped if, for example, an EDHOC session can't be found, or for denial-of-service reasons; see Section 9.7. also, error messages in EDHOC are always fatal ๐Ÿ’€ so after you send one, the sender MUST abort the EDHOC session. the receiver SHOULD treat an error message as a sign that the other party has probably aborted the session. but since error messages can be forged, the receiver MAY try to continue the EDHOC session anyway ๐Ÿซถ

an EDHOC error message can be sent by either endpoint as a reply to any non-error EDHOC message โœจ how errors at the EDHOC layer actually get carried over the wire depends on the lower layers, and those lower layers need to make sure error messages can be sent and processed the way they're meant to be ๐ŸŒธ

error SHALL be a CBOR Sequence (see Appendix C.1), as defined below. ๐Ÿ’–

error = (
  ERR_CODE : int,
  ERR_INFO : any,
)

Figure 7: EDHOC Error Message

where:

  • ERR_CODE is an error code encoded as an integer. The value 0 is reserved for success and can only be used internally; all other values (negative or positive) indicate errors. ๐Ÿ“
  • ERR_INFO is error information. Its content and encoding depend on the error code. ๐Ÿงš

the rest of this section goes through the error codes we currently have defined, see Table 3 ๐Ÿ’œ additional error codes and their error information may be specified too.

+==========+===============+===============================+
| ERR_CODE | ERR_INFO Type | Description                   |
+==========+===============+===============================+
|        0 |               | Reserved for success          |
+----------+---------------+-------------------------------+
|        1 | tstr          | Unspecified error             |
+----------+---------------+-------------------------------+
|        2 | suites        | Wrong selected cipher suite   |
+----------+---------------+-------------------------------+
|        3 | true          | Unknown credential referenced |
+----------+---------------+-------------------------------+
|       23 |               | Reserved                      |
+----------+---------------+-------------------------------+

Table 3: EDHOC Error Codes and Error Information

6.1. Success ๐ŸŽ€

error code 0 MAY be used internally in an application to mean success, so basically as a standard "no error" value, e.g., for status reporting or log files ๐ŸŒˆ but error code 0 MUST NOT be used as part of the EDHOC message exchange. if an endpoint receives an error message with error code 0, then it MUST abort the EDHOC session and MUST NOT send an error message back. not me being dramatic about it ๐Ÿ™ˆ

6.2. Unspecified Error ๐Ÿงš

error code 1 is for errors that don't have a specific error code defined yet. ERR_INFO MUST be a text string containing a human-readable diagnostic message that SHOULD be written in English, for example, "Method not supported" ๐Ÿ‡ฌ๐Ÿ‡ง the diagnostic text is mainly for software engineers who need to read it while debugging, so they can make sense of it in the context of the EDHOC specification ๐Ÿ” the diagnostic message SHOULD be handed to the calling application, where it SHOULD be logged ๐Ÿ“

6.3. Wrong Selected Cipher Suite ๐Ÿฆ‹

okay this one is a whole thing ๐Ÿ’… error code 2 MUST only be used when replying to message_1, and only in two situations: either the cipher suite the Initiator selected isn't supported by the Responder, or the Responder supports a cipher suite that the Initiator likes more than the selected one; see Section 5.2.3. in that case, ERR_INFO = SUITES_R, and it's of type suites; see Section 5.2.1. if the Responder doesn't support the selected cipher suite, then SUITES_R MUST include one or more supported cipher suites โœจ if the Responder supports a cipher suite in SUITES_I other than the selected one (whether or not the selected one is supported), then SUITES_R MUST include the supported cipher suite from SUITES_I that the Initiator prefers most ๐Ÿ’– SUITES_R MAY include a single cipher suite, and in that case it's encoded as an int ๐ŸŒธ and if the Responder doesn't support any cipher suite in SUITES_I, it SHOULD include all of its supported cipher suites in SUITES_R ๐Ÿซถ

and yep, the order of the cipher suites in SUITES_R doesn't matter at all, unlike SUITES_I ๐Ÿ’…

6.3.1. Cipher Suite Negotiation ๐ŸŒธ

after the Initiator gets SUITES_R, it can work out which cipher suite to pick (if any) for the next EDHOC run with that Responder ๐Ÿง  the Initiator SHOULD remember the selected cipher suite until the next message_1 has been sent ๐Ÿ” otherwise, the two of them end up in an infinite loop: the Initiator keeps picking its favourite, and the Responder keeps sending back an error with the supported cipher suites ๐Ÿ˜ญ

after a completed EDHOC session, the Initiator MAY remember the selected cipher suite to use in future EDHOC sessions with that same Responder ๐Ÿ’œ just keep in mind that if the Initiator or Responder gets updated with new cipher suite policies, whatever got cached might be outdated now ๐Ÿ‘€

the Initiator's list of supported cipher suites and its order of preference are fixed (see Sections 5.2.1 and 5.2.2) โœจ and the Responder SHALL only accept message_1 if the selected cipher suite is the first cipher suite in SUITES_I that the Responder also supports (see Section 5.2.3) ๐Ÿ”’ following this procedure makes sure the selected cipher suite is the most preferred one (by the Initiator) that both parties support ๐Ÿ‘‘ for examples, see Section 6.3.2 ๐ŸŽ€

if the selected cipher suite is not the first cipher suite that the Responder supports in the SUITES_I it received in message_1, then the Responder MUST abort the EDHOC session; see Section 5.2.3 ๐Ÿ›‘ and if SUITES_I in message_1 gets manipulated, then the integrity check on message_2 (which contains the transcript hash TH_2) will fail, and the Initiator will abort the EDHOC session ๐Ÿ™…โ€โ™€๏ธ

6.3.2. Examples ๐Ÿ“

let's say the Initiator supports the five cipher suites 5, 6, 7, 8, and 9, in decreasing order of preference ๐ŸŒˆ Figures 8 and 9 show two examples of how the Initiator can format SUITES_I, and how Responders use SUITES_R to tell the Initiator which cipher suites they support ๐Ÿงš

in Example 1 (Figure 8), the Responder supports cipher suite 6 but not the initially selected cipher suite 5 ๐Ÿ’€ so the Responder rejects the first message_1 with an error that says it supports suite 6 in SUITES_R โœจ the Initiator supports suite 6 too, so it selects suite 6 in the second message_1 ๐Ÿ’– the Initiator also puts the more preferred suites (here, suite 5) in front of the selected suite 6 in SUITES_I, to help mitigate a potential attack on the cipher suite negotiation ๐Ÿ›ก๏ธ

Initiator                                                   Responder
|              METHOD, SUITES_I = 5, G_X, C_I, EAD_1                |
+------------------------------------------------------------------>|
|                             message_1                             |
|                                                                   |
|                   ERR_CODE = 2, SUITES_R = 6                      |
|<------------------------------------------------------------------+
|                               error                               |
|                                                                   |
|             METHOD, SUITES_I = [5, 6], G_X, C_I, EAD_1            |
+------------------------------------------------------------------>|
|                             message_1                             |

Figure 8: Cipher Suite Negotiation Example 1

in Example 2 (Figure 9), the Responder supports cipher suites 8 and 9, but not the Initiator's more preferred cipher suites 5, 6, or 7 ๐Ÿ™ˆ to show how the negotiation works, we let the Initiator first guess that the Responder supports suite 6 but not suite 5 ๐Ÿคž since the Responder supports neither 5 nor 6, it rejects the first message_1 with an error that says it supports suites 8 and 9 in SUITES_R (in any order) ๐Ÿ’… the Initiator supports suites 8 and 9 and prefers suite 8, so it selects suite 8 in the second message_1 ๐ŸŽ‰ it also puts the more preferred suites in front of the selected suite 8 in SUITES_I, in order of preference (so suites 5, 6, and 7 here), to mitigate a potential attack on the cipher suite negotiation ๐Ÿฆ‹

Note 1. If the Responder had supported suite 5, then the first message_1 wouldn't have been accepted either, because the Responder would see that suite 5 is more preferred by the Initiator than the selected suite 6 ๐Ÿ˜ณ in that case, the Responder would have included suite 5 in SUITES_R of the response, and it would then have become the selected and only suite in the second message_1 โœจ

Note 2. For each message_1, the Initiator MUST generate a new ephemeral ECDH key pair matching the selected cipher suite ๐Ÿ”‘ no reusing keys, bestie ๐Ÿ™…โ€โ™€๏ธ

Initiator                                                   Responder
|            METHOD, SUITES_I = [5, 6], G_X, C_I, EAD_1             |
+------------------------------------------------------------------>|
|                             message_1                             |
|                                                                   |
|                  ERR_CODE = 2, SUITES_R = [9, 8]                  |
|<------------------------------------------------------------------+
|                               error                               |
|                                                                   |
|           METHOD, SUITES_I = [5, 6, 7, 8], G_X, C_I, EAD_1        |
+------------------------------------------------------------------>|
|                             message_1                             |

Figure 9: Cipher Suite Negotiation Example 2

6.4. Unknown Credential Referenced ๐Ÿ”

error code 3 is for errors where a received credential identifier (ID_CRED_R in message_2, or ID_CRED_I in message_3) references a credential that the receiving endpoint doesn't have access to ๐Ÿ˜ญ the idea is that the endpoint that sent the credential identifier should, for the next EDHOC session, try a different credential identifier that's supported according to the application profile ๐Ÿ”„

for example, an application profile could list x5t and x5chain as supported credential identifiers, and say that x5t should be used if it can be assumed that the X.509 certificate is available on the receiving side ๐ŸŽ€ this error code means the certificate chain only gets sent when it's actually needed ๐ŸŒธ just bear in mind that error messages aren't protected, so an adversary could try to make you send unnecessary, large credential identifiers ๐Ÿ‘€

for error code 3, the error information SHALL be the CBOR simple value true (0xf5) โœจ and error code 3 MUST NOT be used when the received credential identifier type isn't supported ๐Ÿ™…โ€โ™€๏ธ๐Ÿ’–

7. EDHOC Message Deduplication โœจ

Okay so, by default EDHOC just assumes the transport is handling message duplication for it ๐Ÿ’… (CoAP is the example in this section, see Appendix A.2).

Deduplication of CoAP messages is covered in Section 4.5 of [RFC7252] ๐Ÿฆ‹. It deals with the case where the same Confirmable (CON) message shows up more than once because the acknowledgment got lost on the CoAP messaging layer. The recommended processing in [RFC7252] is to acknowledge the duplicate, but the received message only gets processed once by the CoAP stack. Iconic, honestly ๐Ÿ‘‘

Message deduplication is kinda resource-demanding, so it's not supported in every CoAP implementation ๐Ÿฅบ. Since EDHOC is aimed at constrained environments, it's desirable that EDHOC can optionally work with transport layers that don't handle duplication. Special care is needed to avoid issues with duplicate messages, so see Section 5.1 ๐Ÿ™ˆ.

The guiding principle is basically the same vibe as the deduplication on the CoAP messaging layer. A received duplicate EDHOC message SHALL NOT result in another instance of the next EDHOC message. The result MAY be that a duplicate next EDHOC message is sent, as long as it's still relevant to the current protocol state. Either way, the received message MUST NOT be processed more than once in the same EDHOC session. This is called "EDHOC message deduplication" ๐Ÿซถ

An EDHOC implementation MAY store the previously sent EDHOC message so it can resend it ๐Ÿ“

In principle, if the EDHOC implementation could deterministically regenerate the identical EDHOC message it sent before, it would be possible to store the protocol state instead and recreate and resend the message from that. However, even if the protocol state is fixed, message generation may introduce differences that compromise security. Like, in the generation of message_3, if I is doing a (non-deterministic) ECDSA signature (say, method 0 or 1 and cipher suite 2 or 3), then PLAINTEXT_3 is randomized, but K_3 and IV_3 stay the same, which leads to a key and nonce reuse ๐Ÿ˜ญ

The EDHOC implementation MUST NOT store the previous protocol state and regenerate an EDHOC message if there is a risk that the same key and IV are used for two (or more) distinct messages. Not me going back to the same key and nonce ๐Ÿ’€

The previous message or protocol state MUST NOT be kept longer than what is required for retransmission. For example, with CoAP transport, that means no longer than the EXCHANGE_LIFETIME (see Section 4.8.2 of [RFC7252]). Keep it short, bestie ๐Ÿงš

8. Compliance Requirements ๐ŸŽ€

In the absence of an application profile specifying otherwise:

  • An implementation MAY support only an Initiator or only a Responder.
  • An implementation MAY support only a single method. None of the methods are mandatory to implement.
  • Implementations MUST support 'kid' parameters. None of the other COSE header parameters are mandatory to implement.
  • An implementation MAY support only a single credential type (CCS, CWT, X.509, or C509). None of the credential types are mandatory to implement.
  • Implementations MUST support the EDHOC_Exporter.
  • Implementations MAY support message_4. Error codes (ERR_CODE) 1 and 2 MUST be supported.
  • Implementations MUST support EAD.
  • Implementations MUST support cipher suites 2 and 3. Cipher suites 2 (AES-CCM-16-64-128, SHA-256, 8, P-256, ES256, AES-CCM-16-64-128, SHA-256) and 3 (AES-CCM-16-128-128, SHA-256, 16, P-256, ES256, AES-CCM-16-64-128, SHA-256) only differ in the size of the MAC length, so supporting one or both of these is not significantly different. Implementations only need to implement the algorithms needed for their supported methods.

9. Security Considerations ๐Ÿ”

9.1. Security Properties โœจ

okay bestie, let's talk about the security vibes EDHOC gives you ๐Ÿ”๐Ÿ’–. EDHOC has similar security properties to what you can expect from the theoretical SIGMA-I protocol [SIGMA] and the Noise XX pattern [Noise], which are basically methods 0 and 3 ๐Ÿงš. The proven stuff lives in the security analysis publications referenced at the end of this section ๐Ÿ“š.

Using the terminology from [SIGMA], EDHOC gives you forward secrecy, mutual authentication with aliveness, consistency, and peer awareness ๐Ÿ’…. As [SIGMA] explains, message_3 gives the Responder peer awareness, and message_4 gives the Initiator peer awareness ๐Ÿซถ. By including the authentication credentials in the transcript hash, EDHOC is protected against an identity misbinding attack like Duplicate Signature Key Selection (DSKS), which the MAC-then-Sign variant of SIGMA-I is otherwise vulnerable to ๐Ÿ™ˆ.

As [SIGMA] describes, the Initiator and Responder get different levels of identity protection ๐ŸŽ€. EDHOC protects the Initiator's identity against active attacks, and the Responder's identity against passive attacks ๐Ÿฆ‹. An active attacker can grab the Responder's credential identifier by eavesdropping on the destination address used for transporting message_1, then sending its own message_1 to that same address ๐Ÿ‘€. So the roles should be assigned to protect the most sensitive identity/identifier, typically the one that can't be inferred from routing information in the lower layers ๐Ÿ’œ.

EDHOC messages might change in transit, whether from a noisy channel or from an attacker messing with them ๐ŸŒง๏ธ. Changes to message_1 and message_2 are detected when Signature_or_MAC_2 is verified, except for Signature_or_MAC_2 when the signature scheme is not strongly unforgeable. Changes to a Signature_or_MAC_2 that isn't strongly unforgeable, and changes to message_3, are detected when CIPHERTEXT_3 is verified. Changes to message_4 are detected when CIPHERTEXT_4 is verified ๐Ÿ”.

Compared to [SIGMA], EDHOC adds an explicit method type and expands the message authentication coverage to more elements, like algorithms, external authorization data, and previous plaintext messages ๐Ÿง . This protects against an attacker replaying messages or injecting messages from another EDHOC session ๐Ÿšซ.

EDHOC also adds connection identifier selection and downgrade-protected negotiation of cryptographic parameters, so an attacker cannot affect the negotiated parameters ๐Ÿ”’. A single EDHOC session doesn't negotiate cipher suites, but it lets the Responder check that the selected cipher suite is the most preferred one by the Initiator that's supported by both the Initiator and Responder. If it isn't, the Responder can abort the EDHOC session ๐Ÿ™…โ€โ™€๏ธ.

As [RFC7258] requires, IETF protocols need to mitigate pervasive monitoring when possible ๐ŸŒ. So EDHOC only supports methods with ephemeral Diffie-Hellman, and it provides a key update function (see Appendix H) for lightweight application protocol rekeying ๐Ÿ”„. Either of these gives forward secrecy, in the sense that compromising the private authentication keys doesn't compromise past session keys (PRK_out), and compromising a session key doesn't compromise past session keys either ๐ŸŒธ. Frequently re-running EDHOC with ephemeral Diffie-Hellman forces attackers into dynamic key exfiltration, where the attacker has to keep up continuous interaction with the collaborator. That's a significant, sustained attack ๐Ÿ˜ค.

To limit the effect of breaches, it's important to limit the use of symmetric group keys for bootstrapping ๐Ÿงฏ. So EDHOC tries to make the extra cost of using raw public keys and self-signed certificates as small as possible โœจ. Raw public keys and self-signed certificates are not a replacement for a public key infrastructure, but they SHOULD be used instead of symmetric group keys for bootstrapping ๐Ÿ’….

Compromising the long-term keys (private signature or static DH keys) doesn't compromise the security of completed EDHOC sessions ๐Ÿฅฐ. Compromising the private authentication keys of one party lets an active attacker impersonate that party in EDHOC sessions with other parties, but it doesn't let the attacker impersonate other parties in EDHOC sessions with the compromised party ๐ŸŽญ. Compromising the long-term keys doesn't let a passive attacker compromise future session keys (PRK_out) ๐Ÿ™Œ. Compromising the HKDF input parameters (the ECDH shared secret) leads to compromise of all session keys derived from that shared secret ๐Ÿ’€. Compromising one session key doesn't compromise other session keys ๐Ÿ“. Compromising PRK_out leads to compromise of all keying material derived with the EDHOC_Exporter ๐Ÿ˜ญ.

Based on the cryptographic algorithm requirements (Section 9.3), EDHOC provides a minimum of 64-bit security against online brute force attacks and a minimum of 128-bit security against offline brute force attacks ๐Ÿฐ. To break 64-bit security against online brute force, an attacker would on average have to send 4.3 billion messages per second for 68 years, which is infeasible in constrained IoT radio technologies ๐Ÿคฏ. A forgery against a 64-bit MAC in EDHOC breaks the security of all future application data ๐Ÿ˜ฑ. A forgery against a 64-bit MAC in the subsequent application protocol (e.g., OSCORE [RFC8613]) typically only breaks the security of the data in the forged packet ๐Ÿ“ฆ.

Since the EDHOC session is aborted when verification fails, security against online attacks is the sum of the strength of the verified signatures and MACs (including the MAC in AEAD) ๐Ÿงฎ. For example, if EDHOC is used with method 3, cipher suite 2, and message_4, the Responder is authenticated with 128-bit security against online attacks, which is the sum of the 64-bit MACs in message_2 and message_4 ๐Ÿ”ฅ. The same principle applies to MACs in an application protocol keyed by EDHOC, as long as EDHOC is re-run when verification of the first MACs in the application protocol fails ๐Ÿ”. For example, if EDHOC with method 3 and cipher suite 2 is used as in Figure 2 of [EDHOC-CoAP-OSCORE], 128-bit mutual authentication against online attacks can be achieved after the first OSCORE request and response complete ๐ŸŽ‰.

After sending message_3, the Initiator is assured that no party other than the Responder can compute the key PRK_out ๐Ÿซข. The Initiator can securely send protected application data, but the Initiator SHOULD NOT persistently store the keying material PRK_out until it has verified message_4, or a message protected with a derived application key (such as an OSCORE message), from the Responder ๐Ÿงธ. After verifying message_3, the Responder is assured that an honest Initiator has computed the key PRK_out ๐Ÿ’ซ. The Responder can securely derive and store the keying material PRK_out and send protected application data ๐ŸŒˆ.

External authorization data sent in message_1 (EAD_1) or message_2 (EAD_2) should be considered unprotected by EDHOC; see Section 9.5 ๐Ÿ™ˆ. EAD_2 is encrypted, but the Responder hasn't authenticated the Initiator yet, and the encryption doesn't give confidentiality against active attacks ๐Ÿ˜ฌ.

External authorization data sent in message_3 (EAD_3) or message_4 (EAD_4) is protected between the Initiator and Responder by the protocol. But note that EAD fields may be used by the application before message verification is completed; see Section 3.8 โš ๏ธ. Designing a secure mechanism that uses EAD isn't necessarily straightforward ๐Ÿงฉ. This document only provides the EAD transport mechanism, but the problem of agreeing on the surrounding context, and on the meaning of the information passed to and from the application, is still there ๐Ÿซ . Any new uses of EAD should be subject to careful review ๐Ÿ”Ž.

  • Key Compromise Impersonation (KCI): In EDHOC authenticated with signature keys, EDHOC provides KCI protection against an attacker that has access to the long-term key or the ephemeral secret key ๐Ÿ—๏ธ. With static Diffie-Hellman key authentication, KCI protection would be provided against an attacker that has access to the long-term Diffie-Hellman key, but not against an attacker that has access to the ephemeral secret key ๐Ÿซง. Note that the term KCI has typically been used for compromise of long-term keys, and that an attacker with access to the ephemeral secret key can only attack that specific EDHOC session ๐ŸŒท.
  • Repudiation: If an endpoint authenticates with a signature, the other endpoint can prove that the endpoint performed a run of the protocol by presenting the data being signed as well as the signature itself ๐Ÿ“œ. With static Diffie-Hellman key authentication, the authenticating endpoint can deny having participated in the protocol ๐Ÿ™ƒ.

Earlier versions of EDHOC have been formally analyzed [Bruni18] [Norrman20] [CottierPointcheval22] [Jacomme23] [GuentherIlunga22], and the specification has been updated based on that analysis ๐Ÿฅนโœจ.

9.2. Cryptographic Considerations โœจ

okay bestie, crypto time ๐Ÿ”. the SIGMA protocol needs the encryption of message_3 to give confidentiality even against active attackers, and EDHOC message_4 relies on authenticated encryption ๐Ÿ‘€. so the message-authenticating part of the authenticated encryption in EDHOC is super critical ๐Ÿ’…. authenticated encryption MUST NOT be replaced by plain encryption only, even if authentication is handled at another level or through a different mechanism. no cap ๐Ÿ™…โ€โ™€๏ธ

ok, so EDHOC skips explicit nonces to keep messages small ๐Ÿฆ‹ and instead the ephemeral public keys bring the randomness for each EDHOC session. a good amount of randomness matters for key generation to give liveness and to protect against interleaving attacks ๐ŸŒ€. for this reason, the ephemeral keys MUST NOT be used in more than one EDHOC message, and both parties SHALL generate fresh, random ephemeral key pairs. also, one ephemeral key can be used to calculate several ECDH shared secrets. when static Diffie-Hellman authentication is used, the same ephemeral key is used in both the ephemeral-ephemeral and ephemeral-static ECDH. iconic efficiency โœจ

as discussed in [SIGMA], the encryption of message_2 only needs to protect against a passive attacker, since active attackers can always learn the Responder's identity by sending their own message_1 ๐Ÿ™„. EDHOC uses the EDHOC_Expand function (typically HKDF-Expand) as a binary additive stream cipher. it's proven secure as long as the expand function is a Pseudorandom Function (PRF). HKDF-Expand isn't really used as a stream cipher because it's slow on long messages, and most apps want both IND-CCA2 confidentiality and integrity protection ๐Ÿซถ. for the encryption of message_2, the speed difference is negligible, IND-CCA2 doesn't add security, and integrity comes from the inner MAC (and signature, depending on the method) ๐Ÿ’–

requirements for how to securely generate, validate, and process public keys depend on the elliptic curve ๐ŸŒˆ. for X25519 and X448, the requirements are defined in [RFC7748]. for X25519 and X448, the check for all-zero output as specified in Section 6 of [RFC7748] MUST be done. for secp256r1, secp384r1, and secp521r1, the requirements are defined in Section 5 of [SP-800-56A]. for secp256r1, secp384r1, and secp521r1, at least partial public key validation MUST be done ๐Ÿ”ฅ

the same authentication credential MAY be used for both the Initiator and Responder roles ๐ŸŽ€. as noted in Section 12 of [RFC9052], using a single key for multiple algorithms is strongly discouraged unless it's proven secure by a dedicated cryptographic analysis. this especially applies to using the same private key for static Diffie-Hellman authentication and digital signature authentication ๐Ÿ™ˆ. a preliminary conjecture is that a minor change to EDHOC might be enough to fit the analysis of a secure shared signature and ECDH key usage in [Degabriele11] and [Thormarker21]. also, Section 5.6.3.2 of [SP-800-56A] allows a key agreement key pair to be used with a signature algorithm in certificate requests.

the property that a completed EDHOC session implies another identity has been active holds as long as the Initiator does not have its own identity in the set of Responder identities it is allowed to talk to ๐Ÿงš. in trust-on-first-use (TOFU) use cases (see Appendix D.5), the Initiator should verify that the Responder's identity is not equal to its own. future EDHOC methods using, e.g., PSKs might need to handle this in other ways. but here's the tea โ˜•: an active attacker can learn about the set of identities an Initiator is willing to communicate with. if the Initiator is willing to communicate with all identities except its own, an attacker can confirm that a guessed Initiator identity is correct ๐Ÿ˜ญ. so to not leak any long-term identifiers, using a freshly generated authentication key as an identity in each initial TOFU session is RECOMMENDED ๐Ÿ“

NIST SP 800-56A [SP-800-56A] forbids deriving secret and non-secret randomness from the same Key Derivation Function (KDF) instance. this decision has been criticized by Krawczyk in [HKDFpaper], and doing it anyway is common practice ๐Ÿคทโ€โ™€๏ธ. other examples are the challenge in Extensible Authentication Protocol Tunneled Transport Layer Security (EAP-TTLS), the RAND in 3GPP Authentication and Key Agreement (AKA), and the Session-Id in EAP-TLS 1.3, plus IVs. also, part of KEYSTREAM_2 is non-secret randomness, since it's known or predictable to an attacker. the more recent NIST SP 800-108 [SP-800-108] lines up with [HKDFpaper] and says that, for a secure KDF, revealing one portion of the derived keying material must not degrade the security of any other portion of that keying material ๐ŸŒธ


9.3. Cipher Suites and Cryptographic Algorithms ๐Ÿง

when you use a private cipher suite or register new cipher suites, the key lengths used in the different algorithms need to be harmonized ๐ŸŽฏ. that way, a sufficient security level is kept for authentication credentials, the EDHOC session, and the protection of application data. the Initiator and Responder should enforce a minimum security level.

the output size of the EDHOC hash algorithm MUST be at least 256 bits. in particular, the hash algorithms SHA-1 and SHA-256/64 (SHA-256 truncated to 64 bits) SHALL NOT be supported for use in EDHOC, except for certificate identification with x5t and c5t ๐Ÿšซ. for security considerations of SHA-1, see [RFC6194]. since EDHOC integrity protects all the authentication credentials, the choice of hash algorithm in x5t and c5t doesn't affect security. using the same hash algorithm as in the cipher suite, but with as much truncation as possible, is RECOMMENDED. so when the EDHOC hash algorithm is SHA-256, using SHA-256/64 in x5t and c5t is RECOMMENDED ๐Ÿ’…. the EDHOC MAC length MUST be at least 8 bytes, and the tag length of the EDHOC AEAD algorithm MUST be at least 64 bits. side note: secp256k1 is only defined for use with ECDSA and not for ECDH ๐Ÿ™ƒ. also, some COSE algorithms are marked as not recommended in the COSE IANA registry.


9.4. Post-Quantum Considerations ๐Ÿ”ฎ

as of publication of this spec, it's unclear when, or even if, a quantum computer big and powerful enough to break public key cryptography will exist ๐Ÿค”. deployments that need to think about risks decades out should move to Post-Quantum Cryptography (PQC) in the not-too-distant future. many other systems should take a slower wait-and-see approach, where PQC gets phased in when the quantum threat is more imminent. current PQC algorithms have limitations compared to Elliptic Curve Cryptography (ECC), and the data sizes would be problematic in lots of constrained IoT systems ๐Ÿ“ฆ

symmetric algorithms used in EDHOC, such as SHA-256 and AES-CCM-16-64-128, are practically secure even against large quantum computers ๐Ÿ›ก๏ธ. two of NIST's security levels for quantum-resistant public key cryptography are based on AES-128 and SHA-256. a quantum computer will likely be expensive and slow because of heavy error correction. Grover's algorithm, which is proven to be optimal, can't effectively be parallelized, so it gives little or no advantage in attacking AES. AES-128 will remain secure for decades to come [NISTPQC] โœจ

EDHOC supports all signature algorithms defined by COSE, including PQC signature algorithms such as HSS-LMS ๐Ÿฆ‹. EDHOC is currently only specified for use with key exchange algorithms of type ECDH curves, but any Key Encapsulation Method (KEM), including PQC KEMs, can be used in method 0. while the key exchange in method 0 is specified with the terms of the Diffie-Hellman protocol, it adheres to a KEM interface: G_X is then the public key of the Initiator, G_Y is the encapsulation, and G_XY is the shared secret. using PQC KEMs to replace static DH authentication would likely need a specification that updates EDHOC with new methods ๐Ÿ‘‘


9.5. Unprotected Data and Privacy ๐Ÿ•ต๏ธโ€โ™€๏ธ

the Initiator and Responder must make sure that unprotected data and metadata don't reveal any sensitive information ๐Ÿ™Š. this also applies to encrypted data sent to an unauthenticated party. in particular, it applies to EAD_1, ID_CRED_R, EAD_2, and error messages. using the same EAD_1 in several EDHOC sessions lets passive eavesdroppers correlate the different sessions ๐Ÿ˜ฌ. also, even if ead_value is encrypted outside of EDHOC, the ead_labels in EAD_1 are revealed to passive attackers, and the ead_labels in EAD_2 are revealed to active attackers. another thing: the list of supported cipher suites may be used to identify the application ๐Ÿ”. the Initiator and Responder must also make sure that unauthenticated data doesn't trigger any harmful actions. this especially applies to EAD_1 and error messages ๐Ÿšจ

an attacker watching network traffic may use connection identifiers sent in clear in EDHOC or in the subsequent application protocol to correlate packets sent on different paths or at different times. the attacker can use this for traffic flow analysis or to track an endpoint ๐Ÿ‘€. application protocols using connection identifiers from EDHOC SHOULD provide mechanisms to update the connection identifiers, and MAY provide mechanisms to issue several simultaneously active connection identifiers. see [RFC9000] for a non-constrained example of such mechanisms. connection identifiers can, e.g., be chosen randomly among the set of unused 1-byte connection identifiers ๐ŸŽฒ. connection identity privacy mechanisms are only useful when there aren't fixed identifiers, such as an IP address or MAC address in the lower layers ๐Ÿ’œ


9.6. Updated Internet Threat Model Considerations ๐ŸŒ

since publication of [RFC3552], there's been more awareness of the need to protect against endpoints that are compromised or malicious, or whose interests just don't line up with the interests of users ๐Ÿ˜ค [THREAT-MODEL-GUIDANCE]. [RFC7624] describes an updated threat model for Internet confidentiality; see Section 9.1. [THREAT-MODEL-GUIDANCE] goes even further with the threat model. implementations and users should take these threat models into account and consider actions to reduce the risk of tracking by other endpoints ๐Ÿซถ. in particular, even data sent protected to the other endpoint, such as ID_CRED fields and EAD fields, can be used for tracking. see Section 2.7 of [THREAT-MODEL-GUIDANCE] ๐Ÿฅบ

the fields ID_CRED_I, ID_CRED_R, EAD_2, EAD_3, and EAD_4 have variable length, and info about the length may leak to an attacker ๐Ÿ“. a passive attacker may, e.g., be able to tell endpoints apart by identifiers of different lengths. to mitigate this leakage, an implementation may make sure the fields have a fixed length, or use padding. an implementation may, e.g., only use fixed-length identifiers like 'kid' of length 1. alternatively, padding may be used (see Section 3.8.1) to hide the true length of, e.g., certificates by value in 'x5chain' or 'c5c' ๐ŸŽ€

9.7. Denial of Service ๐Ÿ’…

okay bestie, real talk: EDHOC doesn't have its own countermeasures against denial-of-service attacks ๐Ÿ˜ญ. An attacker can send a bunch of new or replayed message_1s and make the Responder allocate state, do crypto operations, and amplify messages ๐Ÿ™ˆ. So an implementation SHOULD make use of available lower layer mechanisms ๐Ÿ›ก๏ธ. For example, when EDHOC is sent as an exchange of CoAP messages, the CoAP server can use the Echo option from [RFC9175], which forces the CoAP client to prove it's reachable at its apparent network address โœจ. To skip an extra round trip, the Initiator can reduce the amplification factor by padding message_1, i.e., using EAD_1; see Section 3.8.1 ๐ŸŽ€.

Note that the Echo option helps with some resource exhaustion from spoofing, but it does not protect against a distributed denial-of-service attack made by real, potentially compromised, clients ๐Ÿ’€. Limiting amplification only reduces the impact, which can still be significant if a large number of clients are part of the attack ๐Ÿ˜ญ.

An attacker can also send a faked message_2, message_3, message_4, or error to trick the receiving party into sending an error message and aborting the EDHOC session ๐Ÿ™ƒ. EDHOC implementations MAY evaluate if a received message is likely to have been forged by an attacker and ignore it without sending an error message or aborting the EDHOC session ๐Ÿซถ.


9.8. Implementation Considerations ๐Ÿง 

the availability of a secure random number generator is essential for the security of EDHOC ๐Ÿ”ฅ. If no true random number generator is available, a random seed MUST be provided from an external source and used with a cryptographically secure pseudorandom number generator ๐ŸŒˆ. Each pseudorandom number must only be used once, so an implementation needs to get a unique input to the pseudorandom number generator after reboot, or continuously store state in nonvolatile memory ๐Ÿ’พ. Appendix B.1.1 of [RFC8613] describes issues and solution approaches for writing to nonvolatile memory ๐Ÿ“. Intentionally or unintentionally weak or predictable pseudorandom number generators can be abused or exploited for malicious purposes ๐Ÿ‘€. [RFC8937] describes a way for security protocol implementations to augment their (pseudo)random number generators using a long-term private key and a deterministic signature function โœจ. This improves randomness from broken or otherwise subverted random number generators ๐Ÿ’ช. The same idea can be used with other secrets and functions, such as a Diffie-Hellman function or a symmetric secret, and a PRF like HMAC or KMAC ๐Ÿฆ‹. It is RECOMMENDED to not trust a single source of randomness and to not put unaugmented random numbers on the wire ๐Ÿšซ.

For many constrained IoT devices, supporting several crypto primitives is a whole problem ๐Ÿ˜ฉ. Existing devices can be expected to support either ECDSA or Edwards-curve Digital Signature Algorithm (EdDSA) ๐Ÿงš. If ECDSA is supported, "deterministic ECDSA", as specified in [RFC6979], MAY be used ๐Ÿ“. Pure deterministic elliptic-curve signatures, such as deterministic ECDSA and EdDSA, have gained popularity over randomized ECDSA because their security doesn't depend on a source of high-quality randomness ๐Ÿ’–. Recent research has however found that implementations of these signature algorithms may be vulnerable to certain side-channel and fault injection attacks because of their determinism ๐Ÿ˜ฑ. For example, see Section 1 of [HEDGED-ECC-SIGS] for a list of attack papers ๐Ÿ“š. As suggested in Section 2.1.1 of [RFC9053], this can be addressed by combining randomness and determinism ๐ŸŽ€.

Appendix D of [CURVE-REPR] describes how Montgomery curves, such as X25519 and X448, and (twisted) Edwards curves, such as Ed25519 and Ed448, can be mapped to and from short-Weierstrass form. This is for implementations on platforms that accelerate elliptic curve group operations in short-Weierstrass form ๐ŸŒธ.

All private keys, symmetric keys, and IVs MUST be secret ๐Ÿคซ. Only the Responder SHALL have access to the Responder's private authentication key, and only the Initiator SHALL have access to the Initiator's private authentication key ๐Ÿ”. Implementations should provide countermeasures to side-channel attacks, such as timing attacks โฑ๏ธ. Intermediate computed values, such as ephemeral ECDH keys and ECDH shared secrets, MUST be deleted after key derivation is completed ๐Ÿ—‘๏ธ.

The Initiator and Responder are responsible for verifying the integrity and validity of certificates. Verifying validity may require the use of a Real-Time Clock (RTC) โฐ. The selection of trusted certification authorities (CAs) should be done very carefully, and certificate revocation should be supported ๐Ÿง. The choice of revocation mechanism is left to the application. For example, for X.509 certificates, Certificate Revocation Lists [RFC5280] or the Online Certificate Status Protocol (OCSP) [RFC6960] may be used ๐Ÿ“œ.

Similar considerations as for certificates are needed for CWT/CCS. The endpoints are responsible for verifying the integrity and validity of CWT/CCS and for handling revocation ๐Ÿชช. The application needs to determine what trust anchors are relevant and have a well-defined trust-establishment process ๐Ÿฐ. A self-signed certificate, CWT, or CCS appearing in the protocol cannot be a trigger to modify the set of trust anchors ๐Ÿ™…โ€โ™€๏ธ. One common way for a new trust anchor to be added to (or removed from) a device is by means of a firmware upgrade ๐Ÿ”„. See [RFC9360] for a longer discussion on trust and validation in constrained devices ๐Ÿ“–.

Just like for certificates, the contents of the COSE header parameters 'kcwt' and 'kccs', defined in Section 10.6, must be processed as untrusted inputs ๐Ÿ•ต๏ธ. Endpoints that intend to rely on the assertions made by a CWT/CCS obtained from any of these methods need to validate the contents ๐Ÿงพ. For 'kccs', which enables transport of raw public keys, the data structure used does not include any protection or verification data ๐Ÿ˜ฌ. 'kccs' may be used for unauthenticated operations, e.g., trust on first use, with the limitations and caveats entailed; see Appendix D.5 โš ๏ธ.

The Initiator and Responder are allowed to select connection identifiers C_I and C_R, respectively, for the other party to use in the ongoing EDHOC session as well as in a subsequent application protocol (e.g., OSCORE [RFC8613]) ๐Ÿ”—. The choice of connection identifier is not security critical in EDHOC, but it's intended to simplify retrieving the right security context when using short identifiers ๐Ÿฅฐ. If the wrong connection identifier of the other party is used in a protocol message, the receiving party either won't be able to retrieve a security context (which aborts the EDHOC session) or will retrieve the wrong one (which also aborts the EDHOC session, as the message cannot be verified) ๐Ÿ™ˆ.

If two nodes unintentionally initiate two simultaneous EDHOC sessions with each other, even if they only want to complete a single EDHOC session, they MAY abort the EDHOC session with the lexicographically smallest G_X ๐Ÿค. Note that when several EDHOC sessions with different parameter sets (method, COSE headers, etc.) are used, an attacker can affect which parameter set will be used by blocking some of the parameter sets ๐Ÿ•ธ๏ธ.

If supported by the device, it is RECOMMENDED that at least the long-term private keys are stored in a Trusted Execution Environment (TEE) (for example, see [RFC9397]), and that sensitive operations using these keys are performed inside the TEE ๐Ÿ . To achieve even higher security, it is RECOMMENDED that additional operations, such as ephemeral key generation, all computations of shared secrets, and storage of the PRK keys, can be done inside the TEE ๐Ÿ‘‘. The use of a TEE aims at preventing code within that environment from being tampered with, and at preventing data used by such code from being read or tampered with by code outside that environment ๐Ÿ›ก๏ธ.

Note that HKDF-Expand has a relatively small maximum output length of 255 โ‹… hash_length, where hash_length is the output size in bytes of the EDHOC hash algorithm of the selected cipher suite ๐Ÿ“. This means that when SHA-256 is used as the hash algorithm, PLAINTEXT_2 cannot be longer than 8160 bytes ๐Ÿ™€. This is probably not a limitation for most intended applications, but to support things like long certificate chains or large external authorization data, there is a backwards compatible method specified in Appendix G ๐ŸŽ.

The sequence of transcript hashes in EDHOC (TH_2, TH_3, and TH_4) does not make use of a so-called running hash. This is a design choice, as running hashes are often not supported on constrained platforms ๐Ÿงฉ.

When parsing a received EDHOC message, implementations MUST abort the EDHOC session if the message does not comply with the CDDL for that message ๐Ÿšจ. Implementations are not required to support non-deterministic encodings, and they MAY abort the EDHOC session if the received EDHOC message is not encoded using deterministic CBOR ๐Ÿ”. Implementations MUST abort the EDHOC session if validation of a received public key fails or if any cryptographic field has the wrong length โŒ. It is RECOMMENDED to abort the EDHOC session if the received EDHOC message is not encoded using deterministic CBOR ๐Ÿ’….


10. IANA Considerations ๐Ÿ“‹

This section gives IANA considerations and, unless otherwise noted, conforms with [RFC8126] ๐ŸŒท.

10.1. EDHOC Exporter Label Registry ๐Ÿท๏ธ

IANA has created a new registry under the new registry group "Ephemeral Diffie-Hellman Over COSE (EDHOC)" as follows ๐ŸŒˆ:

Registry Name: EDHOC Exporter Labels

Reference: RFC 9528

     +=============+==============================+===========+
     | Label       | Description                  | Reference |
     +=============+==============================+===========+
     | 0           | Derived OSCORE Master Secret | RFC 9528  |
     +-------------+------------------------------+-----------+
     | 1           | Derived OSCORE Master Salt   | RFC 9528  |
     +-------------+------------------------------+-----------+
     | 2-22        | Unassigned                   |           |
     +-------------+------------------------------+-----------+
     | 23          | Reserved                     | RFC 9528  |
     +-------------+------------------------------+-----------+
     | 24-32767    | Unassigned                   |           |
     +-------------+------------------------------+-----------+
     | 32768-65535 | Reserved for Private Use     |           |
     +-------------+------------------------------+-----------+

                   Table 4: EDHOC Exporter Labels

This registry also has a "Change Controller" field. For registrations made by IETF documents, the IETF is listed ๐Ÿ™Œ.

              +=============+=========================+
              | Range       | Registration Procedures |
              +=============+=========================+
              | 0-23        | Standards Action        |
              +-------------+-------------------------+
              | 24-32767    | Expert Review           |
              +-------------+-------------------------+
              | 32768-65535 | Private Use             |
              +-------------+-------------------------+

                 Table 5: Registration Procedures for
                        EDHOC Exporter Labels

10.2. EDHOC Cipher Suites Registry ๐Ÿ’–

okay so IANA made a brand new registry under the registry group "Ephemeral Diffie-Hellman Over COSE (EDHOC)" ๐Ÿฆ‹

Registry Name: EDHOC Cipher Suites

Reference: RFC 9528

the columns are Value, Array, Description, and Reference. Value is an integer and the other columns are text strings. here are the initial contents, and they are giving main character energy ๐Ÿ‘‘

+=======+================+=============================+===========+
| Value | Array          | Description                 | Reference |
+=======+================+=============================+===========+
| -24   | N/A            | Private Use                 | RFC 9528  |
+-------+----------------+-----------------------------+-----------+
| -23   | N/A            | Private Use                 | RFC 9528  |
+-------+----------------+-----------------------------+-----------+
| -22   | N/A            | Private Use                 | RFC 9528  |
+-------+----------------+-----------------------------+-----------+
| -21   | N/A            | Private Use                 | RFC 9528  |
+-------+----------------+-----------------------------+-----------+
| 0     | 10, -16, 8, 4, | AES-CCM-16-64-128, SHA-256, | RFC 9528  |
|       | -8, 10, -16    | 8, X25519, EdDSA,           |           |
|       |                | AES-CCM-16-64-128, SHA-256  |           |
+-------+----------------+-----------------------------+-----------+
| 1     | 30, -16, 16,   | AES-CCM-16-128-128,         | RFC 9528  |
|       | 4, -8, 10, -16 | SHA-256, 16, X25519, EdDSA, |           |
|       |                | AES-CCM-16-64-128, SHA-256  |           |
+-------+----------------+-----------------------------+-----------+
| 2     | 10, -16, 8, 1, | AES-CCM-16-64-128, SHA-256, | RFC 9528  |
|       | -7, 10, -16    | 8, P-256, ES256,            |           |
|       |                | AES-CCM-16-64-128, SHA-256  |           |
+-------+----------------+-----------------------------+-----------+
| 3     | 30, -16, 16,   | AES-CCM-16-128-128,         | RFC 9528  |
|       | 1, -7, 10, -16 | SHA-256, 16, P-256, ES256,  |           |
|       |                | AES-CCM-16-64-128, SHA-256  |           |
+-------+----------------+-----------------------------+-----------+
| 4     | 24, -16, 16,   | ChaCha20/Poly1305, SHA-256, | RFC 9528  |
|       | 4, -8, 24, -16 | 16, X25519, EdDSA,          |           |
|       |                | ChaCha20/Poly1305, SHA-256  |           |
+-------+----------------+-----------------------------+-----------+
| 5     | 24, -16, 16,   | ChaCha20/Poly1305, SHA-256, | RFC 9528  |
|       | 1, -7, 24, -16 | 16, P-256, ES256,           |           |
|       |                | ChaCha20/Poly1305, SHA-256  |           |
+-------+----------------+-----------------------------+-----------+
| 6     | 1, -16, 16, 4, | A128GCM, SHA-256, 16,       | RFC 9528  |
|       | -7, 1, -16     | X25519, ES256, A128GCM,     |           |
|       |                | SHA-256                     |           |
+-------+----------------+-----------------------------+-----------+
| 23    |                | Reserved                    | RFC 9528  |
+-------+----------------+-----------------------------+-----------+
| 24    | 3, -43, 16, 2, | A256GCM, SHA-384, 16,       | RFC 9528  |
|       | -35, 3, -43    | P-384, ES384, A256GCM,      |           |
|       |                | SHA-384                     |           |
+-------+----------------+-----------------------------+-----------+
| 25    | 24, -45, 16,   | ChaCha20/Poly1305,          | RFC 9528  |
|       | 5, -8, 24, -45 | SHAKE256, 16, X448, EdDSA,  |           |
|       |                | ChaCha20/Poly1305, SHAKE256 |           |
+-------+----------------+-----------------------------+-----------+

                       Table 6: EDHOC Cipher Suites

          +===============+=====================================+
          | Range         | Registration Procedures             |
          +===============+=====================================+
          | -65536 to -25 | Specification Required              |
          +---------------+-------------------------------------+
          | -24 to -21    | Private Use                         |
          +---------------+-------------------------------------+
          | -20 to 23     | Standards Action with Expert Review |
          +---------------+-------------------------------------+
          | 24 to 65535   | Specification Required              |
          +---------------+-------------------------------------+

             Table 7: Registration Procedures for EDHOC Cipher
                                   Suites

10.3. EDHOC Method Type Registry ๐ŸŒธ

same energy here! IANA made another registry under that same "Ephemeral Diffie-Hellman Over COSE (EDHOC)" registry group โœจ

Registry Name: EDHOC Method Types

Reference: RFC 9528

the columns are Value, Initiator Authentication Key, Responder Authentication Key, and Reference. Value is an integer and the key columns are text strings that describe the authentication keys. the initial contents are in Table 2, and Method 23 is Reserved ๐Ÿงš

+===============+=====================================+
| Range         | Registration Procedures             |
+===============+=====================================+
| -65536 to -25 | Specification Required              |
+---------------+-------------------------------------+
| -24 to 23     | Standards Action with Expert Review |
+---------------+-------------------------------------+
| 24 to 65535   | Specification Required              |
+---------------+-------------------------------------+

          Table 8: Registration Procedures for EDHOC Method Types

10.4. EDHOC Error Codes Registry ๐Ÿšจ

IANA made a registry for these too, again under "Ephemeral Diffie-Hellman Over COSE (EDHOC)" ๐Ÿ’…

Registry Name: EDHOC Error Codes

Reference: RFC 9528

the columns are ERR_CODE, ERR_INFO Type, Description, Change Controller, and Reference. ERR_CODE is an integer, ERR_INFO is a CDDL defined type, and Description is a text string. the initial contents are in Table 3, and error code 23 is Reserved. there's also a "Change Controller" field, and for anything registered by IETF documents, the IETF is listed ๐Ÿซถ

            +===============+=========================+
            | Range         | Registration Procedures |
            +===============+=========================+
            | -65536 to -25 | Expert Review           |
            +---------------+-------------------------+
            | -24 to 23     | Standards Action        |
            +---------------+-------------------------+
            | 24 to 65535   | Expert Review           |
            +---------------+-------------------------+

                Table 9: Registration Procedures for
                         EDHOC Error Codes

10.5. EDHOC External Authorization Data Registry ๐ŸŽ€

one more registry in the same group! This one is for External Authorization Data (EAD) ๐ŸŒˆ

Registry Name: EDHOC External Authorization Data

Reference: RFC 9528

the columns are Name, Label, Description, and Reference. Label is a nonnegative integer and the other columns are text strings. the initial contents are in Table 10, and EAD label 23 is Reserved ๐Ÿ“

     +=========+=======+====================+===============+
     | Name    | Label | Description        | Reference     |
     +=========+=======+====================+===============+
     | Padding | 0     | Randomly generated | RFC 9528,     |
     |         |       | CBOR byte string   | Section 3.8.1 |
     +---------+-------+--------------------+---------------+
     |         | 23    | Reserved           | RFC 9528      |
     +---------+-------+--------------------+---------------+

                    Table 10: EDHOC EAD Labels

       +=============+=====================================+
       | Range       | Registration Procedures             |
       +=============+=====================================+
       | 0 to 23     | Standards Action with Expert Review |
       +-------------+-------------------------------------+
       | 24 to 65535 | Specification Required              |
       +-------------+-------------------------------------+

          Table 11: Registration Procedures for EDHOC EAD
                               Labels

10.6. COSE Header Parameters Registry ๐Ÿง

IANA added entries to the "COSE Header Parameters" registry, which lives under the "CBOR Object Signing and Encryption (COSE)" registry group. see Table 12 for the details ๐Ÿ’œ

the value of the kcwt header parameter is a COSE Web Token (CWT) [RFC8392], and the value of the kccs header parameter is a CWT Claims Set (CCS). check out Section 1.4 for more on that ๐Ÿ‘€ the CWT/CCS must contain a COSE_Key in a cnf claim [RFC8747]. the Value Registry column is empty for this item, so it's left out of the table below ๐Ÿ™ˆ

  +======+=======+===============+===============================+
  | Name | Label | Value Type    | Description                   |
  +======+=======+===============+===============================+
  | kcwt | 13    | COSE_Messages | A CBOR Web Token (CWT)        |
  |      |       |               | containing a COSE_Key in a    |
  |      |       |               | 'cnf' claim and possibly      |
  |      |       |               | other claims.  CWT is defined |
  |      |       |               | in RFC 8392.  COSE_Messages   |
  |      |       |               | is defined in RFC 9052.       |
  +------+-------+---------------+-------------------------------+
  | kccs | 14    | map           | A CWT Claims Set (CCS)        |
  |      |       |               | containing a COSE_Key in a    |
  |      |       |               | 'cnf' claim and possibly      |
  |      |       |               | other claims.  CCS is defined |
  |      |       |               | in RFC 8392.                  |
  +------+-------+---------------+-------------------------------+

               Table 12: COSE Header Parameter Labels

10.7. Well-Known URI Registry ๐ŸŒŸ

IANA added the well-known URI "edhoc" to the "Well-Known URIs" registry. here are the details:

URI Suffix: edhoc

Change Controller: IETF

Reference: RFC 9528

Related Information: None


10.8. Media Types Registry ๐Ÿ“ฑ

IANA added the media types application/edhoc+cbor-seq and application/cid-edhoc+cbor-seq to the "Media Types" registry. two new media types, bestie, so iconic ๐Ÿฆ‹

10.8.1. application/edhoc+cbor-seq Media Type Registration ๐Ÿ’ซ

Type name: application

Subtype name: edhoc+cbor-seq

Required parameters: N/A

Optional parameters: N/A

Encoding considerations: binary

Security considerations: See Section 7 of RFC 9528.

Interoperability considerations: N/A

Published specification: RFC 9528

Applications that use this media type: To be identified

Fragment identifier considerations: N/A

Additional information:

  • Magic number(s): N/A
  • File extension(s): N/A
  • Macintosh file type code(s): N/A

Person & email address to contact for further information: See "Authors' Addresses" section in RFC 9528.

Intended usage: COMMON

Restrictions on usage: N/A

Author: See "Authors' Addresses" section.

Change Controller: IETF

10.8.2. application/cid-edhoc+cbor-seq Media Type Registration ๐ŸŽ€

okay so this is the registration for the application/cid-edhoc+cbor-seq media type, and it's giving very tidy paperwork energy ๐Ÿ’… Here's the whole template, copied exactly:

   Type name:  application

   Subtype name:  cid-edhoc+cbor-seq

   Required parameters:  N/A

   Optional parameters:  N/A

   Encoding considerations:  binary

   Security considerations:  See Section 7 of RFC 9528.

   Interoperability considerations:  N/A

   Published specification:  RFC 9528

   Applications that use this media type:  To be identified

   Fragment identifier considerations:  N/A

   Additional information:

      Magic number(s):  N/A

      File extension(s):  N/A

      Macintosh file type code(s):  N/A

   Person & email address to contact for further information:  See
      "Authors' Addresses" section in RFC 9528.

   Intended usage:  COMMON

   Restrictions on usage:  N/A

   Author:  See "Authors' Addresses" section.

   Change Controller:  IETF

Quick vibe check: encoding is binary, the security section just points you to Section 7 of RFC 9528 (so go read that, it's serious ๐Ÿ˜ญ), and the change controller is the IETF ๐Ÿ‘‘


10.9. CoAP Content-Formats Registry ๐ŸŒธ

okay so IANA added both of our EDHOC media types to the "CoAP Content-Formats" registry, which lives in the "Constrained RESTful Environments (CoRE) Parameters" registry group. It's giving matching-IDs-for-besties ๐Ÿซถ

+================================+================+====+===========+
| Content Type                   | Content Coding | ID | Reference |
+================================+================+====+===========+
| application/edhoc+cbor-seq     | -              | 64 | RFC 9528  |
+--------------------------------+----------------+----+-----------+
| application/cid-edhoc+cbor-seq | -              | 65 | RFC 9528  |
+--------------------------------+----------------+----+-----------+

                 Table 13: CoAP Content-Format IDs

So the plain one is ID 64 and the connection-ID one is ID 65. Both point back to RFC 9528 ๐Ÿฆ‹


IANA also added a new resource type called "core.edhoc" to the "Resource Type (rt=) Link Target Attribute Values" registry, which is in the same "Constrained RESTful Environments (CoRE) Parameters" group. Here's the entry:

Value:  core.edhoc

Description:  EDHOC resource

Reference:  RFC 9528

Basically core.edhoc is the official name for an EDHOC resource, and it's โœจ iconic โœจ


10.11. Expert Review Instructions ๐Ÿงš

okay this section is for the experts who get to review new registrations. The registries in this document use "Expert Review", "Specification Required", or "Standards Action with Expert Review". This part gives the experts some general pointers, but they were picked for a reason, so they get lots of room to make calls ๐Ÿ’…

The experts should think about these things:

  • Clarity and correctness. Entries need a clear purpose and clear use. If a value is supposed to come from a different registry, the expert has to make sure it actually does. Experts can ask relevant IETF working groups to double-check registered parameters. Encodings that aren't clear and complete don't get registered, no exceptions ๐Ÿ™…โ€โ™€๏ธ
  • How the field will actually be used. When approving a code point, weigh the length of the encoded value against how many code points of that length are still free, how small the device using it is, and how many code points of that size are left.
  • Get a specification if you can. Even when the policy is "Expert Review", having a spec is recommended ๐Ÿ“š If a request comes in without one, the description has to contain enough detail to verify the code points in the way described above.

11. References ๐Ÿ“–

11.1. Normative References ๐Ÿ”ฅ

Here's the full list of normative references. Every single one is kept as written:

[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>.

[RFC3279]  Bassham, L., Polk, W., and R. Housley, "Algorithms and
           Identifiers for the Internet X.509 Public Key
           Infrastructure Certificate and Certificate Revocation List
           (CRL) Profile", RFC 3279, DOI 10.17487/RFC3279, April
           2002, <https://www.rfc-editor.org/info/rfc3279>.

[RFC3552]  Rescorla, E. and B. Korver, "Guidelines for Writing RFC
           Text on Security Considerations", BCP 72, RFC 3552,
           DOI 10.17487/RFC3552, July 2003,
           <https://www.rfc-editor.org/info/rfc3552>.

[RFC5116]  McGrew, D., "An Interface and Algorithms for Authenticated
           Encryption", RFC 5116, DOI 10.17487/RFC5116, January 2008,
           <https://www.rfc-editor.org/info/rfc5116>.

[RFC5869]  Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand
           Key Derivation Function (HKDF)", RFC 5869,
           DOI 10.17487/RFC5869, May 2010,
           <https://www.rfc-editor.org/info/rfc5869>.

[RFC6090]  McGrew, D., Igoe, K., and M. Salter, "Fundamental Elliptic
           Curve Cryptography Algorithms", RFC 6090,
           DOI 10.17487/RFC6090, February 2011,
           <https://www.rfc-editor.org/info/rfc6090>.

[RFC6960]  Santesson, S., Myers, M., Ankney, R., Malpani, A.,
           Galperin, S., and C. Adams, "X.509 Internet Public Key
           Infrastructure Online Certificate Status Protocol - OCSP",
           RFC 6960, DOI 10.17487/RFC6960, June 2013,
           <https://www.rfc-editor.org/info/rfc6960>.

[RFC6979]  Pornin, T., "Deterministic Usage of the Digital Signature
           Algorithm (DSA) and Elliptic Curve Digital Signature
           Algorithm (ECDSA)", RFC 6979, DOI 10.17487/RFC6979, August
           2013, <https://www.rfc-editor.org/info/rfc6979>.

[RFC7252]  Shelby, Z., Hartke, K., and C. Bormann, "The Constrained
           Application Protocol (CoAP)", RFC 7252,
           DOI 10.17487/RFC7252, June 2014,
           <https://www.rfc-editor.org/info/rfc7252>.

[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>.

[RFC7959]  Bormann, C. and Z. Shelby, Ed., "Block-Wise Transfers in
           the Constrained Application Protocol (CoAP)", RFC 7959,
           DOI 10.17487/RFC7959, August 2016,
           <https://www.rfc-editor.org/info/rfc7959>.

[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>.

[RFC8392]  Jones, M., Wahlstroem, E., Erdtman, S., and H. Tschofenig,
           "CBOR Web Token (CWT)", RFC 8392, DOI 10.17487/RFC8392,
           May 2018, <https://www.rfc-editor.org/info/rfc8392>.

[RFC8410]  Josefsson, S. and J. Schaad, "Algorithm Identifiers for
           Ed25519, Ed448, X25519, and X448 for Use in the Internet
           X.509 Public Key Infrastructure", RFC 8410,
           DOI 10.17487/RFC8410, August 2018,
           <https://www.rfc-editor.org/info/rfc8410>.

[RFC8610]  Birkholz, H., Vigano, C., and C. Bormann, "Concise Data
           Definition Language (CDDL): A Notational Convention to
           Express Concise Binary Object Representation (CBOR) and
           JSON Data Structures", RFC 8610, DOI 10.17487/RFC8610,
           June 2019, <https://www.rfc-editor.org/info/rfc8610>.

[RFC8613]  Selander, G., Mattsson, J., Palombini, F., and L. Seitz,
           "Object Security for Constrained RESTful Environments
           (OSCORE)", RFC 8613, DOI 10.17487/RFC8613, July 2019,
           <https://www.rfc-editor.org/info/rfc8613>.

[RFC8724]  Minaburo, A., Toutain, L., Gomez, C., Barthel, D., and JC.
           Zuniga, "SCHC: Generic Framework for Static Context Header
           Compression and Fragmentation", RFC 8724,
           DOI 10.17487/RFC8724, April 2020,
           <https://www.rfc-editor.org/info/rfc8724>.

[RFC8742]  Bormann, C., "Concise Binary Object Representation (CBOR)
           Sequences", RFC 8742, DOI 10.17487/RFC8742, February 2020,
           <https://www.rfc-editor.org/info/rfc8742>.

[RFC8747]  Jones, M., Seitz, L., Selander, G., Erdtman, S., and H.
           Tschofenig, "Proof-of-Possession Key Semantics for CBOR
           Web Tokens (CWTs)", RFC 8747, DOI 10.17487/RFC8747, March
           2020, <https://www.rfc-editor.org/info/rfc8747>.

[RFC8949]  Bormann, C. and P. Hoffman, "Concise Binary Object
           Representation (CBOR)", STD 94, RFC 8949,
           DOI 10.17487/RFC8949, December 2020,
           <https://www.rfc-editor.org/info/rfc8949>.

[RFC9052]  Schaad, J., "CBOR Object Signing and Encryption (COSE):
           Structures and Process", STD 96, RFC 9052,
           DOI 10.17487/RFC9052, August 2022,
           <https://www.rfc-editor.org/info/rfc9052>.

[RFC9053]  Schaad, J., "CBOR Object Signing and Encryption (COSE):
           Initial Algorithms", RFC 9053, DOI 10.17487/RFC9053,
           August 2022, <https://www.rfc-editor.org/info/rfc9053>.

[RFC9175]  Amsรผss, C., PreuรŸ Mattsson, J., and G. Selander,
           "Constrained Application Protocol (CoAP): Echo, Request-
           Tag, and Token Processing", RFC 9175,
           DOI 10.17487/RFC9175, February 2022,
           <https://www.rfc-editor.org/info/rfc9175>.

[RFC9360]  Schaad, J., "CBOR Object Signing and Encryption (COSE):
           Header Parameters for Carrying and Referencing X.509
           Certificates", RFC 9360, DOI 10.17487/RFC9360, February
           2023, <https://www.rfc-editor.org/info/rfc9360>.

11.2. Informative References ๐ŸŒˆ

These are the informative references, also kept exactly as written. They're bonus reading, bestie ๐Ÿง 

[Bruni18]  Bruni, A., Sahl Jรธrgensen, T., Grรธnbech Petersen, T., and
           C. Schรผrmann, "Formal Verification of Ephemeral Diffie-
           Hellman Over COSE (EDHOC)", November 2018,
           <https://www.springerprofessional.de/en/formal-
           verification-of-ephemeral-diffie-hellman-over-cose-
           edhoc/16284348>.

[C509-CERTS]
           PreuรŸ Mattsson, J., Selander, G., Raza, S., Hรถglund, J.,
           and M. Furuhed, "CBOR Encoded X.509 Certificates (C509
           Certificates)", Work in Progress, Internet-Draft, draft-
           ietf-cose-cbor-encoded-cert-09, 4 March 2024,
           <https://datatracker.ietf.org/doc/html/draft-ietf-cose-
           cbor-encoded-cert-09>.

[CborMe]   Bormann, C., "CBOR Playground", <https://cbor.me/>.

[CNSA]     Wikipedia, "Commercial National Security Algorithm Suite",
           October 2023, <https://en.wikipedia.org/w/index.php?title=
           Commercial_National_Security_Algorithm_Suite&oldid=1181333
           611>.

[CoAP-SEC-PROT]
           Mattsson, J. P., Palombini, F., and M. Vuฤiniฤ‡,
           "Comparison of CoAP Security Protocols", Work in Progress,
           Internet-Draft, draft-ietf-iotops-security-protocol-
           comparison-04, 4 March 2024,
           <https://datatracker.ietf.org/doc/html/draft-ietf-iotops-
           security-protocol-comparison-04>.

[CottierPointcheval22]
           Cottier, B. and D. Pointcheval, "Security Analysis of the
           EDHOC protocol", September 2022,
           <https://arxiv.org/abs/2209.03599>.

Okay bestie, the source list keeps going, and every single reference is still here ๐Ÿ“šโœจ


Appendix A. Use with OSCORE and Transfer over CoAP โœจ

This appendix explains how to derive an OSCORE security context when EDHOC is used to key OSCORE, and how to move EDHOC messages around over CoAP. Using CoAP or OSCORE with EDHOC is optional, but if you're using CoAP or OSCORE, then certain normative requirements apply, as detailed in the subsections. ๐Ÿซถ

A.1. Deriving the OSCORE Security Context

okay bestie, this section is all about taking the EDHOC output and turning it into the OSCORE security context ๐Ÿ”โœจ it's giving key-derivation glow-up ๐Ÿ’…

once message_3 has been successfully processed, the Client and Server derive the Security Context parameters for OSCORE like this (see Section 3.2 of [RFC8613]) ๐Ÿฆ‹

  • The Master Secret and Master Salt SHALL be derived by using the EDHOC_Exporter interface (see Section 4.2.1) ๐Ÿ”‘
    • The EDHOC Exporter Labels for deriving the OSCORE Master Secret and OSCORE Master Salt are the uints 0 and 1, respectively.
    • The context parameter is h'' (0x40), the empty CBOR byte string.
    • By default, oscore_key_length is the key length (in bytes) of the application AEAD Algorithm of the selected cipher suite for the EDHOC session. Also by default, oscore_salt_length has value 8. The Initiator and Responder MAY agree out-of-band on a longer oscore_key_length than the default and on shorter or longer than the default oscore_salt_length. ๐ŸŒธ
Master Secret = EDHOC_Exporter( 0, h'', oscore_key_length )
Master Salt   = EDHOC_Exporter( 1, h'', oscore_salt_length )
  • The AEAD Algorithm SHALL be the application AEAD algorithm of the selected cipher suite for the EDHOC session. ๐Ÿง
  • The HKDF Algorithm SHALL be the one based on the application hash algorithm of the selected cipher suite for the EDHOC session. For example, if SHA-256 is the application hash algorithm of the selected cipher suite, HKDF SHA-256 is used as the HKDF Algorithm in the OSCORE Security Context. ๐Ÿ“
  • The relationship between identifiers in OSCORE and EDHOC is specified in Section 3.3.3. The OSCORE Sender ID and Recipient ID SHALL be determined by EDHOC connection identifiers C_R and C_I for the EDHOC session as shown in Table 14. ๐Ÿช„
       +=================+==================+=====================+
       |                 | OSCORE Sender ID | OSCORE Recipient ID |
       +=================+==================+=====================+
       | EDHOC Initiator |       C_R        |         C_I         |
       +-----------------+------------------+---------------------+
       | EDHOC Responder |       C_I        |         C_R         |
       +-----------------+------------------+---------------------+

Table 14: Usage of Connection Identifiers in OSCORE

The Client and Server SHALL use the parameters above to establish an OSCORE Security Context, as per Section 3.2.1 of [RFC8613]. this is the part where it all clicks โœจ

From then on, the Client and Server retrieve the OSCORE protocol state using the Recipient ID and optionally other transport information such as the 5-tuple. ๐Ÿ’œ


A.2. Transferring EDHOC over CoAP

this section is about how EDHOC can ride along as an exchange of CoAP [RFC7252] messages ๐Ÿš€ CoAP is a reliable transport that keeps packets in order, does flow and congestion control, and handles duplicate messages. it can also do fragmentation and help mitigate certain denial-of-service attacks ๐Ÿ›ก๏ธ the underlying CoAP transport should be used in reliable mode, especially when fragmentation is used, so you don't get awkward situations with hanging endpoints just waiting on each other ๐Ÿฅฒ

EDHOC may run with the Initiator being either a CoAP client or a CoAP server. we call the first one the "forward message flow" (see Appendix A.2.1) and the second one the "reverse message flow" (see Appendix A.2.2). by default we assume the forward message flow, but the roles SHOULD be chosen to protect the most sensitive identity; see Section 9. main character energy ๐Ÿ‘‘

according to this specification, EDHOC is transferred in POST requests to the Uri-Path /.well-known/edhoc (see Section 10.7) with 2.04 (Changed) responses. an application may define its own path that can be discovered, e.g., using a resource directory [RFC9176]. client applications can use the resource type "core.edhoc" to discover a server's EDHOC resource, i.e., where to send a request for executing the EDHOC protocol; see Section 10.10. ๐Ÿ—บ๏ธ an alternative transfer of the forward message flow is specified in [EDHOC-CoAP-OSCORE].

so the server can correlate a message from a client with one it previously sent in the same EDHOC session over CoAP, messages sent by the client SHALL be prepended with the CBOR serialization of the connection identifier that the server has selected; see Section 3.4.1. this applies to both the forward and the reverse message flows ๐Ÿ”— to start a new EDHOC session in the forward message flow, message_1 SHALL be prepended with the CBOR simple value true (0xf5). even if CoAP runs over a reliable transport like TCP, the prepending of identifiers specified here SHALL be practiced so things stay interoperable no matter how CoAP is transported ๐Ÿซถ

the prepended identifiers are encoded in CBOR, so they're self-delimiting ๐Ÿง  the representation of identifiers described in Section 3.3.2 SHALL be used. they get sent in front of the actual EDHOC message to keep track of messages in an EDHOC session, and only the part of the body after the identifier is used for EDHOC processing. the connection identifiers inside the EDHOC messages are not affected by the prepended identifiers, so nothing gets tangled ๐ŸŽ€

an EDHOC message has media type "application/edhoc+cbor-seq", while an EDHOC message with a connection identifier prepended has media type "application/cid-edhoc+cbor-seq"; see Section 10.9. ๐Ÿ“ฎ

to mitigate certain denial-of-service attacks, the CoAP server MAY respond to the first POST request with a 4.01 (Unauthorized) containing an Echo option [RFC9175]. this forces the Initiator to prove it can be reached at its apparent network address ๐Ÿ•ต๏ธโ€โ™€๏ธ if message fragmentation is needed, the EDHOC messages may be fragmented using the CoAP Block-Wise Transfer mechanism [RFC7959]. ๐Ÿงฉ

EDHOC error messages need to be sent in response to a message that failed (see Section 6). EDHOC error messages transported with CoAP are carried in the payload. ๐Ÿšจ

note that the transport over CoAP can serve as a blueprint for other client-server protocols ๐Ÿ’–

  • The client prepends the connection identifier selected by the server (or, for message_1, the CBOR simple value true) to any request message it sends.
  • The server does not send any such indicator, as responses are matched to request by the client-server protocol design.

A.2.1. The Forward Message Flow

in the forward message flow, the CoAP client is the Initiator and the CoAP server is the Responder ๐Ÿƒโ€โ™€๏ธ this flow protects the client identity against active attackers and the server identity against passive attackers ๐Ÿฆ‹

in the forward message flow, the CoAP Token enables correlation on the Initiator (client) side, and the prepended C_R enables correlation on the Responder (server) side. ๐Ÿ”

  • EDHOC message_1 is sent in the payload of a POST request from the client to the server's resource for EDHOC, prepended with the identifier true (0xf5), indicating a new EDHOC session.
  • EDHOC message_2 or the EDHOC error message is sent from the server to the client in the payload of the response, in the former case with response code 2.04 (Changed) and in the latter with response code as specified in Appendix A.2.3.
  • EDHOC message_3 or the EDHOC error message is sent from the client to the server's resource in the payload of a POST request, prepended with connection identifier C_R.
  • If EDHOC message_4 is used, or in case of an error message, it is sent from the server to the client in the payload of the response, with response codes analogously to message_2. In case of an error message sent in response to message_4, it is sent analogously to the error message sent in response to message_2.

here's a full EDHOC session over CoAP in the forward message flow, Figure 10 style ๐ŸŽฌ

   Client    Server
     |          |
     +--------->| Header: POST (Code=0.02)
     |   POST   | Uri-Path: "/.well-known/edhoc"
     |          | Content-Format: application/cid-edhoc+cbor-seq
     |          | Payload: true, EDHOC message_1
     |          |
     |<---------+ Header: 2.04 Changed
     |   2.04   | Content-Format: application/edhoc+cbor-seq
     |          | Payload: EDHOC message_2
     |          |
     +--------->| Header: POST (Code=0.02)
     |   POST   | Uri-Path: "/.well-known/edhoc"
     |          | Content-Format: application/cid-edhoc+cbor-seq
     |          | Payload: C_R, EDHOC message_3
     |          |
     |<---------+ Header: 2.04 Changed
     |   2.04   | Content-Format: application/edhoc+cbor-seq
     |          | Payload: EDHOC message_4
     |          |

Figure 10: Example of the Forward Message Flow

the forward message flow of EDHOC can be combined with an OSCORE exchange in a total of two round trips; see [EDHOC-CoAP-OSCORE]. โšก

A.2.2. The Reverse Message Flow

in the reverse message flow, the CoAP client is the Responder and the CoAP server is the Initiator ๐Ÿ”„ this flow protects the server identity against active attackers and the client identity against passive attackers ๐Ÿซฃ

in the reverse message flow, the CoAP Token enables correlation on the Responder (client) side, and the prepended C_I enables correlation on the Initiator (server) side. ๐Ÿ’ซ

  • To trigger a new EDHOC session, the client makes an empty POST request to the server's resource for EDHOC.
  • EDHOC message_1 is sent from the server to the client in the payload of the response with response code 2.04 (Changed).
  • EDHOC message_2 or the EDHOC error message is sent from the client to the server's resource in the payload of a POST request, prepended with connection identifier C_I.
  • EDHOC message_3 or the EDHOC error message is sent from the server to the client in the payload of the response, in the former case with response code 2.04 (Changed) and in the latter with response code as specified in Appendix A.2.3.
  • If EDHOC message_4 is used, or in case of an error message, it is sent from the client to the server's resource in the payload of a POST request, prepended with connection identifier C_I. In case of an error message sent in response to message_4, it is sent analogously to an error message sent in response to message_2.

and here's the reverse flow, Figure 11 ๐ŸŒˆ

   Client    Server
     |          |
     +--------->| Header: POST (Code=0.02)
     |   POST   | Uri-Path: "/.well-known/edhoc"
     |          |
     |<---------+ Header: 2.04 Changed
     |   2.04   | Content-Format: application/edhoc+cbor-seq
     |          | Payload: EDHOC message_1
     |          |
     +--------->| Header: POST (Code=0.02)
     |   POST   | Uri-Path: "/.well-known/edhoc"
     |          | Content-Format: application/cid-edhoc+cbor-seq
     |          | Payload: C_I, EDHOC message_2
     |          |
     |<---------+ Header: 2.04 Changed
     |   2.04   | Content-Format: application/edhoc+cbor-seq
     |          | Payload: EDHOC message_3
     |          |

Figure 11: Example of the Reverse Message Flow

A.2.3. Errors in EDHOC over CoAP โœจ

okay bestie, errors time ๐Ÿ˜ญ When EDHOC is running over CoAP, EDHOC error messages sent as CoAP responses MUST be sent in the payload of the error response, which means they MUST specify a CoAP error response code. ๐Ÿ’… It is RECOMMENDED that those error responses use 4.00 (Bad Request) when the client messed up (like a malformed EDHOC message ๐Ÿ™ˆ), or 5.00 (Internal Server Error) when the server is the one having a moment (like a failure while deriving EDHOC keying material ๐Ÿ’€). And the Content-Format of the error response MUST be set to application/edhoc+cbor-seq. See Section 10.9 ๐ŸŽ€

Appendix B. Compact Representation

This section defines a format for compact representation, based on the Elliptic-Curve-Point-to-Octet-String Conversion from Section 2.3.3 of [SECG] ๐Ÿฆ‹

As described in Section 4.2 of [RFC6090], the x-coordinate of an elliptic curve public key is a suitable representative for the whole point whenever scalar multiplication is used as a one-way function. One example is ECDH with compact output, where only the x-coordinate of the computed value gets used as the shared secret. It's giving efficiency ๐Ÿงš

In EDHOC, compact representation is used for the ephemeral public keys (G_X and G_Y). See Section 3.7. Using the notation from [SECG], the output is an octet string of length ceil( (log2 q) / 8 ), where ceil(x) is the smallest integer not less than x. See [SECG] for a definition of q, M, X, xp, and ~yp. The steps in Section 2.3.3 of [SECG] get replaced with the following steps:

  1. Convert the field element xp to an octet string X of length ceil( (log2 q) / 8 ) octets, using the conversion routine from Section 2.3.5 of [SECG].
  2. Output M = X.

The encoding of the point at infinity is not supported. ๐Ÿ™…โ€โ™€๏ธ

Compact representation does not change any requirements on validation. See Section 9.2. Using compact representation has some security benefits ๐Ÿ” An implementation doesn't need to check that the point is not the point at infinity (the identity element). Also, since not even the sign of the y-coordinate is encoded, compact representation trivially avoids so-called "benign malleability" attacks, where an attacker changes the sign. See [SECG] ๐Ÿ‘‘

The following may be needed for validation, or for compatibility with APIs that don't support compact representation or don't support the full [SECG] format:

  • If a compressed y-coordinate is required, then the value ~yp set to zero can be used. In that case, the compact representation described above can be transformed into the Standards for Efficient Cryptography Group (SECG) point-compressed format by prepending it with the single byte 0x02 (i.e., M = 0x02 || X).
  • If an uncompressed y-coordinate is required, then a y-coordinate has to be calculated following Section 2.3.4 of [SECG] or Appendix C of [RFC6090]. Any of the square roots (see [SECG] or [RFC6090]) can be used. The uncompressed SECG format is M = 0x04 || X || Y.

For example, the curve P-256 has these parameters (using the notation in [RFC6090]):

  • p = 2^256 - 2^224 + 2^192 + 2^96 - 1
  • a = -3
  • b = 41058363725152142129326129780047268409114441015993725554835256314039467401291

Given an example x:

  • x = 115792089183396302095546807154740558443406795108653336398970697772788799766525

We can calculate y as the square root w = (x^3 + a โ‹… x + b)^((p + 1)/4) (mod p). ๐Ÿงฎ

  • y = 83438718007019280682007586491862600528145125996401575416632522940595860276856
Note that this does not guarantee that (x, y) is on the correct elliptic curve. A full validation according to Section 5.6.2.3.3 of [SP-800-56A] is done by also checking that 0 โ‰ค x < p and that y^2 โ‰ก x^3 + a โ‹… x + b (mod p). ๐Ÿ™ˆ

Appendix C. Use of CBOR, CDDL, and COSE in EDHOC

This appendix is here to help implementors who aren't familiar with CBOR [RFC8949], CDDL [RFC8610], COSE [RFC9052], and HKDF [RFC5869]. Don't worry, we got you ๐Ÿซถ

C.1. CBOR and CDDL

The Concise Binary Object Representation (CBOR) [RFC8949] is a data format designed for small code size and small message size. CBOR builds on the JSON data model but extends it by, e.g., encoding binary data directly without base64 conversion. On top of the binary CBOR encoding, CBOR also has a diagnostic notation that humans can read and edit ๐ŸŒธ The Concise Data Definition Language (CDDL) [RFC8610] gives a way to express structures for protocol messages and APIs that use CBOR. [RFC8610] also extends the diagnostic notation.

CBOR data items get encoded to or decoded from byte strings using a type-length-value encoding scheme, where the three highest order bits of the initial byte contain information about the major type. CBOR supports several types of data items: integers (int, uint), simple values, byte strings (bstr), and text strings (tstr). CBOR also supports arrays [] of data items, maps {} of pairs of data items, and sequences [RFC8742] of data items. Some examples are below ๐Ÿ“

The EDHOC spec sometimes uses CDDL names in CBOR diagnostic notation, like << ID_CRED_R, ? EAD_2 >>. This means that EAD_2 is optional, and that ID_CRED_R and EAD_2 should be substituted with their values before evaluation. So, if ID_CRED_R = { 4 : h'' } and EAD_2 is omitted, then << ID_CRED_R, ? EAD_2 >> = << { 4 : h'' } >>, which encodes to 0x43a10440. We also use the occurrence symbol "*", like in 2* int, meaning two or more CBOR integers. ๐Ÿ’œ

For a complete specification and more examples, see [RFC8949] and [RFC8610]. We recommend implementors get used to CBOR by using the CBOR playground [CborMe]. ๐ŸŒˆ

          +==================+==============+==================+
          | Diagnostic       | Encoded      | Type             |
          +==================+==============+==================+
          | 1                | 0x01         | unsigned integer |
          +------------------+--------------+------------------+
          | 24               | 0x1818       | unsigned integer |
          +------------------+--------------+------------------+
          | -24              | 0x37         | negative integer |
          +------------------+--------------+------------------+
          | -25              | 0x3818       | negative integer |
          +------------------+--------------+------------------+
          | true             | 0xf5         | simple value     |
          +------------------+--------------+------------------+
          | h''              | 0x40         | byte string      |
          +------------------+--------------+------------------+
          | h'12cd'          | 0x4212cd     | byte string      |
          +------------------+--------------+------------------+
          | '12cd'           | 0x4431326364 | byte string      |
          +------------------+--------------+------------------+
          | "12cd"           | 0x6431326364 | text string      |
          +------------------+--------------+------------------+
          | { 4 : h'cd' }    | 0xa10441cd   | map              |
          +------------------+--------------+------------------+
          | << 1, 2, true >> | 0x430102f5   | byte string      |
          +------------------+--------------+------------------+
          | [ 1, 2, true ]   | 0x830102f5   | array            |
          +------------------+--------------+------------------+
          | ( 1, 2, true )   | 0x0102f5     | sequence         |
          +------------------+--------------+------------------+
          | 1, 2, true       | 0x0102f5     | sequence         |
          +------------------+--------------+------------------+

Table 15: Examples of Use of CBOR and CDDL ๐Ÿง

C.2. CDDL Definitions

This section pulls together all the CDDL definitions in one place, so they're easy to find โœจ

   suites = [ 2* int ] / int

   ead = (
     ead_label : int,
     ? ead_value : bstr,
   )

   EAD_1 = 1* ead
   EAD_2 = 1* ead
   EAD_3 = 1* ead
   EAD_4 = 1* ead

   message_1 = (
     METHOD : int,
     SUITES_I : suites,
     G_X : bstr,
     C_I : bstr / -24..23,
     ? EAD_1,
   )

   message_2 = (
     G_Y_CIPHERTEXT_2 : bstr,
   )

   PLAINTEXT_2 = (
     C_R,
     ID_CRED_R : map / bstr / -24..23,
     Signature_or_MAC_2 : bstr,
     ? EAD_2,
   )

   message_3 = (
     CIPHERTEXT_3 : bstr,
   )

   PLAINTEXT_3 = (
     ID_CRED_I : map / bstr / -24..23,
     Signature_or_MAC_3 : bstr,
     ? EAD_3,
   )

   message_4 = (
     CIPHERTEXT_4 : bstr,
   )

   PLAINTEXT_4 = (
     ? EAD_4,
   )

   error = (
     ERR_CODE : int,
     ERR_INFO : any,
   )

   info = (
     info_label : int,
     context : bstr,
     length : uint,
   )

C.3. COSE ๐ŸŽ€

okay bestie, let's talk about COSE ๐Ÿ’… CBOR Object Signing and Encryption [RFC9052] is the spec that tells you how to make and process signatures, MACs, and encryption using CBOR. It's basically the cousin of JOSE, but it's been glowed up for constrained devices โœจ EDHOC uses three COSE objects while processing messages: COSE_Key, COSE_Encrypt0, and COSE_Sign1 ๐Ÿ”ฅ

  • ECDH ephemeral public keys of type EC2 or OKP in message_1 and message_2 are carried in the COSE_Key parameter named x. see Sections 7.1 and 7.2 of [RFC9053] ๐ŸŒธ
  • The ciphertexts in message_3 and message_4 are a subset of the single recipient encrypted data object COSE_Encrypt0. It's described in Sections 5.2 and 5.3 of [RFC9052] ๐Ÿฆ‹ The ciphertext is computed over the plaintext and associated data, using an encryption key and an initialization vector. The associated data is an Enc_structure made of protected headers and externally supplied data (external_aad). COSE builds the input to the AEAD [RFC5116] for message_i (i = 3 or 4; see Sections 5.4 and 5.5, respectively) like this:
    • Secret key K = K_i
    • Nonce N = IV_i
    • Plaintext P for message_i
    • Associated Data A = [ "Encrypt0", h'', TH_i ]
  • Signatures in message_2 of method 0 and 2, and in message_3 of method 0 and 1, are a subset of the single signer data object COSE_Sign1. It's described in Sections 4.2 and 4.4 of [RFC9052] ๐Ÿ’œ The signature is computed over a Sig_structure that holds the payload, protected headers, and externally supplied data (external_aad), using a private signature key. Verification uses the matching public signature key. For COSE_Sign1, the message to be signed is:
[ "Signature1", protected, external_aad, payload ]

where protected, external_aad, and payload are specified in Sections 5.3 and 5.4. ๐Ÿซถ

Different header parameters let you identify X.509 or C509 certificates by reference. They're defined in [RFC9360] and [C509-CERTS] ๐Ÿ‘‘

  • By a hash value, using the 'x5t' or 'c5t' parameters, respectively:
    • ID_CRED_x = { 34 : COSE_CertHash }, for x = I or R and
    • ID_CRED_x = { 22 : COSE_CertHash }, for x = I or R,
  • or by a URI, using the 'x5u' or 'c5u' parameters, respectively:
    • ID_CRED_x = { 35 : uri }, for x = I or R, and
    • ID_CRED_x = { 23 : uri }, for x = I or R.

When ID_CRED_x doesn't contain the actual credential, it may be super short, e.g., if the endpoints agreed to use a key identifier parameter 'kid' ๐Ÿ™ˆ

  • ID_CRED_x = { 4 : kid_x }, where kid_x : kid, for x = I or R. For further optimization, see Section 3.5.3. ๐Ÿ“

Note that ID_CRED_x can contain several header parameters, for example, { x5u, x5t } or { kid, kid_context } ๐Ÿงš

ID_CRED_x MAY also identify the credential by value. For example, a certificate chain can be transported in an ID_CRED field with COSE header parameter c5c or x5chain, as defined in [C509-CERTS] and [RFC9360] ๐ŸŒˆ Credentials of type CWT and CCS can be transported with the COSE header parameters registered in Section 10.6. โœจ


okay so EDHOC does some authentication-related operations (see Section 3.5), but honestly you usually still need to do extra verifications on top of EDHOC message processing ๐Ÿ’€ Which checks you need depend on the deployment, especially the trust model and the security policies. Most of the time they come down to verifying credential content ๐Ÿ’…

EDHOC assumes there are mechanisms for generating and distributing authentication credentials and other credentials. Think certification authority, trusted third party, pre-provisioning, that kind of thing ๐Ÿฆ‹ It also assumes trust anchors exist (CA certificates, trusted public keys, etc.). For example, a public key certificate or CWT might rely on a trusted third party whose public key is pre-provisioned. Meanwhile, a CCS or a self-signed certificate / CWT can be used when trust in the public key is achieved by other means, or in the case of trust on first use, see Appendix D.5 ๐ŸŒธ

In this section, we give some examples of these verifications. They're the application's responsibility, but they may be implemented as part of an EDHOC library ๐ŸŽ€

D.1. Validating the Authentication Credential ๐Ÿง

Besides the authentication key, the authentication credential may have other parameters that need checking. For example:

  • In X.509 and C509 certificates, signature keys typically have key usage "digitalSignature", and Diffie-Hellman public keys typically have key usage "keyAgreement" [RFC3279] [RFC8410] ๐Ÿ”ฅ
  • In X.509 and C509 certificates, validity is expressed using Not After and Not Before. In CWT and CCS, the "exp" and "nbf" claims have similar meanings. โณ

D.2. Identities ๐Ÿชช

The application has to decide whether to allow a connection, depending on the intended endpoint. In particular, it needs to know whether that endpoint is one specific identity or one of a set of identities. To prevent misbinding attacks, the identity of the endpoint is included in a MAC verified through the protocol. More details and examples are in this section ๐Ÿ‘‘

Policies for which connections to allow are usually set based on the identity of the other endpoint. Endpoints typically only allow connections from a specific identity or a small restricted set of identities ๐Ÿ’– For example, when a device connects to a network, the network may only allow connections from devices that authenticate with certificates in a particular range of serial numbers and signed by a particular CA. The other way around, a device may only connect to a network that authenticates with a particular public key ๐Ÿ™ˆ

  • When a Public Key Infrastructure (PKI) is used with certificates, the identity is the subject whose unique name is included in the endpoint's certificate. That name could be a domain name, a Network Access Identifier (NAI), or an Extended Unique Identifier (EUI) ๐ŸŒ
  • Similarly, when a PKI is used with CWTs, the identity is the subject identified by the relevant claim(s), such as 'sub' (subject). ๐Ÿงพ
  • When PKI is not used (e.g., CCS, self-signed certificate / CWT), the identity is typically directly tied to the authentication key of the other party. For example, if identities can be expressed as unique subject names assigned to public keys, then a binding to identity is achieved by including both the public key and the associated subject name in the authentication credential. CRED_I or CRED_R may be a self-signed certificate / CWT or CCS containing the authentication key and the subject name; see Section 3.5.2. So each endpoint needs to know the specific authentication key / unique associated subject name, or the set of public authentication keys / unique associated subject names, that it's allowed to talk to. ๐Ÿ“

To prevent misbinding attacks in systems where an attacker can register public keys without proving knowledge of the private key, SIGMA [SIGMA] enforces a MAC to be calculated over the "identity". EDHOC follows SIGMA by calculating a MAC over the whole authentication credential. For an X.509 or C509 certificate, that includes the "subject" and "subjectAltName" fields. For CWT or CCS, it includes the "sub" claim ๐Ÿ›ก๏ธ

(While the SIGMA paper only focuses on the identity, the same principle applies to other information, such as policies associated with the public key.) ๐ŸŒธ

D.3. Certification Path and Trust Anchors ๐Ÿ›ค๏ธ

When a PKI is used with certificates, the trust anchor is a certification authority (CA) certificate. Each party needs at least one CA public key certificate or just the CA public key. The certification path contains proof that the subject of the certificate owns the public key in that certificate. Only validated public key certificates are to be accepted โœ…

Similarly, when a PKI is used with CWTs, each party needs at least one trusted third-party public key as a trust anchor to verify the end entity CWTs. That trusted third-party public key can, e.g., be stored in a self-signed CWT or in a CCS ๐Ÿซถ

The signature of the authentication credential needs to be verified with the public key of the issuer. X.509 and C509 certificates include the "Issuer" field. In CWT and CCS, the "iss" claim has a similar meaning. The public key is either a trust anchor, or the public key in another valid and trusted credential in a certification path from the trust anchor to the authentication credential ๐Ÿ”—

Similar verifications as those made on the authentication credential (see Appendix D.1) are also needed for the other credentials in the certification path. ๐Ÿงฉ

When PKI is not used (CCS and self-signed certificate / CWT), the trust anchor is the authentication key of the other party. In that case there's no certification path. ๐Ÿฆ‹

D.4. Revocation Status ๐Ÿšซ

The application may need to verify that the credentials aren't revoked; see Section 9.8. Some use cases may be served by short-lived credentials, for example, where the validity of the credential is on par with the interval between revocation checks. But in general, credential lifetime and revocation checking are complementary measures for controlling credential status. Revocation information may be transported as External Authorization Data (EAD); see Appendix E. ๐Ÿ’œ

D.5. Unauthenticated Operation ๐Ÿ•ต๏ธ

EDHOC might be used without authentication, by letting the Initiator or Responder communicate with any identity except its own. โš ๏ธ Note that EDHOC without mutual authentication is vulnerable to active on-path attacks and therefore unsafe for general use. ๐Ÿ’€ That said, it's possible to set up a trust relationship with an unknown or not-yet-trusted endpoint later on. Some examples are listed below:

  • The EDHOC authentication credential can be verified out-of-band at a later stage. ๐Ÿ—๏ธ
  • The EDHOC session key can be bound to an identity out-of-band at a later stage. ๐ŸŽ€
  • Trust on first use (TOFU) can be used to verify that several EDHOC connections are made to the same identity. TOFU combined with proximity is a common IoT deployment model that provides good security if done correctly. Note that secure proximity based on short range wireless technology requires very low signal strength or very low latency. ๐Ÿ“กโœจ

Appendix E. Use of External Authorization Data

Okay so this appendix is all about EAD (external authorization data)! ๐ŸŽ€ The idea is that you can plug external security apps into EDHOC by tucking their data inside the messages. Why? To cut down on messages and round trips, or to make processing simpler. Lowkey genius ๐Ÿ’…โœจ

The EAD format itself lives in Section 3.8. This appendix is the bestie guide with examples and extra details for using EAD alongside an accompanying spec. ๐Ÿฆ‹

  • One example is third-party-assisted authorization. You request it with EAD_1, and the authorization artifact (a "voucher", cf. [RFC8366]) comes back in EAD_2. See [LAKE-AUTHZ]. ๐Ÿงš
  • Another example is remote attestation. You request it in EAD_2, and an Entity Attestation Token (EAT) [EAT] gets returned in EAD_3. ๐Ÿ”ฅ
  • A third example is certificate enrollment. A Certificate Signing Request (CSR) [RFC2986] goes in EAD_3, and the issued public key certificate (X.509 [RFC5280] and C509 [C509-CERTS]), or a reference to it, comes back in EAD_4. ๐Ÿ’œ

Now the important part, bestie ๐Ÿซถ: EAD should be considered unprotected by EDHOC. That means the protection of EAD is the responsibility of the security application (third-party authorization, remote attestation, certificate enrollment, etc.). The security properties of the EAD fields (after EDHOC processing) are discussed in Section 9.1. ๐Ÿ™ˆ

The content of the EAD field can be used in the EDHOC processing of the message it's in. For example, authentication-related info like assertions and revocation information carried in EAD fields may give input about trust anchors or the validity of credentials that matter for authentication processing. So the EAD fields (just like ID_CRED fields) are made available to the application before the message is verified. See message processing details in Section 5. ๐ŸŒˆ In the first example above, a voucher in EAD_2 that the application can see may let the Initiator verify the identity or the public key of the Responder before verifying the signature. Iconic. ๐Ÿ‘‘ An application that allows EAD fields with authentication information may therefore need to handle the authentication-related verifications tied to EAD processing. โญ

Conversely, the security application may need to wait for EDHOC message verification to finish. In the third example above, the Responder does not start validating a CSR carried in EAD_3 until EDHOC has successfully verified message_3 and proven the Initiator's possession of its private key. Patience is a virtue, babe ๐ŸŒธ

The security application may reuse EDHOC protocol fields, which therefore need to be available to the application. For example, it may use the same crypto algorithms as the EDHOC session, so it needs access to the selected cipher suite (or the whole SUITES_I). The application may also use the ephemeral public keys G_X and G_Y as ephemeral keys or as nonces; see [LAKE-AUTHZ]. ๐Ÿ’–

Processing an EAD item (ead_label, ? ead_value) by the security application needs to be described in the specification where the ead_label is registered (see Section 10.5). That spec covers the optional ead_value for each message and the actions to take in case of errors. โœจ An application may support multiple security applications that use EAD, which can result in multiple EAD items in one EAD field; see Section 3.8. Any dependencies on security applications with previously registered EAD items need to be documented, and the processing has to consider their simultaneous use. ๐Ÿ“

Since data carried in EAD may be unprotected, or processed by the application before the EDHOC message is verified, you need special considerations so it doesn't violate the security and privacy requirements of the service using that data; see Section 9.5. The content of an EAD item may impact the security properties EDHOC provides. Security applications making use of EAD items must perform the necessary security analysis. ๐Ÿ˜ญ๐Ÿ’€


Appendix F. Application Profile Example

This appendix has a rudimentary example of an application profile; see Section 3.9. ๐Ÿงš

For use of EDHOC with application X, the following assumptions are made:

  1. Transfer in CoAP as specified in Appendix A.2, with requests expected by the CoAP server (= Responder) at /app1-edh, no Content-Format needed. ๐ŸŽ€
  2. METHOD = 1 (I uses signature key; R uses static DH key.) ๐Ÿฆ‹
  3. CRED_I is an IEEE 802.1AR Initial Device Identifier (IDevID) encoded as a C509 certificate of type 0 [C509-CERTS].
    • R acquires CRED_I out-of-band, indicated in EAD_1.
    • ID_CRED_I = {4: h''} is a 'kid' with the value of the empty CBOR byte string. ๐Ÿ“
  4. CRED_R is a CCS of type OKP as specified in Section 3.5.2.
    • The CBOR map has parameters 1 (kty), -1 (crv), and -2 (x-coordinate).
    • ID_CRED_R is {14 : CCS}. ๐Ÿ’…
  5. External authorization data is defined and processed as specified in [LAKE-AUTHZ]. ๐ŸŒˆ
  6. EUI-64 is used as the identity of the endpoint (see an example in Section 3.5.2). ๐Ÿ’œ
  7. No use of message_4. The application sends protected messages from R to I. ๐Ÿซถ

Appendix G. Long PLAINTEXT_2

Okay, so by the definition of encrypting PLAINTEXT_2 with KEYSTREAM_2, it's limited to lengths of PLAINTEXT_2 not exceeding the output of EDHOC_KDF; see Section 4.1.2. If the EDHOC hash algorithm is SHA-2, then HKDF-Expand is used, which limits the EDHOC_KDF output to 255 โ‹… hash_length, where hash_length is the length of the output of the EDHOC hash algorithm given by the cipher suite. For example, with SHA-256 as the EDHOC hash algorithm, the hash output is 32 bytes, so the maximum length of PLAINTEXT_2 is 255 โ‹… 32 = 8160 bytes. ๐Ÿ˜ณ

PLAINTEXT_2 is expected to be much shorter than 8 kB for the intended use cases, but it's still prudent to specify a solution in case this turns out to be a limitation. ๐Ÿง

A potential work-around is to use a cipher suite with a different hash function. In particular, the use of KMAC removes all practical limitations in this respect. โœจ

This section specifies a solution that works with any hash function by making use of multiple invocations of HKDF-Expand and negative values of info_label. ๐Ÿฆ‹

Consider PLAINTEXT_2 partitioned into parts P(i) of length equal to M = 255 โ‹… hash_length, except possibly the last part P(last), which has 0 < length โ‰ค M.

PLAINTEXT_2 = P(0) | P(1) | ... | P(last)

where "|" indicates concatenation.

The object is to define a matching KEYSTREAM_2 of the same length and perform the encryption in the same way as defined in Section 5.3.2:

CIPHERTEXT_2 = PLAINTEXT_2 XOR KEYSTREAM_2

Define the keystream as:

KEYSTREAM_2 = OKM(0) | OKM(1)  | ... | OKM(last)

where:

OKM(i) = EDHOC_KDF( PRK_2e, -i, TH_2, length(P(i)) )

Note that if length(PLAINTEXT_2) โ‰ค M, then P(0) = PLAINTEXT_2 and the definition of KEYSTREAM_2 = OKM(0) coincides with Figure 6. ๐ŸŒธ

This describes the processing of the Responder when sending message_2. The Initiator makes the same calculations when receiving message_2, but interchanging PLAINTEXT_2 and CIPHERTEXT_2. ๐Ÿ”ฅ

An application profile may specify whether it supports or does not support the method described in this appendix. ๐Ÿ’œ


Appendix H. EDHOC_KeyUpdate

To provide forward secrecy in an even more efficient way than re-running EDHOC, this section specifies the optional function EDHOC_KeyUpdate in terms of EDHOC_KDF and PRK_out. ๐ŸŒˆ

When EDHOC_KeyUpdate is called, a new PRK_out is calculated as the output of the EDHOC_Expand function with the old PRK_out as input. The change of PRK_out causes a change to PRK_exporter, which enables deriving new application keys that supersede the old ones, using EDHOC_Exporter; see Section 4.2.1. The process is illustrated by the following pseudocode. ๐Ÿงš

EDHOC_KeyUpdate( context ):
   new PRK_out = EDHOC_KDF( old PRK_out, 11, context, hash_length )
   new PRK_exporter = EDHOC_KDF( new PRK_out, 10, h'', hash_length )

where hash_length denotes the output size in bytes of the EDHOC hash algorithm of the selected cipher suite.

The EDHOC_KeyUpdate takes a context as input to enable binding of the updated PRK_out to some event that triggered the key update. The Initiator and Responder need to agree on the context, which can, e.g., be a counter, a pseudorandom number, or a hash. To provide forward secrecy, the old PRK_out and keys derived from it (old PRK_exporter and old application keys) must be deleted as soon as they are not needed. When to delete the old keys and how to verify that they are not needed is up to the application. Note that the security properties depend on the type of context and the number of KeyUpdate iterations. ๐Ÿซถ

An application using EDHOC_KeyUpdate needs to store PRK_out. Compromise of PRK_out leads to compromise of all keying material derived with the EDHOC_Exporter since the last invocation of the EDHOC_KeyUpdate function. ๐Ÿ˜ญ

While this key update method provides forward secrecy, it does not give as strong security properties as re-running EDHOC. EDHOC_KeyUpdate can be used to meet cryptographic limits and provide partial protection against key leakage, but it provides significantly weaker security properties than re-running EDHOC with ephemeral Diffie-Hellman. Even with frequent use of EDHOC_KeyUpdate, compromise of one session key compromises all future session keys, and an attacker therefore only needs to perform static key exfiltration [RFC7624], which is less complicated and has a lower risk profile than the dynamic case; see Section 9.1. ๐Ÿ’€โš ๏ธ

Bestie, this one is a big deal: even with frequent KeyUpdates, one compromised session key still compromises all future session keys. Don't treat EDHOC_KeyUpdate as a substitute for re-running EDHOC with ephemeral Diffie-Hellman! ๐Ÿšจ

A similar method to do a key update for OSCORE is KUDOS; see [KUDOS]. ๐Ÿฆ‹


Appendix I. Example Protocol State Machine

This appendix describes an example protocol state machine for the Initiator and Responder. States are denoted in all capitals, and parentheses denote actions taken only in some circumstances. ๐ŸŽ€

Note that this state machine is just an example, and that details of processing are omitted. For example:

  • when error messages are being sent (with one exception);
  • how credentials and EAD are processed by EDHOC and the application in the RCVD state; and
  • what verifications are made, which includes not only MACs and signatures. ๐ŸŒˆ

I.1. Initiator State Machine

Okay so bestie, the Initiator kicks things off by sending message_1 ๐Ÿฆ‹, which moves the state machine from START to WAIT_M2 ๐Ÿ’ซ, and then it just waits for message_2 ๐Ÿ‘€.

If what comes back is an error message ๐Ÿ™ˆ, the Initiator goes from WAIT_M2 straight to ABORTED ๐Ÿ’€. But if it's error code 2 (Wrong Selected Cipher Suite) ๐ŸŽ€, the Initiator remembers which cipher suites this particular Responder supports and goes from ABORTED back to START ๐Ÿ”„. The message_1 it sends next takes into account the cipher suites the Responder supports, so it's giving smart retry energy ๐Ÿ’….

When a non-error message shows up, the Initiator moves from WAIT_M2 to RCVD_M2 and processes it ๐ŸŒธ. If processing message_2 goes wrong, it's ABORTED time ๐Ÿ˜ญ. If processing goes well, the Initiator moves from RCVD_M2 to VRFD_M2 โœจ.

Next the Initiator prepares and processes message_3 for sending ๐Ÿ“. If any processing error shows up, it goes from VRFD_M2 to ABORTED ๐Ÿ’€. If message_3 gets sent successfully, the Initiator moves from VRFD_M2 to COMPLETED ๐ŸŽ‰.

Now, if the application profile includes message_4 ๐Ÿงš, the Initiator waits for message_4. If an error message comes in, it goes from COMPLETED to ABORTED ๐Ÿ’€. When a non-error message arrives, the Initiator moves from COMPLETED (="WAIT_M4") to RCVD_M4 and processes it ๐Ÿซถ. If processing message_4 errors out, it's ABORTED again ๐Ÿ˜ญ. If processing goes well, the Initiator moves from RCVD_M4 to PERSISTED (="VRFD_M4") ๐Ÿ‘‘.

If the application profile does not include message_4 ๐Ÿ™…, the Initiator just waits for an incoming application message ๐Ÿ‘‚. If decrypting and verifying that application message works, the Initiator goes from COMPLETED to PERSISTED ๐ŸŒˆ.

Figure 12: Initiator State Machine ๐Ÿฆ‹

        +- - - - - - - - - -> START
        |                       |
                                | Send message_1
        |                       |
              Receive error     v
    ABORTED <---------------- WAIT_M2
        ^                       |
        |                       | Receive message_2
        |                       |
        |    Processing error   v
        +-------------------- RCVD_M2
        ^                       |
        |                       | Verify message_2
        |                       |
        |    Processing error   v
        +-------------------- VRFD_M2
        ^                       |
        |                       | Send message_3
        |                       |
        |    (Receive error)    v
        +-------------------- COMPLETED ----------------+
        ^                       |                       |
        |                       | (Receive message_4)   |
        |                       |                       |
        |   (Processing error)  v                       | (Verify
        +------------------- (RCVD_M4)                  |  application
                                |                       |  message)
                                | (Verify message_4)    |
                                |                       |
                                v                       |
                              PERSISTED <---------------+

I.2. Responder State Machine

Okay, so the Responder's side ๐ŸŽ€. When message_1 arrives, the Responder goes from START to RCVD_M1 ๐Ÿ“ฉ.

If processing message_1 errors out, the Responder goes from RCVD_M1 to ABORTED ๐Ÿ’€. That includes sending an error message with error code 2 (Wrong Selected Cipher Suite) if the selected cipher suite in message_1 isn't supported ๐Ÿ™ˆ. If processing message_1 goes fine, the Responder moves from RCVD_M1 to VRFD_M1 โœจ.

The Responder prepares and processes message_2 for sending ๐ŸŒธ. If any processing error pops up, the Responder goes from VRFD_M1 to ABORTED ๐Ÿ˜ญ. If message_2 gets sent successfully, the Initiator moves from VRFD_M2 to WAIT_M3 and waits for message_3 ๐Ÿฆ‹. (Yes, the text says Initiator there, and yes, it's giving mix-up vibes, but that's what the original says ๐Ÿคญ.)

If the incoming message is an error message, the Responder goes from WAIT_M3 to ABORTED ๐Ÿ’€.

When message_3 arrives, the Responder moves from WAIT_M3 to RCVD_M3 ๐Ÿ’Œ. If processing message_3 goes wrong, it's RCVD_M3 to ABORTED ๐Ÿ˜ญ. If processing goes well, the Responder moves from RCVD_M3 to COMPLETED (="VRFD_M3") ๐Ÿ’–.

If the application profile includes message_4 ๐Ÿงš, the Responder prepares and processes message_4 for sending. If any processing error shows up, the Responder goes from COMPLETED to ABORTED ๐Ÿ’€.

If message_4 is sent successfully, or if the application profile doesn't include message_4 ๐Ÿ™Œ, the Responder moves from COMPLETED to PERSISTED ๐Ÿ‘‘.

                                     START
                                       |
                                       | Receive message_1
                                       |
                    Processing error   v
           ABORTED <---------------- RCVD_M1
               ^                       |
               |                       | Verify message_1
               |                       |
               |    Processing error   v
               +-------------------- VRFD_M1
               ^                       |
               |                       | Send message_2
               |                       |
               |     Receive error     v
               +-------------------- WAIT_M3
               ^                       |
               |                       | Receive message_3
               |                       |
               |    Processing error   v
               +-------------------- RCVD_M3
               ^                       |
               |                       | Verify message_3
               |                       |
               |   (Processing error)  v
               +------------------- COMPLETED
                                       |
                                       | (Send message_4)
                                       |
                                       v
                                    PERSISTED

Figure 13: Responder State Machine ๐Ÿ‘


Acknowledgments ๐Ÿ™

Huge shoutout to Christian Amsรผss, Karthikeyan Bhargavan, Carsten Bormann, Alessandro Bruni, Timothy Claeys, Baptiste Cottier, Roman Danyliw, Martin Disch, Martin Duke, Donald Eastlake 3rd, Lars Eggert, Stephen Farrell, Loรฏc Ferreira, Theis Grรธnbech Petersen, Felix Gรผnther, Dan Harkins, Klaus Hartke, Russ Housley, Stefan Hristozov, Marc Ilunga, Charlie Jacomme, Elise Klein, Erik Kline, Steve Kremer, Alexandros Krontiris, Ilari Liusvaara, Rafa Marรญn-Lรณpez, Kathleen Moriarty, David Navarro, Karl Norrman, Salvador Pรฉrez, Radia Perlman, David Pointcheval, Maรฏwenn Racouchot, Eric Rescorla, Michael Richardson, Thorvald Sahl Jรธrgensen, Zaheduzzaman Sarker, Jim Schaad, Michael Scharf, Carsten Schรผrmann, John Scudder, Ludwig Seitz, Brian Sipos, Stanislav Smyshlyaev, Valery Smyslov, Peter van der Stok, Rene Struik, Vaishnavi Sundararajan, Erik Thormarker, Marco Tiloca, Sean Turner, Michel Veillette, Maliลกa Vuฤiniฤ‡, Paul Wouters, and Lei Yan for reviewing and commenting on intermediate draft versions of this document ๐Ÿ’œ.

We are especially indebted to the late Jim Schaad for his continuous review and implementation of draft versions of this document, as well as his work on other technologies such as COSE and OSCORE without which EDHOC would not have been ๐Ÿฅบ๐Ÿซถ.

Work on this document has in part been supported by the H2020 project SIFIS-Home (grant agreement 952652) ๐ŸŒŸ.


Authors' Addresses ๐Ÿ’Œ

Gรถran Selander Ericsson AB SE-164 80 Stockholm Sweden Email: goran.selander@ericsson.com

John PreuรŸ Mattsson Ericsson AB SE-164 80 Stockholm Sweden Email: john.mattsson@ericsson.com

Francesca Palombini Ericsson AB SE-164 80 Stockholm Sweden Email: francesca.palombini@ericsson.com

๐Ÿ“ฆ where this page comes from