RFC 8613 (OSCORE) message protection for CoAP, with the crypto/protocol core implemented in Rust.
This module handles security context derivation, message protection and
verification, and replay-window bookkeeping. Full CoAP message framing and
OSCORE option classification (Class E/I/U, see RFC 8613 §4.1) are the
caller's responsibility: inner_options is the already-serialized CoAP
Class E options to encrypt, and class_i_options is the already-serialized
Class I options to authenticate (unencrypted).
Only the mandatory AES-CCM-16-64-128 / HKDF-SHA-256 suite is supported.
Summary
Types
An atom describing why an OSCORE operation failed.
Functions
Derives a Security Context (RFC 8613 §3.2) from a Master Secret and the Sender/Recipient IDs.
Protects an outgoing CoAP request (RFC 8613 §8.1).
Protects an outgoing CoAP response (RFC 8613 §8.3) matching echo.
Returns the next Sender Sequence Number ctx will use to protect an outgoing
message.
Verifies an incoming CoAP request (RFC 8613 §8.2): decrypts it and checks the Replay Window.
Verifies an incoming CoAP response (RFC 8613 §8.4) against the
RequestEcho of the request it answers.
Types
Functions
@spec derive_context(keyword()) :: {:ok, OSCORE.Context.t()} | {:error, error_reason()}
Derives a Security Context (RFC 8613 §3.2) from a Master Secret and the Sender/Recipient IDs.
Sender and Recipient IDs must be at most 7 bytes (the AEAD nonce length
minus 6, per RFC 8613 §3.3); a longer ID returns {:error, :id_too_long}.
Options
:master_secret(required):sender_id(required):recipient_id(required):master_salt- defaults to<<>>(the RFC 8613 default):id_context- defaults tonil(not present):sender_seq- the initial Sender Sequence Number, defaults to0. Restore a persisted value here to avoid AEAD nonce reuse across restarts (RFC 8613 Appendix B.1); seesender_seq/1.
@spec protect_request( OSCORE.Context.t(), keyword() ) :: {:ok, OSCORE.Protected.t(), OSCORE.RequestEcho.t()} | {:error, error_reason()}
Protects an outgoing CoAP request (RFC 8613 §8.1).
Encrypts code, inner_options, and payload under a freshly
incremented Sender Sequence Number, and returns the protected message
along with a RequestEcho that must be kept around to later protect or
verify the matching response.
Options
:code(required):inner_options- defaults to<<>>:payload- defaults to<<>>
@spec protect_response(OSCORE.Context.t(), OSCORE.RequestEcho.t(), keyword()) :: {:ok, OSCORE.Protected.t()} | {:error, error_reason()}
Protects an outgoing CoAP response (RFC 8613 §8.3) matching echo.
By default reuses the request's AEAD nonce (no Partial IV is sent - the
common case for a single response). Pass partial_iv: :new to generate a
fresh Partial IV instead, as required for Observe notifications after the
first one.
Options
:code(required):inner_options- defaults to<<>>:payload- defaults to<<>>:partial_iv-:reuse_request(default) or:new
@spec sender_seq(OSCORE.Context.t()) :: non_neg_integer()
Returns the next Sender Sequence Number ctx will use to protect an outgoing
message.
Persist this value and restore it via derive_context/1's :sender_seq
option after a restart so the same AEAD nonce is never reused under the same
key (RFC 8613 Appendix B.1). Persist it before the message that consumes it
is sent (and consider restoring to the persisted value plus a safety margin),
since a crash between using and persisting a sequence number would otherwise
reuse it.
@spec unprotect_request( OSCORE.Context.t(), keyword() ) :: {:ok, code :: byte(), inner_options :: binary(), payload :: binary(), OSCORE.RequestEcho.t()} | {:error, error_reason()}
Verifies an incoming CoAP request (RFC 8613 §8.2): decrypts it and checks the Replay Window.
Returns the decrypted code, inner_options, and payload, plus the
RequestEcho needed to protect the matching response.
Options
:oscore_option(required):ciphertext(required):class_i_options- defaults to<<>>
@spec unprotect_response(OSCORE.Context.t(), OSCORE.RequestEcho.t(), keyword()) :: {:ok, code :: byte(), inner_options :: binary(), payload :: binary()} | {:error, error_reason()}
Verifies an incoming CoAP response (RFC 8613 §8.4) against the
RequestEcho of the request it answers.
Options
:oscore_option(required):ciphertext(required):class_i_options- defaults to<<>>