RFC 9053

CBOR Object Signing and Encryption (COSE): Initial Algorithms

๐Ÿ“… published August 2022, from ietf

RFC 9053: CBOR Object Signing and Encryption (COSE): Initial Algorithms ๐ŸŽ€

Okay bestie, this one is RFC 9053, and it's giving "the algorithm shelf for COSE" ๐Ÿ’…. It was written by J. Schaad at August Cellars and dated August 2022. It's an Informational document (not a Standards Track spec) with ISSN 2070-1721, and it obsoletes RFC 8152 ๐Ÿฆ‹. It works together with RFC 9052, which is the main COSE spec.

Table of Contents โœจ

1.  Introduction
  1.1.  Requirements Terminology
  1.2.  Changes from RFC 8152
  1.3.  Document Terminology
  1.4.  CDDL Grammar for CBOR Data Structures
  1.5.  Examples
2.  Signature Algorithms
  2.1.  ECDSA
    2.1.1.  Security Considerations for ECDSA
  2.2.  Edwards-Curve Digital Signature Algorithm (EdDSA)
    2.2.1.  Security Considerations for EdDSA
3.  Message Authentication Code (MAC) Algorithms
  3.1.  Hash-Based Message Authentication Codes (HMACs)
    3.1.1.  Security Considerations for HMAC
  3.2.  AES Message Authentication Code (AES-CBC-MAC)
    3.2.1.  Security Considerations for AES-CBC-MAC
4.  Content Encryption Algorithms
  4.1.  AES-GCM
    4.1.1.  Security Considerations for AES-GCM
  4.2.  AES-CCM
    4.2.1.  Security Considerations for AES-CCM
  4.3.  ChaCha20 and Poly1305
    4.3.1.  Security Considerations for ChaCha20/Poly1305
5.  Key Derivation Functions (KDFs)
  5.1.  HMAC-Based Extract-and-Expand Key Derivation Function
        (HKDF)
  5.2.  Context Information Structure
6.  Content Key Distribution Methods
  6.1.  Direct Encryption
    6.1.1.  Direct Key
    6.1.2.  Direct Key with KDF
  6.2.  Key Wrap
    6.2.1.  AES Key Wrap
  6.3.  Direct Key Agreement
    6.3.1.  Direct ECDH
  6.4.  Key Agreement with Key Wrap
    6.4.1.  ECDH with Key Wrap
7.  Key Object Parameters
  7.1.  Elliptic Curve Keys
    7.1.1.  Double Coordinate Curves
  7.2.  Octet Key Pair
  7.3.  Symmetric Keys
8.  COSE Capabilities
  8.1.  Assignments for Existing Algorithms
  8.2.  Assignments for Existing Key Types
  8.3.  Examples
9.  CBOR Encoding Restrictions
10. IANA Considerations
  10.1.  Changes to the "COSE Key Types" Registry
  10.2.  Changes to the "COSE Algorithms" Registry
  10.3.  Changes to the "COSE Key Type Parameters" Registry
  10.4.  Expert Review Instructions
11. Security Considerations
12. References
  12.1.  Normative References
  12.2.  Informative References
Acknowledgments
Author's Address

Abstract ๐Ÿ’–

Concise Binary Object Representation (CBOR) is a data format built for small code size and small message size ๐Ÿงš. People need basic security services for this format too, so this document defines a set of algorithms for use with the CBOR Object Signing and Encryption (COSE) protocol (RFC 9052). Together with RFC 9052, it obsoletes RFC 8152 โœจ.

Status of This Memo ๐Ÿ“œ

This is not an Internet Standards Track specification. It's published for informational purposes ๐ŸŒธ.

It's a product of the Internet Engineering Task Force (IETF) and represents the consensus of the IETF community. It went through public review and was approved for publication by the Internet Engineering Steering Group (IESG). Not every IESG-approved document is a candidate for any level of Internet Standard, so see Section 2 of RFC 7841 for the details ๐Ÿ™ˆ.

You can find info on the current status of this document, any errata, and how to give feedback at https://www.rfc-editor.org/info/rfc9053.

Copyright (c) 2022 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) in effect on the date it was published. Please read these carefully, because they spell out your rights and restrictions for this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions, and they're provided without warranty as described in the Revised BSD License ๐Ÿซถ.

1. Introduction โœจ

So there's been a huge focus on small, constrained devices that make up the Internet of Things (IoT) ๐ŸŒˆ. One of the standards that came out of this is "Concise Binary Object Representation (CBOR)" [STD94]. CBOR extended the data model of JavaScript Object Notation (JSON) [STD90] by allowing binary data, among other changes. Several IETF working groups in the IoT world have adopted CBOR as their way of encoding data structures, and honestly it's iconic ๐Ÿ‘‘. CBOR was designed to be small in both messages transported and implementation size, and to have a schema-free decoder. Since we need message security services for IoT, using CBOR as the message-encoding format makes total sense ๐Ÿ’….

The core COSE specification is made of two documents. [RFC9052] holds the serialization structures and the procedures for using the different cryptographic algorithms. This document gives you an initial set of algorithms to use with those structures ๐ŸŽ€.

1.1. Requirements Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here ๐Ÿ”ฅ.

1.2. Changes from RFC 8152

  • We pulled the sections about specific algorithms out of RFC 8152 and put them into this document. The sections on structure and general processing rules now live in [RFC9052] ๐Ÿงš.
  • Text clarifications and terminology changes were made ๐ŸŒธ.
  • All the details about countersignatures were removed and moved to [COUNTERSIGN] ๐Ÿฆ‹.

1.3. Document Terminology

Here's the terminology we're using in this document ๐Ÿ“:

Byte: A synonym for octet.

Constrained Application Protocol (CoAP): A specialized web transfer protocol for use in constrained systems. It is defined in [RFC7252].

Authenticated Encryption (AE) algorithms [RFC5116]: Encryption algorithms that provide an authentication check of the contents along with the encryption service. An example of an AE algorithm used in COSE is AES Key Wrap [RFC3394]. These algorithms are used for key encryption, but Authenticated Encryption with Associated Data (AEAD) algorithms would be preferred ๐Ÿ’œ.

AEAD algorithms [RFC5116]: Encryption algorithms that provide the same authentication service for the content as AE algorithms do, and also allow associated data that isn't part of the encrypted body to be included in the authentication service. An example of an AEAD algorithm used in COSE is AES-GCM [RFC5116]. These algorithms are used for content encryption and can be used for key encryption as well โœจ.

The term "byte string" is used for sequences of bytes, while the term "text string" is used for sequences of characters ๐Ÿ’–.

The tables for algorithms have these columns ๐ŸŒˆ:

  • A name for the algorithm for use in documents.
  • The value used on the wire for the algorithm. One place this is used is the algorithm header parameter of a message.
  • A short description so the algorithm can be easily identified when you're scanning the IANA registry.

Tables may have additional columns depending on the algorithms ๐Ÿฆ‹.

1.4. CDDL Grammar for CBOR Data Structures

When COSE was originally written, the Concise Data Definition Language (CDDL) [RFC8610] hadn't been published in an RFC yet. That means it couldn't be used as the data description language to normatively describe the CBOR data structures COSE uses. So the CBOR data objects defined here are described in prose ๐Ÿ“. Additional (non-normative) descriptions of the COSE data objects are provided in a subset of CDDL, described in [RFC9052] ๐Ÿซถ.

1.5. Examples

A GitHub project was created at [GitHub-Examples] with a set of testing examples ๐Ÿงช. Each example is in a JSON file that holds the inputs used to create the example, some of the intermediate values you can use for debugging, and the output of the example. The results are encoded in both hexadecimal and CBOR diagnostic notation format ๐Ÿ’….

Some examples are designed as failure-testing cases, and the JSON file clearly marks them as such ๐Ÿ’€.

2. Signature Algorithms ๐Ÿ–Š๏ธ

Section 8.1 of [RFC9052] contains a generic description of signature algorithms. This document defines signature algorithm identifiers for two signature algorithms ๐Ÿ”ฅ.


To be continued in Part 2 ๐Ÿ’–

2.1. ECDSA ๐Ÿฆ‹

okay so ECDSA (the Elliptic Curve Digital Signature Algorithm) [DSS] is a signature algorithm that runs on Elliptic Curve Cryptography (ECC) ๐Ÿ’… bestie, the main move is that implementations SHOULD use a deterministic version of ECDSA, like the one in [RFC6979] โœจ. Why? Deterministic signing means you don't have to lean on a random number generator to pick the per-message "k" value (the random value used for each message). Biased "k" generation can get attacked, and if two "k" values collide, your keys leak ๐Ÿ˜ญ. It also lets you run deterministic tests on the signature algorithm, which is so smart ๐Ÿงš. Just know that going deterministic does NOT mean you can be lazy about randomness when you make the private key ๐Ÿ™ˆ

The ECDSA signature algorithm takes a hash function (h) as a parameter ๐ŸŒธ. If the hash output is longer than the group of the key, you just use the leftmost bytes of the hash output ๐ŸŽ€

Here are the algorithms from this document, all laid out in Table 1 ๐Ÿ’–

          +=======+=======+=========+==================+
          | Name  | Value | Hash    | Description      |
          +=======+=======+=========+==================+
          | ES256 |   -7  | SHA-256 | ECDSA w/ SHA-256 |
          +-------+-------+---------+------------------+
          | ES384 |  -35  | SHA-384 | ECDSA w/ SHA-384 |
          +-------+-------+---------+------------------+
          | ES512 |  -36  | SHA-512 | ECDSA w/ SHA-512 |
          +-------+-------+---------+------------------+

                 Table 1: ECDSA Algorithm Values

This document only defines ECDSA for the curves P-256, P-384, and P-521 ๐Ÿฆ‹ It also requires that the curves are encoded with the "EC2" (two coordinate elliptic curve) key type. Implementations need to check that the key type and curve are correct when they create and verify a signature, no skipping this step ๐Ÿ‘‘ Future documents may define it for other curves and key types.

To keep things interoperable, it's suggested that SHA-256 only gets used with P-256, SHA-384 only with P-384, and SHA-512 only with P-521 โœจ This lines up with the recommendation in Section 4 of [RFC5480] ๐Ÿซถ

The signature algorithm gives you a pair of integers (R, S). These integers are the same length as the key used for signing ๐ŸŒˆ To encode the signature, you turn each integer into a byte string the same length as the key size. That length gets rounded up to the nearest byte and left padded with zero bits to hit the right length. Then you concatenate the two integers into one byte string, and that's your signature ๐Ÿ’œ

Using the function defined in [RFC8017], the signature is:

Signature = I2OSP(R, n) | I2OSP(S, n)

where n = ceiling(key_length / 8)

When you use a COSE key for this algorithm, these checks happen ๐Ÿ”ฅ

  • The "kty" field MUST be present, and it MUST be "EC2".
  • If the "alg" field is present, it MUST match the ECDSA signature algorithm being used.
  • If the "key_ops" field is present, it MUST include "sign" when creating an ECDSA signature.
  • If the "key_ops" field is present, it MUST include "verify" when verifying an ECDSA signature.

2.1.1. Security Considerations for ECDSA ๐Ÿ™ˆ

The security strength of the signature is no greater than the minimum of two things: the security strength tied to the bit length of the key, and the security strength of the hash function. So it's only as strong as its weakest link, bestie ๐Ÿ’€

Note: Using a deterministic signature technique is a good idea even when you have good random number generation. It cuts down on the chance of two signature operations using the same "k" value, and it gives you reproducible signature values, which makes testing way easier ๐Ÿ“ There have been recent attacks where people fault the device to extract the key, and this can be handled by combining both randomness and determinism [CFRG-DET-SIGS] ๐Ÿ˜ญ

