diff options
Diffstat (limited to 'asn1_decoder.cpp')
-rw-r--r-- | asn1_decoder.cpp | 253 |
1 files changed, 110 insertions, 143 deletions
diff --git a/asn1_decoder.cpp b/asn1_decoder.cpp index ca4ee5267..a9dfccc58 100644 --- a/asn1_decoder.cpp +++ b/asn1_decoder.cpp @@ -14,178 +14,145 @@ * limitations under the License. */ -#include <malloc.h> -#include <stdint.h> -#include <string.h> - #include "asn1_decoder.h" +#include <stdint.h> -typedef struct asn1_context { - size_t length; - const uint8_t* p; - int app_type; -} asn1_context_t; - - -static const int kMaskConstructed = 0xE0; -static const int kMaskTag = 0x7F; -static const int kMaskAppType = 0x1F; - -static const int kTagOctetString = 0x04; -static const int kTagOid = 0x06; -static const int kTagSequence = 0x30; -static const int kTagSet = 0x31; -static const int kTagConstructed = 0xA0; - -asn1_context_t* asn1_context_new(const uint8_t* buffer, size_t length) { - asn1_context_t* ctx = (asn1_context_t*) calloc(1, sizeof(asn1_context_t)); - if (ctx == NULL) { - return NULL; - } - ctx->p = buffer; - ctx->length = length; - return ctx; -} - -void asn1_context_free(asn1_context_t* ctx) { - free(ctx); +int asn1_context::peek_byte() const { + if (length_ <= 0) { + return -1; + } + return *p_; } -static inline int peek_byte(asn1_context_t* ctx) { - if (ctx->length <= 0) { - return -1; - } - return *ctx->p; -} +int asn1_context::get_byte() { + if (length_ <= 0) { + return -1; + } -static inline int get_byte(asn1_context_t* ctx) { - if (ctx->length <= 0) { - return -1; - } - int byte = *ctx->p; - ctx->p++; - ctx->length--; - return byte; + int byte = *p_; + p_++; + length_--; + return byte; } -static inline bool skip_bytes(asn1_context_t* ctx, size_t num_skip) { - if (ctx->length < num_skip) { - return false; - } - ctx->p += num_skip; - ctx->length -= num_skip; - return true; +bool asn1_context::skip_bytes(size_t num_skip) { + if (length_ < num_skip) { + return false; + } + p_ += num_skip; + length_ -= num_skip; + return true; } -static bool decode_length(asn1_context_t* ctx, size_t* out_len) { - int num_octets = get_byte(ctx); - if (num_octets == -1) { - return false; - } - if ((num_octets & 0x80) == 0x00) { - *out_len = num_octets; - return 1; - } - num_octets &= kMaskTag; - if ((size_t)num_octets >= sizeof(size_t)) { - return false; - } - size_t length = 0; - for (int i = 0; i < num_octets; ++i) { - int byte = get_byte(ctx); - if (byte == -1) { - return false; - } - length <<= 8; - length += byte; - } - *out_len = length; +bool asn1_context::decode_length(size_t* out_len) { + int num_octets = get_byte(); + if (num_octets == -1) { + return false; + } + if ((num_octets & 0x80) == 0x00) { + *out_len = num_octets; return true; + } + num_octets &= kMaskTag; + if (static_cast<size_t>(num_octets) >= sizeof(size_t)) { + return false; + } + size_t length = 0; + for (int i = 0; i < num_octets; ++i) { + int byte = get_byte(); + if (byte == -1) { + return false; + } + length <<= 8; + length += byte; + } + *out_len = length; + return true; } /** * Returns the constructed type and advances the pointer. E.g. A0 -> 0 */ -asn1_context_t* asn1_constructed_get(asn1_context_t* ctx) { - int type = get_byte(ctx); - if (type == -1 || (type & kMaskConstructed) != kTagConstructed) { - return NULL; - } - size_t length; - if (!decode_length(ctx, &length) || length > ctx->length) { - return NULL; - } - asn1_context_t* app_ctx = asn1_context_new(ctx->p, length); - app_ctx->app_type = type & kMaskAppType; - return app_ctx; +asn1_context* asn1_context::asn1_constructed_get() { + int type = get_byte(); + if (type == -1 || (type & kMaskConstructed) != kTagConstructed) { + return nullptr; + } + size_t length; + if (!decode_length(&length) || length > length_) { + return nullptr; + } + asn1_context* app_ctx = new asn1_context(p_, length); + app_ctx->app_type_ = type & kMaskAppType; + return app_ctx; } -bool asn1_constructed_skip_all(asn1_context_t* ctx) { - int byte = peek_byte(ctx); - while (byte != -1 && (byte & kMaskConstructed) == kTagConstructed) { - skip_bytes(ctx, 1); - size_t length; - if (!decode_length(ctx, &length) || !skip_bytes(ctx, length)) { - return false; - } - byte = peek_byte(ctx); +bool asn1_context::asn1_constructed_skip_all() { + int byte = peek_byte(); + while (byte != -1 && (byte & kMaskConstructed) == kTagConstructed) { + skip_bytes(1); + size_t length; + if (!decode_length(&length) || !skip_bytes(length)) { + return false; } - return byte != -1; + byte = peek_byte(); + } + return byte != -1; } -int asn1_constructed_type(asn1_context_t* ctx) { - return ctx->app_type; +int asn1_context::asn1_constructed_type() const { + return app_type_; } -asn1_context_t* asn1_sequence_get(asn1_context_t* ctx) { - if ((get_byte(ctx) & kMaskTag) != kTagSequence) { - return NULL; - } - size_t length; - if (!decode_length(ctx, &length) || length > ctx->length) { - return NULL; - } - return asn1_context_new(ctx->p, length); +asn1_context* asn1_context::asn1_sequence_get() { + if ((get_byte() & kMaskTag) != kTagSequence) { + return nullptr; + } + size_t length; + if (!decode_length(&length) || length > length_) { + return nullptr; + } + return new asn1_context(p_, length); } -asn1_context_t* asn1_set_get(asn1_context_t* ctx) { - if ((get_byte(ctx) & kMaskTag) != kTagSet) { - return NULL; - } - size_t length; - if (!decode_length(ctx, &length) || length > ctx->length) { - return NULL; - } - return asn1_context_new(ctx->p, length); +asn1_context* asn1_context::asn1_set_get() { + if ((get_byte() & kMaskTag) != kTagSet) { + return nullptr; + } + size_t length; + if (!decode_length(&length) || length > length_) { + return nullptr; + } + return new asn1_context(p_, length); } -bool asn1_sequence_next(asn1_context_t* ctx) { - size_t length; - if (get_byte(ctx) == -1 || !decode_length(ctx, &length) || !skip_bytes(ctx, length)) { - return false; - } - return true; +bool asn1_context::asn1_sequence_next() { + size_t length; + if (get_byte() == -1 || !decode_length(&length) || !skip_bytes(length)) { + return false; + } + return true; } -bool asn1_oid_get(asn1_context_t* ctx, const uint8_t** oid, size_t* length) { - if (get_byte(ctx) != kTagOid) { - return false; - } - if (!decode_length(ctx, length) || *length == 0 || *length > ctx->length) { - return false; - } - *oid = ctx->p; - return true; +bool asn1_context::asn1_oid_get(const uint8_t** oid, size_t* length) { + if (get_byte() != kTagOid) { + return false; + } + if (!decode_length(length) || *length == 0 || *length > length_) { + return false; + } + *oid = p_; + return true; } -bool asn1_octet_string_get(asn1_context_t* ctx, const uint8_t** octet_string, size_t* length) { - if (get_byte(ctx) != kTagOctetString) { - return false; - } - if (!decode_length(ctx, length) || *length == 0 || *length > ctx->length) { - return false; - } - *octet_string = ctx->p; - return true; +bool asn1_context::asn1_octet_string_get(const uint8_t** octet_string, size_t* length) { + if (get_byte() != kTagOctetString) { + return false; + } + if (!decode_length(length) || *length == 0 || *length > length_) { + return false; + } + *octet_string = p_; + return true; } |