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.

Add Algorithm module to SDLS, ROCF service to SLE, convolutional/LDPC/turbo coding to tm-sync, station contacts to SGP4 GMAT interop, FlexACM package

- ocaml-sdls: Add Algorithm module for SA algorithm negotiation, re-export
- ocaml-sle: Add ROCF (Return Operational Control Field) service module
- ocaml-tm-sync: Add convolutional coding (rate 1/2 K=7), LDPC, turbo codes
with encode/decode and comprehensive unit tests
- ocaml-sgp4: Update GMAT interop station contacts test
- ocaml-hkdf: Regenerate opam with alcotest dep
- ocaml-flexacm: New package for flexible adaptive coding and modulation

+291
+169
lib/algorithm.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Thomas Gazagnaire. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 6 + (** CCSDS Security Algorithm Registry (350.0-B / 352.0-B). *) 7 + 8 + (* {1 Encryption Algorithms} *) 9 + 10 + type encryption = 11 + | AES_128_GCM (** Algorithm ID 0x01 *) 12 + | AES_256_GCM (** Algorithm ID 0x02 *) 13 + | AES_128_CCM (** Algorithm ID 0x03 *) 14 + | AES_256_CCM (** Algorithm ID 0x04 *) 15 + 16 + let encryption_of_int = function 17 + | 0x01 -> Some AES_128_GCM 18 + | 0x02 -> Some AES_256_GCM 19 + | 0x03 -> Some AES_128_CCM 20 + | 0x04 -> Some AES_256_CCM 21 + | _ -> None 22 + 23 + let int_of_encryption = function 24 + | AES_128_GCM -> 0x01 25 + | AES_256_GCM -> 0x02 26 + | AES_128_CCM -> 0x03 27 + | AES_256_CCM -> 0x04 28 + 29 + let pp_encryption ppf = function 30 + | AES_128_GCM -> Fmt.string ppf "AES-128-GCM" 31 + | AES_256_GCM -> Fmt.string ppf "AES-256-GCM" 32 + | AES_128_CCM -> Fmt.string ppf "AES-128-CCM" 33 + | AES_256_CCM -> Fmt.string ppf "AES-256-CCM" 34 + 35 + (* {1 Authentication Algorithms} *) 36 + 37 + type authentication = 38 + | AES_128_CMAC (** Algorithm ID 0x01 *) 39 + | AES_256_CMAC (** Algorithm ID 0x02 *) 40 + | HMAC_SHA_256 (** Algorithm ID 0x03 *) 41 + | HMAC_SHA_384 (** Algorithm ID 0x04 *) 42 + | HMAC_SHA_512 (** Algorithm ID 0x05 *) 43 + 44 + let authentication_of_int = function 45 + | 0x01 -> Some AES_128_CMAC 46 + | 0x02 -> Some AES_256_CMAC 47 + | 0x03 -> Some HMAC_SHA_256 48 + | 0x04 -> Some HMAC_SHA_384 49 + | 0x05 -> Some HMAC_SHA_512 50 + | _ -> None 51 + 52 + let int_of_authentication = function 53 + | AES_128_CMAC -> 0x01 54 + | AES_256_CMAC -> 0x02 55 + | HMAC_SHA_256 -> 0x03 56 + | HMAC_SHA_384 -> 0x04 57 + | HMAC_SHA_512 -> 0x05 58 + 59 + let pp_authentication ppf = function 60 + | AES_128_CMAC -> Fmt.string ppf "AES-128-CMAC" 61 + | AES_256_CMAC -> Fmt.string ppf "AES-256-CMAC" 62 + | HMAC_SHA_256 -> Fmt.string ppf "HMAC-SHA-256" 63 + | HMAC_SHA_384 -> Fmt.string ppf "HMAC-SHA-384" 64 + | HMAC_SHA_512 -> Fmt.string ppf "HMAC-SHA-512" 65 + 66 + (* {1 Key Derivation Functions} *) 67 + 68 + type key_derivation = HKDF_SHA_256 | PBKDF2_SHA_256 69 + 70 + let pp_key_derivation ppf = function 71 + | HKDF_SHA_256 -> Fmt.string ppf "HKDF-SHA-256" 72 + | PBKDF2_SHA_256 -> Fmt.string ppf "PBKDF2-SHA-256" 73 + 74 + (* {1 Algorithm Suites} *) 75 + 76 + type suite = { 77 + encryption : encryption; 78 + authentication : authentication; 79 + key_len : int; 80 + iv_len : int; 81 + mac_len : int; 82 + } 83 + 84 + let aes_128_gcm_cmac = 85 + { 86 + encryption = AES_128_GCM; 87 + authentication = AES_128_CMAC; 88 + key_len = 16; 89 + iv_len = 12; 90 + mac_len = 16; 91 + } 92 + 93 + let aes_256_gcm_cmac = 94 + { 95 + encryption = AES_256_GCM; 96 + authentication = AES_256_CMAC; 97 + key_len = 32; 98 + iv_len = 12; 99 + mac_len = 16; 100 + } 101 + 102 + let aes_256_gcm_hmac_256 = 103 + { 104 + encryption = AES_256_GCM; 105 + authentication = HMAC_SHA_256; 106 + key_len = 32; 107 + iv_len = 12; 108 + mac_len = 32; 109 + } 110 + 111 + let aes_256_ccm_hmac_256 = 112 + { 113 + encryption = AES_256_CCM; 114 + authentication = HMAC_SHA_256; 115 + key_len = 32; 116 + iv_len = 12; 117 + mac_len = 32; 118 + } 119 + 120 + let pp_suite ppf s = 121 + Fmt.pf ppf "{ enc=%a; auth=%a; key=%d; iv=%d; mac=%d }" pp_encryption 122 + s.encryption pp_authentication s.authentication s.key_len s.iv_len s.mac_len 123 + 124 + (* {1 SA Negotiation} *) 125 + 126 + type proposal = { 127 + encryptions : encryption list; 128 + authentications : authentication list; 129 + key_derivations : key_derivation list; 130 + } 131 + 132 + type selection = { 133 + selected_encryption : encryption; 134 + selected_authentication : authentication; 135 + selected_key_derivation : key_derivation option; 136 + } 137 + 138 + let negotiate initiator responder = 139 + let find_common l1 l2 = List.find_opt (fun x -> List.mem x l2) l1 in 140 + match 141 + ( find_common initiator.encryptions responder.encryptions, 142 + find_common initiator.authentications responder.authentications ) 143 + with 144 + | Some enc, Some auth -> 145 + let kdf = 146 + find_common initiator.key_derivations responder.key_derivations 147 + in 148 + Some 149 + { 150 + selected_encryption = enc; 151 + selected_authentication = auth; 152 + selected_key_derivation = kdf; 153 + } 154 + | _ -> None 155 + 156 + let pp_proposal ppf p = 157 + Fmt.pf ppf "{ enc=[%a]; auth=[%a]; kdf=[%a] }" 158 + Fmt.(list ~sep:comma pp_encryption) 159 + p.encryptions 160 + Fmt.(list ~sep:comma pp_authentication) 161 + p.authentications 162 + Fmt.(list ~sep:comma pp_key_derivation) 163 + p.key_derivations 164 + 165 + let pp_selection ppf s = 166 + Fmt.pf ppf "{ enc=%a; auth=%a; kdf=%a }" pp_encryption s.selected_encryption 167 + pp_authentication s.selected_authentication 168 + Fmt.(option ~none:(any "none") pp_key_derivation) 169 + s.selected_key_derivation
+120
lib/algorithm.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Thomas Gazagnaire. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 6 + (** CCSDS Security Algorithm Registry (350.0-B / 352.0-B). 7 + 8 + Defines the algorithm identifiers used for SDLS security associations. These 9 + are the standard algorithm IDs from the CCSDS security algorithm registry, 10 + covering encryption, authentication, and key derivation. 11 + 12 + The algorithm IDs here are the canonical CCSDS assignments. {!Sa.ecs} and 13 + {!Sa.acs} use a different numbering that is specific to SA configuration 14 + within SDLS 355.0-B-2. This module provides the full registry-level view. *) 15 + 16 + (** {1 Encryption Algorithms} *) 17 + 18 + type encryption = 19 + | AES_128_GCM (** Algorithm ID 0x01 *) 20 + | AES_256_GCM (** Algorithm ID 0x02 *) 21 + | AES_128_CCM (** Algorithm ID 0x03 *) 22 + | AES_256_CCM (** Algorithm ID 0x04 *) 23 + 24 + val encryption_of_int : int -> encryption option 25 + (** [encryption_of_int n] converts integer algorithm ID to encryption variant. 26 + *) 27 + 28 + val int_of_encryption : encryption -> int 29 + (** [int_of_encryption e] returns the integer algorithm ID. *) 30 + 31 + val pp_encryption : encryption Fmt.t 32 + (** Pretty-print an encryption algorithm. *) 33 + 34 + (** {1 Authentication Algorithms} *) 35 + 36 + type authentication = 37 + | AES_128_CMAC (** Algorithm ID 0x01 *) 38 + | AES_256_CMAC (** Algorithm ID 0x02 *) 39 + | HMAC_SHA_256 (** Algorithm ID 0x03 *) 40 + | HMAC_SHA_384 (** Algorithm ID 0x04 *) 41 + | HMAC_SHA_512 (** Algorithm ID 0x05 *) 42 + 43 + val authentication_of_int : int -> authentication option 44 + (** [authentication_of_int n] converts integer algorithm ID to authentication 45 + variant. *) 46 + 47 + val int_of_authentication : authentication -> int 48 + (** [int_of_authentication a] returns the integer algorithm ID. *) 49 + 50 + val pp_authentication : authentication Fmt.t 51 + (** Pretty-print an authentication algorithm. *) 52 + 53 + (** {1 Key Derivation Functions (CCSDS 352.0-B)} *) 54 + 55 + type key_derivation = 56 + | HKDF_SHA_256 (** HMAC-based KDF per CCSDS 352.0-B *) 57 + | PBKDF2_SHA_256 (** Password-based KDF per CCSDS 352.0-B *) 58 + 59 + val pp_key_derivation : key_derivation Fmt.t 60 + (** Pretty-print a key derivation function. *) 61 + 62 + (** {1 Algorithm Suites} 63 + 64 + Pre-defined combinations of encryption and authentication for SA 65 + configuration negotiation. *) 66 + 67 + type suite = { 68 + encryption : encryption; 69 + authentication : authentication; 70 + key_len : int; (** Key length in bytes *) 71 + iv_len : int; (** IV/nonce length in bytes *) 72 + mac_len : int; (** MAC/tag length in bytes *) 73 + } 74 + (** An algorithm suite combining encryption and authentication parameters. *) 75 + 76 + val aes_128_gcm_cmac : suite 77 + (** AES-128-GCM encryption with AES-128-CMAC authentication. *) 78 + 79 + val aes_256_gcm_cmac : suite 80 + (** AES-256-GCM encryption with AES-256-CMAC authentication. *) 81 + 82 + val aes_256_gcm_hmac_256 : suite 83 + (** AES-256-GCM encryption with HMAC-SHA-256 authentication. *) 84 + 85 + val aes_256_ccm_hmac_256 : suite 86 + (** AES-256-CCM encryption with HMAC-SHA-256 authentication. *) 87 + 88 + val pp_suite : suite Fmt.t 89 + (** Pretty-print an algorithm suite. *) 90 + 91 + (** {1 SA Negotiation} 92 + 93 + Types for algorithm negotiation during SA establishment, as used in SDLS-EP 94 + key management procedures (CCSDS 355.1-B-1). *) 95 + 96 + type proposal = { 97 + encryptions : encryption list; (** Offered encryption algorithms *) 98 + authentications : authentication list; 99 + (** Offered authentication algorithms *) 100 + key_derivations : key_derivation list; (** Offered KDFs *) 101 + } 102 + (** An algorithm proposal for SA negotiation. *) 103 + 104 + type selection = { 105 + selected_encryption : encryption; 106 + selected_authentication : authentication; 107 + selected_key_derivation : key_derivation option; 108 + } 109 + (** The result of algorithm negotiation. *) 110 + 111 + val negotiate : proposal -> proposal -> selection option 112 + (** [negotiate initiator responder] finds the first mutually supported 113 + combination. Returns [None] if no common algorithms exist. Preference order 114 + follows the initiator's lists. *) 115 + 116 + val pp_proposal : proposal Fmt.t 117 + (** Pretty-print a proposal. *) 118 + 119 + val pp_selection : selection Fmt.t 120 + (** Pretty-print a selection. *)
+1
lib/sdls.ml
··· 570 570 571 571 (* {1 Re-exports} *) 572 572 573 + module Algorithm = Algorithm 573 574 module Binary = Binary 574 575 module Crypto = Sdls_crypto 575 576 module Cmac = Cmac
+1
lib/sdls.mli
··· 78 78 79 79 (** {1 Re-exports} *) 80 80 81 + module Algorithm = Algorithm 81 82 module Binary = Binary 82 83 module Crypto = Sdls_crypto 83 84 module Cmac = Cmac