beaconcrypt 0.6.0

Cryptographic transport for C2 channels
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
#ifndef _BEACON_CRYPT_H_
#define _BEACON_CRYPT_H_

/* Generated with cbindgen:0.29.4 */

// Do not modify manually.

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

/**
 * Maximum complete encoded transport message size in bytes, including all framing.
 */
#define beaconcrypt_MAX_MESSAGE_SIZE 33554432



#define beaconcrypt_KDF_STATE_SIZE 32

/**
 * crypto_aead::chacha20poly1305_ietf::KEYBYTES
 */
#define beaconcrypt_AEAD_KEY_LEN 32

/**
 * crypto_aead::chacha20poly1305_ietf::NPUBBYTES
 */
#define beaconcrypt_AEAD_NONCE_LEN 12

/**
 * crypto_aead::chacha20poly1305_ietf::ABYTES
 */
#define beaconcrypt_AEAD_TAG_LEN 16

#define beaconcrypt_KDF_RATCHET_OUTPUT_LEN ((beaconcrypt_AEAD_KEY_LEN + beaconcrypt_KDF_STATE_SIZE) + beaconcrypt_AEAD_NONCE_LEN)

#define beaconcrypt_RATCHET_MAX_GAP 50

#define beaconcrypt_COMMITMENT_SIZE 64

#define beaconcrypt_MESSAGE_OVERHEAD (beaconcrypt_COMMITMENT_SIZE + beaconcrypt_AEAD_TAG_LEN)

#define beaconcrypt_KEX_KDF_OUT_LEN 32

/**
 * crypto_scalarmult::BYTES
 */
#define beaconcrypt_DH_OUT_LEN 32

#define beaconcrypt_ED25519_SEED_SIZE 32

#define beaconcrypt_STATUS_OK 0

#define beaconcrypt_STATUS_REJECTED 1

#define beaconcrypt_STATUS_INVALID_ARGUMENT 2

#define beaconcrypt_STATUS_MISSING_SNAPSHOT 3

#define beaconcrypt_STATUS_INVALID_SNAPSHOT 4

#define beaconcrypt_STATUS_NON_CANONICAL_SNAPSHOT 5

#define beaconcrypt_STATUS_STALE_GENERATION 6

#define beaconcrypt_STATUS_GENERATION_EXHAUSTED 7

#define beaconcrypt_STATUS_ENCODING 8

#define beaconcrypt_STATUS_OUTPUT_ENCODING 9

#define beaconcrypt_STATUS_INITIALIZATION 10

#define beaconcrypt_STATUS_DIGEST 11

#define beaconcrypt_STATUS_POISONED 12

/**
 * Opaque beacon handle exposed by the C API and owned by its caller.
 */
typedef struct beaconcrypt_Beacon beaconcrypt_Beacon;

/**
 * Opaque server handle owned by the C caller.
 *
 * Callers must serialize all access to one handle, including queries and destruction. Store callbacks must not reenter their owning handle.
 */
/**
 * Server backed by trusted snapshot storage. Store callbacks must not reenter this server.
 */
typedef struct beaconcrypt_Server beaconcrypt_Server;

/**
 * Heap-allocated byte buffer returned by the C API.
 *
 * A non-empty buffer must be released exactly once with `beaconcrypt_free_buffer`. An empty buffer has a null `ptr` and indicates either empty output or failure, depending on the called function.
 */
typedef struct beaconcrypt_Buffer {
  /**
   * Pointer to the first byte, or null when the buffer is empty.
   */
  uint8_t *ptr;
  /**
   * Number of initialized bytes available through `ptr`.
   */
  uintptr_t len;
  /**
   * Allocation capacity reserved for `beaconcrypt_free_buffer`; callers must not modify it.
   */
  uintptr_t cap;
} beaconcrypt_Buffer;

/**
 * Non-secret identity of one complete server snapshot. Its digest is not an authenticator.
 */
typedef struct beaconcrypt_SnapshotHeadInfo {
  uint8_t lineage[32];
  uint64_t generation;
  uint8_t digest[32];
} beaconcrypt_SnapshotHeadInfo;