There are two substitution attacks that could theoretically be mounted against the ECDSA signature algorithm ๐Ÿ˜ฑ

  • Changing the curve used to validate the signature: If someone changes the curve used to validate the signature, they could potentially have two messages with the same signature, each computed under a different curve. The only requirements on the new curve are that its order matches the old one and that it's acceptable to the client. An example would be switching from secp256r1 (aka P-256) to secp256k1. (Both are 256-bit curves.) Right now we don't have a way to deal with this version of the attack except by restricting the overall set of curves that can be used ๐Ÿšซ
  • Changing the hash function used to validate the signature: If someone has two different hash functions of the same length, or can truncate a hash function, they could potentially find collisions between the hash functions instead of within a single hash function. For example, truncating SHA-512 to 256 bits might collide with a SHA-256 hash value. Since the hash algorithm is part of the signature algorithm identifier, this attack is mitigated by including a signature algorithm identifier in the protected-header bucket ๐Ÿ›ก๏ธ

2.2. Edwards-Curve Digital Signature Algorithm (EdDSA) ๐ŸŒธ

[RFC8032] describes the Edwards-curve Digital Signature Algorithm (EdDSA) elliptic curve signature scheme ๐Ÿงš In that document, the signature algorithm is set up with parameters for the edwards25519 and edwards448 curves. It also describes two variants of EdDSA: Pure EdDSA, where no hash function gets applied to the content before signing, and HashEdDSA, where a hash function is applied to the content first and then the hash result is what gets signed. For EdDSA, the content being signed (either the message or the prehash value) gets processed twice inside the signature algorithm ๐ŸŒ€

For use with COSE, only pure EdDSA is used. The reason is that extremely large contents aren't expected to be needed, and because of how the message structure is arranged, the whole message has to be held in memory to create or verify a signature. So there doesn't seem to be a need for block updates of the hash followed by dropping the message from memory ๐Ÿ’… Applications can get the same features by defining the content of the message as a hash value and transporting the COSE object (with the hash value) and the content as separate items ๐Ÿซถ

The algorithm in this document is in Table 2. A single signature algorithm is defined, and it can be used with multiple curves โœจ

                  +=======+=======+=============+
                  | Name  | Value | Description |
                  +=======+=======+=============+
                  | EdDSA |   -8  | EdDSA       |
                  +-------+-------+-------------+

                   Table 2: EdDSA Algorithm Value

[RFC8032] describes how to encode the signature value ๐ŸŒˆ

When you use a COSE key for this algorithm, these checks happen ๐Ÿ‘‘

  • The "kty" field MUST be present, and it MUST be "OKP" (Octet Key Pair).
  • The "crv" field MUST be present, and it MUST be a curve defined for this signature algorithm.
  • If the "alg" field is present, it MUST match "EdDSA".
  • If the "key_ops" field is present, it MUST include "sign" when creating an EdDSA signature.
  • If the "key_ops" field is present, it MUST include "verify" when verifying an EdDSA signature.

2.2.1. Security Considerations for EdDSA ๐Ÿ”

Public values get computed differently in EdDSA and Elliptic Curve Diffie-Hellman (ECDH), so for that reason the public key from one should not be used with the other algorithm ๐Ÿ™…โ€โ™€๏ธ

If batch signature verification is performed, a well-seeded cryptographic random number generator is REQUIRED (Section 8.2 of [RFC8032]) ๐Ÿšจ Signing and nonbatch signature verification are deterministic operations, so they don't need random numbers of any kind ๐Ÿ’–

3. Message Authentication Code (MAC) Algorithms โœจ

Section 8.2 of [RFC9052] has a generic description of MAC algorithms ๐ŸŽ€ This section sets out the conventions for two MAC algorithms ๐Ÿฆ‹

3.1. Hash-Based Message Authentication Codes (HMACs) ๐Ÿ’–

okay so HMAC [RFC2104] [RFC4231] was literally built to stop length extension attacks ๐Ÿ™…โ€โ™€๏ธ ๐Ÿ”ฅ and it was also designed so you can plug in new hash functions without changing the hash function itself. The HMAC design process has been shown to be really solid ๐Ÿ‘‘. Even though the security of hash functions like MD5 has gone down over time, nobody has shown HMAC combined with MD5 to be compromised [RFC6151] ๐Ÿงš

HMAC is parameterized by an inner and outer padding, a hash function (h), and an authentication tag value length ๐ŸŽ€. For this specification, the inner and outer padding are fixed to the values set in [RFC2104] ๐Ÿ’…. The length of the authentication tag is what decides how hard it is to forge one ๐Ÿ˜ค. For constrained environments, we define one truncated HMAC algorithm ๐Ÿฆ‹. There are currently no known issues with truncation, BUT the security strength of the tag gets reduced to match โš ๏ธ. When truncating, you keep and transmit the leftmost tag-length bits ๐Ÿ“.

The algorithms defined in this document are in Table 3 ๐Ÿ’œ.

+=============+=======+=========+============+======================+
| Name        | Value | Hash    | Tag Length | Description          |
+=============+=======+=========+============+======================+
| HMAC        |   4   | SHA-256 |     64     | HMAC w/ SHA-256      |
| 256/64      |       |         |            | truncated to 64 bits |
+-------------+-------+---------+------------+----------------------+
| HMAC        |   5   | SHA-256 |    256     | HMAC w/ SHA-256      |
| 256/256     |       |         |            |                      |
+-------------+-------+---------+------------+----------------------+
| HMAC        |   6   | SHA-384 |    384     | HMAC w/ SHA-384      |
| 384/384     |       |         |            |                      |
+-------------+-------+---------+------------+----------------------+
| HMAC        |   7   | SHA-512 |    512     | HMAC w/ SHA-512      |
| 512/512     |       |         |            |                      |
+-------------+-------+---------+------------+----------------------+

Table 3: HMAC Algorithm Values โœจ

Some recipient algorithms transport the key, and others derive a key from secret data ๐ŸŒˆ. For the ones that transport the key (like AES Key Wrap), the size of the HMAC key SHOULD be the same size as the output of the underlying hash function ๐Ÿซถ. For the ones that derive the key (like ECDH), the derived key MUST be the same size as the output of the underlying hash function ๐Ÿ”ฅ.

When you use a COSE key for this algorithm, these checks happen ๐Ÿ•ต๏ธโ€โ™€๏ธ:

  • The "kty" field MUST be present, and it MUST be "Symmetric".
  • If the "alg" field is present, it MUST match the HMAC algorithm being used.
  • If the "key_ops" field is present, it MUST include "MAC create" when creating an HMAC authentication tag.
  • If the "key_ops" field is present, it MUST include "MAC verify" when verifying an HMAC authentication tag.

Implementations creating and validating MAC values MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved ๐Ÿ™Œ. No skipping this, bestie ๐Ÿ’€.

3.1.1. Security Considerations for HMAC ๐Ÿ”

HMAC has proved to be resistant to attack even when used with weakened hash algorithms ๐Ÿ’ช. The current best known attack is to brute force the key ๐Ÿ˜ฌ. This means the key size is going to be directly related to the security of an HMAC operation, so go big on those keys ๐Ÿ‘‘โœจ.

3.2. AES Message Authentication Code (AES-CBC-MAC) ๐ŸŒธ

