28#define DER_LONG_FORM_FLAG 0x80
29#define DER_FIRST_BYTE_VALUE_MASK 0x7f
42 PRINTF(
"Failed to extract uint8 value from TLV data (tag 0x%x)\n", data->
tag);
45 if (value != expected_value) {
47 "Value mismatch for tag 0x%x: expected %u, got %u\n", data->
tag, expected_value, value);
66 if (data == NULL || value == NULL) {
67 PRINTF(
"Received NULL parameter\n");
71 PRINTF(
"Invalid length (%u bytes) for tag 0x%x (expected 1-%zu bytes)\n",
79 uint8_t buffer[
sizeof(uint64_t)] = {0};
82 *value = U8BE(buffer, 0);
98 if (data == NULL || value == NULL) {
99 PRINTF(
"Received NULL parameter\n");
106 *value = (uint32_t) tmp_value;
122 if (data == NULL || value == NULL) {
123 PRINTF(
"Received NULL parameter\n");
130 *value = (uint16_t) tmp_value;
146 if (data == NULL || value == NULL) {
147 PRINTF(
"Received NULL parameter\n");
154 *value = (uint8_t) tmp_value;
171 if (data == NULL || value == NULL) {
172 PRINTF(
"Received NULL parameter\n");
179 *value = (tmp_value == 1);
200 if (data == NULL || out == NULL) {
201 PRINTF(
"Received NULL parameter\n");
205 if (min_size != 0 && data->
value.
size < min_size) {
206 PRINTF(
"Expected at least %d bytes, found %d\n", min_size, data->
value.
size);
209 if (max_size != 0 && data->
value.
size > max_size) {
210 PRINTF(
"Expected at most %d bytes, found %d\n", max_size, data->
value.
size);
238 if (data == NULL || out == NULL) {
239 PRINTF(
"Received NULL parameter\n");
244 size_t actual_length = 0;
249 PRINTF(
"Embedded null byte at offset %u\n", (
unsigned) actual_length);
253 if (min_length != 0 && data->
value.
size < min_length) {
254 PRINTF(
"Expected at least %u bytes, found %u\n", min_length, data->
value.
size);
258 if (out_size != 0 && data->
value.
size + 1 > out_size) {
259 PRINTF(
"Expected at most %u bytes, found %u (+1)\n", out_size, data->
value.
size);
284 uint8_t buf[
sizeof(*value)];
286 if (payload == NULL || offset == NULL || value == NULL) {
287 PRINTF(
"Received NULL parameter\n");
294 if ((*offset + byte_length) > payload->
size) {
295 PRINTF(
"TLV payload too small for DER encoded value\n");
298 if (byte_length >
sizeof(buf) || byte_length == 0) {
299 PRINTF(
"Unexpectedly long DER-encoded value (%u bytes)\n", byte_length);
302 memset(buf, 0, (
sizeof(buf) - byte_length));
303 memcpy(buf + (
sizeof(buf) - byte_length), &payload->
ptr[*offset], byte_length);
304 *value = U4BE(buf, 0);
305 *offset += byte_length;
309 *value = payload->
ptr[*offset];
332 *value = (uint16_t) tmp_value;
351 for (
size_t i = 0; i < tag_count; i++) {
354 PRINTF(
"No flag found for tag 0x%x\n", tags[i]);
357 if ((received.
flags & flag) != flag) {
358 PRINTF(
"Tag 0x%x no received\n", tags[i]);
374 uint8_t handlers_count,
378 for (uint8_t idx = 0; idx < handlers_count; ++idx) {
379 if (handlers[idx].tag == tag) {
380 return &handlers[idx];
409 uint8_t handlers_count,
419 size_t tag_start_offset;
425 explicit_bzero(received_tags_flags,
sizeof(*received_tags_flags));
428 PRINTF(
"Parsing TLV payload %.*H\n", payload->
size, payload->
ptr);
434 tag_start_offset = offset;
439 if (handler == NULL) {
440 PRINTF(
"No handler found for tag 0x%x\n", data.
tag);
456 PRINTF(
"Error: can't read %d + %d, only %d\n",
464 PRINTF(
"Handling tag 0x%02x length %d value '%.*H'\n",
472 PRINTF(
"Handling tag 0x%02x length %d\n", data.
tag, data.
value.
size);
477 data.
raw.
ptr = &payload->
ptr[tag_start_offset];
478 data.
raw.
size = offset - tag_start_offset;
482 if (handler->
is_unique && ((received_tags_flags->
flags & flag) == flag)) {
483 PRINTF(
"Tag = %d was already received and is flagged unique\n", data.
tag);
488 fptr = PIC(common_handler);
489 if (fptr != NULL && !(*fptr)(&data, tlv_out)) {
490 PRINTF(
"Common handler error while handling tag 0x%x\n", handler->
tag);
495 fptr = PIC(handler->
func);
496 if (fptr != NULL && !(*fptr)(&data, tlv_out)) {
497 PRINTF(
"Handler error while handling tag 0x%x\n", handler->
tag);
502 received_tags_flags->
flags |= flag;
511 PRINTF(
"Error: unexpected end step %d\n", step);
514 if (offset != payload->
size) {
515 PRINTF(
"Error: unexpected data at the end of the TLV payload!\n");
tag_to_flag_function_t * tag_to_flag_function
size_t size
Pointer to byte buffer.
TLV_flag_t() tag_to_flag_function_t(TLV_tag_t tag)
enum tlv_step_e tlv_step_t
bool get_uint16_t_from_tlv_data(const tlv_data_t *data, uint16_t *value)
Extract a uint16_t value from TLV data.
#define DER_LONG_FORM_FLAG
bool get_string_from_tlv_data(const tlv_data_t *data, char *out, uint16_t min_length, uint16_t out_size)
Copy a NUL-terminated string from TLV data.
bool get_uint64_t_from_tlv_data(const tlv_data_t *data, uint64_t *value)
Extract a uint64_t value from TLV data.
bool get_bool_from_tlv_data(const tlv_data_t *data, bool *value)
Extract a boolean value from TLV data.
#define DER_FIRST_BYTE_VALUE_MASK
bool get_uint8_t_from_tlv_data(const tlv_data_t *data, uint8_t *value)
Extract a uint8_t value from TLV data.
static bool get_der_value_as_uint32(const buffer_t *payload, size_t *offset, uint32_t *value)
bool tlv_check_received_tags(TLV_reception_t received, const TLV_tag_t *tags, size_t tag_count)
Check that every tag in tags was received during parsing.
static const _internal_tlv_handler_t * find_handler(const _internal_tlv_handler_t *handlers, uint8_t handlers_count, TLV_tag_t tag)
Find the handler registered for a given tag.
static bool get_der_value_as_uint16(const buffer_t *payload, size_t *offset, uint16_t *value)
Parse a DER-encoded value and fit it into a uint16_t, or fail.
bool tlv_enforce_u8_value(const tlv_data_t *data, uint8_t expected_value)
Enforce that a TLV data contains the expected uint8 value.
bool _parse_tlv_internal(const _internal_tlv_handler_t *handlers, uint8_t handlers_count, tlv_handler_cb_t *common_handler, tag_to_flag_function_t *tag_to_flag_function, const buffer_t *payload, void *tlv_out, TLV_reception_t *received_tags_flags)
Parse a raw TLV payload using a pre-built handler table.
bool get_buffer_from_tlv_data(const tlv_data_t *data, buffer_t *out, uint16_t min_size, uint16_t max_size)
Extract a sized buffer from TLV data (zero-copy).
bool get_uint32_t_from_tlv_data(const tlv_data_t *data, uint32_t *value)
Extract a uint32_t value from TLV data.
bool() tlv_handler_cb_t(const tlv_data_t *data, void *tlv_extracted)