/**
 * Trusted, rollback-resistant, linearizable durable storage for one server lineage.
 *
 * `load` returns false without calling `sink` for an empty store. Otherwise it calls `sink` synchronously exactly once with nonempty borrowed snapshot bytes and returns true; Rust copies the bytes before `sink` returns. `compare_and_swap` compares the complete current head against `expected` (null means an empty store), validates the successor, and durably stores the exact replacement bytes and head before returning true. The store must protect integrity, provenance and freshness; snapshot bytes and digests do not authenticate themselves.
 *
 * Constructors take ownership of `context` immediately, including on failure. `destroy`, when supplied, runs exactly once after the final callback; otherwise the caller manages the context lifetime. All callbacks and borrowed arguments remain valid until they return, must not unwind, retain borrowed pointers, call the sink after `load` returns, or reenter the owning handle. The caller serializes access to the handle and store.
 */
typedef struct beaconcrypt_SnapshotStoreCallbacks {
  void *context;
  bool (*load)(void *context, void *sink_context, void (*sink)(void*, const uint8_t*, uintptr_t));
  bool (*compare_and_swap)(void *context,
                           const struct beaconcrypt_SnapshotHeadInfo *expected,
                           const uint8_t *replacement,
                           uintptr_t replacement_len);
  void (*destroy)(void *context);
} beaconcrypt_SnapshotStoreCallbacks;

/**
 * Result returned after a successful server-side beacon registration.
 */
typedef struct beaconcrypt_RegistrationResponse {
  /**
   * Serialized registration response for the beacon.
   */
  struct beaconcrypt_Buffer response;
  /**
   * Key identifier assigned to the registered beacon.
   */
  uint64_t key_id;
} beaconcrypt_RegistrationResponse;

/**
 * Message output accompanied by observational ratchet metadata.
 */
typedef struct beaconcrypt_EncryptState {
  /**
   * Ciphertext for encryption calls or plaintext for decryption calls.
   */
  struct beaconcrypt_Buffer data;
  /**
   * Inert plaintext ratchet JSON for observation only.
   * It is secret-bearing, unauthenticated, and not restorable.
   */
  struct beaconcrypt_Buffer state;
  /**
   * Key identifier used by the ratchet operation.
   */
  uint64_t key_id;
  /**
   * Ratchet sequence number used by the operation.
   */
  uint64_t seq;
} beaconcrypt_EncryptState;



#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

/**
 * Release a byte buffer returned by this API.
 *
 * Passing an empty buffer is allowed. The buffer and its pointer must not be used after this call.
 * The complete allocation is wiped before release. Copies retained by the caller are not erased.
 */
void beaconcrypt_free_buffer(struct beaconcrypt_Buffer buffer);

/**
 * Create a server with a randomly generated identity key.
 *
 * Returns an owned handle, or null on failure. Release a non-null handle with `beaconcrypt_server_free`.
 */
struct beaconcrypt_Server *beaconcrypt_server_new(uint64_t server_kid);

/**
 * Create a server with an optional deterministic identity seed.
 *
 * A null pointer or zero length selects a random identity key. A non-empty seed must contain exactly `beaconcrypt_ED25519_SEED_SIZE` readable bytes.
 *
 * Returns an owned handle, or null when creation fails. Release a non-null handle with `beaconcrypt_server_free`.
 */
struct beaconcrypt_Server *beaconcrypt_server_new_from_seed(uint64_t server_kid,
                                                            const uint8_t *seed_ptr,
                                                            uintptr_t seed_len);

/**
 * Create a server whose results are released only after the store's durable compare-and-swap succeeds.
 *
 * The callbacks take ownership of their context even when construction fails. A null seed or zero seed length selects a random identity. `status_out` may be null; otherwise it receives a `beaconcrypt_STATUS_*` code. Returns null on failure.
 */
struct beaconcrypt_Server *beaconcrypt_server_create_with_store(uint64_t server_kid,
                                                                const uint8_t *seed_ptr,
                                                                uintptr_t seed_len,
                                                                struct beaconcrypt_SnapshotStoreCallbacks callbacks,
                                                                uint32_t *status_out);

/**
 * Create a durable server under a caller-provisioned 32-byte lineage.
 *
 * Allocate each lineage to exactly one rollback-resistant authoritative store head. Callback context ownership and `status_out` follow `beaconcrypt_server_create_with_store`.
 */
struct beaconcrypt_Server *beaconcrypt_server_create_with_store_and_lineage(uint64_t server_kid,
                                                                            const uint8_t *seed_ptr,
                                                                            uintptr_t seed_len,
                                                                            struct beaconcrypt_SnapshotStoreCallbacks callbacks,
                                                                            const uint8_t *lineage_ptr,
                                                                            uintptr_t lineage_len,
                                                                            uint32_t *status_out);

