Added conversion functions between string OIDs and its DER encoding
authorMartin Willi <martin@revosec.ch>
Tue, 14 Dec 2010 13:47:44 +0000 (14:47 +0100)
committerMartin Willi <martin@revosec.ch>
Wed, 5 Jan 2011 15:46:02 +0000 (16:46 +0100)
src/libstrongswan/asn1/asn1.c
src/libstrongswan/asn1/asn1.h

index 6f549d4..f80c2b9 100644 (file)
@@ -126,6 +126,100 @@ chunk_t asn1_build_known_oid(int n)
 /*
  * Defined in header.
  */
+chunk_t asn1_oid_from_string(char *str)
+{
+       enumerator_t *enumerator;
+       u_char buf[32];
+       char *end;
+       int i = 0, pos = 0;
+       u_int val, first = 0;
+
+       enumerator = enumerator_create_token(str, ".", "");
+       while (enumerator->enumerate(enumerator, &str))
+       {
+               val = strtoul(str, &end, 10);
+               if (end == str || pos > countof(buf))
+               {
+                       pos = 0;
+                       break;
+               }
+               switch (i++)
+               {
+                       case 0:
+                               first = val;
+                               break;
+                       case 1:
+                               buf[pos++] = first * 40 + val;
+                               break;
+                       default:
+                               if (val < 128)
+                               {
+                                       buf[pos++] = val;
+                               }
+                               else
+                               {
+                                       buf[pos++] = 128 | (val >> 7);
+                                       buf[pos++] = (val % 256) & 0x7F;
+                               }
+                               break;
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       return chunk_clone(chunk_create(buf, pos));
+}
+
+/*
+ * Defined in header.
+ */
+char *asn1_oid_to_string(chunk_t oid)
+{
+       char buf[64], *pos = buf;
+       int len;
+       u_int val;
+
+       if (!oid.len)
+       {
+               return NULL;
+       }
+       val = oid.ptr[0] / 40;
+       len = snprintf(buf, sizeof(buf), "%d.%d", val, oid.ptr[0] - val * 40);
+       oid = chunk_skip(oid, 1);
+       if (len < 0 || len >= sizeof(buf))
+       {
+               return NULL;
+       }
+       pos += len;
+
+       while (oid.len)
+       {
+               if (oid.ptr[0] < 128)
+               {
+                       len = snprintf(pos, sizeof(buf) + buf - pos, ".%d", oid.ptr[0]);
+                       oid = chunk_skip(oid, 1);
+               }
+               else
+               {
+                       if (oid.len == 1)
+                       {
+                               return NULL;
+                       }
+                       val = ((u_int)(oid.ptr[0] & 0x7F) << 7) + oid.ptr[1];
+                       len = snprintf(pos, sizeof(buf) + buf - pos, ".%d", val);
+                       oid = chunk_skip(oid, 2);
+               }
+               if (len < 0 || len >= sizeof(buf) + buf - pos)
+               {
+                       return NULL;
+               }
+               pos += len;
+       }
+       return strdup(buf);
+}
+
+/*
+ * Defined in header.
+ */
 size_t asn1_length(chunk_t *blob)
 {
        u_char n;
index 866c280..05a0608 100644 (file)
@@ -115,6 +115,22 @@ int asn1_known_oid(chunk_t object);
 chunk_t asn1_build_known_oid(int n);
 
 /**
+ * Convert human readable OID to ASN.1 DER encoding, without OID header.
+ *
+ * @param str          OID string (e.g. 1.2.345.67.8)
+ * @return                     allocated ASN.1 encoded OID, chunk_empty on error
+ */
+chunk_t asn1_oid_from_string(char *str);
+
+/**
+ * Convert a DER encoded ASN.1 OID to a human readable string.
+ *
+ * @param oid          DER encoded OID, without header
+ * @return                     human readable OID string, allocated, NULL on error
+ */
+char* asn1_oid_to_string(chunk_t oid);
+
+/**
  * Returns the length of an ASN.1 object
  * The blob pointer is advanced past the tag length fields
  *