CCSDS Space Data Link Security (355.0-B-2)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

OCaml 88.1%
C 9.2%
PHP 0.5%
Roff 0.2%
Shell 0.2%
Dune 0.2%
Other 1.5%
48 1 0

Clone this repository

https://tangled.org/gazagnaire.org/ocaml-sdls https://tangled.org/did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-sdls
git@git.recoil.org:gazagnaire.org/ocaml-sdls git@git.recoil.org:did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-sdls

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

sdls#

CCSDS Space Data Link Security for OCaml.

sdls implements the link-layer security mechanisms of CCSDS 355.0-B-2: authenticated encryption for space frames using AES-GCM, AES-CCM, or authentication-only with AES-CMAC / HMAC, plus security associations, keystores, anti-replay windows, and Over- The-Air Rekeying (OTAR, 355.1-B-1). Frame protection is generic over frame type — the caller passes raw header bytes and plaintext. sdls-eio adds file-backed persistence with PBKDF2 / HKDF key derivation.

Packages#

  • sdls — SAs, keystores, frame protect/unprotect, OTAR, wire codecs.
  • sdls-eio — Eio-based persistence and key derivation.

Installation#

Install with opam:

$ opam install sdls sdls-eio

If opam cannot find the packages, they may not yet be released in the public opam-repository. Add the overlay repository, then install them:

$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install sdls sdls-eio

Usage#

Algorithm registry#

The standard CCSDS algorithm IDs map to typed variants:

# Sdls.Algorithm.int_of_encryption Sdls.Algorithm.AES_256_GCM
- : int = 2
# Sdls.Algorithm.encryption_of_int 4
- : Sdls.Algorithm.encryption option = Some Sdls.Algorithm.AES_256_CCM

Keystore#

An in-memory keystore tracks key material with a per-key lifecycle (Pre_active, Active, Deactivated, Destroyed). add_for_cipher rejects keys whose length is wrong for the advertised cipher suite:

# let ks = Sdls.Keystore.in_memory () in
  let kid = Sdls.Keyid.of_int_exn 1 in
  Sdls.Keystore.add ks kid (Bytes.make 32 '\x00');
  let _ = Sdls.Keystore.activate ks kid in
  Sdls.Keystore.list_by_state ks Sdls.Keystore.Active
  |> List.map (fun k -> Fmt.str "%a" Sdls.Keyid.pp k)
- : string list = ["1"]

add_for_cipher validates the length up front:

# let ks = Sdls.Keystore.in_memory () in
  Sdls.Keystore.add_for_cipher ks (Sdls.Keyid.of_int_exn 2)
    Sdls.Keystore.AES_256 (Bytes.make 16 '\x00')
  |> Result.is_error
- : bool = true

Frame protection#

protect_frame and unprotect_frame are generic over the frame type — the caller hands in raw header bytes, plaintext, and a Binary.Writer.t / Binary.Reader.t pair. The function returns the updated SA so anti-replay state is persisted on success:

let protect ~sa ~keys ~frame_hdr ~plaintext w =
  Sdls.protect_frame
    ~sa ~keys
    ~get_ek:Sdls.Keystore.get_encryption_key
    ~get_ak:Sdls.Keystore.get_auth_key
    ~frame_hdr_bytes:frame_hdr
    ~plaintext
    w

The pipeline selects AES-GCM vs AES-CCM vs CMAC based on Sa.entry.ecs / acs. Authentication-only modes emit a MAC over the header and plaintext; confidentiality+integrity modes replace the plaintext with ciphertext and append an authenticator.

Persistence (sdls-eio)#

sdls-eio serialises SAs, keystores, and OTAR state through a pluggable key-value schema, with PBKDF2/HKDF helpers for password- derived key encryption.

Licence#

ISC