MatterEx.CASE.Messages (matter_ex v0.4.0)

Copy Markdown View Source

TLV codec for CASE Sigma protocol messages.

Each message type has an encode and decode function. Encoding produces a TLV binary; decoding returns a plain map.

Summary

Functions

build_tbs(noc, icac, sender_eph_pub, receiver_eph_pub)

@spec build_tbs(binary(), binary() | nil, binary(), binary()) :: binary()

Build TBS (to-be-signed) data as a TLV structure.

Matter CASE TBS contains:

  • Tag 1: Sender NOC certificate
  • Tag 2: Sender ICAC certificate (optional)
  • Tag 3: Sender ephemeral public key (65 bytes)
  • Tag 4: Receiver ephemeral public key (65 bytes)

compute_destination_id(ipk, initiator_random, root_public_key, fabric_id, node_id)

@spec compute_destination_id(
  binary(),
  binary(),
  binary(),
  non_neg_integer(),
  non_neg_integer()
) ::
  binary()

Compute CASE destination identifier.

dest_id = HMAC-SHA256(IPK, initiator_random || root_public_key || fabric_id_le64 || node_id_le64)

The root_public_key is the full 65-byte uncompressed EC point (including 0x04 prefix).

decode_noc(data)

@spec decode_noc(binary()) :: {:ok, map()} | {:error, :invalid_message}

Decode a NOC. Accepts both X.509 DER certificates (as sent by chip-tool) and the simplified TLV format used in internal tests.

decode_sigma1(data)

@spec decode_sigma1(binary()) :: {:ok, map()} | {:error, :invalid_message}

decode_sigma2(data)

@spec decode_sigma2(binary()) :: {:ok, map()} | {:error, :invalid_message}

decode_sigma3(data)

@spec decode_sigma3(binary()) :: {:ok, map()} | {:error, :invalid_message}

decode_tbe_data2(data)

@spec decode_tbe_data2(binary()) :: {:ok, map()} | {:error, :invalid_message}

decode_tbe_data3(data)

@spec decode_tbe_data3(binary()) :: {:ok, map()} | {:error, :invalid_message}

decrypt_tbe(which, key, data)

@spec decrypt_tbe(:sigma2 | :sigma3, binary(), binary()) :: {:ok, binary()} | :error

Decrypt TBE data with AES-128-CCM.

default_session_parameters()

@spec default_session_parameters() :: map()

Default secure-channel session parameters.

These mirror the fields emitted by connectedhomeip's PairingSession EncodeSessionParameters: MRP timings plus protocol revision hints.

derive_sigma2_key(ipk, shared_secret, responder_random, responder_eph_pub, transcript_hash)

@spec derive_sigma2_key(binary(), binary(), binary(), binary(), binary()) :: binary()

Derive S2K key for Sigma2 TBE encryption.

Salt = IPK(16) || responder_random(32) || responder_eph_pub(65) || transcript_hash(32) = 145 bytes. The transcript_hash is SHA256 of sigma1 payload only.

derive_sigma3_key(ipk, shared_secret, transcript_hash)

@spec derive_sigma3_key(binary(), binary(), binary()) :: binary()

Derive S3K key for Sigma3 TBE encryption.

Salt = IPK(16) || transcript_hash(32) = 48 bytes. The transcript_hash is SHA256 of sigma1 || sigma2 payloads.

encode_noc(node_id, fabric_id, public_key)

@spec encode_noc(non_neg_integer(), non_neg_integer(), binary()) :: binary()

Encode a simplified NOC containing node_id, fabric_id, and public_key.

encode_sigma1(initiator_random, session_id, destination_id, eph_pub)

@spec encode_sigma1(binary(), non_neg_integer(), binary(), binary()) :: binary()

encode_sigma2(responder_random, session_id, eph_pub, encrypted2)

@spec encode_sigma2(binary(), non_neg_integer(), binary(), binary()) :: binary()

encode_sigma2(responder_random, session_id, eph_pub, encrypted2, session_params)

@spec encode_sigma2(binary(), non_neg_integer(), binary(), binary(), map() | nil) ::
  binary()

encode_sigma3(encrypted3)

@spec encode_sigma3(binary()) :: binary()

encode_tbe_data2(noc, icac, signature, resumption_id)

@spec encode_tbe_data2(binary(), binary() | nil, binary(), binary()) :: binary()

encode_tbe_data3(noc, icac, signature)

@spec encode_tbe_data3(binary(), binary() | nil, binary()) :: binary()

encrypt_tbe(which, key, plaintext)

@spec encrypt_tbe(:sigma2 | :sigma3, binary(), binary()) :: binary()

Encrypt TBE data with AES-128-CCM. Returns ciphertext <> tag.

extract_public_key(data)

@spec extract_public_key(binary()) :: binary() | nil

Extract the public key from an X.509 DER certificate.

Returns the raw EC point (65 bytes for P-256 uncompressed) or nil. Works with any X.509 cert (root CA, ICAC, or NOC).