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