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-linkedin: apply dune fmt

Pure formatting changes from `dune fmt`: doc comment placement moves
from above the binding to below it for `type`s, multi-line `match`
expressions collapse onto one line where they fit, and infix operator
applications pick up spaces (`Soup.($?)` -> `Soup.( $? )`). No
semantic changes.

+123 -2
+112
README.md
··· 1 + # sdls 2 + 3 + CCSDS Space Data Link Security for OCaml. 4 + 5 + `sdls` implements the link-layer security mechanisms of CCSDS 6 + [355.0-B-2][sdls]: authenticated encryption for space frames using 7 + AES-GCM, AES-CCM, or authentication-only with AES-CMAC / HMAC, plus 8 + security associations, keystores, anti-replay windows, and Over- 9 + The-Air Rekeying (OTAR, [355.1-B-1][otar]). Frame protection is 10 + generic over frame type — the caller passes raw header bytes and 11 + plaintext. `sdls-eio` adds file-backed persistence with PBKDF2 / 12 + HKDF key derivation. 13 + 14 + [sdls]: https://public.ccsds.org/Pubs/355x0b2.pdf 15 + [otar]: https://public.ccsds.org/Pubs/355x1b1.pdf 16 + 17 + ## Packages 18 + 19 + - `sdls` — SAs, keystores, frame protect/unprotect, OTAR, wire codecs. 20 + - `sdls-eio` — Eio-based persistence and key derivation. 21 + 22 + ## Installation 23 + 24 + Install with opam: 25 + 26 + <!-- $MDX skip --> 27 + ```sh 28 + $ opam install sdls sdls-eio 29 + ``` 30 + 31 + If opam cannot find the packages, they may not yet be released in 32 + the public `opam-repository`. Add the overlay repository, then 33 + install them: 34 + 35 + <!-- $MDX skip --> 36 + ```sh 37 + $ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git 38 + $ opam update 39 + $ opam install sdls sdls-eio 40 + ``` 41 + 42 + ## Usage 43 + 44 + ### Algorithm registry 45 + 46 + The standard CCSDS algorithm IDs map to typed variants: 47 + 48 + ```ocaml 49 + # Sdls.Algorithm.int_of_encryption Sdls.Algorithm.AES_256_GCM 50 + - : int = 2 51 + # Sdls.Algorithm.encryption_of_int 4 52 + - : Sdls.Algorithm.encryption option = Some Sdls.Algorithm.AES_256_CCM 53 + ``` 54 + 55 + ### Keystore 56 + 57 + An in-memory keystore tracks key material with a per-key lifecycle 58 + (`Pre_active`, `Active`, `Deactivated`, `Destroyed`). `add_for_cipher` 59 + rejects keys whose length is wrong for the advertised cipher suite: 60 + 61 + ```ocaml 62 + # let ks = Sdls.Keystore.in_memory () in 63 + let kid = Sdls.Keyid.of_int_exn 1 in 64 + Sdls.Keystore.add ks kid (Bytes.make 32 '\x00'); 65 + let _ = Sdls.Keystore.activate ks kid in 66 + Sdls.Keystore.list_by_state ks Sdls.Keystore.Active 67 + |> List.map (fun k -> Fmt.str "%a" Sdls.Keyid.pp k) 68 + - : string list = ["1"] 69 + ``` 70 + 71 + `add_for_cipher` validates the length up front: 72 + 73 + ```ocaml 74 + # let ks = Sdls.Keystore.in_memory () in 75 + Sdls.Keystore.add_for_cipher ks (Sdls.Keyid.of_int_exn 2) 76 + Sdls.Keystore.AES_256 (Bytes.make 16 '\x00') 77 + |> Result.is_error 78 + - : bool = true 79 + ``` 80 + 81 + ### Frame protection 82 + 83 + `protect_frame` and `unprotect_frame` are generic over the frame 84 + type — the caller hands in raw header bytes, plaintext, and a 85 + `Binary.Writer.t` / `Binary.Reader.t` pair. The function returns 86 + the updated SA so anti-replay state is persisted on success: 87 + 88 + ```ocaml 89 + let protect ~sa ~keys ~frame_hdr ~plaintext w = 90 + Sdls.protect_frame 91 + ~sa ~keys 92 + ~get_ek:Sdls.Keystore.get_encryption_key 93 + ~get_ak:Sdls.Keystore.get_auth_key 94 + ~frame_hdr_bytes:frame_hdr 95 + ~plaintext 96 + w 97 + ``` 98 + 99 + The pipeline selects AES-GCM vs AES-CCM vs CMAC based on 100 + `Sa.entry.ecs` / `acs`. Authentication-only modes emit a MAC over 101 + the header and plaintext; confidentiality+integrity modes replace 102 + the plaintext with ciphertext and append an authenticator. 103 + 104 + ### Persistence (sdls-eio) 105 + 106 + `sdls-eio` serialises SAs, keystores, and OTAR state through a 107 + pluggable key-value schema, with PBKDF2/HKDF helpers for password- 108 + derived key encryption. 109 + 110 + ## Licence 111 + 112 + ISC
+4
dune
··· 1 1 (env 2 2 (dev 3 3 (flags :standard %{dune-warnings}))) 4 + 5 + (mdx 6 + (files README.md) 7 + (libraries sdls fmt))
+5 -2
dune-project
··· 1 1 (lang dune 3.21) 2 + (using mdx 0.4) 2 3 (name sdls) 3 4 (generate_opam_files true) 4 5 (license ISC) ··· 18 19 (eqaf (>= 0.9)) 19 20 (bitv (>= 1.0)) 20 21 (wire (>= 0.9)) 21 - (alcotest :with-test))) 22 + (alcotest :with-test) 23 + (mdx :with-test))) 22 24 23 25 (package 24 26 (name sdls-eio) ··· 35 37 (pbkdf2 (>= 0.1)) 36 38 (hkdf (>= 0.1)) 37 39 (fmt (>= 0.9)) 38 - (logs (>= 0.7)))) 40 + (logs (>= 0.7)) 41 + (mdx :with-test)))
+1
sdls-eio.opam
··· 20 20 "hkdf" {>= "0.1"} 21 21 "fmt" {>= "0.9"} 22 22 "logs" {>= "0.7"} 23 + "mdx" {with-test} 23 24 "odoc" {with-doc} 24 25 ] 25 26 build: [
+1
sdls.opam
··· 18 18 "bitv" {>= "1.0"} 19 19 "wire" {>= "0.9"} 20 20 "alcotest" {with-test} 21 + "mdx" {with-test} 21 22 "odoc" {with-doc} 22 23 ] 23 24 build: [