AES-CBC-MAC is the instantiation of the CBC-MAC construction (defined in [MAC]) using AES as the block cipher ๐ŸŽ€. For brevity, we also call it "AES-MAC" ๐Ÿ’…. (Note that this is NOT the same algorithm as AES Cipher-Based Message Authentication Code (AES-CMAC) [RFC4493] ๐Ÿ™ˆ, so don't mix them up, iykyk.)

AES-CBC-MAC is parameterized by the key length, the authentication tag length, and the Initialization Vector (IV) used ๐Ÿงš. For all of these algorithms, the IV is fixed to all zeros ๐Ÿ–ค. We give you an array of algorithms for different key and tag lengths ๐ŸŒˆ. The algorithms defined in this document are in Table 4 ๐Ÿ’œ.

+=========+=======+============+============+==================+
| Name    | Value | Key Length | Tag Length | Description      |
+=========+=======+============+============+==================+
| AES-MAC |   14  |    128     |     64     | AES-MAC 128-bit  |
| 128/64  |       |            |            | key, 64-bit tag  |
+---------+-------+------------+------------+------------------+
| AES-MAC |   15  |    256     |     64     | AES-MAC 256-bit  |
| 256/64  |       |            |            | key, 64-bit tag  |
+---------+-------+------------+------------+------------------+
| AES-MAC |   25  |    128     |    128     | AES-MAC 128-bit  |
| 128/128 |       |            |            | key, 128-bit tag |
+---------+-------+------------+------------+------------------+
| AES-MAC |   26  |    256     |    128     | AES-MAC 256-bit  |
| 256/128 |       |            |            | key, 128-bit tag |
+---------+-------+------------+------------+------------------+

Table 4: AES-MAC Algorithm Values โœจ

Keys may come from either a key structure or a recipient structure ๐Ÿ—๏ธ. Implementations creating and validating MAC values MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved ๐Ÿซถ.

When you use a COSE key for this algorithm, these checks happen ๐Ÿ•ต๏ธโ€โ™€๏ธ:

  • The "kty" field MUST be present, and it MUST be "Symmetric".
  • If the "alg" field is present, it MUST match the AES-MAC algorithm being used.
  • If the "key_ops" field is present, it MUST include "MAC create" when creating an AES-MAC authentication tag.
  • If the "key_ops" field is present, it MUST include "MAC verify" when verifying an AES-MAC authentication tag.

3.2.1. Security Considerations for AES-CBC-MAC ๐Ÿšจ

A number of attacks exist against Cipher Block Chaining Message Authentication Code (CBC-MAC) that need to be considered ๐Ÿ˜ฐ. Let's go through them, bestie:

  • A single key must only be used for messages of a fixed or known length ๐Ÿ“. If this is not the case, an attacker will be able to generate a message with a valid tag given two message and tag pairs ๐Ÿ’€. You can fix this by using different keys for messages of different lengths ๐Ÿ”‘. The current structure mitigates this problem, because a specific encoding structure that includes lengths is built and signed โœจ. (CMAC also addresses this issue.)
  • In Cipher Block Chaining (CBC) mode, if the same key is used for both encryption and authentication operations, an attacker can produce messages with a valid authentication code ๐Ÿ˜ฑ. Do NOT do this, periodt ๐Ÿ›‘.
  • If the IV can be modified, then messages can be forged ๐Ÿฅฒ. This is addressed by fixing the IV to all zeros ๐Ÿ–ค.

4. Content Encryption Algorithms โœจ

Section 8.3 of [RFC9052] contains a generic description of content encryption algorithms ๐Ÿ“–. This document defines the identifier and usages for three content encryption algorithms ๐ŸŒŸ.

4.1. AES-GCM ๐Ÿฆ‹

The Galois/Counter Mode (GCM) is a generic AEAD block cipher mode defined in [AES-GCM] ๐Ÿ’–. GCM mode gets combined with the AES block encryption algorithm to define an AEAD cipher ๐Ÿ’œ.

GCM mode is parameterized by the size of the authentication tag and the size of the nonce ๐ŸŽ€. This document fixes the nonce size at 96 bits ๐Ÿ”’. The authentication tag size is limited to a small set of values ๐Ÿ™ƒ. For this document, though, the tag size is fixed at 128 bits ๐Ÿ’….

The set of algorithms defined in this document is in Table 5 ๐ŸŒธ.

+=========+=======+==========================================+
| Name    | Value | Description                              |
+=========+=======+==========================================+
| A128GCM |   1   | AES-GCM mode w/ 128-bit key, 128-bit tag |
+---------+-------+------------------------------------------+
| A192GCM |   2   | AES-GCM mode w/ 192-bit key, 128-bit tag |
+---------+-------+------------------------------------------+
| A256GCM |   3   | AES-GCM mode w/ 256-bit key, 128-bit tag |
+---------+-------+------------------------------------------+

Table 5: Algorithm Values for AES-GCM โœจ

Keys may come from either a key structure or a recipient structure ๐Ÿ—๏ธ. Implementations that are encrypting or decrypting MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved ๐Ÿซถ.

When you use a COSE key for this algorithm, these checks happen ๐Ÿ•ต๏ธโ€โ™€๏ธ:

  • The "kty" field MUST be present, and it MUST be "Symmetric".
  • If the "alg" field is present, it MUST match the AES-GCM algorithm being used.
  • If the "key_ops" field is present, it MUST include "encrypt" or "wrap key" when encrypting.
  • If the "key_ops" field is present, it MUST include "decrypt" or "unwrap key" when decrypting.

4.1.1. Security Considerations for AES-GCM ๐Ÿ›ก๏ธ

When using AES-GCM, the following restrictions MUST be enforced ๐Ÿšซ:

  • The key and nonce pair MUST be unique for every message encrypted ๐Ÿ”‘.
  • The total number of messages encrypted for a single key MUST NOT exceed 2^32 [SP800-38D] ๐Ÿ˜ฑ. An explicit check is required only in environments where it is expected that this limit might be exceeded.
  • [RFC8446] contains an analysis on the use of AES-CGM for its environment ๐Ÿง. Based on that recommendation, one should restrict the number of messages encrypted to 2^24.5 ๐ŸŒ™.
  • A more recent analysis in [ROBUST] indicates that the number of failed decryptions needs to be taken into account when deciding when a key rollover is to be done ๐Ÿ”„. Following the recommendation in DTLS (Section 4.5.3 of [RFC9147]), the number of failed message decryptions should be limited to 2^36 ๐Ÿ™.

Consideration was given to supporting smaller tag values ๐Ÿค”, because the constrained community would really like tag sizes in the 64-bit range ๐Ÿฅบ. Such use drastically changes both the maximum message size (generally not an issue) and the number of times a key can be used ๐Ÿ˜ตโ€๐Ÿ’ซ. Given that Counter with CBC-MAC (CCM) is the usual mode for constrained environments, restricted modes are not supported ๐ŸŒˆโœจ.

4.2. AES-CCM ๐ŸŽ€

okay so CCM is a generic authentication encryption block cipher mode defined in [RFC3610] ๐Ÿ’– It gets paired with AES block encryption to make an AEAD cipher that's super popular on constrained devices ๐Ÿงš

CCM has two parameter choices. The first is M, the size of the authentication field. Picking M is a trade-off between message growth (from the tag) and the chance that an attacker can change a message without anyone noticing ๐Ÿ‘€ The second is L, the size of the length field. L is a trade-off between the max message size and the size of the nonce ๐Ÿซถ

ngl the CCM spec counts L and M in bytes instead of bits, which is so confusing ๐Ÿ˜ญ That's why people say AES-CCM-8 when they mean a 64-bit tag, not an 8-bit one. Most crypto specs use bit counts, so this doc follows that convention to make comparing the algorithms way easier ๐Ÿ’…

We define a matrix of algorithms over the values of L and M. Constrained devices are usually sending short messages and want to avoid recipient-specific crypto operations, so that favors smaller values of both L and M. Less-constrained devices want bigger messages and are more than fine generating new keys for every operation, so that favors larger values of L and M ๐Ÿ”ฅ

The following values are used for L:

  • 16 bits (2): This limits messages to 2^16 bytes (64 KiB) in length. This is sufficiently long for messages in the constrained world. The nonce length is 13 bytes, allowing for 2^104 possible values of the nonce without repeating.
  • 64 bits (8): This limits messages to 2^64 bytes in length. The nonce length is 7 bytes, allowing for 2^56 possible values of the nonce without repeating.

The following values are used for M:

  • 64 bits (8): This produces a 64-bit authentication tag. This implies that there is a 1 in 2^64 chance that a modified message will authenticate.
  • 128 bits (16): This produces a 128-bit authentication tag. This implies that there is a 1 in 2^128 chance that a modified message will authenticate.

Here's the full algorithm table ๐Ÿฆ‹

+====================+=======+====+=====+========+===============+
| Name               | Value | L  | M   |  Key   | Description   |
|                    |       |    |     | Length |               |
+====================+=======+====+=====+========+===============+
| AES-CCM-16-64-128  |   10  | 16 | 64  |  128   | AES-CCM mode  |
|                    |       |    |     |        | 128-bit key,  |
|                    |       |    |     |        | 64-bit tag,   |
|                    |       |    |     |        | 13-byte nonce |
+--------------------+-------+----+-----+--------+---------------+
| AES-CCM-16-64-256  |   11  | 16 | 64  |  256   | AES-CCM mode  |
|                    |       |    |     |        | 256-bit key,  |
|                    |       |    |     |        | 64-bit tag,   |
|                    |       |    |     |        | 13-byte nonce |
+--------------------+-------+----+-----+--------+---------------+
| AES-CCM-64-64-128  |   12  | 64 | 64  |  128   | AES-CCM mode  |
|                    |       |    |     |        | 128-bit key,  |
|                    |       |    |     |        | 64-bit tag,   |
|                    |       |    |     |        | 7-byte nonce  |
+--------------------+-------+----+-----+--------+---------------+
| AES-CCM-64-64-256  |   13  | 64 | 64  |  256   | AES-CCM mode  |
|                    |       |    |     |        | 256-bit key,  |
|                    |       |    |     |        | 64-bit tag,   |
|                    |       |    |     |        | 7-byte nonce  |
+--------------------+-------+----+-----+--------+---------------+
| AES-CCM-16-128-128 |   30  | 16 | 128 |  128   | AES-CCM mode  |
|                    |       |    |     |        | 128-bit key,  |
|                    |       |    |     |        | 128-bit tag,  |
|                    |       |    |     |        | 13-byte nonce |
+--------------------+-------+----+-----+--------+---------------+
| AES-CCM-16-128-256 |   31  | 16 | 128 |  256   | AES-CCM mode  |
|                    |       |    |     |        | 256-bit key,  |
|                    |       |    |     |        | 128-bit tag,  |
|                    |       |    |     |        | 13-byte nonce |
+--------------------+-------+----+-----+--------+---------------+
| AES-CCM-64-128-128 |   32  | 64 | 128 |  128   | AES-CCM mode  |
|                    |       |    |     |        | 128-bit key,  |
|                    |       |    |     |        | 128-bit tag,  |
|                    |       |    |     |        | 7-byte nonce  |
+--------------------+-------+----+-----+--------+---------------+
| AES-CCM-64-128-256 |   33  | 64 | 128 |  256   | AES-CCM mode  |
|                    |       |    |     |        | 256-bit key,  |
|                    |       |    |     |        | 128-bit tag,  |
|                    |       |    |     |        | 7-byte nonce  |
+--------------------+-------+----+-----+--------+---------------+

Table 6: Algorithm Values for AES-CCM

Keys may be obtained from either a key structure or a recipient structure. Implementations that are encrypting or decrypting MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved.

When using a COSE key for this algorithm, the following checks are made:

  • The "kty" field MUST be present, and it MUST be "Symmetric".
  • If the "alg" field is present, it MUST match the AES-CCM algorithm being used.
  • If the "key_ops" field is present, it MUST include "encrypt" or "wrap key" when encrypting.
  • If the "key_ops" field is present, it MUST include "decrypt" or "unwrap key" when decrypting.

4.2.1. Security Considerations for AES-CCM ๐Ÿ’€

When using AES-CCM, the following restrictions MUST be enforced:

  • The key and nonce pair MUST be unique for every message encrypted. Note that the value of L influences the number of unique nonces.
  • The total number of times the AES block cipher is used MUST NOT exceed 2^61 operations. This limit is the sum of times the block cipher is used in computing the MAC value and performing stream encryption operations. An explicit check is required only in environments where it is expected that this limit might be exceeded.
  • [RFC9147] contains an analysis on the use of AES-CCM for its environment. Based on that recommendation, one should restrict the number of messages encrypted to 2^23.
  • In addition to the number of messages successfully decrypted, the number of failed decryptions needs to be tracked as well. Following the recommendation in DTLS (Section 4.5.3 of [RFC9147]), the number of failed message decryptions should be limited to 2^23.5. If one is using the 64-bit tag, then the limits are significantly smaller if one wants to keep the same integrity limits. A protocol recommending this needs to analyze what level of integrity is acceptable for the smaller tag size. It may be that, to keep the desired level of integrity, one needs to rekey as often as every 2^7 messages.

[RFC3610] additionally calls out one other consideration of note. It is possible to do a precomputation attack against the algorithm in cases where portions of the plaintext are highly predictable. This reduces the security of the key size by half. Ways to deal with this attack include adding a random portion to the nonce value and/or increasing the key size used. Using a portion of the nonce for a random value will decrease the number of messages that a single key can be used for. Increasing the key size may require more resources in the constrained device. See Sections 5 and 10 of [RFC3610] for more information.

4.3. ChaCha20 and Poly1305 ๐Ÿฆ‹

ChaCha20 and Poly1305 combined together is an AEAD mode that is defined in [RFC8439] โœจ This is an algorithm built on a cipher that is not AES, so it wouldn't suffer from any future weaknesses found in AES. These functions are designed to be fast in software-only implementations ๐Ÿƒโ€โ™€๏ธ

The ChaCha20/Poly1305 AEAD construction defined in [RFC8439] has no parameterization. It takes as inputs a 256-bit key and a 96-bit nonce, as well as the plaintext and additional data, and produces the ciphertext as an output. We define one algorithm identifier for this algorithm in Table 7 ๐ŸŒธ

+===================+=======+==========================+
| Name              | Value | Description              |
+===================+=======+==========================+
| ChaCha20/Poly1305 |   24  | ChaCha20/Poly1305 w/     |
|                   |       | 256-bit key, 128-bit tag |
+-------------------+-------+--------------------------+

Table 7: Algorithm Value for ChaCha20/Poly1305

Keys may be obtained from either a key structure or a recipient structure. Implementations that are encrypting or decrypting MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved.

When using a COSE key for this algorithm, the following checks are made:

  • The "kty" field MUST be present, and it MUST be "Symmetric".
  • If the "alg" field is present, it MUST match the ChaCha20/Poly1305 algorithm being used.
  • If the "key_ops" field is present, it MUST include "encrypt" or "wrap key" when encrypting.
  • If the "key_ops" field is present, it MUST include "decrypt" or "unwrap key" when decrypting.

4.3.1. Security Considerations for ChaCha20/Poly1305 ๐Ÿ’œ

The key and nonce values MUST be a unique pair for every invocation of the algorithm. Nonce counters are considered to be an acceptable way of ensuring that they are unique.

A more recent analysis in [ROBUST] indicates that the number of failed decryptions needs to be taken into account as part of determining when a key rollover is to be done. Following the recommendation in DTLS (Section 4.5.3 of [RFC9147]), the number of failed message decryptions should be limited to 2^36.

[RFC8446] notes that the (64-bit) record sequence number would wrap before the safety limit is reached for ChaCha20/Poly1305. COSE implementations should not send more than 2^64 messages encrypted using a single ChaCha20/Poly1305 key.

5. Key Derivation Functions (KDFs) ๐ŸŒˆ

Section 8.4 of [RFC9052] contains a generic description of key derivation functions. This document defines a single context structure and a single KDF. These elements are used for all of the recipient algorithms defined in this document that require a KDF process. These algorithms are defined in Sections 6.1.2, 6.3.1, and 6.4.1 ๐Ÿ‘‘

5.1. HMAC-Based Extract-and-Expand Key Derivation Function (HKDF) ๐Ÿฆ‹

Okay bestie, the HKDF key derivation algorithm is defined in [RFC5869] and [HKDF]. ๐Ÿ’–

The HKDF algorithm takes these inputs:

  • secret: A shared value that is secret. Secrets can be previously shared, or they can be derived from things like a Diffie-Hellman (DH) key agreement. ๐Ÿ”
  • salt: An optional value that is used to change the generation process. The salt can be public or private. If the salt is public and carried in the message, then the "salt" algorithm header parameter defined in Table 9 is used. [RFC5869] suggests that the salt be the same length as the underlying hash value, but ANY positive salt length improves security, because different key values get generated. โœจ This parameter is protected by being included in the key computation, so it doesn't need to be authenticated separately. The salt value doesn't need to be unique for every message sent. ๐ŸŒธ
  • length: The number of bytes of output that need to be generated. ๐Ÿ“
  • context information: Information that describes the context where the resulting value will be used. Making it specific to that context means the resulting material is always tied to that usage. The context structure defined in Section 5.2 is what the KDFs in this document use. ๐Ÿงš
  • PRF: The underlying pseudorandom function used in the HKDF algorithm. The PRF is encoded into the HKDF algorithm selection. ๐Ÿ“

HKDF is defined to use HMAC as the underlying PRF. However, it's possible to use other functions in the same construct to get a different KDF that's more appropriate in the constrained world. Specifically, you can use AES-CBC-MAC as the PRF for the expand step, but not for the extract step. When you have a good random shared secret of the correct length, the extract step can be skipped. For the AES algorithm versions, the extract step is always skipped. ๐Ÿ’…

The extract step can't be skipped if the secret isn't uniformly random, for example if it's the result of an ECDH key agreement step. This means the AES HKDF version can't be used with ECDH. ๐Ÿ™ˆ If the extract step is skipped, the "salt" value isn't used as part of the HKDF functionality.

The algorithms defined in this document are found in Table 8. ๐Ÿ‘‘

       +==============+===================+========================+
       | Name         | PRF               | Description            |
       +==============+===================+========================+
       | HKDF SHA-256 | HMAC with SHA-256 | HKDF using HMAC        |
       |              |                   | SHA-256 as the PRF     |
       +--------------+-------------------+------------------------+
       | HKDF SHA-512 | HMAC with SHA-512 | HKDF using HMAC        |
       |              |                   | SHA-512 as the PRF     |
       +--------------+-------------------+------------------------+
       | HKDF AES-    | AES-CBC-MAC-128   | HKDF using AES-MAC as  |
       | MAC-128      |                   | the PRF w/ 128-bit key |
       +--------------+-------------------+------------------------+
       | HKDF AES-    | AES-CBC-MAC-256   | HKDF using AES-MAC as  |
       | MAC-256      |                   | the PRF w/ 256-bit key |
       +--------------+-------------------+------------------------+

                          Table 8: HKDF Algorithms
    +======+=======+======+============================+=============+
    | Name | Label | Type | Algorithm                  | Description |
    +======+=======+======+============================+=============+
    | salt | -20   | bstr | direct+HKDF-SHA-256,       | Random salt |
    |      |       |      | direct+HKDF-SHA-512,       |             |
    |      |       |      | direct+HKDF-AES-128,       |             |
    |      |       |      | direct+HKDF-AES-256, ECDH- |             |
    |      |       |      | ES+HKDF-256, ECDH-ES+HKDF- |             |
    |      |       |      | 512, ECDH-SS+HKDF-256,     |             |
    |      |       |      | ECDH-SS+HKDF-512, ECDH-    |             |
    |      |       |      | ES+A128KW, ECDH-ES+A192KW, |             |
    |      |       |      | ECDH-ES+A256KW, ECDH-      |             |
    |      |       |      | SS+A128KW, ECDH-SS+A192KW, |             |
    |      |       |      | ECDH-SS+A256KW             |             |
    +------+-------+------+----------------------------+-------------+

                    Table 9: HKDF Algorithm Parameters

5.2. Context Information Structure ๐ŸŽ€

The context information structure is what makes the derived keying material "bound" to the context of the transaction, so it can't be floating around unattached. ๐Ÿฆ‹ The one used here is based on the one defined in [SP800-56A]. Since CBOR does the encoding, we automatically get the same type and length separation of fields that ASN.1 gives us. That means there's no need to encode lengths for the base elements, which is what the encoding used in JSON Object Signing and Encryption (JOSE) does (Section 4.6.2 of [RFC7518]). Literally so efficient. ๐Ÿซถ

The context information structure refers to PartyU and PartyV as the two parties doing the key derivation. Unless the application protocol defines it differently, we assign PartyU to the entity creating the message and PartyV to the entity receiving it. Defining this association means different keys get derived for each direction, because the context information is different in each direction. ๐ŸŒˆ

The context structure is built from information that both entities already know. That information can come from a few different places:

  • Fields can be defined by the application. This is commonly used to assign fixed names to parties, but it can be used for other things too, like nonces. ๐Ÿ“
  • Fields can be defined by usage of the output. Examples are the algorithm and the key size being generated. โญ
  • Fields can be defined by parameters from the message. We define a set of header parameters in Table 10 that can carry the values associated with the context structure. Examples are identities and nonce values. These header parameters are designed to be placed in the unprotected bucket of the recipient structure. They don't need to be in the protected bucket, since they're already included in the cryptographic computation by virtue of being in the context structure. Iconic, no notes. ๐Ÿ’œ
   +==========+=======+======+===========================+=============+
   | Name     | Label | Type | Algorithm                 | Description |
   +==========+=======+======+===========================+=============+
   | PartyU   | -21   | bstr | direct+HKDF-SHA-256,      | PartyU      |
   | identity |       |      | direct+HKDF-SHA-512,      | identity    |
   |          |       |      | direct+HKDF-AES-128,      | information |
   |          |       |      | direct+HKDF-AES-256,      |             |
   |          |       |      | ECDH-ES+HKDF-256,         |             |
   |          |       |      | ECDH-ES+HKDF-512,         |             |
   |          |       |      | ECDH-SS+HKDF-256,         |             |
   |          |       |      | ECDH-SS+HKDF-512,         |             |
   |          |       |      | ECDH-ES+A128KW,           |             |
   |          |       |      | ECDH-ES+A192KW,           |             |
   |          |       |      | ECDH-ES+A256KW,           |             |
   |          |       |      | ECDH-SS+A128KW,           |             |
   |          |       |      | ECDH-SS+A192KW,           |             |
   |          |       |      | ECDH-SS+A256KW            |             |
   +----------+-------+------+---------------------------+-------------+
   | PartyU   | -22   | bstr | direct+HKDF-SHA-256,      | PartyU      |
   | nonce    |       | /    | direct+HKDF-SHA-512,      | provided    |
   |          |       | int  | direct+HKDF-AES-128,      | nonce       |
   |          |       |      | direct+HKDF-AES-256,      |             |
   |          |       |      | ECDH-ES+HKDF-256,         |             |
   |          |       |      | ECDH-ES+HKDF-512,         |             |
   |          |       |      | ECDH-SS+HKDF-256,         |             |
   |          |       |      | ECDH-SS+HKDF-512,         |             |
   |          |       |      | ECDH-ES+A128KW,           |             |
   |          |       |      | ECDH-ES+A192KW,           |             |
   |          |       |      | ECDH-ES+A256KW,           |             |
   |          |       |      | ECDH-SS+A128KW,           |             |
   |          |       |      | ECDH-SS+A192KW,           |             |
   |          |       |      | ECDH-SS+A256KW            |             |
   +----------+-------+------+---------------------------+-------------+
   | PartyU   | -23   | bstr | direct+HKDF-SHA-256,      | PartyU      |
   | other    |       |      | direct+HKDF-SHA-512,      | other       |
   |          |       |      | direct+HKDF-AES-128,      | provided    |
   |          |       |      | direct+HKDF-AES-256,      | information |
   |          |       |      | ECDH-ES+HKDF-256,         |             |
   |          |       |      | ECDH-ES+HKDF-512,         |             |
   |          |       |      | ECDH-SS+HKDF-256,         |             |
   |          |       |      | ECDH-SS+HKDF-512,         |             |
   |          |       |      | ECDH-ES+A128KW,           |             |
   |          |       |      | ECDH-ES+A192KW,           |             |
   |          |       |      | ECDH-ES+A256KW,           |             |
   |          |       |      | ECDH-SS+A128KW,           |             |
   |          |       |      | ECDH-SS+A192KW,           |             |
   |          |       |      | ECDH-SS+A256KW            |             |
   +----------+-------+------+---------------------------+-------------+
   | PartyV   | -24   | bstr | direct+HKDF-SHA-256,      | PartyV      |
   | identity |       |      | direct+HKDF-SHA-512,      | identity    |
   |          |       |      | direct+HKDF-AES-128,      | information |
   |          |       |      | direct+HKDF-AES-256,      |             |
   |          |       |      | ECDH-ES+HKDF-256,         |             |
   |          |       |      | ECDH-ES+HKDF-512,         |             |
   |          |       |      | ECDH-SS+HKDF-256,         |             |
   |          |       |      | ECDH-SS+HKDF-512,         |             |
   |          |       |      | ECDH-ES+A128KW,           |             |
   |          |       |      | ECDH-ES+A192KW,           |             |
   |          |       |      | ECDH-ES+A256KW,           |             |
   |          |       |      | ECDH-SS+A128KW,           |             |
   |          |       |      | ECDH-SS+A192KW,           |             |
   |          |       |      | ECDH-SS+A256KW            |             |
   +----------+-------+------+---------------------------+-------------+
   | PartyV   | -25   | bstr | direct+HKDF-SHA-256,      | PartyV      |
   | nonce    |       | /    | direct+HKDF-SHA-512,      | provided    |
   |          |       | int  | direct+HKDF-AES-128,      | nonce       |
   |          |       |      | direct+HKDF-AES-256,      |             |
   |          |       |      | ECDH-ES+HKDF-256,         |             |
   |          |       |      | ECDH-ES+HKDF-512,         |             |
   |          |       |      | ECDH-SS+HKDF-256,         |             |
   |          |       |      | ECDH-SS+HKDF-512,         |             |
   |          |       |      | ECDH-ES+A128KW,           |             |
   |          |       |      | ECDH-ES+A192KW,           |             |
   |          |       |      | ECDH-ES+A256KW,           |             |
   |          |       |      | ECDH-SS+A128KW,           |             |
   |          |       |      | ECDH-SS+A192KW,           |             |
   |          |       |      | ECDH-SS+A256KW            |             |
   +----------+-------+------+---------------------------+-------------+
   | PartyV   | -26   | bstr | direct+HKDF-SHA-256,      | PartyV      |
   | other    |       |      | direct+HKDF-SHA-512,      | other       |
   |          |       |      | direct+HKDF-AES-128,      | provided    |
   |          |       |      | direct+HKDF-AES-256,      | information |
   |          |       |      | ECDH-ES+HKDF-256,         |             |
   |          |       |      | ECDH-ES+HKDF-512,         |             |
   |          |       |      | ECDH-SS+HKDF-256,         |             |
   |          |       |      | ECDH-SS+HKDF-512,         |             |
   |          |       |      | ECDH-ES+A128KW,           |             |
   |          |       |      | ECDH-ES+A192KW,           |             |
   |          |       |      | ECDH-ES+A256KW,           |             |
   |          |       |      | ECDH-SS+A128KW,           |             |
   |          |       |      | ECDH-SS+A192KW,           |             |
   |          |       |      | ECDH-SS+A256KW            |             |
   +----------+-------+------+---------------------------+-------------+

                   Table 10: Context Algorithm Parameters

Okay so bestie, we're still hanging out in 5.2 Context Information Structure ๐ŸŽ€ We define a CBOR object to hold the context information, and it's called COSE_KDF_Context. It's built on a CBOR array type, and the fields go in this order, no shuffling ๐Ÿ’…

AlgorithmID: This field tells you which algorithm the key material is for. Usually that's a key wrap algorithm identifier or a content encryption algorithm identifier, and the values come from the "COSE Algorithms" registry. This field is required to be present ๐Ÿ”ฅ It's in the context info so that every algorithm gets its own key, even if everything else in the context is identical. Like, if algorithm A gets broken and finding its key is suddenly pretty easy, the key derived for algorithm B still won't match the key derived for algorithm A. Main character energy for sure ๐Ÿ‘‘

PartyUInfo: This field holds all the info about PartyU, encoded as a CBOR array. The elements show up in exactly the order listed below ๐Ÿฆ‹ They are:

  • identity: This is the identity info for PartyU, and identities can be assigned in one of two ways. The first is by roles, so a protocol might give the roles "client" and "server" to different entities, and each one uses the right label for whatever it sends or receives. The second is by using a name from a naming system, like DNS or X.509 names ๐ŸŒธ We define an algorithm parameter, "PartyU identity", that can carry identity info in the message. But honestly, identity is often already part of the protocol, so it can be inferred instead of spelled out. If identity info does get carried in the message, applications SHOULD have a way of validating the identity info they're given ๐Ÿซถ It doesn't have to be specified, and if it isn't, it's set to nil.
  • nonce: This holds a nonce value. The nonce can be implicit from the protocol, or it can be carried as a value in the unprotected header bucket โœจ We define an algorithm parameter, "PartyU nonce", that can carry this value in the message, but the application could also decide the nonce value and get it some other way. This option doesn't need to be specified, and if it's not needed, it's set to nil ๐Ÿงš
  • other: This holds other info that the protocol defines. Again, it doesn't need to be specified, and if it's not needed, it's set to nil ๐Ÿ’œ

PartyVInfo: This field holds info about PartyV. It's the same structure as PartyUInfo, just for PartyV ๐Ÿ’–

SuppPubInfo: This field has public info that both parties already know, and it's encoded as a CBOR array ๐ŸŒˆ

  • keyDataLength: This is set to the number of bits in the output value you want. Here's the tea: if algorithm A can use two different key lengths, the key derived for the longer size won't have the key for the shorter size sitting in it as a prefix ๐Ÿ˜ญ
  • protected: This field holds the protected parameter field. If there are no elements in the "protected" field, you use a zero-length bstr instead ๐Ÿ“
  • other: This one is free-form data that the application defines. For example, an application could use two different byte strings here so it can make different keys for a data stream versus a control stream ๐Ÿ”ฅ This field is optional and only shows up if the application defines a structure for this info. Applications that define this SHOULD use CBOR so the types and lengths are encoded correctly ๐Ÿ™ˆ

SuppPrivInfo: This field holds private info that's mutually known privately between the two parties. A pre-existing shared secret is a good example ๐Ÿ’€ (It could, for instance, be combined with an ECDH key agreement to give a secondary proof of identity, which is giving security genius โœจ) The field is optional and only shows up if the application defines a structure for this info. Applications that define this SHOULD use CBOR so the types and lengths are correctly included ๐ŸŒธ

The following CDDL fragment matches everything I just gushed about ๐ŸŽ€

PartyInfo = (
    identity : bstr / nil,
    nonce : bstr / int / nil,
    other : bstr / nil
)
COSE_KDF_Context = [
    AlgorithmID : int / tstr,
    PartyUInfo : [ PartyInfo ],
    PartyVInfo : [ PartyInfo ],
    SuppPubInfo : [
        keyDataLength : uint,
        protected : empty_or_serialized_map,
        ? other : bstr
    ],
    ? SuppPrivInfo : bstr
]

6. Content Key Distribution Methods โœจ

Okay bestie, time for the part where we figure out how the keys actually get handed out ๐Ÿ’… Section 8.5 of [RFC9052] has the generic description of content key distribution methods, and this document is where the identifiers and usage for a bunch of them get defined ๐ŸŽ€

6.1. Direct Encryption

Direct encryption is defined in Section 8.5.1 of [RFC9052] ๐Ÿฆ‹ The info about how to fill in the COSE_Recipient structure is all over there, so go look if you need it!

6.1.1. Direct Key

This recipient algorithm is the simplest one, and honestly so iconic ๐Ÿ“ The identified key is directly used as the key for the next layer down in the message. There are no algorithm parameters defined for this algorithm. The algorithm identifier value is assigned in Table 11.

When this algorithm is used, the "protected" field MUST be zero length. The key type MUST be "Symmetric".

    +========+=======+============================================+
    | Name   | Value | Description                                |
    +========+=======+============================================+
    | direct |   -6  | Direct use of content encryption key (CEK) |
    +--------+-------+--------------------------------------------+

                          Table 11: Direct Key

6.1.1.1. Security Considerations for Direct Key

Okay this one has some real drama, so pay attention ๐Ÿ˜ญ This recipient algorithm has several potential problems that need to be considered:

  • These keys need to have some method of being regularly updated over time. All of the content encryption algorithms specified in this document have limits on how many times a key can be used without significant loss of security. ๐Ÿ’€
  • These keys need to be dedicated to a single algorithm. There have been a number of attacks developed over time when a single key is used for multiple different algorithms. One example of this is the use of a single key for both the CBC encryption mode and the CBC-MAC authentication mode. ๐Ÿ™ˆ
  • Breaking one message means all messages are broken. If an adversary succeeds in determining the key for a single message, then the key for all messages is also determined. Not a vibe, bestie ๐Ÿ˜ญ๐Ÿ”ฅ

6.1.2. Direct Key with KDF

These recipient algorithms take a common shared secret between the two parties and apply the HKDF function (Section 5.1), using the context structure defined in Section 5.2, to transform the shared secret into the CEK โœจ The "protected" field can be of nonzero length. Either the "salt" parameter for HKDF (Table 9) or the "PartyU nonce" parameter for the context structure (Table 10) MUST be present (both can be present if desired). The value in the "salt"/"nonce" parameter can be generated either randomly or deterministically. The requirement is that it be a unique value for the shared secret in question.

If the salt/nonce value is generated randomly, then it is suggested that the length of the random value be the same length as the output of the hash function underlying HKDF. While there is no way to guarantee that it will be unique, there is a high probability that it will be unique. If the salt/nonce value is generated deterministically, it can be guaranteed to be unique, and thus there is no length requirement. Deterministic is giving certainty, random is giving vibes ๐ŸŒˆ

A new IV must be used for each message if the same key is used. The IV can be modified in a predictable manner, a random manner, or an unpredictable manner (e.g., encrypting a counter).

The IV used for a key can also be generated using the same HKDF functionality used to generate the key. If HKDF is used for generating the IV, the algorithm identifier is set to 34 ("IV-GENERATION") ๐Ÿงš

The set of algorithms defined in this document can be found in Table 12.

    +=====================+=======+==============+=====================+
    | Name                | Value | KDF          | Description         |
    +=====================+=======+==============+=====================+
    | direct+HKDF-SHA-256 |  -10  | HKDF SHA-256 | Shared secret w/    |
    |                     |       |              | HKDF and SHA-256    |
    +---------------------+-------+--------------+---------------------+
    | direct+HKDF-SHA-512 |  -11  | HKDF SHA-512 | Shared secret w/    |
    |                     |       |              | HKDF and SHA-512    |
    +---------------------+-------+--------------+---------------------+
    | direct+HKDF-AES-128 |  -12  | HKDF AES-    | Shared secret w/    |
    |                     |       | MAC-128      | AES-MAC 128-bit key |
    +---------------------+-------+--------------+---------------------+
    | direct+HKDF-AES-256 |  -13  | HKDF AES-    | Shared secret w/    |
    |                     |       | MAC-256      | AES-MAC 256-bit key |
    +---------------------+-------+--------------+---------------------+

                      Table 12: Direct Key with KDF

When using a COSE key for this algorithm, the following checks are made:

  • The "kty" field MUST be present, and it MUST be "Symmetric".
  • If the "alg" field is present, it MUST match the algorithm being used.
  • If the "key_ops" field is present, it MUST include "derive key" or "derive bits". ๐Ÿ”

6.1.2.1. Security Considerations for Direct Key with KDF

Real talk, this part is a lot ๐Ÿ˜ญ The shared secret needs to have some method of being regularly updated over time. The shared secret forms the basis of trust. Although not used directly, it should still be subject to scheduled rotation.

These methods do not provide for perfect forward secrecy, as the same shared secret is used for all of the keys generated. However, if the key for any single message is discovered, only the message or series of messages using that derived key are compromised. A new key derivation step will generate a new key that requires the same amount of work to get the key. ๐Ÿ›ก๏ธ

6.2. Key Wrap

Key wrap is defined in Section 8.5.2 of [RFC9052]. The info about how to fill in the COSE_Recipient structure is detailed there ๐ŸŽ€

6.2.1. AES Key Wrap

The AES Key Wrap algorithm is defined in [RFC3394]. This algorithm uses an AES key to wrap a value that is a multiple of 64 bits. As such, it can be used to wrap a key for any of the content encryption algorithms defined in this document. The algorithm requires a single fixed parameter, the initial value. This is fixed to the value specified in Section 2.2.3.1 of [RFC3394]. There are no public key parameters that vary on a per-invocation basis. The protected header bucket MUST be empty.

Keys may be obtained from either a key structure or a recipient structure. Implementations that are encrypting or decrypting MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved. ๐Ÿซถ

When using a COSE key for this algorithm, the following checks are made:

  • The "kty" field MUST be present, and it MUST be "Symmetric".
  • If the "alg" field is present, it MUST match the AES Key Wrap algorithm being used.
  • If the "key_ops" field is present, it MUST include "encrypt" or "wrap key" when encrypting.
  • If the "key_ops" field is present, it MUST include "decrypt" or "unwrap key" when decrypting. ๐Ÿ”‘
        +========+=======+==========+=============================+
        | Name   | Value | Key Size | Description                 |
        +========+=======+==========+=============================+
        | A128KW |   -3  |   128    | AES Key Wrap w/ 128-bit key |
        +--------+-------+----------+-----------------------------+
        | A192KW |   -4  |   192    | AES Key Wrap w/ 192-bit key |
        +--------+-------+----------+-----------------------------+
        | A256KW |   -5  |   256    | AES Key Wrap w/ 256-bit key |
        +--------+-------+----------+-----------------------------+

                  Table 13: AES Key Wrap Algorithm Values

6.2.1.1. Security Considerations for AES Key Wrap

The shared secret needs to have some method of being regularly updated over time. The shared secret is the basis of trust. Yes, rotation is still a whole thing, bestie ๐Ÿ’€

6.3. Direct Key Agreement

Direct Key Agreement is defined in Section 8.5.4 of [RFC9052]. The info about how to fill in the COSE_Recipient structure is detailed there โœจ

6.3.1. Direct ECDH โœจ

Okay so the math behind ECDH lives in [RFC6090], and this doc takes that and glams it up so it works with the two curves from [RFC7748] ๐Ÿ’…๐Ÿฆ‹

ECDH has a few settings you need to get right:

  • Curve Type/Curve: The curve you pick decides how big the shared secret is and also the actual math used to compute it. It also controls how a point on the curve gets represented and what happens with the identity points. This spec lets you use several curves, and the set is listed in Table 18. The math comes from the curve, not from ECDH itself, so you don't need a brand-new algorithm for every curve ๐ŸŒˆ
  • Computed Secret to Shared Secret: Once you have the computed secret, it needs to become a byte string before it goes into the KDF. The x-coordinate is used for every curve in this document. For X25519 and X448, the value gets used directly, since it's already a byte string of a known length ๐Ÿงš For P-256, P-384, and P-521, the x-coordinate goes through the I2OSP function from [RFC8017], using the same computation for n that's defined in Section 2.1.
  • Ephemeral-Static or Static-Static: The sender can do the key agreement with either a static key or an ephemeral key. When it uses ephemeral keys, the sender MUST generate a brand-new ephemeral key for every key agreement operation. That ephemeral key goes in the "ephemeral key" parameter, and it MUST be present for every algorithm identifier that uses ephemeral keys ๐Ÿ’–

When it uses static keys, the sender MUST either generate a new random value or create a unique value to use as a KDF input. For the KDFs used here, that means either the "salt" parameter for HKDF (Table 9) or the "PartyU nonce" parameter in the context structure (Table 10) MUST be present. Both can show up if you want ๐Ÿซถ Whatever goes in that parameter MUST be unique for the pair of keys being used. Using a global counter that goes up for every Static-Static operation and using its value is fine. Just be careful to save that counter to permanent storage in a way that stops it from getting reused ๐Ÿ˜ญ

When you use static keys, the static key should be identified to the recipient. You can do that by providing the key itself ("static key") or a key identifier for it ("static key id"). Both of these header parameters are defined in Table 15 ๐Ÿ”ฅ

  • Key Derivation Algorithm: The result of an ECDH key agreement isn't a uniformly random secret, so it needs to go through a KDF to become a usable key. Running it through the KDF also lets you mix in context: how the key is going to be used, plus one-time material for Static-Static agreement. Every algorithm in this document uses one of the HKDF algorithms from Section 5.1, with the context structure from Section 5.2 ๐Ÿ‘‘
  • Key Wrap Algorithm: No key wrap algorithm is used here. Table 14 shows this as "none". The key size for the context structure is the size of the content layer encryption algorithm ๐Ÿ“

COSE doesn't define an Ephemeral-Ephemeral version, and the reason is kinda iconic: COSE isn't an online protocol on its own, so it has no way to set up ephemeral secrets on both sides ๐Ÿ™ˆ The expectation is that a protocol sets up the secrets for both sides and then COSE uses them as Static-Static. Or the protocol generates a shared secret and direct encryption gets used instead.

The direct ECDH algorithms defined in this document are listed in Table 14:

+==========+=======+=========+==================+=====+=============+
|Name      | Value | KDF     | Ephemeral-Static |Key  |Description  |
|          |       |         |                  |Wrap |             |
+==========+=======+=========+==================+=====+=============+
|ECDH-ES + | -25   | HKDF -- | yes              |none |ECDH ES w/   |
|HKDF-256  |       | SHA-256 |                  |     |HKDF --      |
|          |       |         |                  |     |generate key |
|          |       |         |                  |     |directly     |
+----------+-------+---------+------------------+-----+-------------+
|ECDH-ES + | -26   | HKDF -- | yes              |none |ECDH ES w/   |
|HKDF-512  |       | SHA-512 |                  |     |HKDF --      |
|          |       |         |                  |     |generate key |
|          |       |         |                  |     |directly     |
+----------+-------+---------+------------------+-----+-------------+
|ECDH-SS + | -27   | HKDF -- | no               |none |ECDH SS w/   |
|HKDF-256  |       | SHA-256 |                  |     |HKDF --      |
|          |       |         |                  |     |generate key |
|          |       |         |                  |     |directly     |
+----------+-------+---------+------------------+-----+-------------+
|ECDH-SS + | -28   | HKDF -- | no               |none |ECDH SS w/   |
|HKDF-512  |       | SHA-512 |                  |     |HKDF --      |
|          |       |         |                  |     |generate key |
|          |       |         |                  |     |directly     |
+----------+-------+---------+------------------+-----+-------------+

Table 14: ECDH Algorithm Values

+===========+=======+==========+===================+=============+
| Name      | Label | Type     | Algorithm         | Description |
+===========+=======+==========+===================+=============+
| ephemeral | -1    | COSE_Key | ECDH-ES+HKDF-256, | Ephemeral   |
| key       |       |          | ECDH-ES+HKDF-512, | public key  |
|           |       |          | ECDH-ES+A128KW,   | for the     |
|           |       |          | ECDH-ES+A192KW,   | sender      |
|           |       |          | ECDH-ES+A256KW    |             |
+-----------+-------+----------+-------------------+-------------+
| static    | -2    | COSE_Key | ECDH-SS+HKDF-256, | Static      |
| key       |       |          | ECDH-SS+HKDF-512, | public key  |
|           |       |          | ECDH-SS+A128KW,   | for the     |
|           |       |          | ECDH-SS+A192KW,   | sender      |
|           |       |          | ECDH-SS+A256KW    |             |
+-----------+-------+----------+-------------------+-------------+
| static    | -3    | bstr     | ECDH-SS+HKDF-256, | Static      |
| key id    |       |          | ECDH-SS+HKDF-512, | public key  |
|           |       |          | ECDH-SS+A128KW,   | identifier  |
|           |       |          | ECDH-SS+A192KW,   | for the     |
|           |       |          | ECDH-SS+A256KW    | sender      |
+-----------+-------+----------+-------------------+-------------+

Table 15: ECDH Algorithm Parameters

This document defines these algorithms for use with the curves P-256, P-384, P-521, X25519, and X448. Implementations MUST verify that the key type and curve are correct ๐Ÿง Different curves are limited to different key types. Implementations MUST also verify that the curve and algorithm suit the entities involved โœจ

When you use a COSE key with this algorithm, these checks happen:

  • The "kty" field MUST be present, and it MUST be "EC2" or "OKP" ๐Ÿ’…
  • If the "alg" field is present, it MUST match the key agreement algorithm being used.
  • If the "key_ops" field is present, it MUST include "derive key" or "derive bits" for the private key.
  • If the "key_ops" field is present, it MUST be empty for the public key.

6.3.1.1. Security Considerations for ECDH ๐Ÿ”

There's a way to check that points coming from external entities are valid. For the "EC2" key format, you can do that by checking that the x and y values form a point on the curve. For the "OKP" format, there's no simple way to do point validation, so that's the tricky one ๐Ÿ˜ฌ

People did think about requiring that both entities' public keys be included in the key derivation process, the way Section 6.1 of [RFC7748] recommends. They didn't go with it, because COSE is used in a store-and-forward format and not in online key exchange. For this to be a real problem, either the receiver's public key has to be picked maliciously or the sender has to be malicious. And honestly, if either of those happens, all security is gone anyway ๐Ÿ’€

A proof of possession of the private key tied to a public key is recommended whenever a key moves from untrusted to trusted. That can happen because the end user says so, or because the entity responsible for making trust statements about keys does ๐Ÿ”ฅ

6.4. Key Agreement with Key Wrap ๐ŸŽ€

Key Agreement with Key Wrap is defined in Section 8.5.5 of [RFC9052]. If you want to know how to fill in the COSE_Recipient structure, the details are all there ๐Ÿ“š

6.4.1. ECDH with Key Wrap โœจ

okay so these algorithms are all defined in Table 16 ๐Ÿ’…

ECDH with Key Agreement is parameterized by the same header parameters as plain ECDH (see Section 6.3.1), with a few tweaks ๐ŸŽ€

  • Key Wrap Algorithm: any of the key wrap algorithms from Section 6.2 are supported โœจ The size of the key used for the key wrap algorithm gets fed into the KDF ๐Ÿ”ฅ The full set of identifiers lives in Table 16 ๐Ÿงš
+=========+=====+=========+==================+========+=============+
|Name     |Value| KDF     | Ephemeral-Static |Key Wrap|Description  |
+=========+=====+=========+==================+========+=============+
|ECDH-ES +|-29  | HKDF -- | yes              |A128KW  |ECDH ES w/   |
|A128KW   |     | SHA-256 |                  |        |HKDF and AES |
|         |     |         |                  |        |Key Wrap w/  |
|         |     |         |                  |        |128-bit key  |
+---------+-----+---------+------------------+--------+-------------+
|ECDH-ES +|-30  | HKDF -- | yes              |A192KW  |ECDH ES w/   |
|A192KW   |     | SHA-256 |                  |        |HKDF and AES |
|         |     |         |                  |        |Key Wrap w/  |
|         |     |         |                  |        |192-bit key  |
+---------+-----+---------+------------------+--------+-------------+
|ECDH-ES +|-31  | HKDF -- | yes              |A256KW  |ECDH ES w/   |
|A256KW   |     | SHA-256 |                  |        |HKDF and AES |
|         |     |         |                  |        |Key Wrap w/  |
|         |     |         |                  |        |256-bit key  |
+---------+-----+---------+------------------+--------+-------------+
|ECDH-SS +|-32  | HKDF -- | no               |A128KW  |ECDH SS w/   |
|A128KW   |     | SHA-256 |                  |        |HKDF and AES |
|         |     |         |                  |        |Key Wrap w/  |
|         |     |         |                  |        |128-bit key  |
+---------+-----+---------+------------------+--------+-------------+
|ECDH-SS +|-33  | HKDF -- | no               |A192KW  |ECDH SS w/   |
|A192KW   |     | SHA-256 |                  |        |HKDF and AES |
|         |     |         |                  |        |Key Wrap w/  |
|         |     |         |                  |        |192-bit key  |
+---------+-----+---------+------------------+--------+-------------+
|ECDH-SS +|-34  | HKDF -- | no               |A256KW  |ECDH SS w/   |
|A256KW   |     | SHA-256 |                  |        |HKDF and AES |
|         |     |         |                  |        |Key Wrap w/  |
|         |     |         |                  |        |256-bit key  |
+---------+-----+---------+------------------+--------+-------------+

               Table 16: ECDH Algorithm Values with Key Wrap

when you're using a COSE key for this algorithm, these checks happen ๐Ÿ”

  • The kty field MUST be present, and it MUST be EC2 or OKP. ๐Ÿ’–
  • If the alg field is present, it MUST match the key agreement algorithm being used. ๐Ÿซถ
  • If the key_ops field is present, it MUST include derive key or derive bits for the private key. ๐Ÿ”
  • If the key_ops field is present, it MUST be empty for the public key. ๐ŸŒธ

7. Key Object Parameters โœจ

the COSE_Key object gives you a way to hold a single key object ๐ŸŽ€ but the members for each individual key type still have to be defined, and this section is where we do that for an initial set ๐Ÿงš

for each key type we define both public and private members ๐Ÿ’œ The public members are what gets sent to other people so they can use the key ๐Ÿฆ‹ Private members let people archive keys ๐Ÿ—„๏ธ There are some situations where private keys might get handed out to entities in a protocol, though ๐Ÿ‘€ For example: entities with poor random number generation, centralized key creation for multicast-type operations, and protocols where a shared secret is used as a bearer token for authorization ๐Ÿ™ˆ

key types are identified by the kty member of the COSE_Key object ๐Ÿ”‘ In this document we define four values for that member ๐Ÿ’…

          +===========+=======+==========================+
          | Name      | Value | Description              |
          +===========+=======+==========================+
          | OKP       |   1   | Octet Key Pair           |
          +-----------+-------+--------------------------+
          | EC2       |   2   | Elliptic Curve Keys w/   |
          |           |       | x- and y-coordinate pair |
          +-----------+-------+--------------------------+
          | Symmetric |   4   | Symmetric Keys           |
          +-----------+-------+--------------------------+
          | Reserved  |   0   | This value is reserved   |
          +-----------+-------+--------------------------+

                     Table 17: Key Type Values

7.1. Elliptic Curve Keys ๐Ÿงš

okay so there are two different key structures for elliptic curve keys ๐ŸŒˆ One version uses both an x-coordinate and a y-coordinate, possibly with point compression (EC2) ๐Ÿ’ซ That's the conventional elliptic curve (EC) point representation used in [RFC5480] ๐Ÿ“œ The other version uses only the x-coordinate, because the y-coordinate is either recomputed or not needed for the key agreement operation (OKP) ๐Ÿฆ‹

Applications MUST check that the curve and the key type are consistent, and reject a key if they are not. ๐Ÿšซ

+=========+=======+==========+=====================================+
| Name    | Value | Key Type | Description                         |
+=========+=======+==========+=====================================+
| P-256   |   1   |   EC2    | NIST P-256, also known as secp256r1 |
+---------+-------+----------+-------------------------------------+
| P-384   |   2   |   EC2    | NIST P-384, also known as secp384r1 |
+---------+-------+----------+-------------------------------------+
| P-521   |   3   |   EC2    | NIST P-521, also known as secp521r1 |
+---------+-------+----------+-------------------------------------+
| X25519  |   4   |   OKP    | X25519 for use w/ ECDH only         |
+---------+-------+----------+-------------------------------------+
| X448    |   5   |   OKP    | X448 for use w/ ECDH only           |
+---------+-------+----------+-------------------------------------+
| Ed25519 |   6   |   OKP    | Ed25519 for use w/ EdDSA only       |
+---------+-------+----------+-------------------------------------+
| Ed448   |   7   |   OKP    | Ed448 for use w/ EdDSA only         |
+---------+-------+----------+-------------------------------------+

                    Table 18: Elliptic Curves

7.1.1. Double Coordinate Curves ๐Ÿ’œ

generally, protocols send elliptic-curve points as either the x-coordinate and y-coordinate, or the x-coordinate plus a sign bit for the y-coordinate ๐ŸŒธ The IETF hasn't recommended the latter encoding because of potential IPR issues ๐Ÿ˜ฌ That said, when you're operating in constrained environments, being able to shrink a message by not sending the y-coordinate can be seriously useful ๐Ÿ“

for EC keys with both coordinates, the kty member is set to 2 (EC2) โœจ The key parameters defined in this section are summarized in Table 19 ๐Ÿ’… The members defined for this key type are:

  • crv: this contains an identifier of the curve to be used with the key ๐ŸŒˆ The curves defined in this document for this key type can be found in Table 18 ๐Ÿงš Other curves may be registered in the future, and private curves can be used as well ๐Ÿ”ฎ
  • x: this contains the x-coordinate for the EC point ๐Ÿ“ The integer is converted to a byte string as defined in [SEC1] ๐Ÿซถ Leading-zero octets MUST be preserved. ๐ŸŒŸ
  • y: this contains either the sign bit or the value of the y-coordinate for the EC point ๐ŸŽ€ When encoding the value y, the integer is converted to a byte string (as defined in [SEC1]) and encoded as a CBOR bstr ๐Ÿ“ฆ Leading-zero octets MUST be preserved. ๐Ÿ’– Compressed point encoding is also supported ๐Ÿฆ‹ Compute the sign bit as laid out in the Elliptic-Curve-Point-to-Octet-String Conversion function of [SEC1] โœจ If the sign bit is zero, encode y as a CBOR false value; otherwise, encode y as a CBOR true value ๐Ÿ” The encoding of the infinity point is not supported ๐Ÿšซ
  • d: this contains the private key ๐Ÿ”

for public keys, it is REQUIRED that crv, x, and y be present in the structure ๐Ÿ’Œ For private keys, it is REQUIRED that crv and d be present in the structure ๐Ÿ—๏ธ For private keys, it is RECOMMENDED that x and y also be present, but they can be recomputed from the required elements, and omitting them saves on space ๐Ÿฐ

 +======+======+=======+========+=================================+
 | Key  | Name | Label | CBOR   | Description                     |
 | Type |      |       | Type   |                                 |
 +======+======+=======+========+=================================+
 |  2   | crv  |   -1  | int /  | EC identifier -- Taken from the |
 |      |      |       | tstr   | "COSE Elliptic Curves" registry |
 +------+------+-------+--------+---------------------------------+
 |  2   |  x   |   -2  | bstr   | x-coordinate                    |
 +------+------+-------+--------+---------------------------------+
 |  2   |  y   |   -3  | bstr / | y-coordinate                    |
 |      |      |       | bool   |                                 |
 +------+------+-------+--------+---------------------------------+
 |  2   |  d   |   -4  | bstr   | Private key                     |
 +------+------+-------+--------+---------------------------------+

                     Table 19: EC Key Parameters

7.2. Octet Key Pair ๐Ÿฆ‹

okay so a brand new key type got created for Octet Key Pairs (OKPs) ๐Ÿ’– and the big thing to remember is: do NOT assume these keys are elliptic curves ๐Ÿ™ˆ this key type could totally be used for other curve types too (like math based on hyper-elliptic surfaces, which is giving very galaxy brain ๐ŸŒŒ).

the key parameters for this section are all summarized in Table 20 โœจ these are the members defined for this key type:

  • crv: this holds an identifier for the curve used with the key ๐Ÿ’… the curves defined in this document for this key type are in Table 18. other curves can be registered later, and private curves are allowed too ๐ŸŒˆ
  • x: this holds the public key ๐Ÿซถ the byte string has the public key as the algorithm defines it. (for X25519, it's internally a little-endian integer, so don't freak out ๐Ÿ˜ญ)
  • d: this holds the private key ๐Ÿ”

now the rules for which fields show up: for public keys, it is REQUIRED that "crv" and "x" be present in the structure ๐ŸŽ€ for private keys, it is REQUIRED that "crv" and "d" be present in the structure ๐Ÿ’œ and for private keys, it is RECOMMENDED that "x" also be present, BUT it can be recomputed from the required elements, so leaving it out saves space โœจ

   +======+==========+=======+=======+=================================+
   | Name |   Key    | Label | Type  | Description                     |
   |      |   Type   |       |       |                                 |
   +======+==========+=======+=======+=================================+
   | crv  |    1     |   -1  | int / | EC identifier -- Taken from the |
   |      |          |       | tstr  | "COSE Elliptic Curves" registry |
   +------+----------+-------+-------+---------------------------------+
   | x    |    1     |   -2  | bstr  | Public Key                      |
   +------+----------+-------+-------+---------------------------------+
   | d    |    1     |   -4  | bstr  | Private key                     |
   +------+----------+-------+-------+---------------------------------+

                    Table 20: Octet Key Pair Parameters

7.3. Symmetric Keys ๐Ÿ”‘

sometimes a symmetric key needs to be sent between entities, and this key structure is literally made for that ๐Ÿงš

for symmetric keys, the "kty" member is set to 4 ("Symmetric") ๐Ÿ’ซ the only member defined for this key type is:

  • k: this holds the value of the key ๐Ÿ—๏ธ

this key structure doesn't have a form that only contains public members (no vibes of "safe to share" here ๐Ÿ™…โ€โ™€๏ธ). because it's expected to be transmitted, you have to be super careful that it is NEVER sent accidentally or insecurely ๐Ÿ’€ for symmetric keys, it is REQUIRED that "k" be present in the structure.

             +======+==========+=======+======+=============+
             | Name | Key Type | Label | Type | Description |
             +======+==========+=======+======+=============+
             |  k   |    4     |   -1  | bstr | Key Value   |
             +------+----------+-------+------+-------------+

                    Table 21: Symmetric Key Parameters

8. COSE Capabilities ๐Ÿ‘‘

sometimes you need to specify what an algorithm or key type is capable of, and that's where capabilities come in ๐ŸŒธ there's a counterpart in the S/MIME world, where SMIMECapabilities is defined in Section 2.5.2 of [RFC8551]. this document does the same thing for COSE, so it's giving continuity โœจ

the algorithm identifier is NOT included in the capabilities data, because it should be encoded somewhere else in the message ๐Ÿ™ƒ the key type identifier IS included, since it's not expected to be encoded anywhere else.

there are two types of capabilities: ones for algorithms and ones for key types. once they're defined by registration with IANA, the list of capabilities for an algorithm or key type is immutable ๐ŸงŠ if a new capability is needed later, a new code point has to be assigned for it. as a general rule, capabilities map to algorithm-specific header parameters or key parameters, but they don't have to ๐Ÿฆ‹ the HSS-LMS key type capabilities below are an example of that, since they include the hash algorithm used.

the capability structure is an array of values, and what goes in it depends on the specific algorithm or key type ๐Ÿ’… for algorithm capabilities, the first element should always be a key type value if applicable, but items specific to a key (like a curve) should not be included in the algorithm capabilities. so if you want to list every capability for a device that does ECDH, you need every combination of algorithms and key pairs spelled out ๐Ÿ˜ฉ the last example in Section 8.3 shows this with a cross product between an array of algorithm capabilities and key type capabilities (see the ECDH-ES+A25KW element). for a key, the first element should be the key type value. yes this duplicates the key type value if you use both an algorithm and key capability, but the key type is needed to understand the rest of the values ๐Ÿง 

8.1. Assignments for Existing Algorithms ๐ŸŒˆ

for the current algorithms in the registry (other than IV-GENERATION), so the ones in this document plus the ones in [RFC8230], [RFC8778], and [RFC9021], the capabilities list is an array with ONE element: the key type (from the "COSE Key Types" Registry) โœจ it's expected that future registered algorithms could have zero, one, or multiple elements, so keep your eyes open ๐Ÿ‘€

8.2. Assignments for Existing Key Types ๐Ÿ’œ

there are a bunch of key types that already exist, and the following bit covers how to make the capability definition for those structures:

  • OKP, EC2: the list of capabilities is:
    • the key type value (1 for OKP or 2 for EC2) ๐Ÿ”ข
    • one curve for that key type from the "COSE Elliptic Curves" registry ๐ŸŒˆ
  • RSA: the list of capabilities is:
    • the key type value (3) ๐Ÿ”ข
  • Symmetric: the list of capabilities is:
    • the key type value (4) ๐Ÿ”ข
  • HSS-LMS: the list of capabilities is:
    • the key type value (5) ๐Ÿ”ข
    • the algorithm identifier for the underlying hash function from the "COSE Algorithms" registry ๐Ÿง
  • WalnutDSA: the list of capabilities is:
    • the key type value (6) ๐Ÿ”ข
    • the N value (group and matrix size) for the key, a uint ๐Ÿ“
    • the q value (finite field order) for the key, a uint ๐Ÿ“

8.3. Examples ๐ŸŽ€

capabilities can be used in a key derivation process so that both sides are using the same parameters ๐Ÿค the three examples below show different ways you might use parameters when you're specifying an application protocol:

  • Only an algorithm capability: this is useful if the protocol wants to require a specific algorithm, like ES256, but doesn't care which curve is used. this requires that the algorithm identifier be specified in the protocol. see the first example.
  • Only a key type capability: this is useful if the protocol wants to require a specific key type and curve, like P-256, but will accept any algorithm using that curve (e.g., both ECDSA and ECDH). see the second example.
  • Both algorithm and key type capabilities: this is used if the protocol needs to nail down ALL of the options around an algorithm, e.g., EdDSA with the curve Ed25519 ๐Ÿ’… like the first example, the algorithm identifier needs to be specified in the protocol. see the third example, which just concatenates the two capabilities together.
Algorithm ES256

0x8102                 / [2 \ EC2 \ ] /

Key type EC2 with P-256 curve:

0x820201               / [2 \ EC2 \, 1 \ P-256 \] /

ECDH-ES + A256KW with an X25519 curve:

0x8101820104           / [1 \ OKP \],[1 \ OKP \, 4 \ X25519 \] /

capabilities can also be used by an entity to advertise what it's capable of doing ๐Ÿ“ฃ the decoded example below is just ONE of many encodings that could be used for that purpose. each array element includes three fields: the algorithm identifier, one or more algorithm capabilities, and one or more key type capabilities.

[
 [-8 / EdDSA /,
   [1 / OKP key type /],
   [
     [1 / OKP /, 6 / Ed25519 / ],
     [1 /OKP/, 7 /Ed448 /]
   ]
 ],
 [-7 / ECDSA with SHA-256/,
   [2 /EC2 key type/],
   [
     [2 /EC2/, 1 /P-256/],
     [2 /EC2/, 3 /P-521/]
   ]
 ],
 [ -31 / ECDH-ES+A256KW/,
   [
     [ 2 /EC2/],
     [1 /OKP/ ]
   ],
   [
     [2 /EC2/, 1 /P-256/],
     [1 /OKP/, 4 / X25519/ ]
   ]
 ],
 [ 1 / A128GCM /,
   [ 4 / Symmetric / ],
   [ 4 / Symmetric /]
 ]
]

okay so reading the above:

  • the first element says the entity supports EdDSA with the curves Ed25519 and Ed448 ๐Ÿฆ‹
  • the second element says the entity supports ECDSA with SHA-256 with the curves P-256 and P-521 ๐ŸŒธ
  • the third element says the entity supports Ephemeral-Static ECDH using AES256 key wrap ๐Ÿ”ฅ it can do the P-256 curve with an EC2 key type, and the X25519 curve with an OKP key type
  • the last element says the entity supports AES-GCM of 128 bits for content encryption โœจ

the entity does NOT advertise support for any MAC algorithms ๐Ÿ™…โ€โ™€๏ธ

9. CBOR Encoding Restrictions ๐Ÿงš

this document limits the restrictions it puts on how the CBOR Encoder needs to work ๐Ÿ’– the new encoding restrictions line up with the Core Deterministic Encoding Requirements in Section 4.2.1 of RFC 8949 [STD94]. they've been narrowed down to these restrictions:

  • the restriction applies to the encoding of the COSE_KDF_Context ๐ŸŽ€
  • encoding MUST be done using definite lengths, and the length of the (encoded) argument MUST be the minimum possible length. this means the integer 1 is encoded as "0x01" and NOT "0x1801" ๐Ÿ™ˆ
  • applications MUST NOT generate messages with the same label used twice as a key in a single map. applications MUST NOT parse and process messages with the same label used twice as a key in a single map. applications can enforce the parse-and-process requirement by using parsers that fail the parse step, or by using parsers that pass all keys to the application, and the application does the check for duplicate keys ๐Ÿ”

10. IANA Considerations ๐ŸŒˆ

IANA has updated all COSE registries except for "COSE Header Parameters" and "COSE Key Common Parameters" so they point to this document instead of [RFC8152] โœจ

10.1. Changes to the "COSE Key Types" Registry ๐Ÿ—‚๏ธ

Okay so IANA added a brand new column to the "COSE Key Types" registry, and it's called "Capabilities" ๐Ÿ’…. It's been filled in using Table 22, which is right here:

            +=======+===========+============================+
            | Value | Name      | Capabilities               |
            +=======+===========+============================+
            | 1     | OKP       | [kty(1), crv]              |
            +-------+-----------+----------------------------+
            | 2     | EC2       | [kty(2), crv]              |
            +-------+-----------+----------------------------+
            | 3     | RSA       | [kty(3)]                   |
            +-------+-----------+----------------------------+
            | 4     | Symmetric | [kty(4)]                   |
            +-------+-----------+----------------------------+
            | 5     | HSS-LMS   | [kty(5), hash algorithm]   |
            +-------+-----------+----------------------------+
            | 6     | WalnutDSA | [kty(6), N value, q value] |
            +-------+-----------+----------------------------+

                     Table 22: Key Type Capabilities

10.2. Changes to the "COSE Algorithms" Registry ๐Ÿงฎ

Same energy here: IANA added a new "Capabilities" column to the "COSE Algorithms" registry. Every current, nonprovisional registration got filled with "[kty]" ๐ŸŽ€

IANA also updated the Reference column in that registry so it lists this document for every row that didn't already have it. โœจ

And then IANA added a brand new row to the registry, which looks like this ๐Ÿฆ‹

    +===============+=======+===============+===========+=============+
    | Name          | Value | Description   | Reference | Recommended |
    +===============+=======+===============+===========+=============+
    | IV-GENERATION | 34    | For doing IV  | RFC 9053  | No          |
    |               |       | generation    |           |             |
    |               |       | for symmetric |           |             |
    |               |       | algorithms.   |           |             |
    +---------------+-------+---------------+-----------+-------------+

            Table 23: New entry in the COSE Algorithms registry

For this one, the Capabilities column is to be empty ๐Ÿซถ

10.3. Changes to the "COSE Key Type Parameters" Registry ๐Ÿ”ง

IANA changed the description to "Public Key" for the row where "Key Type" is 1 and "Name" is x. Check out Table 20, since it's been updated with this change too ๐Ÿ’œ

10.4. Expert Review Instructions ๐Ÿง

Every IANA registry set up by [RFC8152] is, at least partly, defined as Expert Review [RFC8126]. This section gives some general guidance on what the experts should be looking for, but they were picked as experts for a reason, so they should get substantial latitude. Trust the experts, bestie ๐Ÿ™Œ

Expert reviewers should take the following into consideration:

  • Point squatting should be discouraged. Reviewers are encouraged to get enough information in registration requests to make sure the usage won't duplicate an existing registration and that the code point is likely to show up in real deployments. The ranges tagged as private use are meant for testing and closed environments, so code points in other ranges should not be assigned for testing. ๐Ÿšซ
  • Standards Track or BCP RFCs are required to register a code point in the Standards Action range. Specifications should exist for Specification Required ranges, but early assignment before an RFC is available is considered to be permissible. Specifications are needed for the first-come, first-served range if the points are expected to be used outside of closed environments in an interoperable way. When specifications are not provided, the description provided needs to have sufficient information to identify what the point is being used for. ๐Ÿ“œ
  • Experts should take into account the expected usage of fields when approving code point assignment. The fact that the Standards Action range is only available to Standards Track documents does not mean that a Standards Track document cannot have points assigned outside of that range. The length of the encoded value should be weighed against how many code points of that length are left and the size of device it will be used on. ๐Ÿ“
  • When algorithms are registered, vanity registrations should be discouraged. One way to do this is to require registrations to provide additional documentation on security analysis of the algorithm. Another thing that should be considered is requesting an opinion on the algorithm from the Crypto Forum Research Group (CFRG). Algorithms are expected to meet the security requirements of the community and the requirements of the message structures in order to be suitable for registration. No vanity, only vibes that are actually secure ๐Ÿ”

11. Security Considerations ๐Ÿ”

Okay, this part is seriously important, so read it carefully ๐Ÿฅบ There are a bunch of security considerations implementers need to keep in mind. The ones specific to a particular algorithm live right next to that algorithm's description. Some have been highlighted here, but more can be found in the documents listed in the references ๐Ÿ“š

Implementations need to protect the private key material for all individuals. A few cases in this document need extra attention on this, so here they are:

  • Using the same key for two different algorithms can leak information about the key. So it's recommended that keys be restricted to a single algorithm. ๐Ÿ”‘
  • Using "direct" as a recipient algorithm combined with a second recipient algorithm exposes the direct key to the second recipient. Section 8.5 of [RFC9052] forbids combining "direct" recipient algorithms with other modes. ๐Ÿ™…โ€โ™€๏ธ
  • Several of the algorithms in this document have limits on how many times a key can be used without leaking information about the key. โณ

The use of ECDH and direct plus KDF (with no key wrap) won't directly lead to the private key being leaked, because the one-way function of the KDF prevents that. ๐Ÿ›ก๏ธ BUT there's a different issue that needs fixing. Having two recipients means the CEK has to be shared between them. So the second recipient ends up with a CEK that was derived from material that can be used for the weak proof of origin. That second recipient could create a message using the same CEK and send it to the first recipient. For either Static-Static ECDH or direct plus KDF, the first recipient would then assume the CEK could be used for proof of origin, even though it came from the wrong entity ๐Ÿ˜ญ If the key wrap step is added, then no proof of origin is implied and this isn't an issue anymore.

Although it's been mentioned before, it's worth repeating: using a single key for multiple algorithms has been shown, in some cases, to leak information about a key. That gives attackers the chance to forge integrity tags or learn about encrypted content. Binding a key to a single algorithm prevents these problems. Key creators and key consumers are strongly encouraged to not only create new keys for each different algorithm, but also to include that algorithm selection in any distribution of key material. They should also strictly enforce the matching of algorithms in the key structure to algorithms in the message structure. Checking the algorithms is not enough on its own, because the key form needs to be checked as well. Do not use an "EC2" key where an "OKP" key is expected. ๐Ÿšจ

Before using a key for transmission, or before acting on information received, a trust decision on the key needs to be made. Is the data or action something the entity associated with the key has a right to see or a right to request? A number of factors go into this trust decision. Some highlighted here are:

  • What are the permissions associated with the key owner? ๐Ÿชช
  • Is the cryptographic algorithm acceptable in the current context? ๐Ÿค”
  • Have the restrictions associated with the key, such as algorithm or freshness, been checked, and are they correct? โœ…
  • Is the request something that is reasonable, given the current state of the application? ๐Ÿง 
  • Have any security considerations that are part of the message been enforced (as specified by the application or "crit" header parameter)? ๐Ÿ“‹

There are a large number of algorithms in this document that use nonce values. For all of the nonces defined here, there's some kind of restriction on the nonce being a unique value, either for a key or for some other conditions. In all of these cases, there's no known requirement for the nonce to be both unique and unpredictable. Under these circumstances, it's reasonable to use a counter to create the nonce. ๐Ÿ”ข In cases where someone wants the pattern of the nonce to be unpredictable as well as unique, they can use a key created for that purpose and encrypt the counter to produce the nonce value. ๐ŸŽฒ

Traffic analysis of encrypted messages based on message length is a hot topic right now ๐Ÿ‘€ This specification does not provide a uniform method for padding as part of the message structure. An observer can tell apart two different messages (for example, "YES" and "NO") based on the length, for all of the content encryption algorithms defined in this document. So it's up to applications to document how content padding is done in order to prevent or discourage that kind of analysis. (For example, the text strings could be defined as "YES" and "NO ".) ๐Ÿ™ˆ

The analysis done in [RFC9147] is based on the number of records that are sent. This should map well to the number of messages sent when using COSE, so that analysis should hold here as well, as long as the COSE messages are roughly the same size as DTLS records. It needs to be noted that the limits are based on the number of messages, but QUIC and DTLS are always pairwise-based endpoints. In contrast, [OSCORE-GROUPCOMM] uses COSE in a group communication scenario. In that setup, it may be that no single entity sees all of the messages that are encrypted, so no single entity can trigger the rekey operation. ๐Ÿ‘ฏโ€โ™€๏ธ

12. References ๐Ÿ“š

12.1. Normative References โœจ

okay so these are the docs you literally NEED to have read before any of this makes sense ๐Ÿ“š no cap, the spec leans on them hard ๐Ÿ’…


12.2. Informative References ๐ŸŒท

these ones are more of a "go deeper if you're curious" list, not homework (unless you're obsessed like me ๐Ÿ™ˆ)


Acknowledgments ๐Ÿ’œ

this doc is a product of the COSE Working Group of the IETF, so shoutout to everyone in that squad ๐Ÿซถ

the following individuals are to blame for getting me started on this project in the first place: Richard Barnes, Matt Miller, and Martin Thomson. ๐Ÿ™ˆ thank you, bestie-trio, you know what you did โœจ

the initial draft version of the specification was based to some degree on the outputs of the JOSE and S/MIME Working Groups. ๐ŸŒธ

the following individuals provided input into the final form of the document: Carsten Bormann, John Bradley, Brian Campbell, Michael B. Jones, Ilari Liusvaara, Francesca Palombini, Ludwig Seitz, and Gรถran Selander. ๐Ÿ‘‘ the final form owes so much to them, periodt ๐Ÿ’…


Author's Address ๐ŸŽ€

Jim Schaad August Cellars

๐Ÿ“ฆ where this page comes from