OSCORE (OSCORE v0.1.0)

Copy Markdown View Source

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.

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

error_reason()

@type error_reason() ::
  :sequence_number_exhausted
  | :malformed_option
  | :malformed_plaintext
  | :decryption_failed
  | :unknown_kid
  | :replayed
  | :too_old

An atom describing why an OSCORE operation failed.

Functions

derive_context(opts)

@spec derive_context(keyword()) :: {:ok, OSCORE.Context.t()}

Derives a Security Context (RFC 8613 §3.2) from a Master Secret and the Sender/Recipient IDs.

Options

  • :master_secret (required)
  • :sender_id (required)
  • :recipient_id (required)
  • :master_salt - defaults to <<>> (the RFC 8613 default)
  • :id_context - defaults to nil (not present)

protect_request(context, opts)

@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 <<>>

protect_response(context, echo, opts)

@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

unprotect_request(context, opts)

@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 <<>>

unprotect_response(context, echo, opts)

@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 <<>>