From bb7a14009432e814674f0a5dfec12f67e7ef9299 Mon Sep 17 00:00:00 2001 From: "Leonardo B. Tosin" Date: Sat, 21 Sep 2024 15:36:46 -0300 Subject: [PATCH] enhanc: Represent a TLV object as a struct --- include/ber-tlv.h | 14 +++++- src/ber-tlv.c | 106 ++++++++++++++++++++++------------------------ 2 files changed, 63 insertions(+), 57 deletions(-) diff --git a/include/ber-tlv.h b/include/ber-tlv.h index c52e8f9..0f4c70d 100644 --- a/include/ber-tlv.h +++ b/include/ber-tlv.h @@ -4,6 +4,18 @@ #include #include +// TLV schema +typedef struct +{ + uint32_t tag; // TAG + size_t length; // LEN + uint8_t *value; // VAL + int is_constructed; // constructed or primitive? +} TLV; + +// Functions void interpret_tlv(uint8_t *tlvObject, size_t objLen); +TLV parse_tlv(uint8_t *tlv, size_t len); +void print_tlv(TLV *tlv, int indent); -#endif \ No newline at end of file +#endif diff --git a/src/ber-tlv.c b/src/ber-tlv.c index bd6dd99..f8f9ae2 100644 --- a/src/ber-tlv.c +++ b/src/ber-tlv.c @@ -1,5 +1,6 @@ #include #include +#include #include "ber-tlv.h" void print_indent(int indent) @@ -10,105 +11,98 @@ void print_indent(int indent) } } -size_t parse_tag(uint8_t *tlv, size_t len, uint32_t *tag) +// TLV parsing +TLV parse_tlv(uint8_t *tlv, size_t len) { - *tag = tlv[0]; + TLV tlv_obj = {0}; + + // TAG + tlv_obj.tag = tlv[0]; size_t tag_len = 1; - // Multi-byte tag - if ((*tag & 0x1F) == 0x1F) + // Multi-byte TAG + if ((tlv_obj.tag & 0x1F) == 0x1F) { - *tag = 0; - - // Keep processing while MSB is set + tlv_obj.tag = 0; while (tlv[tag_len] & 0x80) { - *tag = (*tag << 7) | (tlv[tag_len] & 0x7F); + tlv_obj.tag = (tlv_obj.tag << 7) | (tlv[tag_len] & 0x7F); tag_len++; } - *tag = (*tag << 7) | (tlv[tag_len] & 0x7F); + tlv_obj.tag = (tlv_obj.tag << 7) | (tlv[tag_len] & 0x7F); tag_len++; } - return tag_len; -} -size_t parse_length(uint8_t *tlv, size_t len, size_t *length) -{ - if (tlv[0] < 0x80) + // LEN + size_t length_len = 1; + if (tlv[tag_len] < 0x80) { - *length = tlv[0]; - return 1; + tlv_obj.length = tlv[tag_len]; } else { - int num_bytes = tlv[0] & 0x7F; - *length = 0; + int num_bytes = tlv[tag_len] & 0x7F; + tlv_obj.length = 0; for (int i = 1; i <= num_bytes; i++) { - *length = (*length << 8) | tlv[i]; + tlv_obj.length = (tlv_obj.length << 8) | tlv[tag_len + i]; } - return 1 + num_bytes; + length_len = 1 + num_bytes; } -} -size_t print_tlv(uint8_t *tlv, size_t len, int indent, int is_first) -{ - if (len == 0) - return 0; + // constructed or primitive? + tlv_obj.is_constructed = (tlv[0] & 0x20) ? 1 : 0; - uint32_t tag; - size_t tag_len = parse_tag(tlv, len, &tag); + // Values + tlv_obj.value = (tlv + tag_len + length_len); - size_t length; - size_t len_len = parse_length(tlv + tag_len, len - tag_len, &length); + return tlv_obj; +} +// Output formatted TLV +void print_tlv(TLV *tlv, int indent) +{ print_indent(indent); - printf("TAG – 0x%02X (%s class, %s)\n", tag, - (tag & 0xC0) == 0xC0 ? "private" : "public", - (tag & 0x20) ? "constructed" : "primitive"); + printf("TAG – 0x%02X (%s class, %s)\n", tlv->tag, + (tlv->tag & 0xC0) == 0xC0 ? "private" : "public", + tlv->is_constructed ? "constructed" : "primitive"); print_indent(indent); - printf("LEN – %zu bytes\n", length); + printf("LEN – %zu bytes\n", tlv->length); - // If LEN is header or with 0 length, jump line - if (is_first || length == 0) + // If LEN = 0 bytes or constructed, jump line + if (tlv->is_constructed || tlv->length == 0) { printf("\n"); } - size_t total_length = tag_len + len_len + length; - - // Process constructed objects (skip value print) - if (tag & 0x20) + // process child objects if constructed + if (tlv->is_constructed) { - size_t processed_len = tag_len + len_len; - while (processed_len < total_length) + size_t offset = 0; + while (offset < tlv->length) { - processed_len += print_tlv(tlv + processed_len, len - processed_len, indent + 1, 0); + TLV child_tlv = parse_tlv(tlv->value + offset, tlv->length - offset); + print_tlv(&child_tlv, indent + 1); + offset += 2 + child_tlv.length; // tag + length } } - else if (length > 0) + else if (tlv->length > 0) { - // Print value for primitive tags - + // Print primitive TLV print_indent(indent); printf("VAL –"); - - for (size_t i = 0; i < length; i++) + for (size_t i = 0; i < tlv->length; i++) { - printf(" 0x%02X", tlv[tag_len + len_len + i]); + printf(" 0x%02X", tlv->value[i]); } - printf("\n"); - - // End of section - printf("\n"); + printf("\n\n"); } - - return total_length; } +// Entry point void interpret_tlv(uint8_t *tlvObject, size_t objLen) { - // Pass 1 to indicate that the first TLV is being processed - print_tlv(tlvObject, objLen, 0, 1); + TLV root_tlv = parse_tlv(tlvObject, objLen); + print_tlv(&root_tlv, 0); }