/**
 * Restore the trusted current snapshot and durably claim its next generation before returning a live owner.
 *
 * Callback context ownership and `status_out` follow `beaconcrypt_server_create_with_store`. The store must protect snapshot integrity, provenance and freshness and coordinate concurrent owners.
 */
struct beaconcrypt_Server *beaconcrypt_server_restore_with_store(struct beaconcrypt_SnapshotStoreCallbacks callbacks,
                                                                 uint32_t *status_out);

/**
 * Read the owner's current non-secret snapshot head. Returns a status code without changing the last operation's status.
 */
uint32_t beaconcrypt_server_head(const struct beaconcrypt_Server *handle,
                                 struct beaconcrypt_SnapshotHeadInfo *out);

/**
 * Query whether a failed commit has fenced this owner. Returns false for null and preserves the last operation's status.
 */
bool beaconcrypt_server_is_poisoned(const struct beaconcrypt_Server *handle);

/**
 * Return the last server operation's status, or `beaconcrypt_STATUS_INVALID_ARGUMENT` for null.
 * Head, identity and poison-state queries preserve this value; checkpoint export records its own status.
 */
uint32_t beaconcrypt_server_last_status(const struct beaconcrypt_Server *handle);

/**
 * Parse a snapshot envelope and compute its exact-byte head. This does not authenticate bytes or establish freshness.
 */
uint32_t beaconcrypt_snapshot_head(const uint8_t *bytes,
                                   uintptr_t len,
                                   struct beaconcrypt_SnapshotHeadInfo *out);

/**
 * Check a snapshot's lineage, next generation and exact parent digest against `expected` (null for an empty store).
 *
 * This does not authenticate bytes or make the store atomic. A store must perform this check together with comparison against its trusted current head inside its durable compare-and-swap transaction.
 */
uint32_t beaconcrypt_snapshot_validate_successor(const uint8_t *bytes,
                                                 uintptr_t len,
                                                 const struct beaconcrypt_SnapshotHeadInfo *expected,
                                                 struct beaconcrypt_SnapshotHeadInfo *out);

/**
 * Restore a server from trusted checkpoint bytes.
 *
 * The caller must reject stale or untrusted checkpoints. These bytes are plaintext and are not cryptographically authenticated.
 *
 * Restoration advances the generation, so export and save the returned handle immediately before using it. Returns an owned handle, or null for invalid state.
 */
struct beaconcrypt_Server *beaconcrypt_server_new_from_state(const uint8_t *state_ptr,
                                                             uintptr_t state_len);

/**
 * Export the current plaintext checkpoint.
 *
 * Save it immediately after every accepted receive or other state-changing call and before using that call's output.
 * A normal rejected receive leaves the checkpoint unchanged.
 * Returns an empty buffer on failure.
 */
struct beaconcrypt_Buffer beaconcrypt_server_export_state(const struct beaconcrypt_Server *handle);

/**
 * Create a beacon bound to a server identity public key.
 *
 * `server_pk_ptr` must point to an Ed25519 public key of the length implied by the API constants.
 *
 * Returns an owned handle, or null for absent or incorrectly sized input or a reported initialization/key-generation failure. Release a non-null handle with `beaconcrypt_beacon_free`.
 */
struct beaconcrypt_Beacon *beaconcrypt_beacon_new(uint64_t server_kid,
                                                  const uint8_t *server_pk_ptr,
                                                  uintptr_t server_pk_len);

/**
 * Release a server handle created by this API.
 *
 * Passing null is allowed. The handle must not be used after this call.
 */
void beaconcrypt_server_free(struct beaconcrypt_Server *handle);

/**
 * Release a beacon handle created by this API.
 *
 * Passing null is allowed. The handle must not be used after this call.
 */
void beaconcrypt_beacon_free(struct beaconcrypt_Beacon *handle);

/**
 * Copy the server identity public key into a caller-owned buffer.
 *
 * Returns an empty buffer when `handle` is null.
 */
struct beaconcrypt_Buffer beaconcrypt_server_identity_pk(const struct beaconcrypt_Server *handle);

/**
 * Copy the beacon identity public key into a caller-owned buffer.
 *
 * Returns an empty buffer when `handle` is null.
 */
struct beaconcrypt_Buffer beaconcrypt_beacon_identity_pk(const struct beaconcrypt_Beacon *handle);

