summaryrefslogtreecommitdiff
path: root/src/libstrongswan/asn1
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/asn1')
-rw-r--r--src/libstrongswan/asn1/asn1.c366
-rw-r--r--src/libstrongswan/asn1/asn1.h223
-rw-r--r--src/libstrongswan/asn1/asn1_parser.c302
-rw-r--r--src/libstrongswan/asn1/asn1_parser.h119
-rw-r--r--src/libstrongswan/asn1/oid.c276
-rw-r--r--src/libstrongswan/asn1/oid.h124
-rw-r--r--src/libstrongswan/asn1/oid.txt70
-rwxr-xr-xsrc/libstrongswan/asn1/pem.c108
-rwxr-xr-xsrc/libstrongswan/asn1/pem.h14
-rw-r--r--src/libstrongswan/asn1/ttodata.c433
-rw-r--r--src/libstrongswan/asn1/ttodata.h28
11 files changed, 1085 insertions, 978 deletions
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index 3f0b829a9..524abfe5e 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -1,10 +1,3 @@
-/**
- * @file asn1.c
- *
- * @brief Simple ASN.1 parser
- *
- */
-
/*
* Copyright (C) 2006 Martin Will
* Copyright (C) 2000-2008 Andreas Steffen
@@ -21,19 +14,23 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: asn1.c 3451 2008-02-05 19:27:05Z andreas $
+ * $Id: asn1.c 4047 2008-06-10 07:36:44Z tobias $
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
-#include "asn1.h"
-
#include <library.h>
#include <debug.h>
-/* some common prefabricated ASN.1 constants */
+#include "oid.h"
+#include "asn1.h"
+#include "asn1_parser.h"
+
+/**
+ * some common prefabricated ASN.1 constants
+ */
static u_char ASN1_INTEGER_0_str[] = { 0x02, 0x00 };
static u_char ASN1_INTEGER_1_str[] = { 0x02, 0x01, 0x01 };
static u_char ASN1_INTEGER_2_str[] = { 0x02, 0x01, 0x02 };
@@ -42,7 +39,9 @@ const chunk_t ASN1_INTEGER_0 = chunk_from_buf(ASN1_INTEGER_0_str);
const chunk_t ASN1_INTEGER_1 = chunk_from_buf(ASN1_INTEGER_1_str);
const chunk_t ASN1_INTEGER_2 = chunk_from_buf(ASN1_INTEGER_2_str);
-/* some popular algorithmIdentifiers */
+/**
+ * some popular algorithmIdentifiers
+ */
static u_char ASN1_md2_id_str[] = {
0x30, 0x0c,
@@ -149,19 +148,8 @@ static const chunk_t ASN1_sha256WithRSA_id = chunk_from_buf(ASN1_sha256WithRSA_i
static const chunk_t ASN1_sha384WithRSA_id = chunk_from_buf(ASN1_sha384WithRSA_id_str);
static const chunk_t ASN1_sha512WithRSA_id = chunk_from_buf(ASN1_sha512WithRSA_id_str);
-/* ASN.1 definiton of an algorithmIdentifier */
-static const asn1Object_t algorithmIdentifierObjects[] = {
- { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */
- { 1, "parameters", ASN1_EOC, ASN1_RAW } /* 2 */
-};
-
-#define ALGORITHM_ID_ALG 1
-#define ALGORITHM_ID_PARAMETERS 2
-#define ALGORITHM_ID_ROOF 3
-
-/**
- * return the ASN.1 encoded algorithm identifier
+/*
+ * Defined in header.
*/
chunk_t asn1_algorithmIdentifier(int oid)
{
@@ -198,11 +186,10 @@ chunk_t asn1_algorithmIdentifier(int oid)
}
}
-/**
- * If the oid is listed in the oid_names table then the corresponding
- * position in the oid_names table is returned otherwise -1 is returned
+/*
+ * Defined in header.
*/
-int known_oid(chunk_t object)
+int asn1_known_oid(chunk_t object)
{
int oid = 0;
@@ -230,8 +217,8 @@ int known_oid(chunk_t object)
return -1;
}
-/**
- * Decodes the length in bytes of an ASN.1 object
+/*
+ * Defined in header.
*/
u_int asn1_length(chunk_t *blob)
{
@@ -278,26 +265,9 @@ u_int asn1_length(chunk_t *blob)
}
/**
- * determines if a character string is of type ASN.1 printableString
- */
-bool is_printablestring(chunk_t str)
-{
- const char printablestring_charset[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
- u_int i;
-
- for (i = 0; i < str.len; i++)
- {
- if (strchr(printablestring_charset, str.ptr[i]) == NULL)
- return FALSE;
- }
- return TRUE;
-}
-
-/**
* Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time
*/
-time_t asn1totime(const chunk_t *utctime, asn1_t type)
+time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
{
struct tm t;
time_t tz_offset;
@@ -372,7 +342,7 @@ time_t asn1totime(const chunk_t *utctime, asn1_t type)
/**
* Convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format
*/
-chunk_t timetoasn1(const time_t *time, asn1_t type)
+chunk_t asn1_from_time(const time_t *time, asn1_t type)
{
int offset;
const char *format;
@@ -397,31 +367,17 @@ chunk_t timetoasn1(const time_t *time, asn1_t type)
return asn1_simple_object(type, formatted_time);
}
-
-/**
- * Initializes the internal context of the ASN.1 parser
- */
-void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0,
- bool implicit, bool private)
-{
- ctx->blobs[0] = blob;
- ctx->level0 = level0;
- ctx->implicit = implicit;
- ctx->private = private;
- memset(ctx->loopAddr, '\0', sizeof(ctx->loopAddr));
-}
-
-/**
- * print the value of an ASN.1 simple object
+/*
+ * Defined in header.
*/
-static void debug_asn1_simple_object(chunk_t object, asn1_t type, bool private)
+void asn1_debug_simple_object(chunk_t object, asn1_t type, bool private)
{
int oid;
switch (type)
{
case ASN1_OID:
- oid = known_oid(object);
+ oid = asn1_known_oid(object);
if (oid != OID_UNKNOWN)
{
DBG2(" '%s'", oid_names[oid].name);
@@ -438,7 +394,7 @@ static void debug_asn1_simple_object(chunk_t object, asn1_t type, bool private)
case ASN1_UTCTIME:
case ASN1_GENERALIZEDTIME:
{
- time_t time = asn1totime(&object, type);
+ time_t time = asn1_to_time(&object, type);
DBG2(" '%T'", &time);
}
@@ -457,147 +413,9 @@ static void debug_asn1_simple_object(chunk_t object, asn1_t type, bool private)
}
/**
- * Parses and extracts the next ASN.1 object
- */
-bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx)
-{
- asn1Object_t obj = objects[*objectID];
- chunk_t *blob;
- chunk_t *blob1;
- u_char *start_ptr;
-
- *object = chunk_empty;
-
- if (obj.flags & ASN1_END) /* end of loop or option found */
- {
- if (ctx->loopAddr[obj.level] && ctx->blobs[obj.level+1].len > 0)
- {
- *objectID = ctx->loopAddr[obj.level]; /* another iteration */
- obj = objects[*objectID];
- }
- else
- {
- ctx->loopAddr[obj.level] = 0; /* exit loop or option*/
- return TRUE;
- }
- }
-
- *level = ctx->level0 + obj.level;
- blob = ctx->blobs + obj.level;
- blob1 = blob + 1;
- start_ptr = blob->ptr;
-
- /* handle ASN.1 defaults values */
- if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
- {
- /* field is missing */
- DBG2("L%d - %s:", *level, obj.name);
- if (obj.type & ASN1_CONSTRUCTED)
- {
- (*objectID)++ ; /* skip context-specific tag */
- }
- return TRUE;
- }
-
- /* handle ASN.1 options */
-
- if ((obj.flags & ASN1_OPT)
- && (blob->len == 0 || *start_ptr != obj.type))
- {
- /* advance to end of missing option field */
- do
- (*objectID)++;
- while (!((objects[*objectID].flags & ASN1_END)
- && (objects[*objectID].level == obj.level)));
- return TRUE;
- }
-
- /* an ASN.1 object must possess at least a tag and length field */
-
- if (blob->len < 2)
- {
- DBG1("L%d - %s: ASN.1 object smaller than 2 octets",
- *level, obj.name);
- return FALSE;
- }
-
- blob1->len = asn1_length(blob);
-
- if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len)
- {
- DBG1("L%d - %s: length of ASN.1 object invalid or too large",
- *level, obj.name);
- return FALSE;
- }
-
- blob1->ptr = blob->ptr;
- blob->ptr += blob1->len;
- blob->len -= blob1->len;
-
- /* return raw ASN.1 object without prior type checking */
-
- if (obj.flags & ASN1_RAW)
- {
- DBG2("L%d - %s:", *level, obj.name);
- object->ptr = start_ptr;
- object->len = (size_t)(blob->ptr - start_ptr);
- return TRUE;
- }
-
- if (*start_ptr != obj.type && !(ctx->implicit && *objectID == 0))
- {
- DBG1("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
- *level, obj.name, obj.type, *start_ptr);
- DBG3("%b", start_ptr, (u_int)(blob->ptr - start_ptr));
- return FALSE;
- }
-
- DBG2("L%d - %s:", ctx->level0+obj.level, obj.name);
-
- /* In case of "SEQUENCE OF" or "SET OF" start a loop */
- if (obj.flags & ASN1_LOOP)
- {
- if (blob1->len > 0)
- {
- /* at least one item, start the loop */
- ctx->loopAddr[obj.level] = *objectID + 1;
- }
- else
- {
- /* no items, advance directly to end of loop */
- do
- (*objectID)++;
- while (!((objects[*objectID].flags & ASN1_END)
- && (objects[*objectID].level == obj.level)));
- return TRUE;
- }
- }
-
- if (obj.flags & ASN1_OBJ)
- {
- object->ptr = start_ptr;
- object->len = (size_t)(blob->ptr - start_ptr);
- if (ctx->private)
- {
- DBG4("%B", object);
- }
- else
- {
- DBG3("%B", object);
- }
- }
- else if (obj.flags & ASN1_BODY)
- {
- *object = *blob1;
- debug_asn1_simple_object(*object, obj.type, ctx->private);
- }
- return TRUE;
-}
-
-/**
* parse an ASN.1 simple type
*/
-bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, const char* name)
+bool asn1_parse_simple_object(chunk_t *object, asn1_t type, u_int level, const char* name)
{
size_t len;
@@ -625,44 +443,69 @@ bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, const c
}
DBG2("L%d - %s:", level, name);
- debug_asn1_simple_object(*object, type, FALSE);
+ asn1_debug_simple_object(*object, type, FALSE);
return TRUE;
}
/**
- * extracts an algorithmIdentifier
+ * ASN.1 definition of an algorithmIdentifier
+ */
+static const asn1Object_t algorithmIdentifierObjects[] = {
+ { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */
+ { 1, "parameters", ASN1_EOC, ASN1_RAW }, /* 2 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
+};
+/* parameters are optional in case of ecdsa-with-SHA1 as algorithm (RFC 3279) */
+static const asn1Object_t algorithmIdentifierObjectsOptional[] = {
+ { 0, "algorithmIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
+ { 1, "algorithm", ASN1_OID, ASN1_BODY }, /* 1 */
+ { 1, "parameters", ASN1_EOC, ASN1_RAW|ASN1_OPT }, /* 2 */
+ { 1, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
+};
+#define ALGORITHM_ID_ALG 1
+#define ALGORITHM_ID_PARAMETERS 2
+
+/*
+ * Defined in header
*/
-int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters)
+int asn1_parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters)
{
- asn1_ctx_t ctx;
+ asn1_parser_t *parser;
chunk_t object;
- u_int level;
+ int objectID;
int alg = OID_UNKNOWN;
- int objectID = 0;
+ const asn1Object_t *objects = algorithmIdentifierObjectsOptional;
- asn1_init(&ctx, blob, level0, FALSE, FALSE);
+ if (parameters != NULL)
+ {
+ objects = algorithmIdentifierObjects;
+ }
+
+ parser = asn1_parser_create(objects, blob);
+ parser->set_top_level(parser, level0);
- while (objectID < ALGORITHM_ID_ROOF)
+ while (parser->iterate(parser, &objectID, &object))
{
- if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx))
- return OID_UNKNOWN;
-
switch (objectID)
{
case ALGORITHM_ID_ALG:
- alg = known_oid(object);
+ alg = asn1_known_oid(object);
break;
case ALGORITHM_ID_PARAMETERS:
if (parameters != NULL)
+ {
*parameters = object;
+ }
break;
default:
break;
}
- objectID++;
}
+ parser->destroy(parser);
return alg;
- }
+}
/*
* tests if a blob contains a valid ASN.1 set or sequence
@@ -696,10 +539,27 @@ bool is_asn1(chunk_t blob)
return FALSE;
}
+/*
+ * Defined in header.
+ */
+bool asn1_is_printablestring(chunk_t str)
+{
+ const char printablestring_charset[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '()+,-./:=?";
+ u_int i;
+
+ for (i = 0; i < str.len; i++)
+ {
+ if (strchr(printablestring_charset, str.ptr[i]) == NULL)
+ return FALSE;
+ }
+ return TRUE;
+}
+
/**
* codes ASN.1 lengths up to a size of 16'777'215 bytes
*/
-void code_asn1_length(size_t length, chunk_t *code)
+static void asn1_code_length(size_t length, chunk_t *code)
{
if (length < 128)
{
@@ -732,14 +592,14 @@ void code_asn1_length(size_t length, chunk_t *code)
/**
* build an empty asn.1 object with tag and length fields already filled in
*/
-u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen)
+u_char* asn1_build_object(chunk_t *object, asn1_t type, size_t datalen)
{
u_char length_buf[4];
chunk_t length = { length_buf, 0 };
u_char *pos;
/* code the asn.1 length field */
- code_asn1_length(datalen, &length);
+ asn1_code_length(datalen, &length);
/* allocate memory for the asn.1 TLV object */
object->len = 1 + length.len + datalen;
@@ -759,13 +619,13 @@ u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen)
}
/**
- * build a simple ASN.1 object
+ * Build a simple ASN.1 object
*/
chunk_t asn1_simple_object(asn1_t tag, chunk_t content)
{
chunk_t object;
- u_char *pos = build_asn1_object(&object, tag, content.len);
+ u_char *pos = asn1_build_object(&object, tag, content.len);
memcpy(pos, content.ptr, content.len);
pos += content.len;
@@ -778,7 +638,7 @@ chunk_t asn1_simple_object(asn1_t tag, chunk_t content)
chunk_t asn1_bitstring(const char *mode, chunk_t content)
{
chunk_t object;
- u_char *pos = build_asn1_object(&object, ASN1_BIT_STRING, 1 + content.len);
+ u_char *pos = asn1_build_object(&object, ASN1_BIT_STRING, 1 + content.len);
*pos++ = 0x00;
memcpy(pos, content.ptr, content.len);
@@ -812,7 +672,7 @@ chunk_t asn1_wrap(asn1_t type, const char *mode, ...)
va_end(chunks);
/* allocate needed memory for construct */
- pos = build_asn1_object(&construct, type, construct.len);
+ pos = asn1_build_object(&construct, type, construct.len);
/* copy or move the chunks */
va_start(chunks, mode);
@@ -834,55 +694,39 @@ chunk_t asn1_wrap(asn1_t type, const char *mode, ...)
}
/**
- * convert a MP integer into a DER coded ASN.1 object
- */
-chunk_t asn1_integer_from_mpz(const mpz_t value)
-{
- size_t bits = mpz_sizeinbase(value, 2); /* size in bits */
- chunk_t n;
-
- n.len = 1 + bits / 8; /* size in bytes */
- n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, value);
-
- return asn1_wrap(ASN1_INTEGER, "m", n);
-}
-
-/**
* ASN.1 definition of time
*/
static const asn1Object_t timeObjects[] = {
- { 0, "utcTime", ASN1_UTCTIME, ASN1_OPT|ASN1_BODY }, /* 0 */
- { 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */
- { 0, "generalizeTime",ASN1_GENERALIZEDTIME, ASN1_OPT|ASN1_BODY }, /* 2 */
- { 0, "end opt", ASN1_EOC, ASN1_END } /* 3 */
+ { 0, "utcTime", ASN1_UTCTIME, ASN1_OPT|ASN1_BODY }, /* 0 */
+ { 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */
+ { 0, "generalizeTime", ASN1_GENERALIZEDTIME, ASN1_OPT|ASN1_BODY }, /* 2 */
+ { 0, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
};
#define TIME_UTC 0
#define TIME_GENERALIZED 2
-#define TIME_ROOF 4
/**
* extracts and converts a UTCTIME or GENERALIZEDTIME object
*/
-time_t parse_time(chunk_t blob, int level0)
+time_t asn1_parse_time(chunk_t blob, int level0)
{
- asn1_ctx_t ctx;
+ asn1_parser_t *parser;
chunk_t object;
- u_int level;
- int objectID = 0;
+ int objectID;
+ time_t utc_time = 0;
- asn1_init(&ctx, blob, level0, FALSE, FALSE);
+ parser= asn1_parser_create(timeObjects, blob);
+ parser->set_top_level(parser, level0);
- while (objectID < TIME_ROOF)
+ while (parser->iterate(parser, &objectID, &object))
{
- if (!extract_object(timeObjects, &objectID, &object, &level, &ctx))
- return 0;
-
if (objectID == TIME_UTC || objectID == TIME_GENERALIZED)
{
- return asn1totime(&object, (objectID == TIME_UTC)
- ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME);
+ utc_time = asn1_to_time(&object, (objectID == TIME_UTC)
+ ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME);
}
- objectID++;
}
- return 0;
+ parser->destroy(parser);
+ return utc_time;
}
diff --git a/src/libstrongswan/asn1/asn1.h b/src/libstrongswan/asn1/asn1.h
index d9d85ba44..0f2e6e5c0 100644
--- a/src/libstrongswan/asn1/asn1.h
+++ b/src/libstrongswan/asn1/asn1.h
@@ -1,10 +1,3 @@
-/**
- * @file asn1.h
- *
- * @brief Simple ASN.1 parser
- *
- */
-
/*
* Copyright (C) 2006 Martin Will
* Copyright (C) 2000-2008 Andreas Steffen
@@ -21,23 +14,23 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: asn1.h 3423 2008-01-22 10:32:37Z andreas $
+ * $Id: asn1.h 3876 2008-04-26 09:24:14Z andreas $
+ */
+
+/**
+ * @defgroup asn1i asn1
+ * @{ @ingroup asn1
*/
-#ifndef _ASN1_H
-#define _ASN1_H
+#ifndef ASN1_H_
+#define ASN1_H_
#include <stdarg.h>
-#include <gmp.h>
#include <library.h>
-#include <asn1/oid.h>
-
/**
- * @brief Definition of some primitive ASN1 types
- *
- * @ingroup asn1
+ * Definition of some primitive ASN1 types
*/
typedef enum {
ASN1_EOC = 0x00,
@@ -65,7 +58,6 @@ typedef enum {
ASN1_CONSTRUCTED = 0x20,
ASN1_SEQUENCE = 0x30,
-
ASN1_SET = 0x31,
ASN1_CONTEXT_S_0 = 0x80,
@@ -86,64 +78,155 @@ typedef enum {
ASN1_CONTEXT_C_5 = 0xA5
} asn1_t;
-/* Definition of ASN1 flags */
+#define ASN1_INVALID_LENGTH 0xffffffff
-#define ASN1_NONE 0x00
-#define ASN1_DEF 0x01
-#define ASN1_OPT 0x02
-#define ASN1_LOOP 0x04
-#define ASN1_END 0x08
-#define ASN1_OBJ 0x10
-#define ASN1_BODY 0x20
-#define ASN1_RAW 0x40
+/**
+ * Some common prefabricated ASN.1 constants
+ */
+extern const chunk_t ASN1_INTEGER_0;
+extern const chunk_t ASN1_INTEGER_1;
+extern const chunk_t ASN1_INTEGER_2;
-#define ASN1_INVALID_LENGTH 0xffffffff
-/* definition of an ASN.1 object */
+/** Some ASN.1 analysis functions */
-typedef struct {
- u_int level;
- const u_char *name;
- asn1_t type;
- u_char flags;
-} asn1Object_t;
+/**
+ * Returns some popular algorithmIdentifiers
+ *
+ * @param oid known OID index
+ * @return body of the corresponding OID
+ */
+chunk_t asn1_algorithmIdentifier(int oid);
-#define ASN1_MAX_LEVEL 10
+/**
+ * Converts an ASN.1 OID into a known OID index
+ *
+ * @param object body of an OID
+ * @return index into the oid_names[] table or OID_UNKNOWN
+ */
+int asn1_known_oid(chunk_t object);
-typedef struct {
- bool implicit;
- bool private;
- u_int level0;
- u_int loopAddr[ASN1_MAX_LEVEL+1];
- chunk_t blobs[ASN1_MAX_LEVEL+2];
-} asn1_ctx_t;
+/**
+ * Returns the length of an ASN.1 object
+ * The blob pointer is advanced past the tag length fields
+ *
+ * @param pointer to an ASN.1 coded blob
+ * @return length of ASN.1 object
+ */
+u_int asn1_length(chunk_t *blob);
-/* some common prefabricated ASN.1 constants */
-extern const chunk_t ASN1_INTEGER_0;
-extern const chunk_t ASN1_INTEGER_1;
-extern const chunk_t ASN1_INTEGER_2;
+/**
+ * Parses an ASN.1 algorithmIdentifier object
+ *
+ * @param blob ASN.1 coded blob
+ * @param level0 top-most level offset
+ * @param params returns optional [ASN.1 coded] parameters
+ * @return known OID index or OID_UNKNOWN
+ */
+int asn1_parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *params);
+
+/**
+ * Parse the top-most level of an ASN.1 object
+ *
+ * @param object ASN.1 coded object
+ * @param type Expected ASN.1 type
+ * @param level0 top-most level offset
+ * @param name descriptive name of object
+ * @return TRUE if parsing successful
+ */
+bool asn1_parse_simple_object(chunk_t *object, asn1_t type, u_int level0,
+ const char* name);
+
+/**
+ * Print the value of an ASN.1 simple object
+ *
+ * @param object ASN.1 object to be printed
+ * @param type asn1_t type
+ * @param private ASN.1 data is confidential (use debug level 4)
+ */
+void asn1_debug_simple_object(chunk_t object, asn1_t type, bool private);
+
+/**
+ * Converts an ASN.1 UTCTIME or GENERALIZEDTIME string to time_t
+ *
+ * @param utctime body of an ASN.1 coded time object
+ * @param type ASN1_UTCTIME or ASN1_GENERALIZEDTIME
+ * @return time_t in UTC
+ */
+time_t asn1_to_time(const chunk_t *utctime, asn1_t type);
+
+/**
+ * Converts time_t to an ASN.1 UTCTIME or GENERALIZEDTIME string
+ *
+ * @param time time_t in UTC
+ * @param type ASN1_UTCTIME or ASN1_GENERALIZEDTIME
+ * @return body of an ASN.1 code time object
+ */
+chunk_t asn1_from_time(const time_t *time, asn1_t type);
+
+/**
+ * Parse an ASN.1 UTCTIME or GENERALIZEDTIME object
+ *
+ * @param blob ASN.1 coded time object
+ * @param level top-most level offset
+ * @return time_t in UTC
+ */
+time_t asn1_parse_time(chunk_t blob, int level0);
+
+/**
+ * Determines if a binary blob is ASN.1 coded
+ *
+ * @param blob blob to be tested
+ * @return TRUE if blob is ASN.1 coded (SEQUENCE or SET)
+ */
+bool is_asn1(chunk_t blob);
+
+/**
+ * Determines if a character string can be coded as PRINTABLESTRING
+ *
+ * @param str character string to be tested
+ * @return TRUE if no special characters are contained
+ */
+bool asn1_is_printablestring(chunk_t str);
+
+
+/** some ASN.1 synthesis functions */
+
+/**
+ * Build an empty ASN.1 object with tag and length fields already filled in
+ *
+ * @param object returned object - memory is allocated by function
+ * @param type ASN.1 type to be created
+ * @param datalen size of the body to be created
+ * @return points to the first position in the body
+ */
+u_char* asn1_build_object(chunk_t *object, asn1_t type, size_t datalen);
+
+/**
+ * Build a simple ASN.1 object
+ *
+ * @param tag ASN.1 type to be created
+ * @param content content of the ASN.1 object
+ * @return chunk containing the ASN.1 coded object
+ */
+chunk_t asn1_simple_object(asn1_t tag, chunk_t content);
+
+/**
+ * Build an ASN.1 BITSTRING object
+ *
+ * @param mode 'c' for copy or 'm' for move
+ * @param content content of the BITSTRING
+ * @return chunk containing the ASN.1 coded BITSTRING
+ */
+chunk_t asn1_bitstring(const char *mode, chunk_t content);
+
+/**
+ * Build an ASN.1 object from a variable number of individual chunks
+ *
+ * @param typ ASN.1 type to be created
+ * @param mode for each list member: 'c' for copy or 'm' for move
+ * @return chunk containing the ASN.1 coded object
+ */
+chunk_t asn1_wrap(asn1_t type, const char *mode, ...);
-/* returns some popular algorithmIdentifiers */
-extern chunk_t asn1_algorithmIdentifier(int oid);
-
-extern int known_oid(chunk_t object);
-extern u_int asn1_length(chunk_t *blob);
-extern bool is_printablestring(chunk_t str);
-extern time_t asn1totime(const chunk_t *utctime, asn1_t type);
-extern chunk_t timetoasn1(const time_t *time, asn1_t type);
-extern void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, bool implicit, bool private);
-extern bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx);
-extern bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, const char* name);
-extern int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters);
-extern time_t parse_time(chunk_t blob, int level0);
-
-extern bool is_asn1(chunk_t blob);
-
-extern void code_asn1_length(size_t length, chunk_t *code);
-extern u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen);
-extern chunk_t asn1_integer_from_mpz(const mpz_t value);
-extern chunk_t asn1_simple_object(asn1_t tag, chunk_t content);
-extern chunk_t asn1_bitstring(const char *mode, chunk_t content);
-extern chunk_t asn1_wrap(asn1_t type, const char *mode, ...);
-
-#endif /* _ASN1_H */
+#endif /* ASN1_H_ @}*/
diff --git a/src/libstrongswan/asn1/asn1_parser.c b/src/libstrongswan/asn1/asn1_parser.c
new file mode 100644
index 000000000..7a2028fc3
--- /dev/null
+++ b/src/libstrongswan/asn1/asn1_parser.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2006 Martin Will
+ * Copyright (C) 2000-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * $Id: asn1_parser.c 3894 2008-04-28 18:44:21Z andreas $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include <library.h>
+#include <debug.h>
+
+#include "asn1.h"
+#include "asn1_parser.h"
+
+#define ASN1_MAX_LEVEL 10
+
+typedef struct private_asn1_parser_t private_asn1_parser_t;
+
+/**
+ * Private data of an asn1_cxt_t object.
+ */
+struct private_asn1_parser_t {
+ /**
+ * Public interface.
+ */
+ asn1_parser_t public;
+
+ /**
+ * Syntax definition of ASN.1 object
+ */
+ asn1Object_t const *objects;
+
+ /**
+ * Current syntax definition line
+ */
+ int line;
+
+ /**
+ * Current stat of the parsing operation
+ */
+ bool success;
+
+ /**
+ * Declare object data as private - use debug level 4 to log it
+ */
+ bool private;
+
+ /**
+ * Top-most type is implicit - ignore it
+ */
+ bool implicit;
+
+ /**
+ * Top-most parsing level - defaults to 0
+ */
+ u_int level0;
+
+ /**
+ * Jump back address for loops for each level
+ */
+ int loopAddr[ASN1_MAX_LEVEL + 1];
+
+ /**
+ * Current parsing pointer for each level
+ */
+ chunk_t blobs[ASN1_MAX_LEVEL + 2];
+};
+
+/**
+ * Implementation of asn1_parser_t.iterate
+ */
+static bool iterate(private_asn1_parser_t *this, int *objectID, chunk_t *object)
+{
+ chunk_t *blob, *blob1;
+ u_char *start_ptr;
+ u_int level;
+ asn1Object_t obj;
+
+ *object = chunk_empty;
+
+ /* Advance to the next object syntax definition line */
+ obj = this->objects[++(this->line)];
+
+ /* Terminate if the end of the object syntax definition has been reached */
+ if (obj.flags & ASN1_EXIT)
+ {
+ return FALSE;
+ }
+
+ if (obj.flags & ASN1_END) /* end of loop or option found */
+ {
+ if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0)
+ {
+ this->line = this->loopAddr[obj.level]; /* another iteration */
+ obj = this->objects[this->line];
+ }
+ else
+ {
+ this->loopAddr[obj.level] = 0; /* exit loop or option*/
+ goto end;
+ }
+ }
+
+ level = this->level0 + obj.level;
+ blob = this->blobs + obj.level;
+ blob1 = blob + 1;
+ start_ptr = blob->ptr;
+
+ /* handle ASN.1 defaults values */
+ if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) )
+ {
+ /* field is missing */
+ DBG2("L%d - %s:", level, obj.name);
+ if (obj.type & ASN1_CONSTRUCTED)
+ {
+ this->line++ ; /* skip context-specific tag */
+ }
+ goto end;
+ }
+
+ /* handle ASN.1 options */
+
+ if ((obj.flags & ASN1_OPT)
+ && (blob->len == 0 || *start_ptr != obj.type))
+ {
+ /* advance to end of missing option field */
+ do
+ {
+ this->line++;
+ }
+ while (!((this->objects[this->line].flags & ASN1_END) &&
+ (this->objects[this->line].level == obj.level)));
+ goto end;
+ }
+
+ /* an ASN.1 object must possess at least a tag and length field */
+
+ if (blob->len < 2)
+ {
+ DBG1("L%d - %s: ASN.1 object smaller than 2 octets",
+ level, obj.name);
+ this->success = FALSE;
+ goto end;
+ }
+
+ blob1->len = asn1_length(blob);
+
+ if (blob1->len == ASN1_INVALID_LENGTH || blob->len < blob1->len)
+ {
+ DBG1("L%d - %s: length of ASN.1 object invalid or too large",
+ level, obj.name);
+ this->success = FALSE;
+ }
+
+ blob1->ptr = blob->ptr;
+ blob->ptr += blob1->len;
+ blob->len -= blob1->len;
+
+ /* return raw ASN.1 object without prior type checking */
+
+ if (obj.flags & ASN1_RAW)
+ {
+ DBG2("L%d - %s:", level, obj.name);
+ object->ptr = start_ptr;
+ object->len = (size_t)(blob->ptr - start_ptr);
+ goto end;
+ }
+
+ if (*start_ptr != obj.type && !(this->implicit && this->line == 0))
+ {
+ DBG1("L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x",
+ level, obj.name, obj.type, *start_ptr);
+ DBG3("%b", start_ptr, (u_int)(blob->ptr - start_ptr));
+ this->success = FALSE;
+ goto end;
+ }
+
+ DBG2("L%d - %s:", level, obj.name);
+
+ /* In case of "SEQUENCE OF" or "SET OF" start a loop */
+ if (obj.flags & ASN1_LOOP)
+ {
+ if (blob1->len > 0)
+ {
+ /* at least one item, start the loop */
+ this->loopAddr[obj.level] = this->line + 1;
+ }
+ else
+ {
+ /* no items, advance directly to end of loop */
+ do
+ {
+ this->line++;
+ }
+ while (!((this->objects[this->line].flags & ASN1_END) &&
+ (this->objects[this->line].level == obj.level)));
+ goto end;
+ }
+ }
+
+ if (obj.flags & ASN1_OBJ)
+ {
+ object->ptr = start_ptr;
+ object->len = (size_t)(blob->ptr - start_ptr);
+ if (this->private)
+ {
+ DBG4("%B", object);
+ }
+ else
+ {
+ DBG3("%B", object);
+ }
+ }
+ else if (obj.flags & ASN1_BODY)
+ {
+ *object = *blob1;
+ asn1_debug_simple_object(*object, obj.type, this->private);
+ }
+
+end:
+ *objectID = this->line;
+ return this->success;
+}
+
+/**
+ * Implementation of asn1_parser_t.get_level
+ */
+static u_int get_level(private_asn1_parser_t *this)
+{
+ return this->level0 + this->objects[this->line].level;
+}
+
+/**
+ * Implementation of asn1_parser_t.set_top_level
+ */
+static void set_top_level(private_asn1_parser_t *this, u_int level0)
+{
+ this->level0 = level0;
+}
+
+/**
+ * Implementation of asn1_parser_t.set_flags
+ */
+static void set_flags(private_asn1_parser_t *this, bool implicit, bool private)
+{
+ this->implicit = implicit;
+ this->private = private;
+}
+
+/**
+ * Implementation of asn1_parser_t.success
+ */
+static bool success(private_asn1_parser_t *this)
+{
+ return this->success;
+}
+
+/**
+ * Implementation of asn1_parser_t.destroy
+ */
+static void destroy(private_asn1_parser_t *this)
+{
+ free(this);
+}
+
+/**
+ * Defined in header.
+ */
+asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob)
+{
+ private_asn1_parser_t *this = malloc_thing(private_asn1_parser_t);
+
+ memset(this, '\0', sizeof(private_asn1_parser_t));
+ this->objects = objects;
+ this->blobs[0] = blob;
+ this->line = -1;
+ this->success = TRUE;
+
+ this->public.iterate = (bool (*)(asn1_parser_t*, int*, chunk_t*))iterate;
+ this->public.get_level = (u_int (*)(asn1_parser_t*))get_level;
+ this->public.set_top_level = (void (*)(asn1_parser_t*, u_int))set_top_level;
+ this->public.set_flags = (void (*)(asn1_parser_t*, bool, bool))set_flags;
+ this->public.success = (bool (*)(asn1_parser_t*))success;
+ this->public.destroy = (void (*)(asn1_parser_t*))destroy;
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/asn1/asn1_parser.h b/src/libstrongswan/asn1/asn1_parser.h
new file mode 100644
index 000000000..d84a5336f
--- /dev/null
+++ b/src/libstrongswan/asn1/asn1_parser.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2006 Martin Will
+ * Copyright (C) 2000-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * $Id: asn1_parser.h 3894 2008-04-28 18:44:21Z andreas $
+ */
+
+/**
+ * @defgroup asn1_parser asn1_parser
+ * @{ @ingroup asn1
+ */
+
+#ifndef ASN1_PARSER_H_
+#define ASN1_PARSER_H_
+
+#include <stdarg.h>
+
+#include <library.h>
+
+/**
+ * Definition of ASN.1 flags
+ */
+#define ASN1_NONE 0x00
+#define ASN1_DEF 0x01
+#define ASN1_OPT 0x02
+#define ASN1_LOOP 0x04
+#define ASN1_END 0x08
+#define ASN1_OBJ 0x10
+#define ASN1_BODY 0x20
+#define ASN1_RAW 0x40
+#define ASN1_EXIT 0x80
+
+typedef struct asn1Object_t asn1Object_t;
+
+/**
+ * Syntax definition of an ASN.1 object
+ */
+struct asn1Object_t{
+ u_int level;
+ const u_char *name;
+ asn1_t type;
+ u_char flags;
+};
+
+typedef struct asn1_parser_t asn1_parser_t;
+
+/**
+ * Public interface of an ASN.1 parser
+ */
+struct asn1_parser_t {
+
+ /**
+ * Parse the next ASN.1 object in the hierarchy and return it
+ *
+ * @param objectID current line in the object syntax definition
+ * @param object current object
+ * @return - FALSE if end of object syntax definition was reached
+ * or a parsing error occurred
+ * - TRUE otherwise
+ */
+ bool (*iterate)(asn1_parser_t *this, int *objectID, chunk_t *object);
+
+ /**
+ * Get the current parsing level
+ *
+ * @return current level
+ */
+ u_int (*get_level)(asn1_parser_t *this);
+
+ /**
+ * Set the top-most level
+ *
+ * @param level top-most level
+ */
+ void (*set_top_level)(asn1_parser_t *this, u_int level0);
+
+ /**
+ * Set implicit and private flags
+ *
+ * @param implicit top-most type of object is implicit
+ * @param private object data is private (use debug level 4)
+ */
+ void (*set_flags)(asn1_parser_t *this, bool implicit, bool private);
+
+ /**
+ * Show final parsing status
+ *
+ * @return TRUE if parsing was successful, FALSE otherwise
+ */
+ bool (*success)(asn1_parser_t *this);
+
+ /**
+ * Destroy the ASN.1 parser
+ */
+ void (*destroy)(asn1_parser_t *this);
+};
+
+/**
+ * Create an ASN.1 parser
+ *
+ * @param objects syntax definition of the ASN.1 object to be parsed
+ * @param blob ASN.1 coded binary blob
+ * @return ASN.1 context
+ */
+asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob);
+
+#endif /* ASN1_PARSER_H_ @}*/
diff --git a/src/libstrongswan/asn1/oid.c b/src/libstrongswan/asn1/oid.c
index 63896be6b..f9eb26d1d 100644
--- a/src/libstrongswan/asn1/oid.c
+++ b/src/libstrongswan/asn1/oid.c
@@ -62,10 +62,10 @@ const oid_t oid_names[] = {
{ 0x25, 50, 0, "extendedKeyUsage" }, /* 49 */
{ 0x37, 51, 0, "targetInformation" }, /* 50 */
{ 0x38, 0, 0, "noRevAvail" }, /* 51 */
- {0x2A, 95, 1, "" }, /* 52 */
+ {0x2A, 131, 1, "" }, /* 52 */
{ 0x86, 0, 1, "" }, /* 53 */
{ 0x48, 0, 1, "" }, /* 54 */
- { 0x86, 0, 1, "" }, /* 55 */
+ { 0x86, 95, 1, "" }, /* 55 */
{ 0xF6, 61, 1, "" }, /* 56 */
{ 0x7D, 0, 1, "NortelNetworks" }, /* 57 */
{ 0x07, 0, 1, "Entrust" }, /* 58 */
@@ -105,105 +105,175 @@ const oid_t oid_names[] = {
{ 0x05, 0, 0, "md5" }, /* 92 */
{ 0x03, 0, 1, "encryptionAlgorithm" }, /* 93 */
{ 0x07, 0, 0, "3des-ede-cbc" }, /* 94 */
- {0x2B, 161, 1, "" }, /* 95 */
- { 0x06, 148, 1, "dod" }, /* 96 */
- { 0x01, 0, 1, "internet" }, /* 97 */
- { 0x04, 116, 1, "private" }, /* 98 */
- { 0x01, 0, 1, "enterprise" }, /* 99 */
- { 0x82, 109, 1, "" }, /* 100 */
- { 0x37, 0, 1, "Microsoft" }, /* 101 */
- { 0x0A, 106, 1, "" }, /* 102 */
- { 0x03, 0, 1, "" }, /* 103 */
- { 0x03, 105, 0, "msSGC" }, /* 104 */
- { 0x04, 0, 0, "msEncryptingFileSystem" }, /* 105 */
- { 0x14, 0, 1, "msEnrollmentInfrastructure"}, /* 106 */
- { 0x02, 0, 1, "msCertificateTypeExtension"}, /* 107 */
- { 0x02, 0, 0, "msSmartcardLogon" }, /* 108 */
- { 0x89, 0, 1, "" }, /* 109 */
- { 0x31, 0, 1, "" }, /* 110 */
- { 0x01, 0, 1, "" }, /* 111 */
- { 0x01, 0, 1, "" }, /* 112 */
- { 0x02, 0, 1, "" }, /* 113 */
- { 0x02, 115, 0, "" }, /* 114 */
- { 0x4B, 0, 0, "TCGID" }, /* 115 */
- { 0x05, 0, 1, "security" }, /* 116 */
- { 0x05, 0, 1, "mechanisms" }, /* 117 */
- { 0x07, 0, 1, "id-pkix" }, /* 118 */
- { 0x01, 121, 1, "id-pe" }, /* 119 */
- { 0x01, 0, 0, "authorityInfoAccess" }, /* 120 */
- { 0x03, 131, 1, "id-kp" }, /* 121 */
- { 0x01, 123, 0, "serverAuth" }, /* 122 */
- { 0x02, 124, 0, "clientAuth" }, /* 123 */
- { 0x03, 125, 0, "codeSigning" }, /* 124 */
- { 0x04, 126, 0, "emailProtection" }, /* 125 */
- { 0x05, 127, 0, "ipsecEndSystem" }, /* 126 */
- { 0x06, 128, 0, "ipsecTunnel" }, /* 127 */
- { 0x07, 129, 0, "ipsecUser" }, /* 128 */
- { 0x08, 130, 0, "timeStamping" }, /* 129 */
- { 0x09, 0, 0, "ocspSigning" }, /* 130 */
- { 0x08, 133, 1, "id-otherNames" }, /* 131 */
- { 0x05, 0, 0, "xmppAddr" }, /* 132 */
- { 0x0A, 138, 1, "id-aca" }, /* 133 */
- { 0x01, 135, 0, "authenticationInfo" }, /* 134 */
- { 0x02, 136, 0, "accessIdentity" }, /* 135 */
- { 0x03, 137, 0, "chargingIdentity" }, /* 136 */
- { 0x04, 0, 0, "group" }, /* 137 */
- { 0x30, 0, 1, "id-ad" }, /* 138 */
- { 0x01, 147, 1, "ocsp" }, /* 139 */
- { 0x01, 141, 0, "basic" }, /* 140 */
- { 0x02, 142, 0, "nonce" }, /* 141 */
- { 0x03, 143, 0, "crl" }, /* 142 */
- { 0x04, 144, 0, "response" }, /* 143 */
- { 0x05, 145, 0, "noCheck" }, /* 144 */
- { 0x06, 146, 0, "archiveCutoff" }, /* 145 */
- { 0x07, 0, 0, "serviceLocator" }, /* 146 */
- { 0x02, 0, 0, "caIssuers" }, /* 147 */
- { 0x0E, 154, 1, "oiw" }, /* 148 */
- { 0x03, 0, 1, "secsig" }, /* 149 */
- { 0x02, 0, 1, "algorithms" }, /* 150 */
- { 0x07, 152, 0, "des-cbc" }, /* 151 */
- { 0x1A, 153, 0, "sha-1" }, /* 152 */
- { 0x1D, 0, 0, "sha-1WithRSASignature" }, /* 153 */
- { 0x24, 0, 1, "TeleTrusT" }, /* 154 */
- { 0x03, 0, 1, "algorithm" }, /* 155 */
- { 0x03, 0, 1, "signatureAlgorithm" }, /* 156 */
- { 0x01, 0, 1, "rsaSignature" }, /* 157 */
- { 0x02, 159, 0, "rsaSigWithripemd160" }, /* 158 */
- { 0x03, 160, 0, "rsaSigWithripemd128" }, /* 159 */
- { 0x04, 0, 0, "rsaSigWithripemd256" }, /* 160 */
- {0x60, 0, 1, "" }, /* 161 */
- { 0x86, 0, 1, "" }, /* 162 */
- { 0x48, 0, 1, "" }, /* 163 */
- { 0x01, 0, 1, "organization" }, /* 164 */
- { 0x65, 172, 1, "gov" }, /* 165 */
- { 0x03, 0, 1, "csor" }, /* 166 */
- { 0x04, 0, 1, "nistalgorithm" }, /* 167 */
- { 0x02, 0, 1, "hashalgs" }, /* 168 */
- { 0x01, 170, 0, "id-SHA-256" }, /* 169 */
- { 0x02, 171, 0, "id-SHA-384" }, /* 170 */
- { 0x03, 0, 0, "id-SHA-512" }, /* 171 */
- { 0x86, 0, 1, "" }, /* 172 */
- { 0xf8, 0, 1, "" }, /* 173 */
- { 0x42, 186, 1, "netscape" }, /* 174 */
- { 0x01, 181, 1, "" }, /* 175 */
- { 0x01, 177, 0, "nsCertType" }, /* 176 */
- { 0x03, 178, 0, "nsRevocationUrl" }, /* 177 */
- { 0x04, 179, 0, "nsCaRevocationUrl" }, /* 178 */
- { 0x08, 180, 0, "nsCaPolicyUrl" }, /* 179 */
- { 0x0d, 0, 0, "nsComment" }, /* 180 */
- { 0x03, 184, 1, "directory" }, /* 181 */
- { 0x01, 0, 1, "" }, /* 182 */
- { 0x03, 0, 0, "employeeNumber" }, /* 183 */
- { 0x04, 0, 1, "policy" }, /* 184 */
- { 0x01, 0, 0, "nsSGC" }, /* 185 */
- { 0x45, 0, 1, "verisign" }, /* 186 */
- { 0x01, 0, 1, "pki" }, /* 187 */
- { 0x09, 0, 1, "attributes" }, /* 188 */
- { 0x02, 190, 0, "messageType" }, /* 189 */
- { 0x03, 191, 0, "pkiStatus" }, /* 190 */
- { 0x04, 192, 0, "failInfo" }, /* 191 */
- { 0x05, 193, 0, "senderNonce" }, /* 192 */
- { 0x06, 194, 0, "recipientNonce" }, /* 193 */
- { 0x07, 195, 0, "transID" }, /* 194 */
- { 0x08, 0, 0, "extensionReq" } /* 195 */
+ { 0xCE, 0, 1, "" }, /* 95 */
+ { 0x3D, 0, 1, "ansi-X9-62" }, /* 96 */
+ { 0x02, 99, 1, "id-publicKeyType" }, /* 97 */
+ { 0x01, 0, 0, "id-ecPublicKey" }, /* 98 */
+ { 0x03, 129, 1, "ellipticCurve" }, /* 99 */
+ { 0x00, 121, 1, "c-TwoCurve" }, /* 100 */
+ { 0x01, 102, 0, "c2pnb163v1" }, /* 101 */
+ { 0x02, 103, 0, "c2pnb163v2" }, /* 102 */
+ { 0x03, 104, 0, "c2pnb163v3" }, /* 103 */
+ { 0x04, 105, 0, "c2pnb176w1" }, /* 104 */
+ { 0x05, 106, 0, "c2tnb191v1" }, /* 105 */
+ { 0x06, 107, 0, "c2tnb191v2" }, /* 106 */
+ { 0x07, 108, 0, "c2tnb191v3" }, /* 107 */
+ { 0x08, 109, 0, "c2onb191v4" }, /* 108 */
+ { 0x09, 110, 0, "c2onb191v5" }, /* 109 */
+ { 0x0A, 111, 0, "c2pnb208w1" }, /* 110 */
+ { 0x0B, 112, 0, "c2tnb239v1" }, /* 111 */
+ { 0x0C, 113, 0, "c2tnb239v2" }, /* 112 */
+ { 0x0D, 114, 0, "c2tnb239v3" }, /* 113 */
+ { 0x0E, 115, 0, "c2onb239v4" }, /* 114 */
+ { 0x0F, 116, 0, "c2onb239v5" }, /* 115 */
+ { 0x10, 117, 0, "c2pnb272w1" }, /* 116 */
+ { 0x11, 118, 0, "c2pnb304w1" }, /* 117 */
+ { 0x12, 119, 0, "c2tnb359v1" }, /* 118 */
+ { 0x13, 120, 0, "c2pnb368w1" }, /* 119 */
+ { 0x14, 0, 0, "c2tnb431r1" }, /* 120 */
+ { 0x01, 0, 1, "primeCurve" }, /* 121 */
+ { 0x01, 123, 0, "prime192v1" }, /* 122 */
+ { 0x02, 124, 0, "prime192v2" }, /* 123 */
+ { 0x03, 125, 0, "prime192v3" }, /* 124 */
+ { 0x04, 126, 0, "prime239v1" }, /* 125 */
+ { 0x05, 127, 0, "prime239v2" }, /* 126 */
+ { 0x06, 128, 0, "prime239v3" }, /* 127 */
+ { 0x07, 0, 0, "prime256v1" }, /* 128 */
+ { 0x04, 0, 1, "id-ecSigType" }, /* 129 */
+ { 0x01, 0, 0, "ecdsa-with-SHA1" }, /* 130 */
+ {0x2B, 231, 1, "" }, /* 131 */
+ { 0x06, 184, 1, "dod" }, /* 132 */
+ { 0x01, 0, 1, "internet" }, /* 133 */
+ { 0x04, 152, 1, "private" }, /* 134 */
+ { 0x01, 0, 1, "enterprise" }, /* 135 */
+ { 0x82, 145, 1, "" }, /* 136 */
+ { 0x37, 0, 1, "Microsoft" }, /* 137 */
+ { 0x0A, 142, 1, "" }, /* 138 */
+ { 0x03, 0, 1, "" }, /* 139 */
+ { 0x03, 141, 0, "msSGC" }, /* 140 */
+ { 0x04, 0, 0, "msEncryptingFileSystem" }, /* 141 */
+ { 0x14, 0, 1, "msEnrollmentInfrastructure"}, /* 142 */
+ { 0x02, 0, 1, "msCertificateTypeExtension"}, /* 143 */
+ { 0x02, 0, 0, "msSmartcardLogon" }, /* 144 */
+ { 0x89, 0, 1, "" }, /* 145 */
+ { 0x31, 0, 1, "" }, /* 146 */
+ { 0x01, 0, 1, "" }, /* 147 */
+ { 0x01, 0, 1, "" }, /* 148 */
+ { 0x02, 0, 1, "" }, /* 149 */
+ { 0x02, 151, 0, "" }, /* 150 */
+ { 0x4B, 0, 0, "TCGID" }, /* 151 */
+ { 0x05, 0, 1, "security" }, /* 152 */
+ { 0x05, 0, 1, "mechanisms" }, /* 153 */
+ { 0x07, 0, 1, "id-pkix" }, /* 154 */
+ { 0x01, 157, 1, "id-pe" }, /* 155 */
+ { 0x01, 0, 0, "authorityInfoAccess" }, /* 156 */
+ { 0x03, 167, 1, "id-kp" }, /* 157 */
+ { 0x01, 159, 0, "serverAuth" }, /* 158 */
+ { 0x02, 160, 0, "clientAuth" }, /* 159 */
+ { 0x03, 161, 0, "codeSigning" }, /* 160 */
+ { 0x04, 162, 0, "emailProtection" }, /* 161 */
+ { 0x05, 163, 0, "ipsecEndSystem" }, /* 162 */
+ { 0x06, 164, 0, "ipsecTunnel" }, /* 163 */
+ { 0x07, 165, 0, "ipsecUser" }, /* 164 */
+ { 0x08, 166, 0, "timeStamping" }, /* 165 */
+ { 0x09, 0, 0, "ocspSigning" }, /* 166 */
+ { 0x08, 169, 1, "id-otherNames" }, /* 167 */
+ { 0x05, 0, 0, "xmppAddr" }, /* 168 */
+ { 0x0A, 174, 1, "id-aca" }, /* 169 */
+ { 0x01, 171, 0, "authenticationInfo" }, /* 170 */
+ { 0x02, 172, 0, "accessIdentity" }, /* 171 */
+ { 0x03, 173, 0, "chargingIdentity" }, /* 172 */
+ { 0x04, 0, 0, "group" }, /* 173 */
+ { 0x30, 0, 1, "id-ad" }, /* 174 */
+ { 0x01, 183, 1, "ocsp" }, /* 175 */
+ { 0x01, 177, 0, "basic" }, /* 176 */
+ { 0x02, 178, 0, "nonce" }, /* 177 */
+ { 0x03, 179, 0, "crl" }, /* 178 */
+ { 0x04, 180, 0, "response" }, /* 179 */
+ { 0x05, 181, 0, "noCheck" }, /* 180 */
+ { 0x06, 182, 0, "archiveCutoff" }, /* 181 */
+ { 0x07, 0, 0, "serviceLocator" }, /* 182 */
+ { 0x02, 0, 0, "caIssuers" }, /* 183 */
+ { 0x0E, 190, 1, "oiw" }, /* 184 */
+ { 0x03, 0, 1, "secsig" }, /* 185 */
+ { 0x02, 0, 1, "algorithms" }, /* 186 */
+ { 0x07, 188, 0, "des-cbc" }, /* 187 */
+ { 0x1A, 189, 0, "sha-1" }, /* 188 */
+ { 0x1D, 0, 0, "sha-1WithRSASignature" }, /* 189 */
+ { 0x24, 197, 1, "TeleTrusT" }, /* 190 */
+ { 0x03, 0, 1, "algorithm" }, /* 191 */
+ { 0x03, 0, 1, "signatureAlgorithm" }, /* 192 */
+ { 0x01, 0, 1, "rsaSignature" }, /* 193 */
+ { 0x02, 195, 0, "rsaSigWithripemd160" }, /* 194 */
+ { 0x03, 196, 0, "rsaSigWithripemd128" }, /* 195 */
+ { 0x04, 0, 0, "rsaSigWithripemd256" }, /* 196 */
+ { 0x81, 0, 1, "" }, /* 197 */
+ { 0x04, 0, 1, "Certicom" }, /* 198 */
+ { 0x00, 0, 1, "curve" }, /* 199 */
+ { 0x01, 201, 0, "sect163k1" }, /* 200 */
+ { 0x02, 202, 0, "sect163r1" }, /* 201 */
+ { 0x03, 203, 0, "sect239k1" }, /* 202 */
+ { 0x04, 204, 0, "sect113r1" }, /* 203 */
+ { 0x05, 205, 0, "sect113r2" }, /* 204 */
+ { 0x06, 206, 0, "secp112r1" }, /* 205 */
+ { 0x07, 207, 0, "secp112r2" }, /* 206 */
+ { 0x08, 208, 0, "secp160r1" }, /* 207 */
+ { 0x09, 209, 0, "secp160k1" }, /* 208 */
+ { 0x0A, 210, 0, "secp256k1" }, /* 209 */
+ { 0x0F, 211, 0, "sect163r2" }, /* 210 */
+ { 0x10, 212, 0, "sect283k1" }, /* 211 */
+ { 0x11, 213, 0, "sect283r1" }, /* 212 */
+ { 0x16, 214, 0, "sect131r1" }, /* 213 */
+ { 0x17, 215, 0, "sect131r2" }, /* 214 */
+ { 0x18, 216, 0, "sect193r1" }, /* 215 */
+ { 0x19, 217, 0, "sect193r2" }, /* 216 */
+ { 0x1A, 218, 0, "sect233k1" }, /* 217 */
+ { 0x1B, 219, 0, "sect233r1" }, /* 218 */
+ { 0x1C, 220, 0, "secp128r1" }, /* 219 */
+ { 0x1D, 221, 0, "secp128r2" }, /* 220 */
+ { 0x1E, 222, 0, "secp160r2" }, /* 221 */
+ { 0x1F, 223, 0, "secp192k1" }, /* 222 */
+ { 0x20, 224, 0, "secp224k1" }, /* 223 */
+ { 0x21, 225, 0, "secp224r1" }, /* 224 */
+ { 0x22, 226, 0, "secp384r1" }, /* 225 */
+ { 0x23, 227, 0, "secp521r1" }, /* 226 */
+ { 0x24, 228, 0, "sect409k1" }, /* 227 */
+ { 0x25, 229, 0, "sect409r1" }, /* 228 */
+ { 0x26, 230, 0, "sect571k1" }, /* 229 */
+ { 0x27, 0, 0, "sect571r1" }, /* 230 */
+ {0x60, 0, 1, "" }, /* 231 */
+ { 0x86, 0, 1, "" }, /* 232 */
+ { 0x48, 0, 1, "" }, /* 233 */
+ { 0x01, 0, 1, "organization" }, /* 234 */
+ { 0x65, 242, 1, "gov" }, /* 235 */
+ { 0x03, 0, 1, "csor" }, /* 236 */
+ { 0x04, 0, 1, "nistalgorithm" }, /* 237 */
+ { 0x02, 0, 1, "hashalgs" }, /* 238 */
+ { 0x01, 240, 0, "id-SHA-256" }, /* 239 */
+ { 0x02, 241, 0, "id-SHA-384" }, /* 240 */
+ { 0x03, 0, 0, "id-SHA-512" }, /* 241 */
+ { 0x86, 0, 1, "" }, /* 242 */
+ { 0xf8, 0, 1, "" }, /* 243 */
+ { 0x42, 256, 1, "netscape" }, /* 244 */
+ { 0x01, 251, 1, "" }, /* 245 */
+ { 0x01, 247, 0, "nsCertType" }, /* 246 */
+ { 0x03, 248, 0, "nsRevocationUrl" }, /* 247 */
+ { 0x04, 249, 0, "nsCaRevocationUrl" }, /* 248 */
+ { 0x08, 250, 0, "nsCaPolicyUrl" }, /* 249 */
+ { 0x0d, 0, 0, "nsComment" }, /* 250 */
+ { 0x03, 254, 1, "directory" }, /* 251 */
+ { 0x01, 0, 1, "" }, /* 252 */
+ { 0x03, 0, 0, "employeeNumber" }, /* 253 */
+ { 0x04, 0, 1, "policy" }, /* 254 */
+ { 0x01, 0, 0, "nsSGC" }, /* 255 */
+ { 0x45, 0, 1, "verisign" }, /* 256 */
+ { 0x01, 0, 1, "pki" }, /* 257 */
+ { 0x09, 0, 1, "attributes" }, /* 258 */
+ { 0x02, 260, 0, "messageType" }, /* 259 */
+ { 0x03, 261, 0, "pkiStatus" }, /* 260 */
+ { 0x04, 262, 0, "failInfo" }, /* 261 */
+ { 0x05, 263, 0, "senderNonce" }, /* 262 */
+ { 0x06, 264, 0, "recipientNonce" }, /* 263 */
+ { 0x07, 265, 0, "transID" }, /* 264 */
+ { 0x08, 0, 0, "extensionReq" } /* 265 */
};
diff --git a/src/libstrongswan/asn1/oid.h b/src/libstrongswan/asn1/oid.h
index 9980221ab..a0fb95f18 100644
--- a/src/libstrongswan/asn1/oid.h
+++ b/src/libstrongswan/asn1/oid.h
@@ -49,37 +49,97 @@ extern const oid_t oid_names[];
#define OID_MD2 91
#define OID_MD5 92
#define OID_3DES_EDE_CBC 94
-#define OID_AUTHORITY_INFO_ACCESS 120
-#define OID_OCSP_SIGNING 130
-#define OID_XMPP_ADDR 132
-#define OID_AUTHENTICATION_INFO 134
-#define OID_ACCESS_IDENTITY 135
-#define OID_CHARGING_IDENTITY 136
-#define OID_GROUP 137
-#define OID_OCSP 139
-#define OID_BASIC 140
-#define OID_NONCE 141
-#define OID_CRL 142
-#define OID_RESPONSE 143
-#define OID_NO_CHECK 144
-#define OID_ARCHIVE_CUTOFF 145
-#define OID_SERVICE_LOCATOR 146
-#define OID_CA_ISSUERS 147
-#define OID_DES_CBC 151
-#define OID_SHA1 152
-#define OID_SHA1_WITH_RSA_OIW 153
-#define OID_SHA256 169
-#define OID_SHA384 170
-#define OID_SHA512 171
-#define OID_NS_REVOCATION_URL 177
-#define OID_NS_CA_REVOCATION_URL 178
-#define OID_NS_CA_POLICY_URL 179
-#define OID_NS_COMMENT 180
-#define OID_PKI_MESSAGE_TYPE 189
-#define OID_PKI_STATUS 190
-#define OID_PKI_FAIL_INFO 191
-#define OID_PKI_SENDER_NONCE 192
-#define OID_PKI_RECIPIENT_NONCE 193
-#define OID_PKI_TRANS_ID 194
+#define OID_EC_PUBLICKEY 98
+#define OID_C2PNB163V1 101
+#define OID_C2PNB163V2 102
+#define OID_C2PNB163V3 103
+#define OID_C2PNB176W1 104
+#define OID_C2PNB191V1 105
+#define OID_C2PNB191V2 106
+#define OID_C2PNB191V3 107
+#define OID_C2PNB191V4 108
+#define OID_C2PNB191V5 109
+#define OID_C2PNB208W1 110
+#define OID_C2PNB239V1 111
+#define OID_C2PNB239V2 112
+#define OID_C2PNB239V3 113
+#define OID_C2PNB239V4 114
+#define OID_C2PNB239V5 115
+#define OID_C2PNB272W1 116
+#define OID_C2PNB304W1 117
+#define OID_C2PNB359V1 118
+#define OID_C2PNB368W1 119
+#define OID_C2PNB431R1 120
+#define OID_PRIME192V1 122
+#define OID_PRIME192V2 123
+#define OID_PRIME192V3 124
+#define OID_PRIME239V1 125
+#define OID_PRIME239V2 126
+#define OID_PRIME239V3 127
+#define OID_PRIME256V1 128
+#define OID_ECDSA_WITH_SHA1 130
+#define OID_AUTHORITY_INFO_ACCESS 156
+#define OID_OCSP_SIGNING 166
+#define OID_XMPP_ADDR 168
+#define OID_AUTHENTICATION_INFO 170
+#define OID_ACCESS_IDENTITY 171
+#define OID_CHARGING_IDENTITY 172
+#define OID_GROUP 173
+#define OID_OCSP 175
+#define OID_BASIC 176
+#define OID_NONCE 177
+#define OID_CRL 178
+#define OID_RESPONSE 179
+#define OID_NO_CHECK 180
+#define OID_ARCHIVE_CUTOFF 181
+#define OID_SERVICE_LOCATOR 182
+#define OID_CA_ISSUERS 183
+#define OID_DES_CBC 187
+#define OID_SHA1 188
+#define OID_SHA1_WITH_RSA_OIW 189
+#define OID_SECT163K1 200
+#define OID_SECT163R1 201
+#define OID_SECT239K1 202
+#define OID_SECT113R1 203
+#define OID_SECT113R2 204
+#define OID_SECT112R1 205
+#define OID_SECT112R2 206
+#define OID_SECT160R1 207
+#define OID_SECT160K1 208
+#define OID_SECT256K1 209
+#define OID_SECT163R2 210
+#define OID_SECT283K1 211
+#define OID_SECT283R1 212
+#define OID_SECT131R1 213
+#define OID_SECT131R2 214
+#define OID_SECT193R1 215
+#define OID_SECT193R2 216
+#define OID_SECT233K1 217
+#define OID_SECT233R1 218
+#define OID_SECT128R1 219
+#define OID_SECT128R2 220
+#define OID_SECT160R2 221
+#define OID_SECT192K1 222
+#define OID_SECT224K1 223
+#define OID_SECT224R1 224
+#define OID_SECT384R1 225
+#define OID_SECT521R1 226
+#define OID_SECT409K1 227
+#define OID_SECT409R1 228
+#define OID_SECT571K1 229
+#define OID_SECT571R1 230
+#define OID_SHA256 239
+#define OID_SHA384 240
+#define OID_SHA512 241
+#define OID_NS_REVOCATION_URL 247
+#define OID_NS_CA_REVOCATION_URL 248
+#define OID_NS_CA_POLICY_URL 249
+#define OID_NS_COMMENT 250
+#define OID_PKI_MESSAGE_TYPE 259
+#define OID_PKI_STATUS 260
+#define OID_PKI_FAIL_INFO 261
+#define OID_PKI_SENDER_NONCE 262
+#define OID_PKI_RECIPIENT_NONCE 263
+#define OID_PKI_TRANS_ID 264
#endif /* OID_H_ */
diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt
index e6dede287..6bb765787 100644
--- a/src/libstrongswan/asn1/oid.txt
+++ b/src/libstrongswan/asn1/oid.txt
@@ -93,6 +93,42 @@
0x05 "md5" OID_MD5
0x03 "encryptionAlgorithm"
0x07 "3des-ede-cbc" OID_3DES_EDE_CBC
+ 0xCE ""
+ 0x3D "ansi-X9-62"
+ 0x02 "id-publicKeyType"
+ 0x01 "id-ecPublicKey" OID_EC_PUBLICKEY
+ 0x03 "ellipticCurve"
+ 0x00 "c-TwoCurve"
+ 0x01 "c2pnb163v1" OID_C2PNB163V1
+ 0x02 "c2pnb163v2" OID_C2PNB163V2
+ 0x03 "c2pnb163v3" OID_C2PNB163V3
+ 0x04 "c2pnb176w1" OID_C2PNB176W1
+ 0x05 "c2tnb191v1" OID_C2PNB191V1
+ 0x06 "c2tnb191v2" OID_C2PNB191V2
+ 0x07 "c2tnb191v3" OID_C2PNB191V3
+ 0x08 "c2onb191v4" OID_C2PNB191V4
+ 0x09 "c2onb191v5" OID_C2PNB191V5
+ 0x0A "c2pnb208w1" OID_C2PNB208W1
+ 0x0B "c2tnb239v1" OID_C2PNB239V1
+ 0x0C "c2tnb239v2" OID_C2PNB239V2
+ 0x0D "c2tnb239v3" OID_C2PNB239V3
+ 0x0E "c2onb239v4" OID_C2PNB239V4
+ 0x0F "c2onb239v5" OID_C2PNB239V5
+ 0x10 "c2pnb272w1" OID_C2PNB272W1
+ 0x11 "c2pnb304w1" OID_C2PNB304W1
+ 0x12 "c2tnb359v1" OID_C2PNB359V1
+ 0x13 "c2pnb368w1" OID_C2PNB368W1
+ 0x14 "c2tnb431r1" OID_C2PNB431R1
+ 0x01 "primeCurve"
+ 0x01 "prime192v1" OID_PRIME192V1
+ 0x02 "prime192v2" OID_PRIME192V2
+ 0x03 "prime192v3" OID_PRIME192V3
+ 0x04 "prime239v1" OID_PRIME239V1
+ 0x05 "prime239v2" OID_PRIME239V2
+ 0x06 "prime239v3" OID_PRIME239V3
+ 0x07 "prime256v1" OID_PRIME256V1
+ 0x04 "id-ecSigType"
+ 0x01 "ecdsa-with-SHA1" OID_ECDSA_WITH_SHA1
0x2B ""
0x06 "dod"
0x01 "internet"
@@ -159,6 +195,40 @@
0x02 "rsaSigWithripemd160"
0x03 "rsaSigWithripemd128"
0x04 "rsaSigWithripemd256"
+ 0x81 ""
+ 0x04 "Certicom"
+ 0x00 "curve"
+ 0x01 "sect163k1" OID_SECT163K1
+ 0x02 "sect163r1" OID_SECT163R1
+ 0x03 "sect239k1" OID_SECT239K1
+ 0x04 "sect113r1" OID_SECT113R1
+ 0x05 "sect113r2" OID_SECT113R2
+ 0x06 "secp112r1" OID_SECT112R1
+ 0x07 "secp112r2" OID_SECT112R2
+ 0x08 "secp160r1" OID_SECT160R1
+ 0x09 "secp160k1" OID_SECT160K1
+ 0x0A "secp256k1" OID_SECT256K1
+ 0x0F "sect163r2" OID_SECT163R2
+ 0x10 "sect283k1" OID_SECT283K1
+ 0x11 "sect283r1" OID_SECT283R1
+ 0x16 "sect131r1" OID_SECT131R1
+ 0x17 "sect131r2" OID_SECT131R2
+ 0x18 "sect193r1" OID_SECT193R1
+ 0x19 "sect193r2" OID_SECT193R2
+ 0x1A "sect233k1" OID_SECT233K1
+ 0x1B "sect233r1" OID_SECT233R1
+ 0x1C "secp128r1" OID_SECT128R1
+ 0x1D "secp128r2" OID_SECT128R2
+ 0x1E "secp160r2" OID_SECT160R2
+ 0x1F "secp192k1" OID_SECT192K1
+ 0x20 "secp224k1" OID_SECT224K1
+ 0x21 "secp224r1" OID_SECT224R1
+ 0x22 "secp384r1" OID_SECT384R1
+ 0x23 "secp521r1" OID_SECT521R1
+ 0x24 "sect409k1" OID_SECT409K1
+ 0x25 "sect409r1" OID_SECT409R1
+ 0x26 "sect571k1" OID_SECT571K1
+ 0x27 "sect571r1" OID_SECT571R1
0x60 ""
0x86 ""
0x48 ""
diff --git a/src/libstrongswan/asn1/pem.c b/src/libstrongswan/asn1/pem.c
index b752a97ab..d3176b6bc 100755
--- a/src/libstrongswan/asn1/pem.c
+++ b/src/libstrongswan/asn1/pem.c
@@ -1,5 +1,7 @@
/*
- * Copyright (C) 2001-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2001-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -11,7 +13,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * RCSID $Id: pem.c 3256 2007-10-07 13:42:43Z andreas $
+ * $Id: pem.c 4029 2008-06-03 12:14:02Z martin $
*/
#include <stdio.h>
@@ -27,7 +29,6 @@
#include <library.h>
#include <debug.h>
#include <asn1/asn1.h>
-#include <asn1/ttodata.h>
#include <utils/lexparser.h>
#include <crypto/hashers/hasher.h>
@@ -83,7 +84,7 @@ static bool find_boundary(const char* tag, chunk_t *line)
/*
* decrypts a passphrase protected encrypted data block
*/
-static err_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, size_t key_size,
+static bool pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, size_t key_size,
chunk_t *iv, chunk_t *passphrase)
{
hasher_t *hasher;
@@ -95,10 +96,18 @@ static err_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, size_t key_s
u_int8_t padding, *last_padding_pos, *first_padding_pos;
if (passphrase == NULL || passphrase->len == 0)
- return "missing passphrase";
+ {
+ DBG1(" missing passphrase");
+ return FALSE;
+ }
/* build key from passphrase and IV */
- hasher = hasher_create(HASH_MD5);
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
+ if (hasher == NULL)
+ {
+ DBG1(" MD5 hash algorithm not available");
+ return FALSE;
+ }
hash.len = hasher->get_hash_size(hasher);
hash.ptr = alloca(hash.len);
hasher->get_hash(hasher, *passphrase, NULL);
@@ -115,13 +124,23 @@ static err_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, size_t key_s
hasher->destroy(hasher);
/* decrypt blob */
- crypter = crypter_create(alg, key_size);
+ crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size);
+ if (crypter == NULL)
+ {
+ DBG1(" %N encryption algorithm not available",
+ encryption_algorithm_names, alg);
+ return FALSE;
+ }
crypter->set_key(crypter, key);
- if (crypter->decrypt(crypter, *blob, *iv, &decrypted) != SUCCESS)
+
+ if (iv->len != crypter->get_block_size(crypter) ||
+ blob->len % iv->len)
{
crypter->destroy(crypter);
- return "data size is not multiple of block size";
+ DBG1(" data size is not multiple of block size");
+ return FALSE;
}
+ crypter->decrypt(crypter, *blob, *iv, &decrypted);
crypter->destroy(crypter);
memcpy(blob->ptr, decrypted.ptr, blob->len);
chunk_free(&decrypted);
@@ -135,11 +154,14 @@ static err_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, size_t key_s
while (--last_padding_pos > first_padding_pos)
{
if (*last_padding_pos != padding)
- return "invalid passphrase";
+ {
+ DBG1(" invalid passphrase");
+ return FALSE;
+ }
}
/* remove padding */
blob->len -= padding;
- return NULL;
+ return TRUE;
}
/* Converts a PEM encoded file into its binary form
@@ -147,7 +169,7 @@ static err_t pem_decrypt(chunk_t *blob, encryption_algorithm_t alg, size_t key_s
* RFC 1421 Privacy Enhancement for Electronic Mail, February 1993
* RFC 934 Message Encapsulation, January 1985
*/
-err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
+bool pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
{
typedef enum {
PEM_PRE = 0,
@@ -223,7 +245,6 @@ err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
encrypted = TRUE;
else if (match("DEK-Info", &name))
{
- size_t len = 0;
chunk_t dek;
if (!extract_token(&dek, ',', &value))
@@ -251,21 +272,16 @@ err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
}
else
{
- return "encryption algorithm not supported";
+ DBG1(" encryption algorithm '%.s' not supported",
+ dek.len, dek.ptr);
+ return FALSE;
}
-
eat_whitespace(&value);
- ugh = ttodata(value.ptr, value.len, 16, iv.ptr, 16, &len);
- if (ugh)
- return "error in IV";
-
- iv.len = len;
+ iv = chunk_from_hex(value, iv.ptr);
}
}
else /* state is PEM_BODY */
{
- const char *ugh = NULL;
- size_t len = 0;
chunk_t data;
/* remove any trailing whitespace */
@@ -280,21 +296,18 @@ err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
*pgp = TRUE;
data.ptr++;
data.len--;
- DBG2(" Armor checksum: %.*s", (int)data.len, data.ptr);
+ DBG2(" armor checksum: %.*s", (int)data.len, data.ptr);
continue;
}
-
- ugh = ttodata(data.ptr, data.len, 64, dst.ptr, blob->len - dst.len, &len);
- if (ugh)
+
+ if (blob->len - dst.len < data.len / 4 * 3)
{
state = PEM_ABORT;
- break;
- }
- else
- {
- dst.ptr += len;
- dst.len += len;
}
+ data = chunk_from_base64(data, dst.ptr);
+
+ dst.ptr += data.len;
+ dst.len += data.len;
}
}
}
@@ -302,19 +315,24 @@ err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp)
blob->len = dst.len;
if (state != PEM_POST)
- return "file coded in unknown format, discarded";
-
- return (encrypted)? pem_decrypt(blob, alg, key_size, &iv, passphrase) : NULL;
+ {
+ DBG1(" file coded in unknown format, discarded");
+ return FALSE;
+ }
+ if (!encrypted)
+ {
+ return TRUE;
+ }
+ return pem_decrypt(blob, alg, key_size, &iv, passphrase);
+
}
/* load a coded key or certificate file with autodetection
* of binary DER or base64 PEM ASN.1 formats and armored PGP format
*/
-bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
- const char *type, chunk_t *blob, bool *pgp)
+bool pem_asn1_load_file(char *filename, chunk_t *passphrase,
+ chunk_t *blob, bool *pgp)
{
- err_t ugh = NULL;
-
FILE *fd = fopen(filename, "r");
if (fd)
@@ -326,7 +344,7 @@ bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
blob->ptr = malloc(blob->len);
bytes = fread(blob->ptr, 1, blob->len, fd);
fclose(fd);
- DBG1(" loading %s file '%s' (%d bytes)", type, filename, bytes);
+ DBG2(" loading '%s' (%d bytes)", filename, bytes);
*pgp = FALSE;
@@ -341,9 +359,7 @@ bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
DBG4(" passphrase:", passphrase->ptr, passphrase->len);
/* try PEM format */
- ugh = pem_to_bin(blob, passphrase, pgp);
-
- if (ugh == NULL)
+ if (pem_to_bin(blob, passphrase, pgp))
{
if (*pgp)
{
@@ -355,16 +371,16 @@ bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
DBG2(" file coded in PEM format");
return TRUE;
}
- ugh = "file coded in unknown format, discarded";
+ DBG1(" file coded in unknown format, discarded");
}
/* a conversion error has occured */
- DBG1(" %s", ugh);
chunk_free(blob);
}
else
{
- DBG1(" could not open %s file '%s'", type, filename);
+ DBG1(" reading file '%s' failed", filename);
}
return FALSE;
}
+
diff --git a/src/libstrongswan/asn1/pem.h b/src/libstrongswan/asn1/pem.h
index 0f4b7202c..4b76fbe80 100755
--- a/src/libstrongswan/asn1/pem.h
+++ b/src/libstrongswan/asn1/pem.h
@@ -1,5 +1,7 @@
/*
- * Copyright (C) 2001-2004 Andreas Steffen, Zuercher Hochschule Winterthur
+ * Copyright (C) 2001-2008 Andreas Steffen
+ *
+ * Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -10,6 +12,8 @@
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
+ *
+ * $Id: pem.h 4011 2008-05-23 19:18:08Z andreas $
*/
#ifndef PEM_H_
@@ -19,9 +23,9 @@
#include <library.h>
-err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp);
+bool pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp);
-bool pem_asn1_load_file(const char *filename, chunk_t *passphrase,
- const char *type, chunk_t *blob, bool *pgp);
+bool pem_asn1_load_file(char *filename, chunk_t *passphrase,
+ chunk_t *blob, bool *pgp);
-#endif /*PEM_H_*/
+#endif /*PEM_H_ @} */
diff --git a/src/libstrongswan/asn1/ttodata.c b/src/libstrongswan/asn1/ttodata.c
deleted file mode 100644
index 125313c2a..000000000
--- a/src/libstrongswan/asn1/ttodata.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * convert from text form of arbitrary data (e.g., keys) to binary
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
- * License for more details.
- */
-
-#include "ttodata.h"
-
-#include <string.h>
-#include <ctype.h>
-
-/* converters and misc */
-static int unhex(const char *, char *, size_t);
-static int unb64(const char *, char *, size_t);
-static int untext(const char *, char *, size_t);
-static const char *badch(const char *, int, char *, size_t);
-
-/* internal error codes for converters */
-#define SHORT (-2) /* internal buffer too short */
-#define BADPAD (-3) /* bad base64 padding */
-#define BADCH0 (-4) /* invalid character 0 */
-#define BADCH1 (-5) /* invalid character 1 */
-#define BADCH2 (-6) /* invalid character 2 */
-#define BADCH3 (-7) /* invalid character 3 */
-#define BADOFF(code) (BADCH0-(code))
-
-/**
- * @brief convert text to data, with verbose error reports
- *
- * If some of this looks slightly odd, it's because it has changed
- * repeatedly (from the original atodata()) without a major rewrite.
- *
- * @param src
- * @param srclen 0 means apply strlen()
- * @param base 0 means figure it out
- * @param dst need not be valid if dstlen is 0
- * @param dstlen
- * @param lenp where to record length (NULL is nowhere)
- * @param errp error buffer
- * @param flags
- * @return NULL on success, else literal or errp
- */
-const char *ttodatav(const char *src, size_t srclen, int base, char *dst, size_t dstlen, size_t *lenp, char *errp, size_t errlen, unsigned int flags)
-{
- size_t ingroup; /* number of input bytes converted at once */
- char buf[4]; /* output from conversion */
- int nbytes; /* size of output */
- int (*decode)(const char *, char *, size_t);
- char *stop;
- int ndone;
- int i;
- int underscoreok;
- int skipSpace = 0;
-
- if (srclen == 0)
- {
- srclen = strlen(src);
- }
- if (dstlen == 0)
- {
- dst = buf; /* point it somewhere valid */
- }
- stop = dst + dstlen;
-
- if (base == 0)
- {
- if (srclen < 2)
- {
- return "input too short to be valid";
- }
- if (*src++ != '0')
- {
- return "input does not begin with format prefix";
- }
- switch (*src++)
- {
- case 'x':
- case 'X':
- base = 16;
- break;
- case 's':
- case 'S':
- base = 64;
- break;
- case 't':
- case 'T':
- base = 256;
- break;
- default:
- return "unknown format prefix";
- }
- srclen -= 2;
- }
- switch (base)
- {
- case 16:
- decode = unhex;
- underscoreok = 1;
- ingroup = 2;
- break;
- case 64:
- decode = unb64;
- underscoreok = 0;
- ingroup = 4;
- if(flags & TTODATAV_IGNORESPACE)
- {
- skipSpace = 1;
- }
- break;
- case 256:
- decode = untext;
- ingroup = 1;
- underscoreok = 0;
- break;
- default:
- return "unknown base";
- }
-
- /* proceed */
- ndone = 0;
- while (srclen > 0)
- {
- char stage[4]; /* staging area for group */
- size_t sl = 0;
-
- /* Grab ingroup characters into stage,
- * squeezing out blanks if we are supposed to ignore them.
- */
- for (sl = 0; sl < ingroup; src++, srclen--)
- {
- if (srclen == 0)
- {
- return "input ends in mid-byte, perhaps truncated";
- }
- else if (!(skipSpace && (*src == ' ' || *src == '\t')))
- {
- stage[sl++] = *src;
- }
- }
-
- nbytes = (*decode)(stage, buf, sizeof(buf));
- switch (nbytes)
- {
- case BADCH0:
- case BADCH1:
- case BADCH2:
- case BADCH3:
- return badch(stage, nbytes, errp, errlen);
- case SHORT:
- return "internal buffer too short (\"can't happen\")";
- case BADPAD:
- return "bad (non-zero) padding at end of base64 input";
- }
- if (nbytes <= 0)
- {
- return "unknown internal error";
- }
- for (i = 0; i < nbytes; i++)
- {
- if (dst < stop)
- {
- *dst++ = buf[i];
- }
- ndone++;
- }
- while (srclen >= 1 && skipSpace && (*src == ' ' || *src == '\t'))
- {
- src++;
- srclen--;
- }
- if (underscoreok && srclen > 1 && (*src == '_' || *src == ':'))
- {
- /* srclen > 1 means not last character */
- src++;
- srclen--;
- }
- }
-
- if (ndone == 0)
- {
- return "no data bytes specified by input";
- }
- if (lenp != NULL)
- {
- *lenp = ndone;
- }
- return NULL;
-}
-
-/**
- * @brief ttodata - convert text to data
- *
- * @param src
- * @param srclen 0 means apply strlen()
- * @param base 0 means figure it out
- * @param dst need not be valid if dstlen is 0
- * @param dstlen
- * @param lenp where to record length (NULL is nowhere)
- * @return NULL on success, else literal
- */
-const char *ttodata(const char *src, size_t srclen, int base, char *dst, size_t dstlen, size_t *lenp)
-{
- return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL,
- (size_t)0, TTODATAV_SPACECOUNTS);
-}
-
-/**
- * @brief atodata - convert ASCII to data
- *
- * backward-compatibility interface
- *
- * @param src
- * @param srclen
- * @param dst
- * @param dstlen
- * @return 0 for failure, true length for success
- */
-size_t atodata(const char *src, size_t srclen, char *dst, size_t dstlen)
-{
- size_t len;
- const char *err;
-
- err = ttodata(src, srclen, 0, dst, dstlen, &len);
- return (err)? 0:len;
-}
-
-/**
- * @brief atobytes - convert ASCII to data bytes
- *
- * another backward-compatibility interface
- */
-const char *atobytes(const char *src, size_t srclen, char *dst, size_t dstlen, size_t *lenp)
-{
- return ttodata(src, srclen, 0, dst, dstlen, lenp);
-}
-
-/**
- * @brief unhex - convert two ASCII hex digits to byte
- *
- * @param src known to be full length
- * @param dstnumber of result bytes, or error code
- * @param dstlen not large enough is a failure
- * @return
- */
-static int unhex(const char *src, char *dst, size_t dstlen)
-{
- char *p;
- unsigned byte;
- static char hex[] = "0123456789abcdef";
-
- if (dstlen < 1)
- {
- return SHORT;
- }
-
- p = strchr(hex, *src);
- if (p == NULL)
- {
- p = strchr(hex, tolower(*src));
- }
- if (p == NULL)
- {
- return BADCH0;
- }
- byte = (p - hex) << 4;
- src++;
-
- p = strchr(hex, *src);
- if (p == NULL)
- {
- p = strchr(hex, tolower(*src));
- }
- if (p == NULL)
- {
- return BADCH1;
- }
- byte |= (p - hex);
-
- *dst = byte;
- return 1;
-}
-
-/**
- * @brief unb64 - convert four ASCII base64 digits to three bytes
- *
- * Note that a base64 digit group is padded out with '=' if it represents
- * less than three bytes: one byte is dd==, two is ddd=, three is dddd.
- *
- * @param src known to be full length
- * @param dst
- * @param dstlen
- * @return number of result bytes, or error code
- */
-static int unb64(const char *src, char *dst, size_t dstlen)
-{
- char *p;
- unsigned byte1;
- unsigned byte2;
- static char base64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- if (dstlen < 3)
- {
- return SHORT;
- }
- p = strchr(base64, *src++);
-
- if (p == NULL)
- {
- return BADCH0;
- }
- byte1 = (p - base64) << 2; /* first six bits */
-
- p = strchr(base64, *src++);
- if (p == NULL)
- {
- return BADCH1;
- }
-
- byte2 = p - base64; /* next six: two plus four */
- *dst++ = byte1 | (byte2 >> 4);
- byte1 = (byte2 & 0xf) << 4;
-
- p = strchr(base64, *src++);
- if (p == NULL)
- {
- if (*(src-1) == '=' && *src == '=')
- {
- if (byte1 != 0) /* bad padding */
- {
- return BADPAD;
- }
- return 1;
- }
- return BADCH2;
- }
-
- byte2 = p - base64; /* next six: four plus two */
- *dst++ = byte1 | (byte2 >> 2);
- byte1 = (byte2 & 0x3) << 6;
-
- p = strchr(base64, *src++);
- if (p == NULL)
- {
- if (*(src-1) == '=')
- {
- if (byte1 != 0) /* bad padding */
- {
- return BADPAD;
- }
- return 2;
- }
- return BADCH3;
- }
- byte2 = p - base64; /* last six */
- *dst++ = byte1 | byte2;
-
- return 3;
-}
-
-/**
- * @brief untext - convert one ASCII character to byte
- *
- * @param src known to be full length
- * @param dst
- * @param dstlen not large enough is a failure
- * @return number of result bytes, or error code
- */
-static int untext(const char *src, char *dst, size_t dstlen)
-{
- if (dstlen < 1)
- {
- return SHORT;
- }
- *dst = *src;
- return 1;
-}
-
-/**
- * @brief badch - produce a nice complaint about an unknown character
- *
- * If the compiler complains that the array bigenough[] has a negative
- * size, that means the TTODATAV_BUF constant has been set too small.
- *
- * @param src
- * @param errcode
- * @param errp might be NULL
- * @param errlen
- * @return literal or errp
- */
-static const char *badch(const char *src, int errcode, char *errp, size_t errlen)
-{
- static const char pre[] = "unknown character (`";
- static const char suf[] = "') in input";
- char buf[5];
-# define REQD (sizeof(pre) - 1 + sizeof(buf) - 1 + sizeof(suf))
- struct sizecheck {
- char bigenough[TTODATAV_BUF - REQD]; /* see above */
- };
- char ch;
-
- if (errp == NULL || errlen < REQD)
- {
- return "unknown character in input";
- }
- strcpy(errp, pre);
- ch = *(src + BADOFF(errcode));
- if (isprint(ch))
- {
- buf[0] = ch;
- buf[1] = '\0';
- }
- else
- {
- buf[0] = '\\';
- buf[1] = ((ch & 0700) >> 6) + '0';
- buf[2] = ((ch & 0070) >> 3) + '0';
- buf[3] = ((ch & 0007) >> 0) + '0';
- buf[4] = '\0';
- }
- strcat(errp, buf);
- strcat(errp, suf);
- return (const char *)errp;
-}
diff --git a/src/libstrongswan/asn1/ttodata.h b/src/libstrongswan/asn1/ttodata.h
deleted file mode 100644
index 6125c6b82..000000000
--- a/src/libstrongswan/asn1/ttodata.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * convert from text form of arbitrary data (e.g., keys) to binary
- * Copyright (C) 2000 Henry Spencer.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
- * License for more details.
- */
-
-#ifndef TTODATA_H_
-#define TTODATA_H_
-
-#include <library.h>
-
-#define TTODATAV_BUF 40 /* ttodatav's largest non-literal message */
-#define TTODATAV_IGNORESPACE (1<<1) /* ignore spaces in base64 encodings*/
-#define TTODATAV_SPACECOUNTS 0 /* do not ignore spaces in base64 */
-
-err_t ttodata(const char *src, size_t srclen, int base, char *buf, size_t buflen, size_t *needed);
-
-
-#endif /* TTODATA_H_ */