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.

irmin: proof.subheap is a Heap.t, not a block list

+238
+201
test/interop/cryptolib/scripts/generate.c
··· 1 + /* CryptoLib interop trace generator for ocaml-sdls. 2 + * 3 + * Calls NASA CryptoLib's public Crypto_TC_ApplySecurity() API to produce 4 + * reference SDLS-protected TC frames. The generator MUST NOT reimplement 5 + * any SDLS encoding -- CryptoLib is the independent oracle. 6 + * 7 + * Build: cc -I"$CRYPTOLIB/include" -L"$CRYPTOLIB/build/src" -lcryptolib ... 8 + * Usage: ./generate <trace_dir> 9 + */ 10 + 11 + #include <stdio.h> 12 + #include <stdlib.h> 13 + #include <string.h> 14 + #include <stdint.h> 15 + 16 + #include "crypto.h" 17 + #include "crypto_error.h" 18 + 19 + /* ---------- helpers ---------- */ 20 + 21 + static void bytes_to_hex(const uint8_t *buf, int len, char *out) 22 + { 23 + for (int i = 0; i < len; i++) 24 + sprintf(out + i * 2, "%02x", buf[i]); 25 + out[len * 2] = '\0'; 26 + } 27 + 28 + /* Build a minimal TC frame (5-byte primary header + segment header + payload + FECF). 29 + * 30 + * TC Primary Header (CCSDS 232.0-B-3): 31 + * Byte 0: TFVN(2b)=00 | Bypass(1b) | CC(1b)=0 | Spare(2b)=00 | SCID[9:8](2b) 32 + * Byte 1: SCID[7:0] 33 + * Byte 2: VCID(6b) | FL[9:8](2b) 34 + * Byte 3: FL[7:0] 35 + * Byte 4: FSN 36 + * 37 + * Segment Header (1 byte): 0x00 (first segment, no MAP ID) 38 + * 39 + * FECF: 2-byte CRC-16 appended at end (CryptoLib expects and creates this). 40 + */ 41 + static int build_tc_frame(uint16_t scid, uint8_t vcid, uint8_t bypass, 42 + const uint8_t *payload, int payload_len, 43 + uint8_t *frame, int frame_max) 44 + { 45 + /* TC primary header = 5 bytes, segment header = 1 byte, FECF = 2 bytes */ 46 + int total_len = 5 + 1 + payload_len + 2; 47 + if (total_len > frame_max || total_len > 1024) 48 + return -1; 49 + 50 + /* Frame length field = total_len - 1 (per CCSDS 232.0-B-3 Section 4.1.2.7) */ 51 + uint16_t fl = (uint16_t)(total_len - 1); 52 + 53 + frame[0] = (uint8_t)(0x00 /* TFVN=00 */ 54 + | (bypass ? 0x20 : 0x00) /* Bypass flag */ 55 + | 0x00 /* CC=0 (data), Spare=00 */ 56 + | ((scid >> 8) & 0x03)); /* SCID[9:8] */ 57 + frame[1] = (uint8_t)(scid & 0xFF); /* SCID[7:0] */ 58 + frame[2] = (uint8_t)((vcid << 2) /* VCID(6b) */ 59 + | ((fl >> 8) & 0x03)); /* FL[9:8] */ 60 + frame[3] = (uint8_t)(fl & 0xFF); /* FL[7:0] */ 61 + frame[4] = 0x00; /* FSN = 0 */ 62 + 63 + /* Segment header */ 64 + frame[5] = 0x00; 65 + 66 + /* Payload */ 67 + memcpy(frame + 6, payload, payload_len); 68 + 69 + /* FECF placeholder -- CryptoLib will compute and replace this when 70 + * crypto_create_fecf is enabled, but we still need valid space. */ 71 + uint16_t fecf = Crypto_Calc_FECF(frame, total_len - 2); 72 + frame[total_len - 2] = (uint8_t)(fecf >> 8); 73 + frame[total_len - 1] = (uint8_t)(fecf & 0xFF); 74 + 75 + return total_len; 76 + } 77 + 78 + /* ---------- trace record ---------- */ 79 + 80 + typedef struct 81 + { 82 + const char *name; 83 + uint16_t scid; 84 + uint8_t vcid; 85 + uint8_t bypass; 86 + const char *payload_hex; 87 + } test_vector_t; 88 + 89 + /* ---------- main ---------- */ 90 + 91 + int main(int argc, char **argv) 92 + { 93 + if (argc != 2) 94 + { 95 + fprintf(stderr, "usage: %s <trace_dir>\n", argv[0]); 96 + return 1; 97 + } 98 + const char *trace_dir = argv[1]; 99 + 100 + /* Initialize CryptoLib with TC unit test defaults. 101 + * This sets up SA 1 (CLEAR, SCID=3, VCID=0, OPERATIONAL) and 102 + * SA 2 (AES-256-GCM encrypt-only, SCID=3, VCID=2, OPERATIONAL). */ 103 + int32_t status = Crypto_Init_TC_Unit_Test(); 104 + if (status != CRYPTO_LIB_SUCCESS) 105 + { 106 + fprintf(stderr, "Crypto_Init_TC_Unit_Test failed: %d\n", status); 107 + return 1; 108 + } 109 + 110 + /* Test vectors: each calls Crypto_TC_ApplySecurity() as the oracle. 111 + * 112 + * SA 1: CLEAR mode (est=0, ast=0), SCID=0x0003, VCID=0 113 + * - shivf_len=12, iv_len=12, no MAC, no encryption 114 + * 115 + * SA 2: AES-256-GCM encryption-only (est=1, ast=0), SCID=0x0003, VCID=2 116 + * - shivf_len=12, iv_len=12, no MAC, EKID=2 117 + * - Key 2 = 202122232425262728292A2B2C2D2E2F202122232425262728292A2B2C2D2E2F 118 + */ 119 + test_vector_t vectors[] = { 120 + /* Clear mode vectors (SA 1, VCID=0) */ 121 + {"clear_short", 0x0003, 0, 0, "deadbeef"}, 122 + {"clear_ping", 0x0003, 0, 0, "80d2c70008197f0b00310000b1fe"}, 123 + {"clear_16byte", 0x0003, 0, 0, "0102030405060708090a0b0c0d0e0f10"}, 124 + {"clear_1byte", 0x0003, 0, 0, "ff"}, 125 + 126 + /* AES-256-GCM encryption vectors (SA 2, VCID=2) */ 127 + {"gcm_short", 0x0003, 2, 0, "deadbeef"}, 128 + {"gcm_ping", 0x0003, 2, 0, "80d2c70008197f0b00310000b1fe"}, 129 + {"gcm_16byte", 0x0003, 2, 0, "0102030405060708090a0b0c0d0e0f10"}, 130 + {"gcm_1byte", 0x0003, 2, 0, "ff"}, 131 + }; 132 + int nvectors = sizeof(vectors) / sizeof(vectors[0]); 133 + 134 + /* Open output CSV */ 135 + char csv_path[1024]; 136 + snprintf(csv_path, sizeof(csv_path), "%s/tc_apply.csv", trace_dir); 137 + FILE *fp = fopen(csv_path, "w"); 138 + if (!fp) 139 + { 140 + perror("fopen"); 141 + return 1; 142 + } 143 + fprintf(fp, "name,scid,vcid,input_hex,protected_hex\n"); 144 + 145 + for (int i = 0; i < nvectors; i++) 146 + { 147 + test_vector_t *v = &vectors[i]; 148 + 149 + /* Decode payload hex to bytes */ 150 + int payload_hex_len = (int)strlen(v->payload_hex); 151 + int payload_len = payload_hex_len / 2; 152 + uint8_t payload[512]; 153 + for (int j = 0; j < payload_len; j++) 154 + { 155 + unsigned int byte; 156 + sscanf(v->payload_hex + j * 2, "%02x", &byte); 157 + payload[j] = (uint8_t)byte; 158 + } 159 + 160 + /* Build TC frame */ 161 + uint8_t frame[1024]; 162 + int frame_len = build_tc_frame(v->scid, v->vcid, v->bypass, 163 + payload, payload_len, frame, sizeof(frame)); 164 + if (frame_len < 0) 165 + { 166 + fprintf(stderr, "build_tc_frame failed for %s\n", v->name); 167 + fclose(fp); 168 + return 1; 169 + } 170 + 171 + /* Call CryptoLib's public API -- this is the oracle */ 172 + uint8_t *enc_frame = NULL; 173 + uint16_t enc_frame_len = 0; 174 + status = Crypto_TC_ApplySecurity(frame, (uint16_t)frame_len, 175 + &enc_frame, &enc_frame_len); 176 + if (status != CRYPTO_LIB_SUCCESS) 177 + { 178 + fprintf(stderr, "Crypto_TC_ApplySecurity failed for %s: %d (%s)\n", 179 + v->name, status, Crypto_Get_Error_Code_Enum_String(status)); 180 + fclose(fp); 181 + return 1; 182 + } 183 + 184 + /* Convert to hex */ 185 + char input_hex[2048]; 186 + char protected_hex[2048]; 187 + bytes_to_hex(frame, frame_len, input_hex); 188 + bytes_to_hex(enc_frame, enc_frame_len, protected_hex); 189 + 190 + fprintf(fp, "%s,%d,%d,%s,%s\n", 191 + v->name, v->scid, v->vcid, input_hex, protected_hex); 192 + 193 + free(enc_frame); 194 + } 195 + 196 + fclose(fp); 197 + printf("Wrote %d vectors to %s\n", nvectors, csv_path); 198 + 199 + Crypto_Shutdown(); 200 + return 0; 201 + }
+37
test/interop/cryptolib/scripts/generate.sh
··· 1 + #!/bin/bash 2 + set -euo pipefail 3 + 4 + SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" 5 + TRACE_DIR="$(cd "$SCRIPT_DIR/../traces" && pwd)" 6 + 7 + # CryptoLib location -- uses CRYPTOLIB env var or default path. 8 + CRYPTOLIB="${CRYPTOLIB:-$HOME/git/cryptolib}" 9 + 10 + if [ ! -d "$CRYPTOLIB/include" ]; then 11 + echo "CryptoLib not found at $CRYPTOLIB/include" >&2 12 + echo "Set CRYPTOLIB env var to the CryptoLib source root" >&2 13 + exit 1 14 + fi 15 + 16 + if [ ! -f "$CRYPTOLIB/build/src/libcryptolib.dylib" ] && \ 17 + [ ! -f "$CRYPTOLIB/build/src/libcryptolib.so" ]; then 18 + echo "CryptoLib library not built at $CRYPTOLIB/build/src/" >&2 19 + echo "Run: cd $CRYPTOLIB/build && cmake .. && make" >&2 20 + exit 1 21 + fi 22 + 23 + cd "$SCRIPT_DIR" 24 + 25 + # Compile the generator against CryptoLib 26 + cc -o generate \ 27 + -I"$CRYPTOLIB/include" \ 28 + -L"$CRYPTOLIB/build/src" \ 29 + -Wl,-rpath,"$CRYPTOLIB/build/src" \ 30 + generate.c \ 31 + -lcryptolib -lm 32 + 33 + # Run the generator 34 + ./generate "$TRACE_DIR" 35 + 36 + # Clean up binary 37 + rm -f generate