asn1_unwrap() function to parse ASN.1 objects with length/type
authorMartin Willi <martin@strongswan.org>
Fri, 3 Jul 2009 09:06:51 +0000 (11:06 +0200)
committerMartin Willi <martin@strongswan.org>
Mon, 6 Jul 2009 11:15:28 +0000 (13:15 +0200)
src/libstrongswan/asn1/asn1.c
src/libstrongswan/asn1/asn1.h

index ee91c14..ec46b16 100644 (file)
@@ -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 };
index 6a2b594..8072d62 100644 (file)
@@ -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
@@ -123,6 +125,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
  *
  * @param blob         ASN.1 coded blob