Section 8.5 of
RFC 9052 contains a generic description of content key distribution methods. This document defines the identifiers and usage for a number of content key distribution methods.
A direct encryption algorithm is defined in
Section 8.5.1 of
RFC 9052. Information about how to fill in the COSE_Recipient structure is detailed there.
This recipient algorithm is the simplest; 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
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.
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.
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-MAC-128 |
Shared secret w/ AES-MAC 128-bit key |
direct+HKDF-AES-256 |
-13 |
HKDF AES-MAC-256 |
Shared secret w/ 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".
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.
Key wrap is defined in
Section 8.5.2 of
RFC 9052. Information about how to fill in the COSE_Recipient structure is detailed there.
The AES Key Wrap algorithm is defined in [
RFC 3394]. 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
RFC 3394. 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
The shared secret needs to have some method of being regularly updated over time. The shared secret is the basis of trust.
Direct Key Agreement is defined in
Section 8.5.4 of
RFC 9052. Information about how to fill in the COSE_Recipient structure is detailed there.
The mathematics for ECDH can be found in [
RFC 6090]. In this document, the algorithm is extended to be used with the two curves defined in [
RFC 7748].
ECDH is parameterized by the following:
-
Curve Type/Curve:
-
The curve selected controls not only the size of the shared secret, but the mathematics for computing the shared secret. The curve selected also controls how a point in the curve is represented and what happens for the identity points on the curve. In this specification, we allow for a number of different curves to be used. A set of curves is defined in Table 18.
The math used to obtain the computed secret is based on the curve selected and not on the ECDH algorithm. For this reason, a new algorithm does not need to be defined for each of the curves.
-
Computed Secret to Shared Secret:
-
Once the computed secret is known, the resulting value needs to be converted to a byte string to run the KDF. The x-coordinate is used for all of the curves defined in this document. For curves X25519 and X448, the resulting value is used directly, as it is a byte string of a known length. For the P-256, P-384, and P-521 curves, the x-coordinate is run through the Integer-to-Octet-String primitive (I2OSP) function defined in [RFC 8017], using the same computation for n as is defined in Section 2.1.
-
Ephemeral-Static or Static-Static:
-
The key agreement process may be done using either a static or an ephemeral key for the sender's side. When using ephemeral keys, the sender MUST generate a new ephemeral key for every key agreement operation. The ephemeral key is placed in the "ephemeral key" parameter and MUST be present for all algorithm identifiers that use ephemeral keys. When using static keys, the sender MUST either generate a new random value or create a unique value for use as a KDF input. For the KDFs used, this means that 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 parameter MUST be unique for the pair of keys being used. It is acceptable to use a global counter that is incremented for every Static-Static operation and use the resulting value. Care must be taken that the counter is saved to permanent storage in a way that avoids reuse of that counter value. When using static keys, the static key should be identified to the recipient. The static key can be identified by providing either the key ("static key") or a key identifier for the static key ("static key id"). Both of these header parameters are defined in Table 15.
-
Key Derivation Algorithm:
-
The result of an ECDH key agreement process does not provide a uniformly random secret. As such, it needs to be run through a KDF in order to produce a usable key. Processing the secret through a KDF also allows for the introduction of context material: how the key is going to be used and one-time material for Static-Static key agreement. All of the algorithms defined in this document use one of the HKDF algorithms defined in Section 5.1 with the context structure defined in Section 5.2.
-
Key Wrap Algorithm:
-
No key wrap algorithm is used. This is represented in Table 14 as "none". The key size for the context structure is the content layer encryption algorithm size.
COSE does not have an Ephemeral-Ephemeral version defined. The reason for this is that COSE is not an online protocol by itself and thus does not have a method of establishing ephemeral secrets on both sides. The expectation is that a protocol would establish the secrets for both sides, and then they would be used as Static-Static for the purposes of COSE, or that the protocol would generate a shared secret and a direct encryption would be used.
The set of direct ECDH algorithms defined in this document is found in
Table 14.
Name |
Value |
KDF |
Ephemeral-Static |
Key Wrap |
Description |
ECDH-ES + HKDF-256 |
-25 |
HKDF -- SHA-256 |
yes |
none |
ECDH ES w/ HKDF -- generate key directly |
ECDH-ES + HKDF-512 |
-26 |
HKDF -- SHA-512 |
yes |
none |
ECDH ES w/ HKDF -- generate key directly |
ECDH-SS + HKDF-256 |
-27 |
HKDF -- SHA-256 |
no |
none |
ECDH SS w/ HKDF -- generate key directly |
ECDH-SS + HKDF-512 |
-28 |
HKDF -- SHA-512 |
no |
none |
ECDH SS w/ HKDF -- generate key directly |
Table 14: ECDH Algorithm Values
Name |
Label |
Type |
Algorithm |
Description |
ephemeral key |
-1 |
COSE_Key |
ECDH-ES+HKDF-256, ECDH-ES+HKDF-512, ECDH-ES+A128KW, ECDH-ES+A192KW, ECDH-ES+A256KW |
Ephemeral public key for the sender |
static key |
-2 |
COSE_Key |
ECDH-SS+HKDF-256, ECDH-SS+HKDF-512, ECDH-SS+A128KW, ECDH-SS+A192KW, ECDH-SS+A256KW |
Static public key for the sender |
static key id |
-3 |
bstr |
ECDH-SS+HKDF-256, ECDH-SS+HKDF-512, ECDH-SS+A128KW, ECDH-SS+A192KW, ECDH-SS+A256KW |
Static public key identifier for the sender |
Table 15: ECDH Algorithm Parameters
This document defines these algorithms to be used 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 restricted to different key types. Implementations
MUST verify that the curve and algorithm are 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 "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.
There is a method of checking that points provided from external entities are valid. For the "EC2" key format, this can be done by checking that the x and y values form a point on the curve. For the "OKP" format, there is no simple way to perform point validation.
Consideration was given to requiring that the public keys of both entities be provided as part of the key derivation process (as recommended in
Section 6.1 of
RFC 7748). This was not done, because COSE is used in a store-and-forward format rather than in online key exchange. In order for this to be a problem, either the receiver public key has to be chosen maliciously or the sender has to be malicious. In either case, all security evaporates anyway.
A proof of possession of the private key associated with the public key is recommended when a key is moved from untrusted to trusted (either by the end user or by the entity that is responsible for making trust statements on keys).
Key Agreement with Key Wrap is defined in
Section 8.5.5 of
RFC 9052. Information about how to fill in the COSE_Recipient structure is detailed there.
These algorithms are defined in
Table 16.
ECDH with Key Agreement is parameterized by the same header parameters as for ECDH; see
Section 6.3.1, with the following modifications:
-
Key Wrap Algorithm:
-
Any of the key wrap algorithms defined in Section 6.2 are supported. The size of the key used for the key wrap algorithm is fed into the KDF. The set of identifiers is found in Table 16.
Name |
Value |
KDF |
Ephemeral-Static |
Key Wrap |
Description |
ECDH-ES + A128KW |
-29 |
HKDF -- SHA-256 |
yes |
A128KW |
ECDH ES w/ HKDF and AES Key Wrap w/ 128-bit key |
ECDH-ES + A192KW |
-30 |
HKDF -- SHA-256 |
yes |
A192KW |
ECDH ES w/ HKDF and AES Key Wrap w/ 192-bit key |
ECDH-ES + A256KW |
-31 |
HKDF -- SHA-256 |
yes |
A256KW |
ECDH ES w/ HKDF and AES Key Wrap w/ 256-bit key |
ECDH-SS + A128KW |
-32 |
HKDF -- SHA-256 |
no |
A128KW |
ECDH SS w/ HKDF and AES Key Wrap w/ 128-bit key |
ECDH-SS + A192KW |
-33 |
HKDF -- SHA-256 |
no |
A192KW |
ECDH SS w/ HKDF and AES Key Wrap w/ 192-bit key |
ECDH-SS + A256KW |
-34 |
HKDF -- SHA-256 |
no |
A256KW |
ECDH SS w/ HKDF and AES Key Wrap w/ 256-bit key |
Table 16: ECDH Algorithm Values with Key Wrap
When using a COSE key for this algorithm, the following checks are made:
-
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.