diff --git a/include/bravais.h b/include/bravais.h index 39215fe..f795dd6 100644 --- a/include/bravais.h +++ b/include/bravais.h @@ -19,6 +19,11 @@ extern "C" { #define BRAVAIS_NO_TIMEOUT UINT64_MAX +#define BRAVAIS_MAX_DATAGRAM_SIZE 1500 +#define BRAVAIS_MAX_PLAINTEXT_SIZE 65535 + +#define BRAVAIS_KEY_LENGTH 32 // For X25519 private and public - do PQC later + typedef enum { // Error codes; Generally <0 = error, 0 = success BRAVAIS_EMPTY = 1, // Nothing to emit right now diff --git a/src/util/buf.c b/src/util/buf.c new file mode 100644 index 0000000..4664475 --- /dev/null +++ b/src/util/buf.c @@ -0,0 +1,208 @@ +#include "buf.h" +#include "intutils.h" + +// Internal claim functions to avoid code duplication in the cursor functions +static const uint8_t* rcur_claim(bravais_rcur_t* cur, size_t n) { + if (cur->failed || n > cur->len - cur->pos) { + cur->failed = true; + return nullptr; + } + + if (cur->base == nullptr) { + return nullptr; + } + + const uint8_t* start = cur->base + cur->pos; + cur->pos += n; + + return start; +} + +static uint8_t* wcur_claim(bravais_wcur_t* cur, size_t n) { + if (cur->failed || n > cur->len - cur->pos) { + cur->failed = true; + return nullptr; + } + + if (cur->base == nullptr) { + return nullptr; + } + + uint8_t* start = cur->base + cur->pos; + cur->pos += n; + + return start; +} + +void bravais_rcur_init(bravais_rcur_t* cur, const uint8_t* buf, size_t len) { + cur->buf = buf; + cur->len = len; + cur->pos = 0; + cur->failed = false; +} + +uint8_t bravais_rcur_u8(bravais_rcur_t* cur) { + const uint8_t* ptr = rcur_claim(cur, 1); + if (ptr == nullptr) { + return 0; + } + + return ptr[0]; +} + +uint16_t bravais_rcur_u16(bravais_rcur_t* cur) { + const uint8_t* ptr = rcur_claim(cur, 2); + if (ptr == nullptr) { + return 0; + } + + // Assemble from bytes in big-endian order + uint16_t val = (uint16_t)((ptr[0] << 8) | ptr[1]); + + return val; +} + +uint32_t bravais_rcur_u32(bravais_rcur_t* cur) { + const uint8_t* ptr = rcur_claim(cur, 4); + if (ptr == nullptr) { + return 0; + } + + // Assemble from bytes in big-endian order + uint32_t val = (uint32_t)((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]); + + return val; +} + +uint64_t bravais_rcur_u64(bravais_rcur_t* cur) { + const uint8_t* ptr = rcur_claim(cur, 8); + if (ptr == nullptr) { + return 0; + } + + // Assemble from bytes in big-endian order + uint64_t val = ((uint64_t)ptr[0] << 56) + | ((uint64_t)ptr[1] << 48) + | ((uint64_t)ptr[2] << 40) + | ((uint64_t)ptr[3] << 32) + | ((uint64_t)ptr[4] << 24) + | ((uint64_t)ptr[5] << 16) + | ((uint64_t)ptr[6] << 8) + | ((uint64_t)ptr[7]); + + return val; +} + +void bravais_rcur_bytes(bravais_rcur_t* cur, uint8_t* outBuf, size_t len) { + if (len <= 0) { return; } + + const uint8_t* ptr = rcur_claim(cur, len); + if (ptr == nullptr) { + memset(outBuf, 0, len); + return; + } + + memcpy(outBuf, ptr, len); +} + +const uint8_t* bravais_rcur_slice(bravais_rcur_t* cur, size_t len) { + return rcur_claim(cur, len); +} + +void bravais_rcur_skip(bravais_rcur_t* cur, size_t len) { + (void)rcur_claim(cur, len); +} + +size_t bravais_rcur_remaining(const bravais_rcur_t* cur) { + if (cur->failed) { + return 0; + } + + return cur->len - cur->pos; +} + +bool bravais_rcur_ok(const bravais_rcur_t* cur) { + return !cur->failed; +} + +void bravais_wcur_init(bravais_wcur_t* cur, uint8_t* buf, size_t len) { + cur->buf = buf; + cur->len = len; + cur->pos = 0; + cur->failed = false; +} + +void bravais_wcur_u8(bravais_wcur_t* cur, uint8_t val) { + uint8_t* ptr = wcur_claim(cur, 1); + if (ptr == nullptr) { + return; + } + + ptr[0] = val; +} + +void bravais_wcur_u16(bravais_wcur_t* cur, uint16_t val) { + uint8_t* ptr = wcur_claim(cur, 2); + if (ptr == nullptr) { + return; + } + + // Assemble into bytes in big-endian order + ptr[0] = (uint8_t)(val >> 8); + ptr[1] = (uint8_t)(val); +} + +void bravais_wcur_u32(bravais_wcur_t* cur, uint32_t val) { + uint8_t* ptr = wcur_claim(cur, 4); + if (ptr == nullptr) { + return; + } + + ptr[0] = (uint8_t)(val >> 24); + ptr[1] = (uint8_t)(val >> 16); + ptr[2] = (uint8_t)(val >> 8); + ptr[3] = (uint8_t)(val); +} + +void bravais_wcur_u64(bravais_wcur_t* cur, uint64_t val) { + uint8_t* ptr = wcur_claim(cur, 8); + if (ptr == nullptr) { + return; + } + + ptr[0] = (uint8_t)(val >> 56); + ptr[1] = (uint8_t)(val >> 48); + ptr[2] = (uint8_t)(val >> 40); + ptr[3] = (uint8_t)(val >> 32); + ptr[4] = (uint8_t)(val >> 24); + ptr[5] = (uint8_t)(val >> 16); + ptr[6] = (uint8_t)(val >> 8); + ptr[7] = (uint8_t)(val); +} + +void bravais_wcur_bytes(bravais_wcur_t* cur, const uint8_t* val, size_t len) { + if (len <= 0) { return; } + + uint8_t* ptr = wcur_claim(cur, len); + if (ptr == nullptr) { + return; + } + + memcpy(ptr, val, len); +} + +size_t bravais_wcur_written(const bravais_wcur_t* cur) { + return cur->pos; +} + +size_t bravais_wcur_remaining(const bravais_wcur_t* cur) { + if (cur->failed) { + return 0; + } + + return cur->len - cur->pos; +} + +bool bravais_wcur_ok(const bravais_wcur_t* cur) { + return !cur->failed; +} diff --git a/src/util/buf.h b/src/util/buf.h new file mode 100644 index 0000000..37ca01e --- /dev/null +++ b/src/util/buf.h @@ -0,0 +1,54 @@ +// buf.h +// Bounds-checked cursors over a buffer/byte range. +// +// Sticky-failure flags - if an op runs past the end, it sets a "failed" flag and returns a no-op zero value. +// Check with bravais_cur_ok() at the end of a serialization/deserialization operation to see if it succeeded. +// +// Multi-byte integer serialization is big-endian, as per the network order convention. Variable-length might live somewhere else later. +// +// A slice gets returned by bravais_rcur_slice() and points into the underlying buffer. + +#ifndef BRAVAIS_BUF_H +#define BRAVAIS_BUF_H + +#include +#include + +typedef struct { + const uint8_t* buf; + size_t len; + size_t pos; + bool failed; +} bravais_rcur_t; + +typedef struct { + uint8_t* buf; + size_t len; + size_t pos; + bool failed; +} bravais_wcur_t; + +// Reader cursor functions +void bravais_rcur_init(bravais_rcur_t* cur, const uint8_t* buf, size_t len); +uint8_t bravais_rcur_u8(bravais_rcur_t* cur); +uint16_t bravais_rcur_u16(bravais_rcur_t* cur); +uint32_t bravais_rcur_u32(bravais_rcur_t* cur); +uint64_t bravais_rcur_u64(bravais_rcur_t* cur); +void bravais_rcur_bytes(bravais_rcur_t* cur, uint8_t* outBuf, size_t len); // zero-fills on failure +const uint8_t* bravais_rcur_slice(bravais_rcur_t* cur, size_t len); // returns NULL on failure, borrows +void bravais_rcur_skip(bravais_rcur_t* cur, size_t len); // skips bytes, sets failed on overflow +size_t bravais_rcur_remaining(const bravais_rcur_t* cur); // How many bytes are left to read +bool bravais_rcur_ok(const bravais_rcur_t* cur); + +// Writer cursor functions +void bravais_wcur_init(bravais_wcur_t* cur, uint8_t* buf, size_t len); +void bravais_wcur_u8(bravais_wcur_t* cur, uint8_t val); +void bravais_wcur_u16(bravais_wcur_t* cur, uint16_t val); +void bravais_wcur_u32(bravais_wcur_t* cur, uint32_t val); +void bravais_wcur_u64(bravais_wcur_t* cur, uint64_t val); +void bravais_wcur_bytes(bravais_wcur_t* cur, const uint8_t* val, size_t len); +size_t bravais_wcur_written(const bravais_wcur_t* cur); // How many bytes have been written so far +size_t bravais_wcur_remaining(const bravais_wcur_t* cur); // How many bytes are left to write +bool bravais_wcur_ok(const bravais_wcur_t* cur); + +#endif // BRAVAIS_BUF_H diff --git a/src/util/intutils.h b/src/util/intutils.h new file mode 100644 index 0000000..fc1cd30 --- /dev/null +++ b/src/util/intutils.h @@ -0,0 +1,32 @@ +// intutils.h +// Utilities for integers (byte order flipping for now) + +#ifndef BRAVAIS_INTUTILS_H +#define BRAVAIS_INTUTILS_H + +#include +#include + +static inline uint16_t bravais_bswap16(uint16_t x) { + return (uint16_t)((x << 8) | (x >> 8)); +} + +static inline uint32_t bravais_bswap32(uint32_t x) { + return (uint32_t)(((x & 0x000000FF) << 24) | + ((x & 0x0000FF00) << 8) | + ((x & 0x00FF0000) >> 8) | + ((x & 0xFF000000) >> 24)); +} + +static inline uint64_t bravais_bswap64(uint64_t x) { + return (uint64_t)(((x & 0x00000000000000FFULL) << 56) | + ((x & 0x000000000000FF00ULL) << 40) | + ((x & 0x0000000000FF0000ULL) << 24) | + ((x & 0x00000000FF000000ULL) << 8) | + ((x & 0x000000FF00000000ULL) >> 8) | + ((x & 0x0000FF0000000000ULL) >> 24) | + ((x & 0x00FF000000000000ULL) >> 40) | + ((x & 0xFF00000000000000ULL) >> 56)); +} + +#endif // BRAVAIS_INTUTILS_H