core/core.h (view raw)
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 |
#ifndef CIRCE_CORE_H
#define CIRCE_CORE_H
#include "mldsa_native.h"
#include "packet.h"
#include "peer_table.h"
#include <stddef.h>
#include <stdint.h>
#define CIRCE_MAX_OUTGOING_PACKETS 64
#define CIRCE_HEARTBEAT_PERIOD_MS 1000
enum circe_result
{
CIRCE_RESULT_SUCCESS = 0,
CIRCE_RESULT_INSUFFICIENT_MEM,
CIRCE_RESULT_INVALID_PACKET,
CIRCE_RESULT_INVALID_MAC,
CIRCE_RESULT_INTERNAL_ERROR,
CIRCE_RESULT_UNKNOWN_REMOTE,
CIRCE_RESULT_OVER_MTU,
CIRCE_RESULT_HANDSHAKE_PENDING,
CIRCE_RESULT_PEER_TABLE_FULL,
CIRCE_RESULT_RELAY_LOOKUP_FAILED,
CIRCE_RESULT_PACKET_TABLE_FULL,
CIRCE_RESULT_KEX_FAILED,
CIRCE_RESULT_SIGNATURE_FAILED,
CIRCE_RESULT_INVALID_SIGNATURE,
CIRCE_RESULT_INVALID_TIMESTAMP,
CIRCE_RESULT_DUPLICATE_HS_PACKET,
CIRCE_RESULT_HS_OUT_OF_ORDER,
};
enum circe_version
{
CIRCE_VERSION_V1 = 0,
};
struct circe_event
{
enum
{
CIRCE_EVENT_DATA_RECEIVED,
CIRCE_EVENT_NEW_REMOTE,
CIRCE_EVENT_REJECTED_REMOTE,
} event_type;
};
enum circe_deadline
{
CIRCE_DEADLINE_NOW,
CIRCE_DEADLINE_INDEFINITE,
CIRCE_DEADLINE_AS_INDICATED,
};
struct circe_context
{
struct circe_peer peer_table[CIRCE_PEER_TABLE_LEN];
uint64_t peer_handshake_pending_mask;
uint64_t peer_table_free_mask; // 1 if free, 0 if full
struct circe_outgoing_packet outgoing_packets[CIRCE_MAX_OUTGOING_PACKETS];
uint64_t outgoing_packet_table_free_mask; // 1 if free, 0 if full
uint64_t last_tick_ms;
uint8_t my_identity[CIRCE_IDENTITY_LEN];
uint8_t my_mldsa_privkey[MLDSA_SECRETKEYBYTES (44)];
void *ctx_handle;
void (*random_bytes_callback) (void *ctx_handle, uint8_t *out, uint32_t len);
bool (*recall_peer_callback) (void *ctx_handle,
const uint8_t identity[CIRCE_IDENTITY_LEN],
struct circe_peer *out);
};
/// Initialize Circe core's context state
enum circe_result circe_initialize_core (
struct circe_context *ctx, uint8_t identity[CIRCE_IDENTITY_LEN],
uint8_t mldsa_privkey[MLDSA_SECRETKEYBYTES (44)], uint64_t now_ms,
void *ctx_handle,
void (*random_bytes_callback) (void *, uint8_t *, uint32_t),
bool (*recall_peer_callback) (void *, const uint8_t[CIRCE_IDENTITY_LEN],
struct circe_peer *));
/// Process a new incoming raw Circe packet.
enum circe_result circe_handle_packet (struct circe_context *ctx,
const struct circe_location remote,
const uint8_t *restrict in, size_t len,
uint8_t *restrict out, size_t *out_len,
uint64_t now_ms,
struct circe_event *events,
size_t *n_events);
/// Put outgoing packet into Circe's internal logic. DOES NOT ACTUALLY SEND IT
/// OVER THE NETWORK; that is handled opaquely by the caller and `circe_tick`.
enum circe_result
circe_send_outgoing_packet (struct circe_context *ctx,
const uint8_t remote_identity[CIRCE_IDENTITY_LEN],
const uint8_t *in, size_t len, uint64_t now_ms,
struct circe_event *events, size_t *n_events);
/// Get deadline and corresponding millisecond timestamp (for
/// `CIRCE_DEADLINE_AS_INDICATED`) for next timer deadline, at which point
/// `circe_tick` should be called. Should always be called immediately after
/// any other core API function is called to stay up-to-date.
enum circe_deadline circe_next_deadline (struct circe_context *ctx,
uint64_t *ms_timestamp);
/// Iterate the Circe core logic. Assumes `now_ms` increases monotonically with
/// time. If `new_packet_out` is true (do not pass in NULL for `out`), then
/// `out` contains a new raw Circe packet to be sent out to the location
/// `out.destination`.
enum circe_result circe_tick (struct circe_context *ctx, uint64_t now_ms,
struct circe_outgoing_packet *out,
bool *new_packet_out);
#endif
|