/**
 * Generate the beacon's serialized registration bundle.
 *
 * Returns an empty buffer when the handle is invalid or the beacon cannot generate a bundle in its current state.
 */
struct beaconcrypt_Buffer beaconcrypt_generate_registration(struct beaconcrypt_Beacon *handle);

/**
 * Register a beacon and build its initial server response.
 *
 * `msg_ptr` may be null when `msg_len` is zero to omit the initial message. On failure, returns an empty response with key identifier zero.
 */
struct beaconcrypt_RegistrationResponse beaconcrypt_register_beacon(struct beaconcrypt_Server *handle,
                                                                    const uint8_t *reg_ptr,
                                                                    uintptr_t reg_len,
                                                                    const uint8_t *msg_ptr,
                                                                    uintptr_t msg_len);

/**
 * Finish beacon registration and return the optional initial plaintext message.
 *
 * Returns an empty buffer when the input is invalid, registration fails, or no initial message was supplied.
 */
struct beaconcrypt_Buffer beaconcrypt_process_initial_message(struct beaconcrypt_Beacon *handle,
                                                              const uint8_t *ptr,
                                                              uintptr_t len);

/**
 * Encrypt a message from the server to the beacon identified by `key_id`.
 *
 * Returns an empty buffer when the handle or input is invalid, the key is unknown, or encryption fails.
 */
struct beaconcrypt_Buffer beaconcrypt_encrypt_to_beacon(struct beaconcrypt_Server *handle,
                                                        uint64_t key_id,
                                                        const uint8_t *ptr,
                                                        uintptr_t len);

/**
 * Decrypt a beacon-to-server message.
 *
 * Returns an empty buffer when the handle or input is invalid, authentication fails, or the ratchet rejects the message.
 */
struct beaconcrypt_Buffer beaconcrypt_decrypt_beacon_message(struct beaconcrypt_Server *handle,
                                                             const uint8_t *ptr,
                                                             uintptr_t len);

/**
 * Encrypt a server-to-beacon message and return observational ratchet metadata.
 *
 * Returns an empty `beaconcrypt_EncryptState` when the operation fails. Persist the server checkpoint before using the returned output.
 */
struct beaconcrypt_EncryptState beaconcrypt_encrypt_and_update(struct beaconcrypt_Server *handle,
                                                               uint64_t key_id,
                                                               const uint8_t *ptr,
                                                               uintptr_t len);

/**
 * Encrypt a server-to-beacon message and return the result and ratchet metadata as JSON.
 *
 * Returns an empty buffer when the operation fails. Persist the server checkpoint before using the returned output.
 */
struct beaconcrypt_Buffer beaconcrypt_encrypt_and_update_json(struct beaconcrypt_Server *handle,
                                                              uint64_t key_id,
                                                              const uint8_t *ptr,
                                                              uintptr_t len);

/**
 * Decrypt a beacon-to-server message and return observational ratchet metadata.
 *
 * Returns an empty `beaconcrypt_EncryptState` when the operation fails. Persist the server checkpoint before using the returned output.
 */
struct beaconcrypt_EncryptState beaconcrypt_decrypt_and_update(struct beaconcrypt_Server *handle,
                                                               const uint8_t *ptr,
                                                               uintptr_t len);

/**
 * Decrypt a beacon-to-server message and return the result and ratchet metadata as JSON.
 *
 * Returns an empty buffer when the operation fails. Persist the server checkpoint before using the returned output.
 */
struct beaconcrypt_Buffer beaconcrypt_decrypt_and_update_json(struct beaconcrypt_Server *handle,
                                                              const uint8_t *ptr,
                                                              uintptr_t len);

/**
 * Encrypt a message from the beacon to its server.
 *
 * Returns an empty buffer when the handle or input is invalid or encryption fails.
 */
struct beaconcrypt_Buffer beaconcrypt_encrypt_to_server(struct beaconcrypt_Beacon *handle,
                                                        const uint8_t *ptr,
                                                        uintptr_t len);

/**
 * Decrypt a server-to-beacon message.
 *
 * Returns an empty buffer when the handle or input is invalid, authentication fails, or the ratchet rejects the message.
 */
struct beaconcrypt_Buffer beaconcrypt_decrypt_server_message(struct beaconcrypt_Beacon *handle,
                                                             const uint8_t *ptr,
                                                             uintptr_t len);

#ifdef __cplusplus
}  // extern "C"
#endif  // __cplusplus

#endif  /* _BEACON_CRYPT_H_ */