5#if !defined(CWIST_PLATFORM_HOSTED)
18#if defined(__EMSCRIPTEN__)
19#include <emscripten.h>
24#if defined(CWIST_BAREMETAL)
28#if !defined(CWIST_PLATFORM_HOSTED)
29#define SEQ_AUTH_WASM_CRYPTO 1
30#define SEQ_AUTH_TAG_CAP CWIST_SHA256_DIGEST_LEN
44static int seq_auth_memcmp(
const uint8_t *
a,
const uint8_t *b,
size_t len) {
49#define SEQ_AUTH_MEMCMP(a, b, len) seq_auth_memcmp((a), (b), (len))
50#define SEQ_AUTH_CLEANSE(ptr, len) memset((ptr), 0, (len))
52#define SEQ_AUTH_TAG_CAP EVP_MAX_MD_SIZE
53#define SEQ_AUTH_MEMCMP(a, b, len) CRYPTO_memcmp((a), (b), (len))
54#define SEQ_AUTH_CLEANSE(ptr, len) OPENSSL_cleanse((ptr), (len))
57#if defined(__EMSCRIPTEN__)
67struct cwist_seq_auth_context {
74 size_t completed_count;
76 size_t completed_next;
107 out->
seq = read_u16(data);
108 out->
total = read_u16(data + 2);
139 size_t header_len,
const uint8_t *payload,
size_t payload_len,
141#ifdef SEQ_AUTH_WASM_CRYPTO
146 memcpy(
k, ctx->key,
sizeof(ctx->key));
148 for (
size_t i = 0;
i < 64;
i++) {
154 cwist_sha256_init(&
c);
155 cwist_sha256_update(&
c,
ipad,
sizeof(
ipad));
156 cwist_sha256_update(&
c, ctx->session_id,
sizeof(ctx->session_id));
158 cwist_sha256_update(&
c, payload, payload_len);
159 cwist_sha256_final(&
c,
inner);
160 cwist_sha256_init(&
c);
161 cwist_sha256_update(&
c,
opad,
sizeof(
opad));
163 cwist_sha256_final(&
c, tag);
172 HMAC_Update(h, ctx->session_id,
sizeof(ctx->session_id)) == 1 &&
213static void cache_add(
uint8_t *cache,
size_t *
count,
size_t *next,
size_t capacity,
size_t width,
216 *next = (*next + 1) % capacity;
217 if (*
count < capacity) (*count)++;
242 if (!ctx)
return NULL;
243 memset(ctx, 0,
sizeof(*ctx));
250 if (!ctx->nonces || !ctx->completed_ids) {
254 memcpy(ctx->key, key,
sizeof(ctx->key));
255 memcpy(ctx->session_id, session_id,
sizeof(ctx->session_id));
291 if (!out || len == 0 || len >
INT_MAX)
return false;
292#if defined(__EMSCRIPTEN__)
294#elif defined(__wasi__)
296#elif defined(CWIST_BAREMETAL)
328 if (!ctx || !message_id || !nonce || !out || !out_len ||
333 if (!wire)
return false;
340 if (!auth_tag(ctx, wire,
384 if (!auth_tag(ctx, data,
399 cache_add(ctx->nonces, &ctx->nonce_count, &ctx->nonce_next, ctx->capacity,
420 if (!ctx || !message_id)
return;
427 cache_add(ctx->completed_ids, &ctx->completed_count, &ctx->completed_next, ctx->capacity,
Memory allocation wrappers backed by libttak.
void cwist_free(void *ptr)
Free memory obtained via cwist_alloc/cwist_strdup/etc.
void * cwist_alloc_array(size_t count, size_t elem_size)
Allocate zeroed memory for count elements.
void * cwist_alloc(size_t size)
Allocate zeroed memory tracked by libttak.
mbedTLS TLS backend: HMAC subset (HMAC-SHA256, one-shot + streaming).
struct cwist_mtls_hmac_ctx HMAC_CTX
mbedTLS TLS backend: OPENSSL_cleanse (BoringSSL puts it here).
Hooks a bare-metal firmware supplies to CWIST (issue #447).
int cwist_port_entropy(void *buf, size_t len)
Fill a buffer with cryptographically secure random bytes.
mbedTLS TLS backend: RAND_bytes over mbedTLS CTR-DRBG.
#define CWIST_SEQ_MAX_CHUNKS
bool cwist_seq_chunk_parse(const uint8_t *data, size_t len, cwist_seq_chunk_t *out)
Parse a sequence chunk from raw bytes.
#define CWIST_SEQ_HEADER_SIZE
cwist_seq_auth_context_t * cwist_seq_auth_context_create(const uint8_t key[CWIST_SEQ_AUTH_KEY_SIZE], const uint8_t session_id[CWIST_SEQ_AUTH_SESSION_ID_SIZE], size_t replay_window)
Create an authenticated-sequencing context.
bool cwist_seq_auth_wrap(const cwist_seq_auth_context_t *ctx, const uint8_t message_id[CWIST_SEQ_AUTH_MESSAGE_ID_SIZE], const uint8_t nonce[CWIST_SEQ_AUTH_NONCE_SIZE], const uint8_t *chunk, size_t chunk_len, uint8_t **out, size_t *out_len)
Attach message id, nonce, and authentication tag to a chunk.
#define SEQ_AUTH_CLEANSE(ptr, len)
bool cwist_seq_auth_random(uint8_t *out, size_t len)
Fill a buffer with cryptographically secure random bytes.
void cwist_seq_auth_context_destroy(cwist_seq_auth_context_t *ctx)
Destroy an authenticated-sequencing context.
#define SEQ_AUTH_MEMCMP(a, b, len)
bool cwist_seq_auth_unwrap(cwist_seq_auth_context_t *ctx, const uint8_t *data, size_t len, cwist_seq_auth_metadata_t *metadata, cwist_seq_chunk_t *chunk)
Verify, authenticate, and split an incoming authenticated chunk.
void cwist_seq_auth_mark_complete(cwist_seq_auth_context_t *ctx, const uint8_t message_id[CWIST_SEQ_AUTH_MESSAGE_ID_SIZE])
Record a message id as fully received.
Authenticated v2 envelope for CWIST sequenced payloads.
#define CWIST_SEQ_AUTH_NONCE_SIZE
#define CWIST_SEQ_AUTH_SESSION_ID_SIZE
#define CWIST_SEQ_AUTH_TAG_SIZE
#define CWIST_SEQ_AUTH_MESSAGE_ID_SIZE
#define CWIST_SEQ_AUTH_HEADER_SIZE
struct cwist_seq_auth_context cwist_seq_auth_context_t
#define CWIST_SEQ_AUTH_KEY_SIZE
Minimal self-contained SHA-256 and HMAC-SHA256 (RFC 4634 style).
#define CWIST_SHA256_DIGEST_LEN
Parsed view of one sequenced chunk.
uint16_t payload_len
Payload length in this chunk.
uint16_t total
Total chunks in the message.
uint16_t chunk_size
Payload length of a full chunk.
const uint8_t * payload
Pointer to payload bytes.
uint16_t seq
1-based sequence number.