4. Protected Message Fields
OSCORE transforms a CoAP message (which may have been generated from an HTTP message) into an OSCORE message, and vice versa. OSCORE protects as much of the original message as possible while still allowing certain proxy operations (see Sections 10 and 11). This section defines how OSCORE protects the message fields and transfers them end-to-end between client and server (in any direction). The remainder of this section and later sections focus on the behavior in terms of CoAP messages. If HTTP is used for a particular hop in the end-to-end path, then this section applies to the conceptual CoAP message that is mappable to/from the original HTTP message as discussed in Section 11. That is, an HTTP message is conceptually transformed to a CoAP message and then to an OSCORE message, and similarly in the reverse direction. An actual implementation might translate directly from HTTP to OSCORE without the intervening CoAP representation. Protection of signaling messages (Section 5 of [RFC8323]) is specified in Section 4.3. The other parts of this section target request/response messages. Message fields of the CoAP message may be protected end-to-end between CoAP client and CoAP server in different ways: o Class E: encrypted and integrity protected, o Class I: integrity protected only, or o Class U: unprotected. The sending endpoint SHALL transfer Class E message fields in the ciphertext of the COSE object in the OSCORE message. The sending endpoint SHALL include Class I message fields in the AAD of the AEAD algorithm, allowing the receiving endpoint to detect if the value has changed in transfer. Class U message fields SHALL NOT be protected in transfer. Class I and Class U message field values are transferred in the header or options part of the OSCORE message, which is visible to proxies. Message fields not visible to proxies, i.e., transported in the ciphertext of the COSE object, are called "Inner" (Class E). Message fields transferred in the header or options part of the OSCORE message, which is visible to proxies, are called "Outer" (Class I or Class U). There are currently no Class I options defined.
An OSCORE message may contain both an Inner and an Outer instance of a certain CoAP message field. Inner message fields are intended for the receiving endpoint, whereas Outer message fields are used to enable proxy operations.4.1. CoAP Options
A summary of how options are protected is shown in Figure 5. Note that some options may have both Inner and Outer message fields, which are protected accordingly. Certain options require special processing as is described in Section 4.1.3. Options that are unknown or for which OSCORE processing is not defined SHALL be processed as Class E (and no special processing). Specifications of new CoAP options SHOULD define how they are processed with OSCORE. A new COAP option SHOULD be of Class E unless it requires proxy processing. If a new CoAP option is of class U, the potential issues with the option being unprotected SHOULD be documented (see Appendix D.5).4.1.1. Inner Options
Inner option message fields (Class E) are used to communicate directly with the other endpoint. The sending endpoint SHALL write the Inner option message fields present in the original CoAP message into the plaintext of the COSE object (Section 5.3) and then remove the Inner option message fields from the OSCORE message. The processing of Inner option message fields by the receiving endpoint is specified in Sections 8.2 and 8.4.
+------+-----------------+---+---+ | No. | Name | E | U | +------+-----------------+---+---+ | 1 | If-Match | x | | | 3 | Uri-Host | | x | | 4 | ETag | x | | | 5 | If-None-Match | x | | | 6 | Observe | x | x | | 7 | Uri-Port | | x | | 8 | Location-Path | x | | | 9 | OSCORE | | x | | 11 | Uri-Path | x | | | 12 | Content-Format | x | | | 14 | Max-Age | x | x | | 15 | Uri-Query | x | | | 17 | Accept | x | | | 20 | Location-Query | x | | | 23 | Block2 | x | x | | 27 | Block1 | x | x | | 28 | Size2 | x | x | | 35 | Proxy-Uri | | x | | 39 | Proxy-Scheme | | x | | 60 | Size1 | x | x | | 258 | No-Response | x | x | +------+-----------------+---+---+ E = Encrypt and Integrity Protect (Inner) U = Unprotected (Outer) Figure 5: Protection of CoAP Options4.1.2. Outer Options
Outer option message fields (Class U or I) are used to support proxy operations, see Appendix D.2. The sending endpoint SHALL include the Outer option message field present in the original message in the options part of the OSCORE message. All Outer option message fields, including the OSCORE option, SHALL be encoded as described in Section 3.1 of [RFC7252], where the delta is the difference from the previously included instance of Outer option message field. The processing of Outer options by the receiving endpoint is specified in Sections 8.2 and 8.4.
A procedure for integrity-protection-only of Class I option message fields is specified in Section 5.4. Specifications that introduce repeatable Class I options MUST specify that proxies MUST NOT change the order of the instances of such an option in the CoAP message. Note: There are currently no Class I option message fields defined.4.1.3. Special Options
Some options require special processing as specified in this section.4.1.3.1. Max-Age
An Inner Max-Age message field is used to indicate the maximum time a response may be cached by the client (as defined in [RFC7252]), end- to-end from the server to the client, taking into account that the option is not accessible to proxies. The Inner Max-Age SHALL be processed by OSCORE as a normal Inner option, specified in Section 4.1.1. An Outer Max-Age message field is used to avoid unnecessary caching of error responses caused by OSCORE processing at OSCORE-unaware intermediary nodes. A server MAY set a Class U Max-Age message field with value zero to such error responses, described in Sections 7.4, 8.2, and 8.4, since these error responses are cacheable, but subsequent OSCORE requests would never create a hit in the intermediary node caching it. Setting the Outer Max-Age to zero relieves the intermediary from uselessly caching responses. Successful OSCORE responses do not need to include an Outer Max-Age option. Except when the Observe option (see Section 4.1.3.5) is used, responses appear to the OSCORE-unaware intermediary as 2.04 (Changed) responses, which are non-cacheable (see Section 4.2). For Observe responses, which are cacheable, an Outer Max-Age option with value 0 may be used to avoid unnecessary proxy caching. The Outer Max-Age message field is processed according to Section 4.1.2.4.1.3.2. Uri-Host and Uri-Port
When the Uri-Host and Uri-Port are set to their default values (see Section 5.10.1 [RFC7252]), they are omitted from the message (Section 5.4.4 of [RFC7252]), which is favorable both for overhead and privacy. In order to support forward proxy operations, Proxy-Scheme, Uri-Host, and Uri-Port need to be Class U. For the use of Proxy-Uri, see Section 4.1.3.3.
Manipulation of unprotected message fields (including Uri-Host, Uri- Port, destination IP/port or request scheme) MUST NOT lead to an OSCORE message becoming verified by an unintended server. Different servers SHALL have different security contexts.4.1.3.3. Proxy-Uri
When Proxy-Uri is present, the client SHALL first decompose the Proxy-Uri value of the original CoAP message into the Proxy-Scheme, Uri-Host, Uri-Port, Uri-Path, and Uri-Query options according to Section 6.4 of [RFC7252]. Uri-Path and Uri-Query are Class E options and SHALL be protected and processed as Inner options (Section 4.1.1). The Proxy-Uri option of the OSCORE message SHALL be set to the composition of Proxy-Scheme, Uri-Host, and Uri-Port options as specified in Section 6.5 of [RFC7252] and processed as an Outer option of Class U (Section 4.1.2). Note that replacing the Proxy-Uri value with the Proxy-Scheme and Uri-* options works by design for all CoAP URIs (see Section 6 of [RFC7252]). OSCORE-aware HTTP servers should not use the userinfo component of the HTTP URI (as defined in Section 3.2.1 of [RFC3986]), so that this type of replacement is possible in the presence of CoAP- to-HTTP proxies (see Section 11.2). In future specifications of cross-protocol proxying behavior using different URI structures, it is expected that the authors will create Uri-* options that allow decomposing the Proxy-Uri, and specifying the OSCORE processing. An example of how Proxy-Uri is processed is given here. Assume that the original CoAP message contains: o Proxy-Uri = "coap://example.com/resource?q=1" During OSCORE processing, Proxy-Uri is split into: o Proxy-Scheme = "coap" o Uri-Host = "example.com" o Uri-Port = "5683" (default) o Uri-Path = "resource" o Uri-Query = "q=1"
Uri-Path and Uri-Query follow the processing defined in Section 4.1.1; thus, they are encrypted and transported in the COSE object: o Uri-Path = "resource" o Uri-Query = "q=1" The remaining options are composed into the Proxy-Uri included in the options part of the OSCORE message, which has value: o Proxy-Uri = "coap://example.com" See Sections 6.1 and 12.6 of [RFC7252] for more details.4.1.3.4. The Block Options
Block-wise [RFC7959] is an optional feature. An implementation MAY support CoAP [RFC7252] and the OSCORE option without supporting block-wise transfers. The Block options (Block1, Block2, Size1, Size2), when Inner message fields, provide secure message segmentation such that each segment can be verified. The Block options, when Outer message fields, enable hop-by-hop fragmentation of the OSCORE message. Inner and Outer block processing may have different performance properties depending on the underlying transport. The end-to-end integrity of the message can be verified both in case of Inner and Outer Block-wise transfers, provided all blocks are received.4.1.3.4.1. Inner Block Options
The sending CoAP endpoint MAY fragment a CoAP message as defined in [RFC7959] before the message is processed by OSCORE. In this case, the Block options SHALL be processed by OSCORE as normal Inner options (Section 4.1.1). The receiving CoAP endpoint SHALL process the OSCORE message before processing Block-wise as defined in [RFC7959].4.1.3.4.2. Outer Block Options
Proxies MAY fragment an OSCORE message using [RFC7959] by introducing Block option message fields that are Outer (Section 4.1.2). Note that the Outer Block options are neither encrypted nor integrity protected. As a consequence, a proxy can maliciously inject block fragments indefinitely, since the receiving endpoint needs to receive the last block (see [RFC7959]) to be able to compose the OSCORE message and verify its integrity. Therefore, applications supporting OSCORE and [RFC7959] MUST specify a security policy defining a
maximum unfragmented message size (MAX_UNFRAGMENTED_SIZE) considering the maximum size of message that can be handled by the endpoints. Messages exceeding this size SHOULD be fragmented by the sending endpoint using Inner Block options (Section 4.1.3.4.1). An endpoint receiving an OSCORE message with an Outer Block option SHALL first process this option according to [RFC7959], until all blocks of the OSCORE message have been received or the cumulated message size of the blocks exceeds MAX_UNFRAGMENTED_SIZE. In the former case, the processing of the OSCORE message continues as defined in this document. In the latter case, the message SHALL be discarded. Because of encryption of Uri-Path and Uri-Query, messages to the same server may, from the point of view of a proxy, look like they also target the same resource. A proxy SHOULD mitigate a potential mix-up of blocks from concurrent requests to the same server, for example, using the Request-Tag processing specified in Section 3.3.2 of [CoAP-ECHO-REQ-TAG].4.1.3.5. Observe
Observe [RFC7641] is an optional feature. An implementation MAY support CoAP [RFC7252] and the OSCORE option without supporting [RFC7641], in which case the Observe-related processing can be omitted. The support for Observe [RFC7641] with OSCORE targets the requirements on forwarding of Section 2.2.1 of [CoAP-E2E-Sec], i.e., that observations go through intermediary nodes, as illustrated in Figure 8 of [RFC7641]. Inner Observe SHALL be used to protect the value of the Observe option between the endpoints. Outer Observe SHALL be used to support forwarding by intermediary nodes. The server SHALL include a new Partial IV (see Section 5) in responses (with or without the Observe option) to Observe registrations, except for the first response where Partial IV MAY be omitted. For cancellations, Section 3.6 of [RFC7641] specifies that all options MUST be identical to those in the registration request except for the Observe option and the set of ETag options. For OSCORE messages, this matching is to be done to the options in the decrypted message.
[RFC7252] does not specify how the server should act upon receiving the same Token in different requests. When using OSCORE, the server SHOULD NOT remove an active observation just because it receives a request with the same Token. Since POST with the Observe option is not defined, for messages with the Observe option, the Outer Code MUST be set to 0.05 (FETCH) for requests and to 2.05 (Content) for responses (see Section 4.2).4.1.3.5.1. Registrations and Cancellations
The Inner and Outer Observe options in the request MUST contain the Observe value of the original CoAP request; 0 (registration) or 1 (cancellation). Every time a client issues a new request with the Observe option, a new Partial IV MUST be used (see Section 5), and so the payload and OSCORE option are changed. The server uses the Partial IV of the new request as the 'request_piv' of all associated notifications (see Section 5.4). Intermediaries are not assumed to have access to the OSCORE security context used by the endpoints; thus, they cannot make requests or transform responses with the OSCORE option that pass verification (at the receiving endpoint) as having come from the other endpoint. This has the following consequences and limitations for Observe operations. o An intermediary node removing the Outer Observe 0 option does not change the registration request to a request without the Observe option (see Section 2 of [RFC7641]). Instead other means for cancellation may be used as described in Section 3.6 of [RFC7641]. o An intermediary node is not able to transform a normal response into an OSCORE-protected Observe notification (see Figure 7 of [RFC7641]) that verifies as coming from the server. o An intermediary node is not able to initiate an OSCORE protected Observe registration (Observe option with value 0) that verifies as coming from the client. An OSCORE-aware intermediary SHALL NOT initiate registrations of observations (see Section 10). If an OSCORE-unaware proxy resends an old registration message from a client, the replay protection mechanism in the server will be triggered. To prevent this from resulting in the OSCORE-unaware proxy canceling the registration, a server MAY respond to a replayed registration request with a replay of a cached notification. Alternatively, the server MAY send a new notification.
o An intermediary node is not able to initiate an OSCORE-protected Observe cancellation (Observe option with value 1) that verifies as coming from the client. An application MAY decide to allow intermediaries to cancel Observe registrations, e.g., to send the Observe option with value 1 (see Section 3.6 of [RFC7641]); however, that can also be done with other methods, e.g., by sending a RST message. This is out of scope for this specification.4.1.3.5.2. Notifications
If the server accepts an Observe registration, a Partial IV MUST be included in all notifications (both successful and error), except for the first one where the Partial IV MAY be omitted. To protect against replay, the client SHALL maintain a Notification Number for each Observation it registers. The Notification Number is a non- negative integer containing the largest Partial IV of the received notifications for the associated Observe registration. Further details of replay protection of notifications are specified in Section 7.4.1. For notifications, the Inner Observe option value MUST be empty (see Section 3.2 of [RFC7252]). The Outer Observe option in a notification is needed for intermediary nodes to allow multiple responses to one request, and it MAY be set to the value of the Observe option in the original CoAP message. The client performs ordering of notifications and replay protection by comparing their Partial IVs and SHALL ignore the Outer Observe option value. If the client receives a response to an Observe request without an Inner Observe option, then it verifies the response as a non-Observe response, as specified in Section 8.4. If the client receives a response to a non-Observe request with an Inner Observe option, then it stops processing the message, as specified in Section 8.4. A client MUST consider the notification with the highest Partial IV as the freshest, regardless of the order of arrival. In order to support existing Observe implementations, the OSCORE client implementation MAY set the Observe option value to the three least significant bytes of the Partial IV. Implementations need to make sure that the notification without Partial IV is considered the oldest.
4.1.3.6. No-Response
No-Response [RFC7967] is an optional feature used by the client to communicate its disinterest in certain classes of responses to a particular request. An implementation MAY support [RFC7252] and the OSCORE option without supporting [RFC7967]. If used, No-Response MUST be Inner. The Inner No-Response SHALL be processed by OSCORE as specified in Section 4.1.1. The Outer option SHOULD NOT be present. The server SHALL ignore the Outer No-Response option. The client MAY set the Outer No-Response value to 26 (suppress all known codes) if the Inner value is set to 26. The client MUST be prepared to receive and discard 5.04 (Gateway Timeout) error messages from intermediaries potentially resulting from destination time out due to no response.4.1.3.7. OSCORE
The OSCORE option is only defined to be present in OSCORE messages as an indication that OSCORE processing has been performed. The content in the OSCORE option is neither encrypted nor integrity protected as a whole, but some part of the content of this option is protected (see Section 5.4). Nested use of OSCORE is not supported: If OSCORE processing detects an OSCORE option in the original CoAP message, then processing SHALL be stopped.4.2. CoAP Header Fields and Payload
A summary of how the CoAP header fields and payload are protected is shown in Figure 6, including fields specific to CoAP over UDP and CoAP over TCP (marked accordingly in the table). +------------------+---+---+ | Field | E | U | +------------------+---+---+ | Version (UDP) | | x | | Type (UDP) | | x | | Length (TCP) | | x | | Token Length | | x | | Code | x | | | Message ID (UDP) | | x | | Token | | x | | Payload | x | | +------------------+---+---+ E = Encrypt and Integrity Protect (Inner) U = Unprotected (Outer) Figure 6: Protection of CoAP Header Fields and Payload
Most CoAP header fields (i.e., the message fields in the fixed 4-byte header) are required to be read and/or changed by CoAP proxies; thus, they cannot, in general, be protected end-to-end from one endpoint to the other. As mentioned in Section 1, OSCORE protects the CoAP request/response layer only and not the CoAP messaging layer (Section 2 of [RFC7252]), so fields such as Type and Message ID are not protected with OSCORE. The CoAP header field Code is protected by OSCORE. Code SHALL be encrypted and integrity protected (Class E) to prevent an intermediary from eavesdropping on or manipulating it (e.g., changing from GET to DELETE). The sending endpoint SHALL write the Code of the original CoAP message into the plaintext of the COSE object (see Section 5.3). After that, the sending endpoint writes an Outer Code to the OSCORE message. With one exception (see Section 4.1.3.5), the Outer Code SHALL be set to 0.02 (POST) for requests and to 2.04 (Changed) for responses. The receiving endpoint SHALL discard the Outer Code in the OSCORE message and write the Code of the COSE object plaintext (Section 5.3) into the decrypted CoAP message. The other currently defined CoAP header fields are Unprotected (Class U). The sending endpoint SHALL write all other header fields of the original message into the header of the OSCORE message. The receiving endpoint SHALL write the header fields from the received OSCORE message into the header of the decrypted CoAP message. The CoAP Payload, if present in the original CoAP message, SHALL be encrypted and integrity protected; thus, it is an Inner message field. The sending endpoint writes the payload of the original CoAP message into the plaintext (Section 5.3) input to the COSE object. The receiving endpoint verifies and decrypts the COSE object, and it recreates the payload of the original CoAP message.4.3. Signaling Messages
Signaling messages (CoAP Code 7.00-7.31) were introduced to exchange information related to an underlying transport connection in the specific case of CoAP over reliable transports [RFC8323]. OSCORE MAY be used to protect signaling if the endpoints for OSCORE coincide with the endpoints for the signaling message. If OSCORE is used to protect signaling then: o To comply with [RFC8323], an initial empty Capabilities and Settings Message (CSM) SHALL be sent. The subsequent signaling message SHALL be protected.
o Signaling messages SHALL be protected as CoAP request messages, except in the case in which the signaling message is a response to a previous signaling message; then it SHALL be protected as a CoAP response message. For example, 7.02 (Ping) is protected as a CoAP request and 7.03 (Pong) as a CoAP response. o The Outer Code for signaling messages SHALL be set to 0.02 (POST), unless it is a response to a previous signaling message, in which case it SHALL be set to 2.04 (Changed). o All signaling options, except the OSCORE option, SHALL be Inner (Class E). NOTE: Option numbers for signaling messages are specific to the CoAP Code (see Section 5.2 of [RFC8323]). If OSCORE is not used to protect signaling, Signaling messages SHALL be unaltered by OSCORE.5. The COSE Object
This section defines how to use COSE [RFC8152] to wrap and protect data in the original message. OSCORE uses the untagged COSE_Encrypt0 structure (see Section 5.2 of [RFC8152]) with an AEAD algorithm. The AEAD key lengths, AEAD nonce length, and maximum Sender Sequence Number are algorithm dependent. The AEAD algorithm AES-CCM-16-64-128 defined in Section 10.2 of [RFC8152] is mandatory to implement. For AES-CCM-16-64-128, the length of Sender Key and Recipient Key is 128 bits; the length of AEAD nonce and Common IV is 13 bytes. The maximum Sender Sequence Number is specified in Section 12. As specified in [RFC5116], plaintext denotes the data that is to be encrypted and integrity protected, and Additional Authenticated Data (AAD) denotes the data that is to be integrity protected only. The COSE object SHALL be a COSE_Encrypt0 object with fields defined as follows: o The 'protected' field is empty. o The 'unprotected' field includes: * The 'Partial IV' parameter. The value is set to the Sender Sequence Number. All leading bytes of value zero SHALL be removed when encoding the Partial IV, except in the case of Partial IV value 0, which is encoded to the byte string 0x00.
This parameter SHALL be present in requests and will not typically be present in responses (for two exceptions, see Observe notifications (Section 4.1.3.5.2) and Replay Window synchronization (Appendix B.1.2)). * The 'kid' parameter. The value is set to the Sender ID. This parameter SHALL be present in requests and will not typically be present in responses. An example where the Sender ID is included in a response is the extension of OSCORE to group communication [Group-OSCORE]. * Optionally, a 'kid context' parameter (see Section 5.1). This parameter MAY be present in requests and, if so, MUST contain an ID Context (see Section 3.1). This parameter SHOULD NOT be present in responses: an example of how 'kid context' can be used in responses is given in Appendix B.2. If 'kid context' is present in the request, then the server SHALL use a security context with that ID Context when verifying the request. o The 'ciphertext' field is computed from the secret key (Sender Key or Recipient Key), AEAD nonce (see Section 5.2), plaintext (see Section 5.3), and the AAD (see Section 5.4) following Section 5.2 of [RFC8152]. The encryption process is described in Section 5.3 of [RFC8152].5.1. ID Context and 'kid context'
For certain use cases, e.g., deployments where the same Sender ID is used with multiple contexts, it is possible (and sometimes necessary, see Section 3.3) for the client to use an ID Context to distinguish the security contexts (see Section 3.1). For example: o If the client has a unique identifier in some namespace, then that identifier can be used as ID Context. o The ID Context may be used to add randomness into new Sender and Recipient Contexts, see Appendix B.2. o In the case of group communication [Group-OSCORE], a group identifier is used as ID Context to enable different security contexts for a server belonging to multiple groups. The Sender ID and ID Context are used to establish the necessary input parameters and in the derivation of the security context (see Section 3.2).
While the 'kid' parameter is used to transport the Sender ID, the new COSE header parameter 'kid context' is used to transport the ID Context in requests, see Figure 7. +----------+--------+------------+----------------+-----------------+ | Name | Label | Value Type | Value Registry | Description | +----------+--------+------------+----------------+-----------------+ | kid | 10 | bstr | | Identifies the | | context | | | | context for the | | | | | | key identifier | +----------+--------+------------+----------------+-----------------+ Figure 7: Common Header Parameter 'kid context' for the COSE Object If ID Context is non-empty and the client sends a request without 'kid context' resulting in an error indicating that the server could not find the security context, then the client could include the ID Context in the 'kid context' when making another request. Note that since the error is unprotected, it may have been spoofed and the real response blocked by an on-path attacker.5.2. AEAD Nonce
The high-level design of the AEAD nonce follows Section 4.4 of [IV-GEN]. The detailed construction of the AEAD nonce is presented here (see Figure 8): 1. left-pad the Partial IV (PIV) with zeroes to exactly 5 bytes, 2. left-pad the Sender ID of the endpoint that generated the Partial IV (ID_PIV) with zeroes to exactly nonce length minus 6 bytes, 3. concatenate the size of the ID_PIV (a single byte S) with the padded ID_PIV and the padded PIV, 4. and then XOR with the Common IV. Note that in this specification, only AEAD algorithms that use nonces equal or greater than 7 bytes are supported. The nonce construction with S, ID_PIV, and PIV together with endpoint-unique IDs and encryption keys makes it easy to verify that the nonces used with a specific key will be unique, see Appendix D.4. If the Partial IV is not present in a response, the nonce from the request is used. For responses that are not notifications (i.e., when there is a single response to a request), the request and the response should typically use the same nonce to reduce message overhead. Both alternatives provide all the required security
properties, see Section 7.4 and Appendix D.4. Another non-Observe scenario where a Partial IV is included in a response is when the server is unable to perform replay protection, see Appendix B.1.2. For processing instructions see Section 8. <- nonce length minus 6 B -> <-- 5 bytes --> +---+-------------------+--------+---------+-----+ | S | padding | ID_PIV | padding | PIV |----+ +---+-------------------+--------+---------+-----+ | | <---------------- nonce length ----------------> | +------------------------------------------------+ | | Common IV |->(XOR) +------------------------------------------------+ | | <---------------- nonce length ----------------> | +------------------------------------------------+ | | Nonce |<---+ +------------------------------------------------+ Figure 8: AEAD Nonce Formation5.3. Plaintext
The plaintext is formatted as a CoAP message with a subset of the header (see Figure 9) consisting of: o the Code of the original CoAP message as defined in Section 3 of [RFC7252]; and o all Inner option message fields (see Section 4.1.1) present in the original CoAP message (see Section 4.1). The options are encoded as described in Section 3.1 of [RFC7252], where the delta is the difference from the previously included instance of Class E option; and o the Payload of original CoAP message, if present, and in that case prefixed by the one-byte Payload Marker (0xff). NOTE: The plaintext contains all CoAP data that needs to be encrypted end-to-end between the endpoints.
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Code | Class E options (if any) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1 1 1 1 1 1 1 1| Payload (if any) ... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ (only if there is payload) Figure 9: Plaintext5.4. Additional Authenticated Data
The external_aad SHALL be a CBOR array wrapped in a bstr object as defined below, following the notation of [RFC8610] as summarized in Appendix E: external_aad = bstr .cbor aad_array aad_array = [ oscore_version : uint, algorithms : [ alg_aead : int / tstr ], request_kid : bstr, request_piv : bstr, options : bstr, ] where: o oscore_version: contains the OSCORE version number. Implementations of this specification MUST set this field to 1. Other values are reserved for future versions. o algorithms: contains (for extensibility) an array of algorithms, according to this specification only containing alg_aead. o alg_aead: contains the AEAD Algorithm from the security context used for the exchange (see Section 3.1). o request_kid: contains the value of the 'kid' in the COSE object of the request (see Section 5). o request_piv: contains the value of the 'Partial IV' in the COSE object of the request (see Section 5).
o options: contains the Class I options (see Section 4.1.2) present in the original CoAP message encoded as described in Section 3.1 of [RFC7252], where the delta is the difference from the previously included instance of class I option. The oscore_version and algorithms parameters are established out-of- band; thus, they are not transported in OSCORE, but the external_aad allows to verify that they are the same in both endpoints. NOTE: The format of the external_aad is, for simplicity, the same for requests and responses, although some parameters, e.g., request_kid, need not be integrity protected in all requests. The AAD is composed from the external_aad as described in Section 5.3 of [RFC8152] (the notation follows [RFC8610] as summarized in Appendix E): AAD = Enc_structure = [ "Encrypt0", h'', external_aad ] The following is an example of AAD constructed using AEAD Algorithm = AES-CCM-16-64-128 (10), request_kid = 0x00, request_piv = 0x25 and no Class I options: o oscore_version: 0x01 (1 byte) o algorithms: 0x810a (2 bytes) o request_kid: 0x00 (1 byte) o request_piv: 0x25 (1 byte) o options: 0x (0 bytes) o aad_array: 0x8501810a4100412540 (9 bytes) o external_aad: 0x498501810a4100412540 (10 bytes) o AAD: 0x8368456e63727970743040498501810a4100412540 (21 bytes) Note that the AAD consists of a fixed string of 11 bytes concatenated with the external_aad.6. OSCORE Header Compression
The Concise Binary Object Representation (CBOR) [RFC7049] combines very small message sizes with extensibility. The CBOR Object Signing and Encryption (COSE) [RFC8152] uses CBOR to create compact encoding of signed and encrypted data. However, COSE is constructed to
support a large number of different stateless use cases and is not fully optimized for use as a stateful security protocol, leading to a larger than necessary message expansion. In this section, we define a stateless header compression mechanism, simply removing redundant information from the COSE objects, which significantly reduces the per-packet overhead. The result of applying this mechanism to a COSE object is called the "compressed COSE object". The COSE_Encrypt0 object used in OSCORE is transported in the OSCORE option and in the Payload. The Payload contains the ciphertext of the COSE object. The headers of the COSE object are compactly encoded as described in the next section.6.1. Encoding of the OSCORE Option Value
The value of the OSCORE option SHALL contain the OSCORE flag bits, the 'Partial IV' parameter, the 'kid context' parameter (length and value), and the 'kid' parameter as follows: 0 1 2 3 4 5 6 7 <------------- n bytes --------------> +-+-+-+-+-+-+-+-+-------------------------------------- |0 0 0|h|k| n | Partial IV (if any) ... +-+-+-+-+-+-+-+-+-------------------------------------- <- 1 byte -> <----- s bytes ------> +------------+----------------------+------------------+ | s (if any) | kid context (if any) | kid (if any) ... | +------------+----------------------+------------------+ Figure 10: The OSCORE Option Value o The first byte, containing the OSCORE flag bits, encodes the following set of bits and the length of the 'Partial IV' parameter: * The three least significant bits encode the Partial IV length n. If n = 0, then the Partial IV is not present in the compressed COSE object. The values n = 6 and n = 7 are reserved. * The fourth least significant bit is the 'kid' flag, k. It is set to 1 if 'kid' is present in the compressed COSE object. * The fifth least significant bit is the 'kid context' flag, h. It is set to 1 if the compressed COSE object contains a 'kid context' (see Section 5.1).
* The sixth-to-eighth least significant bits are reserved for future use. These bits SHALL be set to zero when not in use. According to this specification, if any of these bits are set to 1, the message is considered to be malformed and decompression fails as specified in item 2 of Section 8.2. The flag bits are registered in the "OSCORE Flag Bits" registry specified in Section 13.7. o The following n bytes encode the value of the Partial IV, if the Partial IV is present (n > 0). o The following 1 byte encodes the length s of the 'kid context' (Section 5.1), if the 'kid context' flag is set (h = 1). o The following s bytes encode the 'kid context', if the 'kid context' flag is set (h = 1). o The remaining bytes encode the value of the 'kid', if the 'kid' is present (k = 1). Note that the 'kid' MUST be the last field of the OSCORE option value, even in the case in which reserved bits are used and additional fields are added to it. The length of the OSCORE option thus depends on the presence and length of Partial IV, 'kid context', 'kid', as specified in this section, and on the presence and length of additional parameters, as defined in the future documents registering those parameters.6.2. Encoding of the OSCORE Payload
The payload of the OSCORE message SHALL encode the ciphertext of the COSE object.6.3. Examples of Compressed COSE Objects
This section covers a list of OSCORE Header Compression examples for requests and responses. The examples assume the COSE_Encrypt0 object is set (which means the CoAP message and cryptographic material is known). Note that the full CoAP unprotected message, as well as the full security context, is not reported in the examples, but only the input necessary to the compression mechanism, i.e., the COSE_Encrypt0 object. The output is the compressed COSE object as defined in Section 6, divided into two parts, since the object is transported in two CoAP fields: the OSCORE option and payload.
1. Request with ciphertext = 0xaea0155667924dff8a24e4cb35b9, kid = 0x25, and Partial IV = 0x05 Before compression (24 bytes): [ h'', { 4:h'25', 6:h'05' }, h'aea0155667924dff8a24e4cb35b9', ] After compression (17 bytes): Flag byte: 0b00001001 = 0x09 (1 byte) Option Value: 0x090525 (3 bytes) Payload: 0xaea0155667924dff8a24e4cb35b9 (14 bytes) 2. Request with ciphertext = 0xaea0155667924dff8a24e4cb35b9, kid = empty string, and Partial IV = 0x00 Before compression (23 bytes): [ h'', { 4:h'', 6:h'00' }, h'aea0155667924dff8a24e4cb35b9', ] After compression (16 bytes): Flag byte: 0b00001001 = 0x09 (1 byte) Option Value: 0x0900 (2 bytes) Payload: 0xaea0155667924dff8a24e4cb35b9 (14 bytes) 3. Request with ciphertext = 0xaea0155667924dff8a24e4cb35b9, kid = empty string, Partial IV = 0x05, and kid context = 0x44616c656b Before compression (30 bytes): [ h'', { 4:h'', 6:h'05', 10:h'44616c656b' }, h'aea0155667924dff8a24e4cb35b9', ]
After compression (22 bytes): Flag byte: 0b00011001 = 0x19 (1 byte) Option Value: 0x19050544616c656b (8 bytes) Payload: 0xae a0155667924dff8a24e4cb35b9 (14 bytes) 4. Response with ciphertext = 0xaea0155667924dff8a24e4cb35b9 and no Partial IV Before compression (18 bytes): [ h'', {}, h'aea0155667924dff8a24e4cb35b9', ] After compression (14 bytes): Flag byte: 0b00000000 = 0x00 (1 byte) Option Value: 0x (0 bytes) Payload: 0xaea0155667924dff8a24e4cb35b9 (14 bytes) 5. Response with ciphertext = 0xaea0155667924dff8a24e4cb35b9 and Partial IV = 0x07 Before compression (21 bytes): [ h'', { 6:h'07' }, h'aea0155667924dff8a24e4cb35b9', ] After compression (16 bytes): Flag byte: 0b00000001 = 0x01 (1 byte) Option Value: 0x0107 (2 bytes) Payload: 0xaea0155667924dff8a24e4cb35b9 (14 bytes)