#include "cbor.h" #include #include #define CIRCE_CBOR_ASSERT(x) \ do \ { \ if (!(x)) \ { \ return false; \ } \ } \ while (false) /* DECODING FUNCTIONS */ bool circe_cbor_get_argument (struct circe_cbor_decoder *dc, uint64_t *out, bool *is_definite) { CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + 1 <= dc->buf_len); *out = *(dc->cursor) & 0b11111; ++dc->cursor; switch (*out) { case 24: CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + 1 <= dc->buf_len); *out = *dc->cursor; ++dc->cursor; break; case 25: CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + 2 <= dc->buf_len); *out = 0; for (unsigned int i = 0; i < 2; ++i) { *out <<= 8; *out |= dc->cursor[i]; } dc->cursor += 2; break; case 26: CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + 4 <= dc->buf_len); *out = 0; for (unsigned int i = 0; i < 4; ++i) { *out <<= 8; *out |= dc->cursor[i]; } dc->cursor += 4; break; case 27: CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + 8 <= dc->buf_len); *out = 0; for (unsigned int i = 0; i < 8; ++i) { *out <<= 8; *out |= dc->cursor[i]; } dc->cursor += 8; break; case 28: case 29: case 30: CIRCE_CBOR_ASSERT (false); } *is_definite = !(*out == 31); return true; } bool circe_cbor_get_major_type (struct circe_cbor_decoder *dc, enum circe_cbor_major_type *out) { CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start < dc->buf_len); *out = (enum circe_cbor_major_type) (*dc->cursor >> 5); return true; } bool circe_cbor_get_simple_type (struct circe_cbor_decoder *dc, enum circe_cbor_simple_type *out) { CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start < dc->buf_len); CIRCE_CBOR_ASSERT ((*dc->cursor & 0b11111) != 24); *out = (enum circe_cbor_simple_type) (*dc->cursor & 0b11111); return true; } bool circe_cbor_extract_length (struct circe_cbor_decoder *dc, uint64_t *out, bool *is_definite) { CIRCE_CBOR_ASSERT (circe_cbor_get_argument (dc, out, is_definite)); return true; } bool circe_cbor_skip (struct circe_cbor_decoder *dc, uint64_t max_depth) { if (max_depth == 0) { return false; } enum circe_cbor_major_type type; CIRCE_CBOR_ASSERT (circe_cbor_get_major_type (dc, &type)); uint64_t num_throwaway; struct circe_cbor_buffer buf_throwaway; uint64_t len; bool is_definite; enum circe_cbor_simple_type st; switch (type) { case CIRCE_CBOR_MAJOR_UNSIGNED: CIRCE_CBOR_ASSERT (circe_cbor_extract_unsigned (dc, &num_throwaway)); break; case CIRCE_CBOR_MAJOR_NEGATIVE: CIRCE_CBOR_ASSERT (circe_cbor_extract_negative (dc, &num_throwaway)); break; case CIRCE_CBOR_MAJOR_BYTESTR: CIRCE_CBOR_ASSERT (circe_cbor_extract_bytestr (dc, &buf_throwaway)); break; case CIRCE_CBOR_MAJOR_TEXTSTR: CIRCE_CBOR_ASSERT (circe_cbor_extract_bytestr (dc, &buf_throwaway)); break; case CIRCE_CBOR_MAJOR_ARRAY: CIRCE_CBOR_ASSERT (circe_cbor_extract_length (dc, &len, &is_definite)); if (!is_definite) { while (true) { CIRCE_CBOR_ASSERT (circe_cbor_get_major_type (dc, &type)); if (type == CIRCE_CBOR_MAJOR_SIMPLE) { enum circe_cbor_simple_type st; CIRCE_CBOR_ASSERT (circe_cbor_get_simple_type (dc, &st)); if (st == CIRCE_CBOR_SIMPLE_BREAK) { break; } } circe_cbor_skip (dc, max_depth - 1); } } else { for (uint64_t i = 0; i < len; ++i) { circe_cbor_skip (dc, max_depth - 1); } } break; case CIRCE_CBOR_MAJOR_MAPPING: CIRCE_CBOR_ASSERT (circe_cbor_extract_length (dc, &len, &is_definite)); if (!is_definite) { while (true) { CIRCE_CBOR_ASSERT (circe_cbor_get_major_type (dc, &type)); if (type == CIRCE_CBOR_MAJOR_SIMPLE) { CIRCE_CBOR_ASSERT (circe_cbor_get_simple_type (dc, &st)); if (st == CIRCE_CBOR_SIMPLE_BREAK) { break; } } circe_cbor_skip (dc, max_depth - 1); circe_cbor_skip (dc, max_depth - 1); } } else { for (uint64_t i = 0; i < len; ++i) { circe_cbor_skip (dc, max_depth - 1); circe_cbor_skip (dc, max_depth - 1); } } break; case CIRCE_CBOR_MAJOR_TAG: CIRCE_CBOR_ASSERT (circe_cbor_extract_tag (dc, &num_throwaway)); circe_cbor_skip (dc, max_depth - 1); break; case CIRCE_CBOR_MAJOR_SIMPLE: CIRCE_CBOR_ASSERT (circe_cbor_get_simple_type (dc, &st)); CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + 1 <= dc->buf_len); ++dc->cursor; if (st == CIRCE_CBOR_SIMPLE_SINGLE) { CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + 4 <= dc->buf_len); dc->cursor += 4; } else if (st == CIRCE_CBOR_SIMPLE_DOUBLE) { CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + 8 <= dc->buf_len); dc->cursor += 8; } } return true; } bool circe_cbor_extract_unsigned (struct circe_cbor_decoder *dc, uint64_t *out) { bool _; CIRCE_CBOR_ASSERT (circe_cbor_get_argument (dc, out, &_)); return true; } bool circe_cbor_extract_negative (struct circe_cbor_decoder *dc, uint64_t *magnitude_out) { bool _; CIRCE_CBOR_ASSERT (circe_cbor_get_argument (dc, magnitude_out, &_)); return true; } bool circe_cbor_extract_bytestr (struct circe_cbor_decoder *dc, struct circe_cbor_buffer *out) { bool is_definite; uint64_t len; CIRCE_CBOR_ASSERT (circe_cbor_get_argument (dc, &len, &is_definite)); if (is_definite) { CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + len <= dc->buf_len); *out = (struct circe_cbor_buffer){ .buf_start = dc->cursor, .buf_len = len, }; dc->cursor += len; } else { uint8_t *start = dc->cursor; while (dc->cursor - dc->buf_start < dc->buf_len && *dc->cursor != 0xFF) { ++dc->cursor; } CIRCE_CBOR_ASSERT (*dc->cursor == 0xFF); ++dc->cursor; *out = (struct circe_cbor_buffer){ .buf_start = start, .buf_len = dc->cursor - start, }; } return true; } bool circe_cbor_extract_textstr (struct circe_cbor_decoder *dc, struct circe_cbor_buffer *out) { return circe_cbor_extract_bytestr (dc, out); } bool circe_cbor_extract_float (struct circe_cbor_decoder *dc, float *out) { uint32_t raw = 0; CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + 4 <= dc->buf_len); for (unsigned int i = 4; i > 0; --i) { // TODO: adapt for non-little-endian raw <<= 8; raw |= *(dc->cursor + i - 1); } *out = *((float *)&raw); return true; } bool circe_cbor_extract_double (struct circe_cbor_decoder *dc, double *out) { uint64_t raw = 0; CIRCE_CBOR_ASSERT (dc->cursor - dc->buf_start + 4 <= dc->buf_len); for (unsigned int i = 8; i > 0; --i) { // TODO: adapt for non-little-endian raw <<= 8; raw |= *(dc->cursor + i - 1); } *out = *((double *)&raw); return true; } bool circe_cbor_extract_tag (struct circe_cbor_decoder *dc, uint64_t *out) { bool _; CIRCE_CBOR_ASSERT (circe_cbor_get_argument (dc, out, &_)); return true; } /* ENCODING FUNCTIONS */ bool circe_cbor_emit_with_arg (struct circe_cbor_encoder *ec, enum circe_cbor_major_type t, uint64_t arg) { unsigned int needed = 1; if (arg >= 24) { ++needed; } if (arg >= UINT8_MAX) { ++needed; } if (arg >= UINT16_MAX) { needed += 2; } if (arg >= UINT32_MAX) { needed += 4; } CIRCE_CBOR_ASSERT (ec->cursor - ec->buf_start + needed <= ec->buf_len); *ec->cursor = (uint8_t)t << 5; switch (needed) { case 1: *ec->cursor |= (uint8_t)arg; break; case 2: *ec->cursor |= 24; *(ec->cursor + 1) = (uint8_t)arg; break; case 3: *ec->cursor |= 25; for (unsigned int i = 0; i < 2; ++i) { *(ec->cursor + 1 + i) = (uint8_t)(arg & 0xff); arg >>= 8; } break; case 5: *ec->cursor |= 26; for (unsigned int i = 0; i < 4; ++i) { *(ec->cursor + 1 + i) = (uint8_t)(arg & 0xff); arg >>= 8; } break; case 9: *ec->cursor |= 27; for (unsigned int i = 0; i < 8; ++i) { *(ec->cursor + 1 + i) = (uint8_t)(arg & 0xff); arg >>= 8; } break; } ec->cursor += needed; return true; } bool circe_cbor_emit_unsigned (struct circe_cbor_encoder *ec, uint64_t n) { CIRCE_CBOR_ASSERT (circe_cbor_emit_with_arg (ec, CIRCE_CBOR_MAJOR_UNSIGNED, n)); return true; } bool circe_cbor_emit_negative (struct circe_cbor_encoder *ec, uint64_t magnitude) { CIRCE_CBOR_ASSERT (circe_cbor_emit_with_arg (ec, CIRCE_CBOR_MAJOR_NEGATIVE, magnitude)); return true; } bool circe_cbor_emit_bytestr (struct circe_cbor_encoder *ec, struct circe_cbor_buffer contents) { CIRCE_CBOR_ASSERT (circe_cbor_emit_with_arg (ec, CIRCE_CBOR_MAJOR_BYTESTR, contents.buf_len)); CIRCE_CBOR_ASSERT (ec->cursor - ec->buf_start + contents.buf_len <= ec->buf_len); for (uint64_t i = 0; i < contents.buf_len; ++i) { ec->cursor[i] = contents.buf_start[i]; } ec->cursor += contents.buf_len; return true; } bool circe_cbor_emit_textstr (struct circe_cbor_encoder *ec, struct circe_cbor_buffer contents) { CIRCE_CBOR_ASSERT (circe_cbor_emit_with_arg (ec, CIRCE_CBOR_MAJOR_TEXTSTR, contents.buf_len)); CIRCE_CBOR_ASSERT (ec->cursor - ec->buf_start + contents.buf_len <= ec->buf_len); for (uint64_t i = 0; i < contents.buf_len; ++i) { ec->cursor[i] = contents.buf_start[i]; } ec->cursor += contents.buf_len; return true; } bool circe_cbor_emit_simple (struct circe_cbor_encoder *ec, enum circe_cbor_simple_type t) { CIRCE_CBOR_ASSERT (ec->cursor - ec->buf_start + 1 <= ec->buf_len); *ec->cursor = ((uint8_t)CIRCE_CBOR_MAJOR_SIMPLE << 5) | (uint8_t)t; ++ec->cursor; return true; } bool circe_cbor_emit_float (struct circe_cbor_encoder *ec, float x) { CIRCE_CBOR_ASSERT (ec->cursor - ec->buf_start + 4 <= ec->buf_len); uint32_t raw = *((uint32_t *)&x); for (unsigned int i = 0; i < 4; ++i) { ec->cursor[i] = (uint8_t)(raw & 0xff); raw >>= 8; } ec->cursor += 4; return true; } bool circe_cbor_emit_double (struct circe_cbor_encoder *ec, double x) { CIRCE_CBOR_ASSERT (ec->cursor - ec->buf_start + 4 <= ec->buf_len); uint64_t raw = *((uint64_t *)&x); for (unsigned int i = 0; i < 8; ++i) { ec->cursor[i] = (uint8_t)(raw & 0xff); raw >>= 8; } ec->cursor += 4; return true; } bool circe_cbor_emit_tag (struct circe_cbor_encoder *ec, uint64_t tagnum) { CIRCE_CBOR_ASSERT (circe_cbor_emit_with_arg (ec, CIRCE_CBOR_MAJOR_TAG, tagnum)); return true; } bool circe_cbor_emit_mapping_header (struct circe_cbor_encoder *ec, uint64_t len) { CIRCE_CBOR_ASSERT (circe_cbor_emit_with_arg (ec, CIRCE_CBOR_MAJOR_MAPPING, len)); return true; } bool circe_cbor_emit_array_header (struct circe_cbor_encoder *ec, uint64_t len) { CIRCE_CBOR_ASSERT (circe_cbor_emit_with_arg (ec, CIRCE_CBOR_MAJOR_ARRAY, len)); return true; }