From 596e0540a579fce6e4e2ab722ae82cb29c60f788 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Fri, 3 Jul 2009 11:06:51 +0200 Subject: [PATCH] asn1_unwrap() function to parse ASN.1 objects with length/type --- src/libstrongswan/asn1/asn1.c | 47 +++++++++++++++++++++++++++++++++++ src/libstrongswan/asn1/asn1.h | 13 +++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c index ee91c14e1..ec46b165b 100644 --- a/src/libstrongswan/asn1/asn1.c +++ b/src/libstrongswan/asn1/asn1.c @@ -311,6 +311,53 @@ size_t asn1_length(chunk_t *blob) return len; } +/* + * See header. + */ +int asn1_unwrap(chunk_t *blob, chunk_t *inner) +{ + chunk_t res; + u_char len; + int type; + + if (blob->len < 2) + { + return ASN1_INVALID; + } + type = blob->ptr[0]; + len = blob->ptr[1]; + *blob = chunk_skip(*blob, 2); + + if ((len & 0x80) == 0) + { /* single length octet */ + res.len = len; + } + else + { /* composite length, determine number of length octets */ + len &= 0x7f; + if (len == 0 || len > sizeof(res.len)) + { + return ASN1_INVALID; + } + res.len = 0; + while (len-- > 0) + { + res.len = 256 * res.len + blob->ptr[0]; + *blob = chunk_skip(*blob, 1); + } + } + if (res.len > blob->len) + { + return ASN1_INVALID; + } + res.ptr = blob->ptr; + *blob = chunk_skip(*blob, res.len); + /* updating inner not before we are finished allows a caller to pass + * blob = inner */ + *inner = res; + return type; +} + #define TIME_MAX 0x7fffffff static const int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; diff --git a/src/libstrongswan/asn1/asn1.h b/src/libstrongswan/asn1/asn1.h index 6a2b594c0..8072d62d6 100644 --- a/src/libstrongswan/asn1/asn1.h +++ b/src/libstrongswan/asn1/asn1.h @@ -74,7 +74,9 @@ typedef enum { ASN1_CONTEXT_C_2 = 0xA2, ASN1_CONTEXT_C_3 = 0xA3, ASN1_CONTEXT_C_4 = 0xA4, - ASN1_CONTEXT_C_5 = 0xA5 + ASN1_CONTEXT_C_5 = 0xA5, + + ASN1_INVALID = 0x100, } asn1_t; #define ASN1_INVALID_LENGTH 0xffffffff @@ -122,6 +124,15 @@ chunk_t asn1_build_known_oid(int n); */ size_t asn1_length(chunk_t *blob); +/** + * Unwrap the inner content of an ASN.1 type/length wrapped object. + * + * @param blob blob to parse header from, moved behind parsed content + * @param content inner content + * @return parsed type, ASN1_INVALID if length parsing failed + */ +int asn1_unwrap(chunk_t *blob, chunk_t *content); + /** * Parses an ASN.1 algorithmIdentifier object *