From 1d025fbceaa9fcff02f2977251dea3d9b5b57e61 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 18 Apr 2006 07:22:20 +0000 Subject: - using asn1 pluto stuff now --- Source/lib/asn1-pluto/Makefile.asn1 | 29 -- Source/lib/asn1-pluto/asn1-pluto.c | 739 ------------------------------------ Source/lib/asn1-pluto/asn1-pluto.h | 137 ------- Source/lib/asn1-pluto/oid.c | 194 ---------- Source/lib/asn1-pluto/oid.h | 75 ---- Source/lib/asn1-pluto/oid.pl | 123 ------ Source/lib/asn1-pluto/oid.txt | 181 --------- Source/lib/asn1-pluto/pem.c | 343 ----------------- Source/lib/asn1-pluto/pem.h | 25 -- Source/lib/asn1-pluto/ttodata.c | 374 ------------------ Source/lib/asn1-pluto/ttodata.h | 30 -- Source/lib/asn1/Makefile.asn1 | 29 ++ Source/lib/asn1/asn1-pluto.c | 739 ++++++++++++++++++++++++++++++++++++ Source/lib/asn1/asn1-pluto.h | 137 +++++++ Source/lib/asn1/oid.c | 194 ++++++++++ Source/lib/asn1/oid.h | 75 ++++ Source/lib/asn1/oid.pl | 123 ++++++ Source/lib/asn1/oid.txt | 181 +++++++++ Source/lib/asn1/pem.c | 343 +++++++++++++++++ Source/lib/asn1/pem.h | 25 ++ Source/lib/asn1/ttodata.c | 374 ++++++++++++++++++ Source/lib/asn1/ttodata.h | 30 ++ Source/lib/crypto/certificate.h | 10 + Source/lib/utils/identification.h | 40 +- Source/lib/utils/leak_detective.c | 63 ++- 25 files changed, 2342 insertions(+), 2271 deletions(-) delete mode 100644 Source/lib/asn1-pluto/Makefile.asn1 delete mode 100644 Source/lib/asn1-pluto/asn1-pluto.c delete mode 100644 Source/lib/asn1-pluto/asn1-pluto.h delete mode 100644 Source/lib/asn1-pluto/oid.c delete mode 100644 Source/lib/asn1-pluto/oid.h delete mode 100644 Source/lib/asn1-pluto/oid.pl delete mode 100644 Source/lib/asn1-pluto/oid.txt delete mode 100755 Source/lib/asn1-pluto/pem.c delete mode 100755 Source/lib/asn1-pluto/pem.h delete mode 100644 Source/lib/asn1-pluto/ttodata.c delete mode 100644 Source/lib/asn1-pluto/ttodata.h create mode 100644 Source/lib/asn1/Makefile.asn1 create mode 100644 Source/lib/asn1/asn1-pluto.c create mode 100644 Source/lib/asn1/asn1-pluto.h create mode 100644 Source/lib/asn1/oid.c create mode 100644 Source/lib/asn1/oid.h create mode 100644 Source/lib/asn1/oid.pl create mode 100644 Source/lib/asn1/oid.txt create mode 100755 Source/lib/asn1/pem.c create mode 100755 Source/lib/asn1/pem.h create mode 100644 Source/lib/asn1/ttodata.c create mode 100644 Source/lib/asn1/ttodata.h (limited to 'Source/lib') diff --git a/Source/lib/asn1-pluto/Makefile.asn1 b/Source/lib/asn1-pluto/Makefile.asn1 deleted file mode 100644 index 44726ffa4..000000000 --- a/Source/lib/asn1-pluto/Makefile.asn1 +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 2006 Martin Willi -# 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 . -# -# 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. -# - -ASN1_DIR= $(LIB_DIR)asn1-pluto/ - - -LIB_OBJS+= $(BUILD_DIR)oid.o -$(BUILD_DIR)oid.o : $(ASN1_DIR)oid.c $(ASN1_DIR)oid.h - $(CC) $(CFLAGS) -c -o $@ $< -LIB_OBJS+= $(BUILD_DIR)asn1-pluto.o -$(BUILD_DIR)asn1-pluto.o : $(ASN1_DIR)asn1-pluto.c $(ASN1_DIR)asn1-pluto.h - $(CC) $(CFLAGS) -c -o $@ $< -LIB_OBJS+= $(BUILD_DIR)pem.o -$(BUILD_DIR)pem.o : $(ASN1_DIR)pem.c $(ASN1_DIR)pem.h - $(CC) $(CFLAGS) -c -o $@ $< -LIB_OBJS+= $(BUILD_DIR)ttodata.o -$(BUILD_DIR)ttodata.o : $(ASN1_DIR)ttodata.c $(ASN1_DIR)ttodata.h - $(CC) $(CFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/Source/lib/asn1-pluto/asn1-pluto.c b/Source/lib/asn1-pluto/asn1-pluto.c deleted file mode 100644 index 01deb5c14..000000000 --- a/Source/lib/asn1-pluto/asn1-pluto.c +++ /dev/null @@ -1,739 +0,0 @@ -/* Simple ASN.1 parser - * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur - * Copyright (C) 2006 Martin Will, 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 . - * - * 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. - */ - -#include -#include -#include - -#include "asn1-pluto.h" -#include "oid.h" - -#include - -static logger_t *logger; - -/* Names of the months */ -static const char* months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -/* 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 }; - -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 */ - -static u_char ASN1_md5_id_str[] = { - 0x30, 0x0C, - 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, - 0x05, 0x00 -}; - -static u_char ASN1_sha1_id_str[] = { - 0x30, 0x09, - 0x06, 0x05, 0x2B, 0x0E,0x03, 0x02, 0x1A, - 0x05, 0x00 -}; - -static u_char ASN1_md5WithRSA_id_str[] = { - 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, - 0x05, 0x00 -}; - -static u_char ASN1_sha1WithRSA_id_str[] = { - 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, - 0x05, 0x00 -}; - -static u_char ASN1_rsaEncryption_id_str[] = { - 0x30, 0x0D, - 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, - 0x05, 0x00 -}; - -const chunk_t ASN1_md5_id = chunk_from_buf(ASN1_md5_id_str); -const chunk_t ASN1_sha1_id = chunk_from_buf(ASN1_sha1_id_str); -const chunk_t ASN1_rsaEncryption_id = chunk_from_buf(ASN1_rsaEncryption_id_str); -const chunk_t ASN1_md5WithRSA_id = chunk_from_buf(ASN1_md5WithRSA_id_str); -const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_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 - */ -chunk_t asn1_algorithmIdentifier(int oid) -{ - switch (oid) - { - case OID_RSA_ENCRYPTION: - return ASN1_rsaEncryption_id; - case OID_MD5_WITH_RSA: - return ASN1_md5WithRSA_id; - case OID_SHA1_WITH_RSA: - return ASN1_sha1WithRSA_id; - case OID_MD5: - return ASN1_md5_id; - case OID_SHA1: - return ASN1_sha1_id; - default: - return CHUNK_INITIALIZER; - } -} - -/* - * 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 - */ -int known_oid(chunk_t object) -{ - int oid = 0; - - while (object.len) - { - if (oid_names[oid].octet == *object.ptr) - { - if (--object.len == 0 || oid_names[oid].down == 0) - { - return oid; /* found terminal symbol */ - } - else - { - object.ptr++; oid++; /* advance to next hex octet */ - } - } - else - { - if (oid_names[oid].next) - oid = oid_names[oid].next; - else - return OID_UNKNOWN; - } - } - return -1; -} - -/* - * Decodes the length in bytes of an ASN.1 object - */ -u_int asn1_length(chunk_t *blob) -{ - u_char n; - size_t len; - - /* advance from tag field on to length field */ - blob->ptr++; - blob->len--; - - /* read first octet of length field */ - n = *blob->ptr++; - blob->len--; - - if ((n & 0x80) == 0) - {/* single length octet */ - return n; - } - - /* composite length, determine number of length octets */ - n &= 0x7f; - - if (n > blob->len) - { - logger->log(logger, ERROR|LEVEL1, "number of length octets is larger than ASN.1 object"); - return ASN1_INVALID_LENGTH; - } - - if (n > sizeof(len)) - { - logger->log(logger, ERROR|LEVEL1, "number of length octets is larger than limit of %d octets", - (int)sizeof(len)); - return ASN1_INVALID_LENGTH; - } - - len = 0; - - while (n-- > 0) - { - len = 256*len + *blob->ptr++; - blob->len--; - } - return len; -} - -/* - * 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; -} - -/* - * Display a date either in local or UTC time - * TODO: Does not seem to be thread save - */ -char* timetoa(const time_t *time, bool utc) -{ - static char buf[30]; - - if (*time == 0) - sprintf(buf, "--- -- --:--:--%s----", (utc)?" UTC ":" "); - else - { - struct tm *t = (utc)? gmtime(time) : localtime(time); - sprintf(buf, "%s %02d %02d:%02d:%02d%s%04d", - months[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, - (utc)?" UTC ":" ", t->tm_year + 1900); - } - return buf; -} - -/* - * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time - */ -time_t asn1totime(const chunk_t *utctime, asn1_t type) -{ - struct tm t; - time_t tz_offset; - u_char *eot = NULL; - - if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL) - { - tz_offset = 0; /* Zulu time with a zero time zone offset */ - } - else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL) - { - int tz_hour, tz_min; - - sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); - tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */ - } - else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL) - { - int tz_hour, tz_min; - - sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); - tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */ - } - else - { - return 0; /* error in time format */ - } - - { - const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d": - "%4d%2d%2d%2d%2d"; - - sscanf(utctime->ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday, - &t.tm_hour, &t.tm_min); - } - - /* is there a seconds field? */ - if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14)) - { - sscanf(eot-2, "%2d", &t.tm_sec); - } - else - { - t.tm_sec = 0; - } - - /* representation of year */ - if (t.tm_year >= 1900) - { - t.tm_year -= 1900; - } - else if (t.tm_year >= 100) - { - return 0; - } - else if (t.tm_year < 50) - { - t.tm_year += 100; - } - - /* representation of month 0..11*/ - t.tm_mon--; - - /* set daylight saving time to off */ - t.tm_isdst = 0; - - /* compensate timezone */ - - return mktime(&t) - timezone - tz_offset; -} - -/* - * Initializes the internal context of the ASN.1 parser - */ -void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, bool implicit) -{ - logger = logger_manager->get_logger(logger_manager, ASN1); - ctx->blobs[0] = blob; - ctx->level0 = level0; - ctx->implicit = implicit; - memset(ctx->loopAddr, '\0', sizeof(ctx->loopAddr)); -} - -/* - * print the value of an ASN.1 simple object - */ -static void debug_asn1_simple_object(chunk_t object, asn1_t type) -{ - int oid; - time_t time; - - switch (type) - { - case ASN1_OID: - oid = known_oid(object); - if (oid != OID_UNKNOWN) - { - logger->log(logger, CONTROL|LEVEL1, " '%s'", oid_names[oid].name); - return; - } - break; - case ASN1_UTF8STRING: - case ASN1_IA5STRING: - case ASN1_PRINTABLESTRING: - case ASN1_T61STRING: - case ASN1_VISIBLESTRING: - logger->log(logger, CONTROL|LEVEL1, " '%.*s'", (int)object.len, object.ptr); - return; - case ASN1_UTCTIME: - case ASN1_GENERALIZEDTIME: - time = asn1totime(&object, type); - logger->log(logger, CONTROL|LEVEL1, " '%s'", timetoa(&time, TRUE)); - return; - default: - break; - } - logger->log_chunk(logger, RAW|LEVEL1, "", object); -} - -/* - * 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_INITIALIZER; - - 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 */ - logger->log(logger, CONTROL|LEVEL1, "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) - { - logger->log(logger, ERROR|LEVEL1, "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) - { - logger->log(logger, ERROR|LEVEL1, "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) - { - logger->log(logger, CONTROL|LEVEL1, "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)) - { - logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x", - *level, obj.name, obj.type, *start_ptr); - logger->log_bytes(logger, RAW|LEVEL1, "", start_ptr, (u_int)(blob->ptr - start_ptr)); - return FALSE; - } - - logger->log(logger, CONTROL|LEVEL1, "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); - logger->log_chunk(logger, RAW|LEVEL1, "", *object); - } - else if (obj.flags & ASN1_BODY) - { - *object = *blob1; - debug_asn1_simple_object(*object, obj.type); - } - 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) -{ - size_t len; - - /* an ASN.1 object must possess at least a tag and length field */ - if (object->len < 2) - { - logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN.1 object smaller than 2 octets", - level, name); - return FALSE; - } - - if (*object->ptr != type) - { - logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x", - level, name, type, *object->ptr); - return FALSE; - } - - len = asn1_length(object); - - if (len == ASN1_INVALID_LENGTH || object->len < len) - { - logger->log(logger, ERROR|LEVEL1, "L%d - %s: length of ASN.1 object invalid or too large", - level, name); - return FALSE; - } - - logger->log(logger, CONTROL|LEVEL1, "L%d - %s:", level, name); - debug_asn1_simple_object(*object, type); - return TRUE; -} - -/* - * extracts an algorithmIdentifier - */ -int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int alg = OID_UNKNOWN; - int objectID = 0; - - asn1_init(&ctx, blob, level0, FALSE); - - while (objectID < ALGORITHM_ID_ROOF) - { - if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx)) - return OID_UNKNOWN; - - switch (objectID) - { - case ALGORITHM_ID_ALG: - alg = known_oid(object); - break; - case ALGORITHM_ID_PARAMETERS: - if (parameters != NULL) - *parameters = object; - break; - default: - break; - } - objectID++; - } - return alg; - } - -/* - * tests if a blob contains a valid ASN.1 set or sequence - */ -bool is_asn1(chunk_t blob) -{ - u_int len; - u_char tag = *blob.ptr; - - if (tag != ASN1_SEQUENCE && tag != ASN1_SET) - { - logger->log(logger, ERROR|LEVEL2, " file content is not binary ASN.1"); - return FALSE; - } - len = asn1_length(&blob); - if (len != blob.len) - { - logger->log(logger, ERROR|LEVEL2, " file size does not match ASN.1 coded length"); - 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) -{ - if (length < 128) - { - code->ptr[0] = length; - code->len = 1; - } - else if (length < 256) - { - code->ptr[0] = 0x81; - code->ptr[1] = (u_char) length; - code->len = 2; - } - else if (length < 65536) - { - code->ptr[0] = 0x82; - code->ptr[1] = length >> 8; - code->ptr[2] = length & 0x00ff; - code->len = 3; - } - else - { - code->ptr[0] = 0x83; - code->ptr[1] = length >> 16; - code->ptr[2] = (length >> 8) & 0x00ff; - code->ptr[3] = length & 0x0000ff; - code->len = 4; - } -} - -/* - * 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 length_buf[4]; - chunk_t length = { length_buf, 0 }; - u_char *pos; - - /* code the asn.1 length field */ - code_asn1_length(datalen, &length); - - /* allocate memory for the asn.1 TLV object */ - object->len = 1 + length.len + datalen; - object->ptr = malloc(object->len); - - /* set position pointer at the start of the object */ - pos = object->ptr; - - /* copy the asn.1 tag field and advance the pointer */ - *pos++ = type; - - /* copy the asn.1 length field and advance the pointer */ - memcpy(pos, length.ptr, length.len); - pos += length.len; - - return pos; -} - -/* - * 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); - memcpy(pos, content.ptr, content.len); - pos += content.len; - - return object; -} - -/* Build an ASN.1 object from a variable number of individual chunks. - * Depending on the mode, chunks either are moved ('m') or copied ('c'). - */ -chunk_t asn1_wrap(asn1_t type, const char *mode, ...) -{ - chunk_t construct; - va_list chunks; - u_char *pos; - int i; - int count = strlen(mode); - - /* sum up lengths of individual chunks */ - va_start(chunks, mode); - construct.len = 0; - for (i = 0; i < count; i++) - { - chunk_t ch = va_arg(chunks, chunk_t); - construct.len += ch.len; - } - va_end(chunks); - - /* allocate needed memory for construct */ - pos = build_asn1_object(&construct, type, construct.len); - - /* copy or move the chunks */ - va_start(chunks, mode); - for (i = 0; i < count; i++) - { - chunk_t ch = va_arg(chunks, chunk_t); - - switch (*mode++) - { - case 'm': - memcpy(pos, ch.ptr, ch.len); - pos += ch.len; - free(ch.ptr); - break; - case 'c': - default: - memcpy(pos, ch.ptr, ch.len); - pos += ch.len; - } - } - va_end(chunks); - - return construct; -} - -/* - * 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); -} - -/* - * convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format - */ -chunk_t timetoasn1(const time_t *time, asn1_t type) -{ - int offset; - const char *format; - char buf[TIMETOA_BUF]; - chunk_t formatted_time; - struct tm *t = gmtime(time); - - if (type == ASN1_GENERALIZEDTIME) - { - format = "%04d%02d%02d%02d%02d%02dZ"; - offset = 1900; - } - else /* ASN1_UTCTIME */ - { - format = "%02d%02d%02d%02d%02d%02dZ"; - offset = (t->tm_year < 100)? 0 : -100; - } - sprintf(buf, format, t->tm_year + offset, t->tm_mon + 1, t->tm_mday - , t->tm_hour, t->tm_min, t->tm_sec); - formatted_time.ptr = buf; - formatted_time.len = strlen(buf); - return asn1_simple_object(type, formatted_time); -} diff --git a/Source/lib/asn1-pluto/asn1-pluto.h b/Source/lib/asn1-pluto/asn1-pluto.h deleted file mode 100644 index 3edaa3254..000000000 --- a/Source/lib/asn1-pluto/asn1-pluto.h +++ /dev/null @@ -1,137 +0,0 @@ -/* Simple ASN.1 parser - * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur - * Copyright (C) 2006 Martin Will, 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 . - * - * 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. - */ - -#ifndef _ASN1_H -#define _ASN1_H - -#include -#include - -#include - - -/* Defines some primitive ASN1 types */ - -typedef enum { - ASN1_EOC = 0x00, - ASN1_BOOLEAN = 0x01, - ASN1_INTEGER = 0x02, - ASN1_BIT_STRING = 0x03, - ASN1_OCTET_STRING = 0x04, - ASN1_NULL = 0x05, - ASN1_OID = 0x06, - ASN1_ENUMERATED = 0x0A, - ASN1_UTF8STRING = 0x0C, - ASN1_NUMERICSTRING = 0x12, - ASN1_PRINTABLESTRING = 0x13, - ASN1_T61STRING = 0x14, - ASN1_VIDEOTEXSTRING = 0x15, - ASN1_IA5STRING = 0x16, - ASN1_UTCTIME = 0x17, - ASN1_GENERALIZEDTIME = 0x18, - ASN1_GRAPHICSTRING = 0x19, - ASN1_VISIBLESTRING = 0x1A, - ASN1_GENERALSTRING = 0x1B, - ASN1_UNIVERSALSTRING = 0x1C, - ASN1_BMPSTRING = 0x1E, - - ASN1_CONSTRUCTED = 0x20, - - ASN1_SEQUENCE = 0x30, - - ASN1_SET = 0x31, - - ASN1_CONTEXT_S_0 = 0x80, - ASN1_CONTEXT_S_1 = 0x81, - ASN1_CONTEXT_S_2 = 0x82, - ASN1_CONTEXT_S_3 = 0x83, - ASN1_CONTEXT_S_4 = 0x84, - ASN1_CONTEXT_S_5 = 0x85, - ASN1_CONTEXT_S_6 = 0x86, - ASN1_CONTEXT_S_7 = 0x87, - ASN1_CONTEXT_S_8 = 0x88, - - ASN1_CONTEXT_C_0 = 0xA0, - ASN1_CONTEXT_C_1 = 0xA1, - ASN1_CONTEXT_C_2 = 0xA2, - ASN1_CONTEXT_C_3 = 0xA3, - ASN1_CONTEXT_C_4 = 0xA4, - ASN1_CONTEXT_C_5 = 0xA5 -} asn1_t; - -/* Definition of ASN1 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_INVALID_LENGTH 0xffffffff - -/* definition of an ASN.1 object */ - -typedef struct { - u_int level; - const u_char *name; - asn1_t type; - u_char flags; -} asn1Object_t; - -#define ASN1_MAX_LEVEL 10 - -typedef struct { - bool implicit; - u_int level0; - u_int loopAddr[ASN1_MAX_LEVEL+1]; - chunk_t blobs[ASN1_MAX_LEVEL+2]; -} asn1_ctx_t; - -/* 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; - -/* some popular algorithmIdentifiers */ -extern const chunk_t ASN1_md5_id; -extern const chunk_t ASN1_sha1_id; -extern const chunk_t ASN1_rsaEncryption_id; -extern const chunk_t ASN1_md5WithRSA_id; -extern const chunk_t ASN1_sha1WithRSA_id; - -#define TIMETOA_BUF 30 - -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 void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, bool implicit); -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 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_wrap(asn1_t type, const char *mode, ...); -extern chunk_t timetoasn1(const time_t *time, asn1_t type); - -#endif /* _ASN1_H */ diff --git a/Source/lib/asn1-pluto/oid.c b/Source/lib/asn1-pluto/oid.c deleted file mode 100644 index 7b0135d5e..000000000 --- a/Source/lib/asn1-pluto/oid.c +++ /dev/null @@ -1,194 +0,0 @@ -/* List of some useful object identifiers (OIDs) - * Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur - * - * This file has been automatically generated by the script oid.pl - * Do not edit manually! - */ - -#include - -#include "oid.h" - -const oid_t oid_names[] = { - {0x02, 7, 1, "ITU-T Administration" }, /* 0 */ - { 0x82, 0, 1, "" }, /* 1 */ - { 0x06, 0, 1, "Germany ITU-T member" }, /* 2 */ - { 0x01, 0, 1, "Deutsche Telekom AG" }, /* 3 */ - { 0x0A, 0, 1, "" }, /* 4 */ - { 0x07, 0, 1, "" }, /* 5 */ - { 0x14, 0, 0, "ND" }, /* 6 */ - {0x09, 18, 1, "data" }, /* 7 */ - { 0x92, 0, 1, "" }, /* 8 */ - { 0x26, 0, 1, "" }, /* 9 */ - { 0x89, 0, 1, "" }, /* 10 */ - { 0x93, 0, 1, "" }, /* 11 */ - { 0xF2, 0, 1, "" }, /* 12 */ - { 0x2C, 0, 1, "" }, /* 13 */ - { 0x64, 0, 1, "pilot" }, /* 14 */ - { 0x01, 0, 1, "pilotAttributeType" }, /* 15 */ - { 0x01, 17, 0, "UID" }, /* 16 */ - { 0x19, 0, 0, "DC" }, /* 17 */ - {0x55, 51, 1, "X.500" }, /* 18 */ - { 0x04, 36, 1, "X.509" }, /* 19 */ - { 0x03, 21, 0, "CN" }, /* 20 */ - { 0x04, 22, 0, "S" }, /* 21 */ - { 0x05, 23, 0, "SN" }, /* 22 */ - { 0x06, 24, 0, "C" }, /* 23 */ - { 0x07, 25, 0, "L" }, /* 24 */ - { 0x08, 26, 0, "ST" }, /* 25 */ - { 0x0A, 27, 0, "O" }, /* 26 */ - { 0x0B, 28, 0, "OU" }, /* 27 */ - { 0x0C, 29, 0, "T" }, /* 28 */ - { 0x0D, 30, 0, "D" }, /* 29 */ - { 0x24, 31, 0, "userCertificate" }, /* 30 */ - { 0x29, 32, 0, "N" }, /* 31 */ - { 0x2A, 33, 0, "G" }, /* 32 */ - { 0x2B, 34, 0, "I" }, /* 33 */ - { 0x2D, 35, 0, "ID" }, /* 34 */ - { 0x48, 0, 0, "role" }, /* 35 */ - { 0x1D, 0, 1, "id-ce" }, /* 36 */ - { 0x09, 38, 0, "subjectDirectoryAttrs" }, /* 37 */ - { 0x0E, 39, 0, "subjectKeyIdentifier" }, /* 38 */ - { 0x0F, 40, 0, "keyUsage" }, /* 39 */ - { 0x10, 41, 0, "privateKeyUsagePeriod" }, /* 40 */ - { 0x11, 42, 0, "subjectAltName" }, /* 41 */ - { 0x12, 43, 0, "issuerAltName" }, /* 42 */ - { 0x13, 44, 0, "basicConstraints" }, /* 43 */ - { 0x15, 45, 0, "reasonCode" }, /* 44 */ - { 0x1F, 46, 0, "crlDistributionPoints" }, /* 45 */ - { 0x20, 47, 0, "certificatePolicies" }, /* 46 */ - { 0x23, 48, 0, "authorityKeyIdentifier" }, /* 47 */ - { 0x25, 49, 0, "extendedKeyUsage" }, /* 48 */ - { 0x37, 50, 0, "targetInformation" }, /* 49 */ - { 0x38, 0, 0, "noRevAvail" }, /* 50 */ - {0x2A, 88, 1, "" }, /* 51 */ - { 0x86, 0, 1, "" }, /* 52 */ - { 0x48, 0, 1, "" }, /* 53 */ - { 0x86, 0, 1, "" }, /* 54 */ - { 0xF7, 0, 1, "" }, /* 55 */ - { 0x0D, 0, 1, "RSADSI" }, /* 56 */ - { 0x01, 83, 1, "PKCS" }, /* 57 */ - { 0x01, 66, 1, "PKCS-1" }, /* 58 */ - { 0x01, 60, 0, "rsaEncryption" }, /* 59 */ - { 0x02, 61, 0, "md2WithRSAEncryption" }, /* 60 */ - { 0x04, 62, 0, "md5WithRSAEncryption" }, /* 61 */ - { 0x05, 63, 0, "sha-1WithRSAEncryption" }, /* 62 */ - { 0x0B, 64, 0, "sha256WithRSAEncryption"}, /* 63 */ - { 0x0C, 65, 0, "sha384WithRSAEncryption"}, /* 64 */ - { 0x0D, 0, 0, "sha512WithRSAEncryption"}, /* 65 */ - { 0x07, 73, 1, "PKCS-7" }, /* 66 */ - { 0x01, 68, 0, "data" }, /* 67 */ - { 0x02, 69, 0, "signedData" }, /* 68 */ - { 0x03, 70, 0, "envelopedData" }, /* 69 */ - { 0x04, 71, 0, "signedAndEnvelopedData" }, /* 70 */ - { 0x05, 72, 0, "digestedData" }, /* 71 */ - { 0x06, 0, 0, "encryptedData" }, /* 72 */ - { 0x09, 0, 1, "PKCS-9" }, /* 73 */ - { 0x01, 75, 0, "E" }, /* 74 */ - { 0x02, 76, 0, "unstructuredName" }, /* 75 */ - { 0x03, 77, 0, "contentType" }, /* 76 */ - { 0x04, 78, 0, "messageDigest" }, /* 77 */ - { 0x05, 79, 0, "signingTime" }, /* 78 */ - { 0x06, 80, 0, "counterSignature" }, /* 79 */ - { 0x07, 81, 0, "challengePassword" }, /* 80 */ - { 0x08, 82, 0, "unstructuredAddress" }, /* 81 */ - { 0x0E, 0, 0, "extensionRequest" }, /* 82 */ - { 0x02, 86, 1, "digestAlgorithm" }, /* 83 */ - { 0x02, 85, 0, "md2" }, /* 84 */ - { 0x05, 0, 0, "md5" }, /* 85 */ - { 0x03, 0, 1, "encryptionAlgorithm" }, /* 86 */ - { 0x07, 0, 0, "3des-ede-cbc" }, /* 87 */ - {0x2B, 149, 1, "" }, /* 88 */ - { 0x06, 136, 1, "dod" }, /* 89 */ - { 0x01, 0, 1, "internet" }, /* 90 */ - { 0x04, 105, 1, "private" }, /* 91 */ - { 0x01, 0, 1, "enterprise" }, /* 92 */ - { 0x82, 98, 1, "" }, /* 93 */ - { 0x37, 0, 1, "Microsoft" }, /* 94 */ - { 0x0A, 0, 1, "" }, /* 95 */ - { 0x03, 0, 1, "" }, /* 96 */ - { 0x03, 0, 0, "msSGC" }, /* 97 */ - { 0x89, 0, 1, "" }, /* 98 */ - { 0x31, 0, 1, "" }, /* 99 */ - { 0x01, 0, 1, "" }, /* 100 */ - { 0x01, 0, 1, "" }, /* 101 */ - { 0x02, 0, 1, "" }, /* 102 */ - { 0x02, 104, 0, "" }, /* 103 */ - { 0x4B, 0, 0, "TCGID" }, /* 104 */ - { 0x05, 0, 1, "security" }, /* 105 */ - { 0x05, 0, 1, "mechanisms" }, /* 106 */ - { 0x07, 0, 1, "id-pkix" }, /* 107 */ - { 0x01, 110, 1, "id-pe" }, /* 108 */ - { 0x01, 0, 0, "authorityInfoAccess" }, /* 109 */ - { 0x03, 120, 1, "id-kp" }, /* 110 */ - { 0x01, 112, 0, "serverAuth" }, /* 111 */ - { 0x02, 113, 0, "clientAuth" }, /* 112 */ - { 0x03, 114, 0, "codeSigning" }, /* 113 */ - { 0x04, 115, 0, "emailProtection" }, /* 114 */ - { 0x05, 116, 0, "ipsecEndSystem" }, /* 115 */ - { 0x06, 117, 0, "ipsecTunnel" }, /* 116 */ - { 0x07, 118, 0, "ipsecUser" }, /* 117 */ - { 0x08, 119, 0, "timeStamping" }, /* 118 */ - { 0x09, 0, 0, "ocspSigning" }, /* 119 */ - { 0x08, 122, 1, "id-otherNames" }, /* 120 */ - { 0x05, 0, 0, "xmppAddr" }, /* 121 */ - { 0x0A, 127, 1, "id-aca" }, /* 122 */ - { 0x01, 124, 0, "authenticationInfo" }, /* 123 */ - { 0x02, 125, 0, "accessIdentity" }, /* 124 */ - { 0x03, 126, 0, "chargingIdentity" }, /* 125 */ - { 0x04, 0, 0, "group" }, /* 126 */ - { 0x30, 0, 1, "id-ad" }, /* 127 */ - { 0x01, 0, 1, "ocsp" }, /* 128 */ - { 0x01, 130, 0, "basic" }, /* 129 */ - { 0x02, 131, 0, "nonce" }, /* 130 */ - { 0x03, 132, 0, "crl" }, /* 131 */ - { 0x04, 133, 0, "response" }, /* 132 */ - { 0x05, 134, 0, "noCheck" }, /* 133 */ - { 0x06, 135, 0, "archiveCutoff" }, /* 134 */ - { 0x07, 0, 0, "serviceLocator" }, /* 135 */ - { 0x0E, 142, 1, "oiw" }, /* 136 */ - { 0x03, 0, 1, "secsig" }, /* 137 */ - { 0x02, 0, 1, "algorithms" }, /* 138 */ - { 0x07, 140, 0, "des-cbc" }, /* 139 */ - { 0x1A, 141, 0, "sha-1" }, /* 140 */ - { 0x1D, 0, 0, "sha-1WithRSASignature" }, /* 141 */ - { 0x24, 0, 1, "TeleTrusT" }, /* 142 */ - { 0x03, 0, 1, "algorithm" }, /* 143 */ - { 0x03, 0, 1, "signatureAlgorithm" }, /* 144 */ - { 0x01, 0, 1, "rsaSignature" }, /* 145 */ - { 0x02, 147, 0, "rsaSigWithripemd160" }, /* 146 */ - { 0x03, 148, 0, "rsaSigWithripemd128" }, /* 147 */ - { 0x04, 0, 0, "rsaSigWithripemd256" }, /* 148 */ - {0x60, 0, 1, "" }, /* 149 */ - { 0x86, 0, 1, "" }, /* 150 */ - { 0x48, 0, 1, "" }, /* 151 */ - { 0x01, 0, 1, "organization" }, /* 152 */ - { 0x65, 160, 1, "gov" }, /* 153 */ - { 0x03, 0, 1, "csor" }, /* 154 */ - { 0x04, 0, 1, "nistalgorithm" }, /* 155 */ - { 0x02, 0, 1, "hashalgs" }, /* 156 */ - { 0x01, 158, 0, "id-SHA-256" }, /* 157 */ - { 0x02, 159, 0, "id-SHA-384" }, /* 158 */ - { 0x03, 0, 0, "id-SHA-512" }, /* 159 */ - { 0x86, 0, 1, "" }, /* 160 */ - { 0xf8, 0, 1, "" }, /* 161 */ - { 0x42, 171, 1, "netscape" }, /* 162 */ - { 0x01, 169, 1, "" }, /* 163 */ - { 0x01, 165, 0, "nsCertType" }, /* 164 */ - { 0x03, 166, 0, "nsRevocationUrl" }, /* 165 */ - { 0x04, 167, 0, "nsCaRevocationUrl" }, /* 166 */ - { 0x08, 168, 0, "nsCaPolicyUrl" }, /* 167 */ - { 0x0d, 0, 0, "nsComment" }, /* 168 */ - { 0x04, 0, 1, "policy" }, /* 169 */ - { 0x01, 0, 0, "nsSGC" }, /* 170 */ - { 0x45, 0, 1, "verisign" }, /* 171 */ - { 0x01, 0, 1, "pki" }, /* 172 */ - { 0x09, 0, 1, "attributes" }, /* 173 */ - { 0x02, 175, 0, "messageType" }, /* 174 */ - { 0x03, 176, 0, "pkiStatus" }, /* 175 */ - { 0x04, 177, 0, "failInfo" }, /* 176 */ - { 0x05, 178, 0, "senderNonce" }, /* 177 */ - { 0x06, 179, 0, "recipientNonce" }, /* 178 */ - { 0x07, 180, 0, "transID" }, /* 179 */ - { 0x08, 0, 0, "extensionReq" } /* 180 */ -}; diff --git a/Source/lib/asn1-pluto/oid.h b/Source/lib/asn1-pluto/oid.h deleted file mode 100644 index 4096af357..000000000 --- a/Source/lib/asn1-pluto/oid.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Object identifiers (OIDs) used by FreeS/WAN - * Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur - * - * This file has been automatically generated by the script oid.pl - * Do not edit manually! - */ - -typedef struct { - u_char octet; - u_int next; - u_int down; - const u_char *name; -} oid_t; - -extern const oid_t oid_names[]; - -#define OID_UNKNOWN -1 -#define OID_ROLE 35 -#define OID_SUBJECT_KEY_ID 38 -#define OID_SUBJECT_ALT_NAME 41 -#define OID_BASIC_CONSTRAINTS 43 -#define OID_CRL_REASON_CODE 44 -#define OID_CRL_DISTRIBUTION_POINTS 45 -#define OID_AUTHORITY_KEY_ID 47 -#define OID_EXTENDED_KEY_USAGE 48 -#define OID_TARGET_INFORMATION 49 -#define OID_NO_REV_AVAIL 50 -#define OID_RSA_ENCRYPTION 59 -#define OID_MD2_WITH_RSA 60 -#define OID_MD5_WITH_RSA 61 -#define OID_SHA1_WITH_RSA 62 -#define OID_SHA256_WITH_RSA 63 -#define OID_SHA384_WITH_RSA 64 -#define OID_SHA512_WITH_RSA 65 -#define OID_PKCS7_DATA 67 -#define OID_PKCS7_SIGNED_DATA 68 -#define OID_PKCS7_ENVELOPED_DATA 69 -#define OID_PKCS7_SIGNED_ENVELOPED_DATA 70 -#define OID_PKCS7_DIGESTED_DATA 71 -#define OID_PKCS7_ENCRYPTED_DATA 72 -#define OID_PKCS9_EMAIL 74 -#define OID_PKCS9_CONTENT_TYPE 76 -#define OID_PKCS9_MESSAGE_DIGEST 77 -#define OID_PKCS9_SIGNING_TIME 78 -#define OID_MD2 84 -#define OID_MD5 85 -#define OID_3DES_EDE_CBC 87 -#define OID_AUTHORITY_INFO_ACCESS 109 -#define OID_OCSP_SIGNING 119 -#define OID_XMPP_ADDR 121 -#define OID_AUTHENTICATION_INFO 123 -#define OID_ACCESS_IDENTITY 124 -#define OID_CHARGING_IDENTITY 125 -#define OID_GROUP 126 -#define OID_OCSP 128 -#define OID_BASIC 129 -#define OID_NONCE 130 -#define OID_CRL 131 -#define OID_RESPONSE 132 -#define OID_NO_CHECK 133 -#define OID_ARCHIVE_CUTOFF 134 -#define OID_SERVICE_LOCATOR 135 -#define OID_DES_CBC 139 -#define OID_SHA1 140 -#define OID_SHA1_WITH_RSA_OIW 141 -#define OID_NS_REVOCATION_URL 165 -#define OID_NS_CA_REVOCATION_URL 166 -#define OID_NS_CA_POLICY_URL 167 -#define OID_NS_COMMENT 168 -#define OID_PKI_MESSAGE_TYPE 174 -#define OID_PKI_STATUS 175 -#define OID_PKI_FAIL_INFO 176 -#define OID_PKI_SENDER_NONCE 177 -#define OID_PKI_RECIPIENT_NONCE 178 -#define OID_PKI_TRANS_ID 179 diff --git a/Source/lib/asn1-pluto/oid.pl b/Source/lib/asn1-pluto/oid.pl deleted file mode 100644 index 52ac8eae0..000000000 --- a/Source/lib/asn1-pluto/oid.pl +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/perl -# Generates oid.h and oid.c out of oid.txt -# Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur -# -# 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 . -# -# 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. -# - -$copyright="Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur"; -$automatic="This file has been automatically generated by the script oid.pl"; -$warning="Do not edit manually!"; - -print "oid.pl generating oid.h and oid.c\n"; - -# Generate oid.h - -open(OID_H, ">oid.h") - or die "could not open 'oid.h': $!"; - -print OID_H "/* Object identifiers (OIDs) used by FreeS/WAN\n", - " * ", $copyright, "\n", - " * \n", - " * ", $automatic, "\n", - " * ", $warning, "\n", - " */\n\n", - "typedef struct {\n", - " u_char octet;\n", - " u_int next;\n", - " u_int down;\n", - " const u_char *name;\n", - "} oid_t;\n", - "\n", - "extern const oid_t oid_names[];\n", - "\n", - "#define OID_UNKNOWN -1\n"; - -# parse oid.txt - -open(SRC, ") -{ - $line =~ m/( *?)(0x\w{2})\s+(".*?")[ \t]*?([\w_]*?)\Z/; - - @order[$counter] = length($1); - @octet[$counter] = $2; - @name[$counter] = $3; - - if (length($1) > $max_order) - { - $max_order = length($1); - } - if (length($3) > $max_name) - { - $max_name = length($3); - } - if (length($4) > 0) - { - printf OID_H "#define %s%s%d\n", $4, "\t" x ((39-length($4))/8), $counter; - } - $counter++; -} - -close SRC; -close OID_H; - -# Generate oid.c - -open(OID_C, ">oid.c") - or die "could not open 'oid.c': $!"; - -print OID_C "/* List of some useful object identifiers (OIDs)\n", - " * ", $copyright, "\n", - " * \n", - " * ", $automatic, "\n", - " * ", $warning, "\n", - " */\n", - "\n", - "#include \n", - "\n", - "#include \"oid.h\"\n", - "\n", - "const oid_t oid_names[] = {\n"; - -for ($c = 0; $c < $counter; $c++) -{ - $next = 0; - - for ($d = $c+1; $d < $counter && @order[$d] >= @order[$c]; $d++) - { - if (@order[$d] == @order[$c]) - { - @next[$c] = $d; - last; - } - } - - printf OID_C " {%s%s,%s%3d, %d, %s%s}%s /* %3d */\n" - ,' ' x @order[$c] - , @octet[$c] - , ' ' x (1 + $max_order - @order[$c]) - , @next[$c] - , @order[$c+1] > @order[$c] - , @name[$c] - , ' ' x ($max_name - length(@name[$c])) - , $c != $counter-1 ? "," : " " - , $c; -} - -print OID_C "};\n" ; -close OID_C; diff --git a/Source/lib/asn1-pluto/oid.txt b/Source/lib/asn1-pluto/oid.txt deleted file mode 100644 index ad05a1270..000000000 --- a/Source/lib/asn1-pluto/oid.txt +++ /dev/null @@ -1,181 +0,0 @@ -0x02 "ITU-T Administration" - 0x82 "" - 0x06 "Germany ITU-T member" - 0x01 "Deutsche Telekom AG" - 0x0A "" - 0x07 "" - 0x14 "ND" -0x09 "data" - 0x92 "" - 0x26 "" - 0x89 "" - 0x93 "" - 0xF2 "" - 0x2C "" - 0x64 "pilot" - 0x01 "pilotAttributeType" - 0x01 "UID" - 0x19 "DC" -0x55 "X.500" - 0x04 "X.509" - 0x03 "CN" - 0x04 "S" - 0x05 "SN" - 0x06 "C" - 0x07 "L" - 0x08 "ST" - 0x0A "O" - 0x0B "OU" - 0x0C "T" - 0x0D "D" - 0x24 "userCertificate" - 0x29 "N" - 0x2A "G" - 0x2B "I" - 0x2D "ID" - 0x48 "role" OID_ROLE - 0x1D "id-ce" - 0x09 "subjectDirectoryAttrs" - 0x0E "subjectKeyIdentifier" OID_SUBJECT_KEY_ID - 0x0F "keyUsage" - 0x10 "privateKeyUsagePeriod" - 0x11 "subjectAltName" OID_SUBJECT_ALT_NAME - 0x12 "issuerAltName" - 0x13 "basicConstraints" OID_BASIC_CONSTRAINTS - 0x15 "reasonCode" OID_CRL_REASON_CODE - 0x1F "crlDistributionPoints" OID_CRL_DISTRIBUTION_POINTS - 0x20 "certificatePolicies" - 0x23 "authorityKeyIdentifier" OID_AUTHORITY_KEY_ID - 0x25 "extendedKeyUsage" OID_EXTENDED_KEY_USAGE - 0x37 "targetInformation" OID_TARGET_INFORMATION - 0x38 "noRevAvail" OID_NO_REV_AVAIL -0x2A "" - 0x86 "" - 0x48 "" - 0x86 "" - 0xF7 "" - 0x0D "RSADSI" - 0x01 "PKCS" - 0x01 "PKCS-1" - 0x01 "rsaEncryption" OID_RSA_ENCRYPTION - 0x02 "md2WithRSAEncryption" OID_MD2_WITH_RSA - 0x04 "md5WithRSAEncryption" OID_MD5_WITH_RSA - 0x05 "sha-1WithRSAEncryption" OID_SHA1_WITH_RSA - 0x0B "sha256WithRSAEncryption" OID_SHA256_WITH_RSA - 0x0C "sha384WithRSAEncryption" OID_SHA384_WITH_RSA - 0x0D "sha512WithRSAEncryption" OID_SHA512_WITH_RSA - 0x07 "PKCS-7" - 0x01 "data" OID_PKCS7_DATA - 0x02 "signedData" OID_PKCS7_SIGNED_DATA - 0x03 "envelopedData" OID_PKCS7_ENVELOPED_DATA - 0x04 "signedAndEnvelopedData" OID_PKCS7_SIGNED_ENVELOPED_DATA - 0x05 "digestedData" OID_PKCS7_DIGESTED_DATA - 0x06 "encryptedData" OID_PKCS7_ENCRYPTED_DATA - 0x09 "PKCS-9" - 0x01 "E" OID_PKCS9_EMAIL - 0x02 "unstructuredName" - 0x03 "contentType" OID_PKCS9_CONTENT_TYPE - 0x04 "messageDigest" OID_PKCS9_MESSAGE_DIGEST - 0x05 "signingTime" OID_PKCS9_SIGNING_TIME - 0x06 "counterSignature" - 0x07 "challengePassword" - 0x08 "unstructuredAddress" - 0x0E "extensionRequest" - 0x02 "digestAlgorithm" - 0x02 "md2" OID_MD2 - 0x05 "md5" OID_MD5 - 0x03 "encryptionAlgorithm" - 0x07 "3des-ede-cbc" OID_3DES_EDE_CBC -0x2B "" - 0x06 "dod" - 0x01 "internet" - 0x04 "private" - 0x01 "enterprise" - 0x82 "" - 0x37 "Microsoft" - 0x0A "" - 0x03 "" - 0x03 "msSGC" - 0x89 "" - 0x31 "" - 0x01 "" - 0x01 "" - 0x02 "" - 0x02 "" - 0x4B "TCGID" - 0x05 "security" - 0x05 "mechanisms" - 0x07 "id-pkix" - 0x01 "id-pe" - 0x01 "authorityInfoAccess" OID_AUTHORITY_INFO_ACCESS - 0x03 "id-kp" - 0x01 "serverAuth" - 0x02 "clientAuth" - 0x03 "codeSigning" - 0x04 "emailProtection" - 0x05 "ipsecEndSystem" - 0x06 "ipsecTunnel" - 0x07 "ipsecUser" - 0x08 "timeStamping" - 0x09 "ocspSigning" OID_OCSP_SIGNING - 0x08 "id-otherNames" - 0x05 "xmppAddr" OID_XMPP_ADDR - 0x0A "id-aca" - 0x01 "authenticationInfo" OID_AUTHENTICATION_INFO - 0x02 "accessIdentity" OID_ACCESS_IDENTITY - 0x03 "chargingIdentity" OID_CHARGING_IDENTITY - 0x04 "group" OID_GROUP - 0x30 "id-ad" - 0x01 "ocsp" OID_OCSP - 0x01 "basic" OID_BASIC - 0x02 "nonce" OID_NONCE - 0x03 "crl" OID_CRL - 0x04 "response" OID_RESPONSE - 0x05 "noCheck" OID_NO_CHECK - 0x06 "archiveCutoff" OID_ARCHIVE_CUTOFF - 0x07 "serviceLocator" OID_SERVICE_LOCATOR - 0x0E "oiw" - 0x03 "secsig" - 0x02 "algorithms" - 0x07 "des-cbc" OID_DES_CBC - 0x1A "sha-1" OID_SHA1 - 0x1D "sha-1WithRSASignature" OID_SHA1_WITH_RSA_OIW - 0x24 "TeleTrusT" - 0x03 "algorithm" - 0x03 "signatureAlgorithm" - 0x01 "rsaSignature" - 0x02 "rsaSigWithripemd160" - 0x03 "rsaSigWithripemd128" - 0x04 "rsaSigWithripemd256" -0x60 "" - 0x86 "" - 0x48 "" - 0x01 "organization" - 0x65 "gov" - 0x03 "csor" - 0x04 "nistalgorithm" - 0x02 "hashalgs" - 0x01 "id-SHA-256" - 0x02 "id-SHA-384" - 0x03 "id-SHA-512" - 0x86 "" - 0xf8 "" - 0x42 "netscape" - 0x01 "" - 0x01 "nsCertType" - 0x03 "nsRevocationUrl" OID_NS_REVOCATION_URL - 0x04 "nsCaRevocationUrl" OID_NS_CA_REVOCATION_URL - 0x08 "nsCaPolicyUrl" OID_NS_CA_POLICY_URL - 0x0d "nsComment" OID_NS_COMMENT - 0x04 "policy" - 0x01 "nsSGC" - 0x45 "verisign" - 0x01 "pki" - 0x09 "attributes" - 0x02 "messageType" OID_PKI_MESSAGE_TYPE - 0x03 "pkiStatus" OID_PKI_STATUS - 0x04 "failInfo" OID_PKI_FAIL_INFO - 0x05 "senderNonce" OID_PKI_SENDER_NONCE - 0x06 "recipientNonce" OID_PKI_RECIPIENT_NONCE - 0x07 "transID" OID_PKI_TRANS_ID - 0x08 "extensionReq" diff --git a/Source/lib/asn1-pluto/pem.c b/Source/lib/asn1-pluto/pem.c deleted file mode 100755 index 24c71c61f..000000000 --- a/Source/lib/asn1-pluto/pem.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (C) 2005 Jan Hutter, Martin Willi - * 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 . - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "pem.h" -#include "ttodata.h" - -#include -#include - - -/* - * check the presence of a pattern in a character string - */ -static bool present(const char* pattern, chunk_t* ch) -{ - u_int pattern_len = strlen(pattern); - - if (ch->len >= pattern_len && strncmp(ch->ptr, pattern, pattern_len) == 0) - { - ch->ptr += pattern_len; - ch->len -= pattern_len; - return TRUE; - } - return FALSE; -} - -/* - * compare string with chunk - */ -static bool match(const char *pattern, const chunk_t *ch) -{ - return ch->len == strlen(pattern) && strncmp(pattern, ch->ptr, ch->len) == 0; -} - -/* - * find a boundary of the form -----tag name----- - */ -static bool find_boundary(const char* tag, chunk_t *line) -{ - chunk_t name = CHUNK_INITIALIZER; - - if (!present("-----", line)) - return FALSE; - if (!present(tag, line)) - return FALSE; - if (*line->ptr != ' ') - return FALSE; - line->ptr++; line->len--; - - /* extract name */ - name.ptr = line->ptr; - while (line->len > 0) - { - if (present("-----", line)) - { - return TRUE; - } - line->ptr++; line->len--; name.len++; - } - return FALSE; -} - -/* - * eat whitespace - */ -static void eat_whitespace(chunk_t *src) -{ - while (src->len > 0 && (*src->ptr == ' ' || *src->ptr == '\t')) - { - src->ptr++; src->len--; - } -} - -/* - * extracts a token ending with a given termination symbol - */ -static bool extract_token(chunk_t *token, char termination, chunk_t *src) -{ - u_char *eot = memchr(src->ptr, termination, src->len); - - /* initialize empty token */ - *token = CHUNK_INITIALIZER; - - if (eot == NULL) /* termination symbol not found */ - { - return FALSE; - } - - /* extract token */ - token->ptr = src->ptr; - token->len = (u_int)(eot - src->ptr); - - /* advance src pointer after termination symbol */ - src->ptr = eot + 1; - src->len -= (token->len + 1); - - return TRUE; -} - -/* - * extracts a name: value pair from the PEM header - */ -static bool extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line) -{ - /* extract name */ - if (!extract_token(name,':', line)) - { - return FALSE; - } - - eat_whitespace(line); - - /* extract value */ - *value = *line; - return TRUE; -} - -/* - * fetches a new line terminated by \n or \r\n - */ -static bool fetchline(chunk_t *src, chunk_t *line) -{ - if (src->len == 0) /* end of src reached */ - return FALSE; - - if (extract_token(line, '\n', src)) - { - if (line->len > 0 && *(line->ptr + line->len -1) == '\r') - line->len--; /* remove optional \r */ - } - else /*last line ends without newline */ - { - *line = *src; - src->ptr += src->len; - src->len = 0; - } - return TRUE; -} - -/* - * decrypts a DES-EDE-CBC encrypted data block - */ -static status_t pem_decrypt(chunk_t *blob, chunk_t *iv, char *passphrase) -{ - hasher_t *hasher; - crypter_t *crypter; - chunk_t hash; - chunk_t decrypted; - chunk_t pass = {passphrase, strlen(passphrase)}; - chunk_t key = {alloca(24), 24}; - u_int8_t padding, *last_padding_pos, *first_padding_pos; - - /* build key from passphrase and IV */ - hasher = hasher_create(HASH_MD5); - hash.len = hasher->get_block_size(hasher); - hash.ptr = alloca(hash.len); - hasher->get_hash(hasher, pass, NULL); - hasher->get_hash(hasher, *iv, hash.ptr); - - memcpy(key.ptr, hash.ptr, hash.len); - - hasher->get_hash(hasher, hash, NULL); - hasher->get_hash(hasher, pass, NULL); - hasher->get_hash(hasher, *iv, hash.ptr); - - memcpy(key.ptr + hash.len, hash.ptr, key.len - hash.len); - - hasher->destroy(hasher); - - /* decrypt blob */ - crypter = crypter_create(ENCR_3DES, 0); - crypter->set_key(crypter, key); - crypter->decrypt(crypter, *blob, *iv, &decrypted); - memcpy(blob->ptr, decrypted.ptr, blob->len); - chunk_free(&decrypted); - - /* determine amount of padding */ - last_padding_pos = blob->ptr + blob->len - 1; - padding = *last_padding_pos; - first_padding_pos = (padding > blob->len) ? blob->ptr : last_padding_pos - padding; - - /* check the padding pattern */ - while (--last_padding_pos > first_padding_pos) - { - if (*last_padding_pos != padding) - return FALSE; - } - /* remove padding */ - blob->len -= padding; - return TRUE; -} - -/* Converts a PEM encoded file into its binary form - * - * RFC 1421 Privacy Enhancement for Electronic Mail, February 1993 - * RFC 934 Message Encapsulation, January 1985 - */ -status_t pemtobin(chunk_t *blob, char *pass) -{ - typedef enum { - PEM_PRE = 0, - PEM_MSG = 1, - PEM_HEADER = 2, - PEM_BODY = 3, - PEM_POST = 4, - PEM_ABORT = 5 - } state_t; - - bool encrypted = FALSE; - - state_t state = PEM_PRE; - - chunk_t src = *blob; - chunk_t dst = *blob; - chunk_t line = CHUNK_INITIALIZER; - chunk_t iv = CHUNK_INITIALIZER; - - u_char iv_buf[16]; /* MD5 digest size */ - - /* zero size of converted blob */ - dst.len = 0; - - /* zero size of IV */ - iv.ptr = iv_buf; - iv.len = 0; - - while (fetchline(&src, &line)) - { - if (state == PEM_PRE) - { - if (find_boundary("BEGIN", &line)) - { - state = PEM_MSG; - } - continue; - } - else - { - if (find_boundary("END", &line)) - { - state = PEM_POST; - break; - } - if (state == PEM_MSG) - { - state = (memchr(line.ptr, ':', line.len) == NULL) ? PEM_BODY : PEM_HEADER; - } - if (state == PEM_HEADER) - { - chunk_t name = CHUNK_INITIALIZER; - chunk_t value = CHUNK_INITIALIZER; - - /* an empty line separates HEADER and BODY */ - if (line.len == 0) - { - state = PEM_BODY; - continue; - } - - /* we are looking for a name: value pair */ - if (!extract_parameter(&name, &value, &line)) - continue; - - if (match("Proc-Type", &name) && *value.ptr == '4') - encrypted = TRUE; - else if (match("DEK-Info", &name)) - { - const char *ugh = NULL; - size_t len = 0; - chunk_t dek; - - if (!extract_token(&dek, ',', &value)) - dek = value; - - /* we support DES-EDE3-CBC encrypted files, only */ - if (!match("DES-EDE3-CBC", &dek)) - return NOT_SUPPORTED; - - eat_whitespace(&value); - ugh = ttodata(value.ptr, value.len, 16, iv.ptr, 16, &len); - if (ugh) - return PARSE_ERROR; - - iv.len = len; - } - } - else /* state is PEM_BODY */ - { - const char *ugh = NULL; - size_t len = 0; - chunk_t data; - - /* remove any trailing whitespace */ - if (!extract_token(&data ,' ', &line)) - { - data = line; - } - - ugh = ttodata(data.ptr, data.len, 64, dst.ptr, blob->len - dst.len, &len); - if (ugh) - { - state = PEM_ABORT; - break; - } - else - { - dst.ptr += len; - dst.len += len; - } - } - } - } - /* set length to size of binary blob */ - blob->len = dst.len; - - if (state != PEM_POST) - return PARSE_ERROR; - - if (encrypted) - return pem_decrypt(blob, &iv, pass); - else - return SUCCESS; -} diff --git a/Source/lib/asn1-pluto/pem.h b/Source/lib/asn1-pluto/pem.h deleted file mode 100755 index a4332fd34..000000000 --- a/Source/lib/asn1-pluto/pem.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2006 Martin Willi - * 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 . - * - * 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. - */ - -#ifndef PEM_H_ -#define PEM_H_ - -#include - -#include - -status_t pemtobin(chunk_t *blob, char *pass); - -#endif /*PEM_H_*/ diff --git a/Source/lib/asn1-pluto/ttodata.c b/Source/lib/asn1-pluto/ttodata.c deleted file mode 100644 index 5e8149955..000000000 --- a/Source/lib/asn1-pluto/ttodata.c +++ /dev/null @@ -1,374 +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 . - * - * 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 -#include - -/* 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)) - -/* - - ttodatav - 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. - */ -const char * /* NULL on success, else literal or errp */ -ttodatav(src, srclen, base, dst, dstlen, lenp, errp, errlen, flags) -const char *src; -size_t srclen; /* 0 means apply strlen() */ -int base; /* 0 means figure it out */ -char *dst; /* need not be valid if dstlen is 0 */ -size_t dstlen; -size_t *lenp; /* where to record length (NULL is nowhere) */ -char *errp; /* error buffer */ -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 == '_') { - /* 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; -} - -/* - - ttodata - convert text to data - */ -const char * /* NULL on success, else literal */ -ttodata(src, srclen, base, dst, dstlen, lenp) -const char *src; -size_t srclen; /* 0 means apply strlen() */ -int base; /* 0 means figure it out */ -char *dst; /* need not be valid if dstlen is 0 */ -size_t dstlen; -size_t *lenp; /* where to record length (NULL is nowhere) */ -{ - return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL, - (size_t)0, TTODATAV_SPACECOUNTS); -} - -/* - - atodata - convert ASCII to data - * backward-compatibility interface - */ -size_t /* 0 for failure, true length for success */ -atodata(src, srclen, dst, dstlen) -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); - if (err != NULL) - return 0; - return len; -} - -/* - - atobytes - convert ASCII to data bytes - * another backward-compatibility interface - */ -const char * -atobytes(src, srclen, dst, dstlen, lenp) -const char *src; -size_t srclen; -char *dst; -size_t dstlen; -size_t *lenp; -{ - return ttodata(src, srclen, 0, dst, dstlen, lenp); -} - -/* - - unhex - convert two ASCII hex digits to byte - */ -static int /* number of result bytes, or error code */ -unhex(src, dst, dstlen) -const char *src; /* known to be full length */ -char *dst; -size_t dstlen; /* not large enough is a failure */ -{ - 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; -} - -/* - - 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. - */ -static int /* number of result bytes, or error code */ -unb64(src, dst, dstlen) -const char *src; /* known to be full length */ -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; -} - -/* - - untext - convert one ASCII character to byte - */ -static int /* number of result bytes, or error code */ -untext(src, dst, dstlen) -const char *src; /* known to be full length */ -char *dst; -size_t dstlen; /* not large enough is a failure */ -{ - if (dstlen < 1) - return SHORT; - - *dst = *src; - return 1; -} - -/* - - 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. - */ -static const char * /* literal or errp */ -badch(src, errcode, errp, errlen) -const char *src; -int errcode; -char *errp; /* might be NULL */ -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/Source/lib/asn1-pluto/ttodata.h b/Source/lib/asn1-pluto/ttodata.h deleted file mode 100644 index d57244ef5..000000000 --- a/Source/lib/asn1-pluto/ttodata.h +++ /dev/null @@ -1,30 +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 . - * - * 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 - -#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 */ - -typedef const char *err_t; /* error message, or NULL for success */ - -err_t ttodata(const char *src, size_t srclen, int base, char *buf, size_t buflen, size_t *needed); - - -#endif /* TTODATA_H_ */ diff --git a/Source/lib/asn1/Makefile.asn1 b/Source/lib/asn1/Makefile.asn1 new file mode 100644 index 000000000..44726ffa4 --- /dev/null +++ b/Source/lib/asn1/Makefile.asn1 @@ -0,0 +1,29 @@ +# Copyright (C) 2006 Martin Willi +# 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 . +# +# 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. +# + +ASN1_DIR= $(LIB_DIR)asn1-pluto/ + + +LIB_OBJS+= $(BUILD_DIR)oid.o +$(BUILD_DIR)oid.o : $(ASN1_DIR)oid.c $(ASN1_DIR)oid.h + $(CC) $(CFLAGS) -c -o $@ $< +LIB_OBJS+= $(BUILD_DIR)asn1-pluto.o +$(BUILD_DIR)asn1-pluto.o : $(ASN1_DIR)asn1-pluto.c $(ASN1_DIR)asn1-pluto.h + $(CC) $(CFLAGS) -c -o $@ $< +LIB_OBJS+= $(BUILD_DIR)pem.o +$(BUILD_DIR)pem.o : $(ASN1_DIR)pem.c $(ASN1_DIR)pem.h + $(CC) $(CFLAGS) -c -o $@ $< +LIB_OBJS+= $(BUILD_DIR)ttodata.o +$(BUILD_DIR)ttodata.o : $(ASN1_DIR)ttodata.c $(ASN1_DIR)ttodata.h + $(CC) $(CFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/Source/lib/asn1/asn1-pluto.c b/Source/lib/asn1/asn1-pluto.c new file mode 100644 index 000000000..01deb5c14 --- /dev/null +++ b/Source/lib/asn1/asn1-pluto.c @@ -0,0 +1,739 @@ +/* Simple ASN.1 parser + * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur + * Copyright (C) 2006 Martin Will, 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 . + * + * 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. + */ + +#include +#include +#include + +#include "asn1-pluto.h" +#include "oid.h" + +#include + +static logger_t *logger; + +/* Names of the months */ +static const char* months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +/* 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 }; + +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 */ + +static u_char ASN1_md5_id_str[] = { + 0x30, 0x0C, + 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, + 0x05, 0x00 +}; + +static u_char ASN1_sha1_id_str[] = { + 0x30, 0x09, + 0x06, 0x05, 0x2B, 0x0E,0x03, 0x02, 0x1A, + 0x05, 0x00 +}; + +static u_char ASN1_md5WithRSA_id_str[] = { + 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, + 0x05, 0x00 +}; + +static u_char ASN1_sha1WithRSA_id_str[] = { + 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, + 0x05, 0x00 +}; + +static u_char ASN1_rsaEncryption_id_str[] = { + 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00 +}; + +const chunk_t ASN1_md5_id = chunk_from_buf(ASN1_md5_id_str); +const chunk_t ASN1_sha1_id = chunk_from_buf(ASN1_sha1_id_str); +const chunk_t ASN1_rsaEncryption_id = chunk_from_buf(ASN1_rsaEncryption_id_str); +const chunk_t ASN1_md5WithRSA_id = chunk_from_buf(ASN1_md5WithRSA_id_str); +const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_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 + */ +chunk_t asn1_algorithmIdentifier(int oid) +{ + switch (oid) + { + case OID_RSA_ENCRYPTION: + return ASN1_rsaEncryption_id; + case OID_MD5_WITH_RSA: + return ASN1_md5WithRSA_id; + case OID_SHA1_WITH_RSA: + return ASN1_sha1WithRSA_id; + case OID_MD5: + return ASN1_md5_id; + case OID_SHA1: + return ASN1_sha1_id; + default: + return CHUNK_INITIALIZER; + } +} + +/* + * 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 + */ +int known_oid(chunk_t object) +{ + int oid = 0; + + while (object.len) + { + if (oid_names[oid].octet == *object.ptr) + { + if (--object.len == 0 || oid_names[oid].down == 0) + { + return oid; /* found terminal symbol */ + } + else + { + object.ptr++; oid++; /* advance to next hex octet */ + } + } + else + { + if (oid_names[oid].next) + oid = oid_names[oid].next; + else + return OID_UNKNOWN; + } + } + return -1; +} + +/* + * Decodes the length in bytes of an ASN.1 object + */ +u_int asn1_length(chunk_t *blob) +{ + u_char n; + size_t len; + + /* advance from tag field on to length field */ + blob->ptr++; + blob->len--; + + /* read first octet of length field */ + n = *blob->ptr++; + blob->len--; + + if ((n & 0x80) == 0) + {/* single length octet */ + return n; + } + + /* composite length, determine number of length octets */ + n &= 0x7f; + + if (n > blob->len) + { + logger->log(logger, ERROR|LEVEL1, "number of length octets is larger than ASN.1 object"); + return ASN1_INVALID_LENGTH; + } + + if (n > sizeof(len)) + { + logger->log(logger, ERROR|LEVEL1, "number of length octets is larger than limit of %d octets", + (int)sizeof(len)); + return ASN1_INVALID_LENGTH; + } + + len = 0; + + while (n-- > 0) + { + len = 256*len + *blob->ptr++; + blob->len--; + } + return len; +} + +/* + * 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; +} + +/* + * Display a date either in local or UTC time + * TODO: Does not seem to be thread save + */ +char* timetoa(const time_t *time, bool utc) +{ + static char buf[30]; + + if (*time == 0) + sprintf(buf, "--- -- --:--:--%s----", (utc)?" UTC ":" "); + else + { + struct tm *t = (utc)? gmtime(time) : localtime(time); + sprintf(buf, "%s %02d %02d:%02d:%02d%s%04d", + months[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, + (utc)?" UTC ":" ", t->tm_year + 1900); + } + return buf; +} + +/* + * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time + */ +time_t asn1totime(const chunk_t *utctime, asn1_t type) +{ + struct tm t; + time_t tz_offset; + u_char *eot = NULL; + + if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL) + { + tz_offset = 0; /* Zulu time with a zero time zone offset */ + } + else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL) + { + int tz_hour, tz_min; + + sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); + tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */ + } + else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL) + { + int tz_hour, tz_min; + + sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min); + tz_offset = -3600*tz_hour - 60*tz_min; /* negative time zone offset */ + } + else + { + return 0; /* error in time format */ + } + + { + const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d": + "%4d%2d%2d%2d%2d"; + + sscanf(utctime->ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday, + &t.tm_hour, &t.tm_min); + } + + /* is there a seconds field? */ + if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14)) + { + sscanf(eot-2, "%2d", &t.tm_sec); + } + else + { + t.tm_sec = 0; + } + + /* representation of year */ + if (t.tm_year >= 1900) + { + t.tm_year -= 1900; + } + else if (t.tm_year >= 100) + { + return 0; + } + else if (t.tm_year < 50) + { + t.tm_year += 100; + } + + /* representation of month 0..11*/ + t.tm_mon--; + + /* set daylight saving time to off */ + t.tm_isdst = 0; + + /* compensate timezone */ + + return mktime(&t) - timezone - tz_offset; +} + +/* + * Initializes the internal context of the ASN.1 parser + */ +void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, bool implicit) +{ + logger = logger_manager->get_logger(logger_manager, ASN1); + ctx->blobs[0] = blob; + ctx->level0 = level0; + ctx->implicit = implicit; + memset(ctx->loopAddr, '\0', sizeof(ctx->loopAddr)); +} + +/* + * print the value of an ASN.1 simple object + */ +static void debug_asn1_simple_object(chunk_t object, asn1_t type) +{ + int oid; + time_t time; + + switch (type) + { + case ASN1_OID: + oid = known_oid(object); + if (oid != OID_UNKNOWN) + { + logger->log(logger, CONTROL|LEVEL1, " '%s'", oid_names[oid].name); + return; + } + break; + case ASN1_UTF8STRING: + case ASN1_IA5STRING: + case ASN1_PRINTABLESTRING: + case ASN1_T61STRING: + case ASN1_VISIBLESTRING: + logger->log(logger, CONTROL|LEVEL1, " '%.*s'", (int)object.len, object.ptr); + return; + case ASN1_UTCTIME: + case ASN1_GENERALIZEDTIME: + time = asn1totime(&object, type); + logger->log(logger, CONTROL|LEVEL1, " '%s'", timetoa(&time, TRUE)); + return; + default: + break; + } + logger->log_chunk(logger, RAW|LEVEL1, "", object); +} + +/* + * 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_INITIALIZER; + + 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 */ + logger->log(logger, CONTROL|LEVEL1, "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) + { + logger->log(logger, ERROR|LEVEL1, "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) + { + logger->log(logger, ERROR|LEVEL1, "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) + { + logger->log(logger, CONTROL|LEVEL1, "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)) + { + logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x", + *level, obj.name, obj.type, *start_ptr); + logger->log_bytes(logger, RAW|LEVEL1, "", start_ptr, (u_int)(blob->ptr - start_ptr)); + return FALSE; + } + + logger->log(logger, CONTROL|LEVEL1, "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); + logger->log_chunk(logger, RAW|LEVEL1, "", *object); + } + else if (obj.flags & ASN1_BODY) + { + *object = *blob1; + debug_asn1_simple_object(*object, obj.type); + } + 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) +{ + size_t len; + + /* an ASN.1 object must possess at least a tag and length field */ + if (object->len < 2) + { + logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN.1 object smaller than 2 octets", + level, name); + return FALSE; + } + + if (*object->ptr != type) + { + logger->log(logger, ERROR|LEVEL1, "L%d - %s: ASN1 tag 0x%02x expected, but is 0x%02x", + level, name, type, *object->ptr); + return FALSE; + } + + len = asn1_length(object); + + if (len == ASN1_INVALID_LENGTH || object->len < len) + { + logger->log(logger, ERROR|LEVEL1, "L%d - %s: length of ASN.1 object invalid or too large", + level, name); + return FALSE; + } + + logger->log(logger, CONTROL|LEVEL1, "L%d - %s:", level, name); + debug_asn1_simple_object(*object, type); + return TRUE; +} + +/* + * extracts an algorithmIdentifier + */ +int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters) +{ + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int alg = OID_UNKNOWN; + int objectID = 0; + + asn1_init(&ctx, blob, level0, FALSE); + + while (objectID < ALGORITHM_ID_ROOF) + { + if (!extract_object(algorithmIdentifierObjects, &objectID, &object, &level, &ctx)) + return OID_UNKNOWN; + + switch (objectID) + { + case ALGORITHM_ID_ALG: + alg = known_oid(object); + break; + case ALGORITHM_ID_PARAMETERS: + if (parameters != NULL) + *parameters = object; + break; + default: + break; + } + objectID++; + } + return alg; + } + +/* + * tests if a blob contains a valid ASN.1 set or sequence + */ +bool is_asn1(chunk_t blob) +{ + u_int len; + u_char tag = *blob.ptr; + + if (tag != ASN1_SEQUENCE && tag != ASN1_SET) + { + logger->log(logger, ERROR|LEVEL2, " file content is not binary ASN.1"); + return FALSE; + } + len = asn1_length(&blob); + if (len != blob.len) + { + logger->log(logger, ERROR|LEVEL2, " file size does not match ASN.1 coded length"); + 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) +{ + if (length < 128) + { + code->ptr[0] = length; + code->len = 1; + } + else if (length < 256) + { + code->ptr[0] = 0x81; + code->ptr[1] = (u_char) length; + code->len = 2; + } + else if (length < 65536) + { + code->ptr[0] = 0x82; + code->ptr[1] = length >> 8; + code->ptr[2] = length & 0x00ff; + code->len = 3; + } + else + { + code->ptr[0] = 0x83; + code->ptr[1] = length >> 16; + code->ptr[2] = (length >> 8) & 0x00ff; + code->ptr[3] = length & 0x0000ff; + code->len = 4; + } +} + +/* + * 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 length_buf[4]; + chunk_t length = { length_buf, 0 }; + u_char *pos; + + /* code the asn.1 length field */ + code_asn1_length(datalen, &length); + + /* allocate memory for the asn.1 TLV object */ + object->len = 1 + length.len + datalen; + object->ptr = malloc(object->len); + + /* set position pointer at the start of the object */ + pos = object->ptr; + + /* copy the asn.1 tag field and advance the pointer */ + *pos++ = type; + + /* copy the asn.1 length field and advance the pointer */ + memcpy(pos, length.ptr, length.len); + pos += length.len; + + return pos; +} + +/* + * 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); + memcpy(pos, content.ptr, content.len); + pos += content.len; + + return object; +} + +/* Build an ASN.1 object from a variable number of individual chunks. + * Depending on the mode, chunks either are moved ('m') or copied ('c'). + */ +chunk_t asn1_wrap(asn1_t type, const char *mode, ...) +{ + chunk_t construct; + va_list chunks; + u_char *pos; + int i; + int count = strlen(mode); + + /* sum up lengths of individual chunks */ + va_start(chunks, mode); + construct.len = 0; + for (i = 0; i < count; i++) + { + chunk_t ch = va_arg(chunks, chunk_t); + construct.len += ch.len; + } + va_end(chunks); + + /* allocate needed memory for construct */ + pos = build_asn1_object(&construct, type, construct.len); + + /* copy or move the chunks */ + va_start(chunks, mode); + for (i = 0; i < count; i++) + { + chunk_t ch = va_arg(chunks, chunk_t); + + switch (*mode++) + { + case 'm': + memcpy(pos, ch.ptr, ch.len); + pos += ch.len; + free(ch.ptr); + break; + case 'c': + default: + memcpy(pos, ch.ptr, ch.len); + pos += ch.len; + } + } + va_end(chunks); + + return construct; +} + +/* + * 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); +} + +/* + * convert a date into ASN.1 UTCTIME or GENERALIZEDTIME format + */ +chunk_t timetoasn1(const time_t *time, asn1_t type) +{ + int offset; + const char *format; + char buf[TIMETOA_BUF]; + chunk_t formatted_time; + struct tm *t = gmtime(time); + + if (type == ASN1_GENERALIZEDTIME) + { + format = "%04d%02d%02d%02d%02d%02dZ"; + offset = 1900; + } + else /* ASN1_UTCTIME */ + { + format = "%02d%02d%02d%02d%02d%02dZ"; + offset = (t->tm_year < 100)? 0 : -100; + } + sprintf(buf, format, t->tm_year + offset, t->tm_mon + 1, t->tm_mday + , t->tm_hour, t->tm_min, t->tm_sec); + formatted_time.ptr = buf; + formatted_time.len = strlen(buf); + return asn1_simple_object(type, formatted_time); +} diff --git a/Source/lib/asn1/asn1-pluto.h b/Source/lib/asn1/asn1-pluto.h new file mode 100644 index 000000000..3edaa3254 --- /dev/null +++ b/Source/lib/asn1/asn1-pluto.h @@ -0,0 +1,137 @@ +/* Simple ASN.1 parser + * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur + * Copyright (C) 2006 Martin Will, 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 . + * + * 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. + */ + +#ifndef _ASN1_H +#define _ASN1_H + +#include +#include + +#include + + +/* Defines some primitive ASN1 types */ + +typedef enum { + ASN1_EOC = 0x00, + ASN1_BOOLEAN = 0x01, + ASN1_INTEGER = 0x02, + ASN1_BIT_STRING = 0x03, + ASN1_OCTET_STRING = 0x04, + ASN1_NULL = 0x05, + ASN1_OID = 0x06, + ASN1_ENUMERATED = 0x0A, + ASN1_UTF8STRING = 0x0C, + ASN1_NUMERICSTRING = 0x12, + ASN1_PRINTABLESTRING = 0x13, + ASN1_T61STRING = 0x14, + ASN1_VIDEOTEXSTRING = 0x15, + ASN1_IA5STRING = 0x16, + ASN1_UTCTIME = 0x17, + ASN1_GENERALIZEDTIME = 0x18, + ASN1_GRAPHICSTRING = 0x19, + ASN1_VISIBLESTRING = 0x1A, + ASN1_GENERALSTRING = 0x1B, + ASN1_UNIVERSALSTRING = 0x1C, + ASN1_BMPSTRING = 0x1E, + + ASN1_CONSTRUCTED = 0x20, + + ASN1_SEQUENCE = 0x30, + + ASN1_SET = 0x31, + + ASN1_CONTEXT_S_0 = 0x80, + ASN1_CONTEXT_S_1 = 0x81, + ASN1_CONTEXT_S_2 = 0x82, + ASN1_CONTEXT_S_3 = 0x83, + ASN1_CONTEXT_S_4 = 0x84, + ASN1_CONTEXT_S_5 = 0x85, + ASN1_CONTEXT_S_6 = 0x86, + ASN1_CONTEXT_S_7 = 0x87, + ASN1_CONTEXT_S_8 = 0x88, + + ASN1_CONTEXT_C_0 = 0xA0, + ASN1_CONTEXT_C_1 = 0xA1, + ASN1_CONTEXT_C_2 = 0xA2, + ASN1_CONTEXT_C_3 = 0xA3, + ASN1_CONTEXT_C_4 = 0xA4, + ASN1_CONTEXT_C_5 = 0xA5 +} asn1_t; + +/* Definition of ASN1 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_INVALID_LENGTH 0xffffffff + +/* definition of an ASN.1 object */ + +typedef struct { + u_int level; + const u_char *name; + asn1_t type; + u_char flags; +} asn1Object_t; + +#define ASN1_MAX_LEVEL 10 + +typedef struct { + bool implicit; + u_int level0; + u_int loopAddr[ASN1_MAX_LEVEL+1]; + chunk_t blobs[ASN1_MAX_LEVEL+2]; +} asn1_ctx_t; + +/* 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; + +/* some popular algorithmIdentifiers */ +extern const chunk_t ASN1_md5_id; +extern const chunk_t ASN1_sha1_id; +extern const chunk_t ASN1_rsaEncryption_id; +extern const chunk_t ASN1_md5WithRSA_id; +extern const chunk_t ASN1_sha1WithRSA_id; + +#define TIMETOA_BUF 30 + +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 void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, bool implicit); +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 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_wrap(asn1_t type, const char *mode, ...); +extern chunk_t timetoasn1(const time_t *time, asn1_t type); + +#endif /* _ASN1_H */ diff --git a/Source/lib/asn1/oid.c b/Source/lib/asn1/oid.c new file mode 100644 index 000000000..7b0135d5e --- /dev/null +++ b/Source/lib/asn1/oid.c @@ -0,0 +1,194 @@ +/* List of some useful object identifiers (OIDs) + * Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur + * + * This file has been automatically generated by the script oid.pl + * Do not edit manually! + */ + +#include + +#include "oid.h" + +const oid_t oid_names[] = { + {0x02, 7, 1, "ITU-T Administration" }, /* 0 */ + { 0x82, 0, 1, "" }, /* 1 */ + { 0x06, 0, 1, "Germany ITU-T member" }, /* 2 */ + { 0x01, 0, 1, "Deutsche Telekom AG" }, /* 3 */ + { 0x0A, 0, 1, "" }, /* 4 */ + { 0x07, 0, 1, "" }, /* 5 */ + { 0x14, 0, 0, "ND" }, /* 6 */ + {0x09, 18, 1, "data" }, /* 7 */ + { 0x92, 0, 1, "" }, /* 8 */ + { 0x26, 0, 1, "" }, /* 9 */ + { 0x89, 0, 1, "" }, /* 10 */ + { 0x93, 0, 1, "" }, /* 11 */ + { 0xF2, 0, 1, "" }, /* 12 */ + { 0x2C, 0, 1, "" }, /* 13 */ + { 0x64, 0, 1, "pilot" }, /* 14 */ + { 0x01, 0, 1, "pilotAttributeType" }, /* 15 */ + { 0x01, 17, 0, "UID" }, /* 16 */ + { 0x19, 0, 0, "DC" }, /* 17 */ + {0x55, 51, 1, "X.500" }, /* 18 */ + { 0x04, 36, 1, "X.509" }, /* 19 */ + { 0x03, 21, 0, "CN" }, /* 20 */ + { 0x04, 22, 0, "S" }, /* 21 */ + { 0x05, 23, 0, "SN" }, /* 22 */ + { 0x06, 24, 0, "C" }, /* 23 */ + { 0x07, 25, 0, "L" }, /* 24 */ + { 0x08, 26, 0, "ST" }, /* 25 */ + { 0x0A, 27, 0, "O" }, /* 26 */ + { 0x0B, 28, 0, "OU" }, /* 27 */ + { 0x0C, 29, 0, "T" }, /* 28 */ + { 0x0D, 30, 0, "D" }, /* 29 */ + { 0x24, 31, 0, "userCertificate" }, /* 30 */ + { 0x29, 32, 0, "N" }, /* 31 */ + { 0x2A, 33, 0, "G" }, /* 32 */ + { 0x2B, 34, 0, "I" }, /* 33 */ + { 0x2D, 35, 0, "ID" }, /* 34 */ + { 0x48, 0, 0, "role" }, /* 35 */ + { 0x1D, 0, 1, "id-ce" }, /* 36 */ + { 0x09, 38, 0, "subjectDirectoryAttrs" }, /* 37 */ + { 0x0E, 39, 0, "subjectKeyIdentifier" }, /* 38 */ + { 0x0F, 40, 0, "keyUsage" }, /* 39 */ + { 0x10, 41, 0, "privateKeyUsagePeriod" }, /* 40 */ + { 0x11, 42, 0, "subjectAltName" }, /* 41 */ + { 0x12, 43, 0, "issuerAltName" }, /* 42 */ + { 0x13, 44, 0, "basicConstraints" }, /* 43 */ + { 0x15, 45, 0, "reasonCode" }, /* 44 */ + { 0x1F, 46, 0, "crlDistributionPoints" }, /* 45 */ + { 0x20, 47, 0, "certificatePolicies" }, /* 46 */ + { 0x23, 48, 0, "authorityKeyIdentifier" }, /* 47 */ + { 0x25, 49, 0, "extendedKeyUsage" }, /* 48 */ + { 0x37, 50, 0, "targetInformation" }, /* 49 */ + { 0x38, 0, 0, "noRevAvail" }, /* 50 */ + {0x2A, 88, 1, "" }, /* 51 */ + { 0x86, 0, 1, "" }, /* 52 */ + { 0x48, 0, 1, "" }, /* 53 */ + { 0x86, 0, 1, "" }, /* 54 */ + { 0xF7, 0, 1, "" }, /* 55 */ + { 0x0D, 0, 1, "RSADSI" }, /* 56 */ + { 0x01, 83, 1, "PKCS" }, /* 57 */ + { 0x01, 66, 1, "PKCS-1" }, /* 58 */ + { 0x01, 60, 0, "rsaEncryption" }, /* 59 */ + { 0x02, 61, 0, "md2WithRSAEncryption" }, /* 60 */ + { 0x04, 62, 0, "md5WithRSAEncryption" }, /* 61 */ + { 0x05, 63, 0, "sha-1WithRSAEncryption" }, /* 62 */ + { 0x0B, 64, 0, "sha256WithRSAEncryption"}, /* 63 */ + { 0x0C, 65, 0, "sha384WithRSAEncryption"}, /* 64 */ + { 0x0D, 0, 0, "sha512WithRSAEncryption"}, /* 65 */ + { 0x07, 73, 1, "PKCS-7" }, /* 66 */ + { 0x01, 68, 0, "data" }, /* 67 */ + { 0x02, 69, 0, "signedData" }, /* 68 */ + { 0x03, 70, 0, "envelopedData" }, /* 69 */ + { 0x04, 71, 0, "signedAndEnvelopedData" }, /* 70 */ + { 0x05, 72, 0, "digestedData" }, /* 71 */ + { 0x06, 0, 0, "encryptedData" }, /* 72 */ + { 0x09, 0, 1, "PKCS-9" }, /* 73 */ + { 0x01, 75, 0, "E" }, /* 74 */ + { 0x02, 76, 0, "unstructuredName" }, /* 75 */ + { 0x03, 77, 0, "contentType" }, /* 76 */ + { 0x04, 78, 0, "messageDigest" }, /* 77 */ + { 0x05, 79, 0, "signingTime" }, /* 78 */ + { 0x06, 80, 0, "counterSignature" }, /* 79 */ + { 0x07, 81, 0, "challengePassword" }, /* 80 */ + { 0x08, 82, 0, "unstructuredAddress" }, /* 81 */ + { 0x0E, 0, 0, "extensionRequest" }, /* 82 */ + { 0x02, 86, 1, "digestAlgorithm" }, /* 83 */ + { 0x02, 85, 0, "md2" }, /* 84 */ + { 0x05, 0, 0, "md5" }, /* 85 */ + { 0x03, 0, 1, "encryptionAlgorithm" }, /* 86 */ + { 0x07, 0, 0, "3des-ede-cbc" }, /* 87 */ + {0x2B, 149, 1, "" }, /* 88 */ + { 0x06, 136, 1, "dod" }, /* 89 */ + { 0x01, 0, 1, "internet" }, /* 90 */ + { 0x04, 105, 1, "private" }, /* 91 */ + { 0x01, 0, 1, "enterprise" }, /* 92 */ + { 0x82, 98, 1, "" }, /* 93 */ + { 0x37, 0, 1, "Microsoft" }, /* 94 */ + { 0x0A, 0, 1, "" }, /* 95 */ + { 0x03, 0, 1, "" }, /* 96 */ + { 0x03, 0, 0, "msSGC" }, /* 97 */ + { 0x89, 0, 1, "" }, /* 98 */ + { 0x31, 0, 1, "" }, /* 99 */ + { 0x01, 0, 1, "" }, /* 100 */ + { 0x01, 0, 1, "" }, /* 101 */ + { 0x02, 0, 1, "" }, /* 102 */ + { 0x02, 104, 0, "" }, /* 103 */ + { 0x4B, 0, 0, "TCGID" }, /* 104 */ + { 0x05, 0, 1, "security" }, /* 105 */ + { 0x05, 0, 1, "mechanisms" }, /* 106 */ + { 0x07, 0, 1, "id-pkix" }, /* 107 */ + { 0x01, 110, 1, "id-pe" }, /* 108 */ + { 0x01, 0, 0, "authorityInfoAccess" }, /* 109 */ + { 0x03, 120, 1, "id-kp" }, /* 110 */ + { 0x01, 112, 0, "serverAuth" }, /* 111 */ + { 0x02, 113, 0, "clientAuth" }, /* 112 */ + { 0x03, 114, 0, "codeSigning" }, /* 113 */ + { 0x04, 115, 0, "emailProtection" }, /* 114 */ + { 0x05, 116, 0, "ipsecEndSystem" }, /* 115 */ + { 0x06, 117, 0, "ipsecTunnel" }, /* 116 */ + { 0x07, 118, 0, "ipsecUser" }, /* 117 */ + { 0x08, 119, 0, "timeStamping" }, /* 118 */ + { 0x09, 0, 0, "ocspSigning" }, /* 119 */ + { 0x08, 122, 1, "id-otherNames" }, /* 120 */ + { 0x05, 0, 0, "xmppAddr" }, /* 121 */ + { 0x0A, 127, 1, "id-aca" }, /* 122 */ + { 0x01, 124, 0, "authenticationInfo" }, /* 123 */ + { 0x02, 125, 0, "accessIdentity" }, /* 124 */ + { 0x03, 126, 0, "chargingIdentity" }, /* 125 */ + { 0x04, 0, 0, "group" }, /* 126 */ + { 0x30, 0, 1, "id-ad" }, /* 127 */ + { 0x01, 0, 1, "ocsp" }, /* 128 */ + { 0x01, 130, 0, "basic" }, /* 129 */ + { 0x02, 131, 0, "nonce" }, /* 130 */ + { 0x03, 132, 0, "crl" }, /* 131 */ + { 0x04, 133, 0, "response" }, /* 132 */ + { 0x05, 134, 0, "noCheck" }, /* 133 */ + { 0x06, 135, 0, "archiveCutoff" }, /* 134 */ + { 0x07, 0, 0, "serviceLocator" }, /* 135 */ + { 0x0E, 142, 1, "oiw" }, /* 136 */ + { 0x03, 0, 1, "secsig" }, /* 137 */ + { 0x02, 0, 1, "algorithms" }, /* 138 */ + { 0x07, 140, 0, "des-cbc" }, /* 139 */ + { 0x1A, 141, 0, "sha-1" }, /* 140 */ + { 0x1D, 0, 0, "sha-1WithRSASignature" }, /* 141 */ + { 0x24, 0, 1, "TeleTrusT" }, /* 142 */ + { 0x03, 0, 1, "algorithm" }, /* 143 */ + { 0x03, 0, 1, "signatureAlgorithm" }, /* 144 */ + { 0x01, 0, 1, "rsaSignature" }, /* 145 */ + { 0x02, 147, 0, "rsaSigWithripemd160" }, /* 146 */ + { 0x03, 148, 0, "rsaSigWithripemd128" }, /* 147 */ + { 0x04, 0, 0, "rsaSigWithripemd256" }, /* 148 */ + {0x60, 0, 1, "" }, /* 149 */ + { 0x86, 0, 1, "" }, /* 150 */ + { 0x48, 0, 1, "" }, /* 151 */ + { 0x01, 0, 1, "organization" }, /* 152 */ + { 0x65, 160, 1, "gov" }, /* 153 */ + { 0x03, 0, 1, "csor" }, /* 154 */ + { 0x04, 0, 1, "nistalgorithm" }, /* 155 */ + { 0x02, 0, 1, "hashalgs" }, /* 156 */ + { 0x01, 158, 0, "id-SHA-256" }, /* 157 */ + { 0x02, 159, 0, "id-SHA-384" }, /* 158 */ + { 0x03, 0, 0, "id-SHA-512" }, /* 159 */ + { 0x86, 0, 1, "" }, /* 160 */ + { 0xf8, 0, 1, "" }, /* 161 */ + { 0x42, 171, 1, "netscape" }, /* 162 */ + { 0x01, 169, 1, "" }, /* 163 */ + { 0x01, 165, 0, "nsCertType" }, /* 164 */ + { 0x03, 166, 0, "nsRevocationUrl" }, /* 165 */ + { 0x04, 167, 0, "nsCaRevocationUrl" }, /* 166 */ + { 0x08, 168, 0, "nsCaPolicyUrl" }, /* 167 */ + { 0x0d, 0, 0, "nsComment" }, /* 168 */ + { 0x04, 0, 1, "policy" }, /* 169 */ + { 0x01, 0, 0, "nsSGC" }, /* 170 */ + { 0x45, 0, 1, "verisign" }, /* 171 */ + { 0x01, 0, 1, "pki" }, /* 172 */ + { 0x09, 0, 1, "attributes" }, /* 173 */ + { 0x02, 175, 0, "messageType" }, /* 174 */ + { 0x03, 176, 0, "pkiStatus" }, /* 175 */ + { 0x04, 177, 0, "failInfo" }, /* 176 */ + { 0x05, 178, 0, "senderNonce" }, /* 177 */ + { 0x06, 179, 0, "recipientNonce" }, /* 178 */ + { 0x07, 180, 0, "transID" }, /* 179 */ + { 0x08, 0, 0, "extensionReq" } /* 180 */ +}; diff --git a/Source/lib/asn1/oid.h b/Source/lib/asn1/oid.h new file mode 100644 index 000000000..4096af357 --- /dev/null +++ b/Source/lib/asn1/oid.h @@ -0,0 +1,75 @@ +/* Object identifiers (OIDs) used by FreeS/WAN + * Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur + * + * This file has been automatically generated by the script oid.pl + * Do not edit manually! + */ + +typedef struct { + u_char octet; + u_int next; + u_int down; + const u_char *name; +} oid_t; + +extern const oid_t oid_names[]; + +#define OID_UNKNOWN -1 +#define OID_ROLE 35 +#define OID_SUBJECT_KEY_ID 38 +#define OID_SUBJECT_ALT_NAME 41 +#define OID_BASIC_CONSTRAINTS 43 +#define OID_CRL_REASON_CODE 44 +#define OID_CRL_DISTRIBUTION_POINTS 45 +#define OID_AUTHORITY_KEY_ID 47 +#define OID_EXTENDED_KEY_USAGE 48 +#define OID_TARGET_INFORMATION 49 +#define OID_NO_REV_AVAIL 50 +#define OID_RSA_ENCRYPTION 59 +#define OID_MD2_WITH_RSA 60 +#define OID_MD5_WITH_RSA 61 +#define OID_SHA1_WITH_RSA 62 +#define OID_SHA256_WITH_RSA 63 +#define OID_SHA384_WITH_RSA 64 +#define OID_SHA512_WITH_RSA 65 +#define OID_PKCS7_DATA 67 +#define OID_PKCS7_SIGNED_DATA 68 +#define OID_PKCS7_ENVELOPED_DATA 69 +#define OID_PKCS7_SIGNED_ENVELOPED_DATA 70 +#define OID_PKCS7_DIGESTED_DATA 71 +#define OID_PKCS7_ENCRYPTED_DATA 72 +#define OID_PKCS9_EMAIL 74 +#define OID_PKCS9_CONTENT_TYPE 76 +#define OID_PKCS9_MESSAGE_DIGEST 77 +#define OID_PKCS9_SIGNING_TIME 78 +#define OID_MD2 84 +#define OID_MD5 85 +#define OID_3DES_EDE_CBC 87 +#define OID_AUTHORITY_INFO_ACCESS 109 +#define OID_OCSP_SIGNING 119 +#define OID_XMPP_ADDR 121 +#define OID_AUTHENTICATION_INFO 123 +#define OID_ACCESS_IDENTITY 124 +#define OID_CHARGING_IDENTITY 125 +#define OID_GROUP 126 +#define OID_OCSP 128 +#define OID_BASIC 129 +#define OID_NONCE 130 +#define OID_CRL 131 +#define OID_RESPONSE 132 +#define OID_NO_CHECK 133 +#define OID_ARCHIVE_CUTOFF 134 +#define OID_SERVICE_LOCATOR 135 +#define OID_DES_CBC 139 +#define OID_SHA1 140 +#define OID_SHA1_WITH_RSA_OIW 141 +#define OID_NS_REVOCATION_URL 165 +#define OID_NS_CA_REVOCATION_URL 166 +#define OID_NS_CA_POLICY_URL 167 +#define OID_NS_COMMENT 168 +#define OID_PKI_MESSAGE_TYPE 174 +#define OID_PKI_STATUS 175 +#define OID_PKI_FAIL_INFO 176 +#define OID_PKI_SENDER_NONCE 177 +#define OID_PKI_RECIPIENT_NONCE 178 +#define OID_PKI_TRANS_ID 179 diff --git a/Source/lib/asn1/oid.pl b/Source/lib/asn1/oid.pl new file mode 100644 index 000000000..52ac8eae0 --- /dev/null +++ b/Source/lib/asn1/oid.pl @@ -0,0 +1,123 @@ +#!/usr/bin/perl +# Generates oid.h and oid.c out of oid.txt +# Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur +# +# 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 . +# +# 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. +# + +$copyright="Copyright (C) 2003-2004 Andreas Steffen, Zuercher Hochschule Winterthur"; +$automatic="This file has been automatically generated by the script oid.pl"; +$warning="Do not edit manually!"; + +print "oid.pl generating oid.h and oid.c\n"; + +# Generate oid.h + +open(OID_H, ">oid.h") + or die "could not open 'oid.h': $!"; + +print OID_H "/* Object identifiers (OIDs) used by FreeS/WAN\n", + " * ", $copyright, "\n", + " * \n", + " * ", $automatic, "\n", + " * ", $warning, "\n", + " */\n\n", + "typedef struct {\n", + " u_char octet;\n", + " u_int next;\n", + " u_int down;\n", + " const u_char *name;\n", + "} oid_t;\n", + "\n", + "extern const oid_t oid_names[];\n", + "\n", + "#define OID_UNKNOWN -1\n"; + +# parse oid.txt + +open(SRC, ") +{ + $line =~ m/( *?)(0x\w{2})\s+(".*?")[ \t]*?([\w_]*?)\Z/; + + @order[$counter] = length($1); + @octet[$counter] = $2; + @name[$counter] = $3; + + if (length($1) > $max_order) + { + $max_order = length($1); + } + if (length($3) > $max_name) + { + $max_name = length($3); + } + if (length($4) > 0) + { + printf OID_H "#define %s%s%d\n", $4, "\t" x ((39-length($4))/8), $counter; + } + $counter++; +} + +close SRC; +close OID_H; + +# Generate oid.c + +open(OID_C, ">oid.c") + or die "could not open 'oid.c': $!"; + +print OID_C "/* List of some useful object identifiers (OIDs)\n", + " * ", $copyright, "\n", + " * \n", + " * ", $automatic, "\n", + " * ", $warning, "\n", + " */\n", + "\n", + "#include \n", + "\n", + "#include \"oid.h\"\n", + "\n", + "const oid_t oid_names[] = {\n"; + +for ($c = 0; $c < $counter; $c++) +{ + $next = 0; + + for ($d = $c+1; $d < $counter && @order[$d] >= @order[$c]; $d++) + { + if (@order[$d] == @order[$c]) + { + @next[$c] = $d; + last; + } + } + + printf OID_C " {%s%s,%s%3d, %d, %s%s}%s /* %3d */\n" + ,' ' x @order[$c] + , @octet[$c] + , ' ' x (1 + $max_order - @order[$c]) + , @next[$c] + , @order[$c+1] > @order[$c] + , @name[$c] + , ' ' x ($max_name - length(@name[$c])) + , $c != $counter-1 ? "," : " " + , $c; +} + +print OID_C "};\n" ; +close OID_C; diff --git a/Source/lib/asn1/oid.txt b/Source/lib/asn1/oid.txt new file mode 100644 index 000000000..ad05a1270 --- /dev/null +++ b/Source/lib/asn1/oid.txt @@ -0,0 +1,181 @@ +0x02 "ITU-T Administration" + 0x82 "" + 0x06 "Germany ITU-T member" + 0x01 "Deutsche Telekom AG" + 0x0A "" + 0x07 "" + 0x14 "ND" +0x09 "data" + 0x92 "" + 0x26 "" + 0x89 "" + 0x93 "" + 0xF2 "" + 0x2C "" + 0x64 "pilot" + 0x01 "pilotAttributeType" + 0x01 "UID" + 0x19 "DC" +0x55 "X.500" + 0x04 "X.509" + 0x03 "CN" + 0x04 "S" + 0x05 "SN" + 0x06 "C" + 0x07 "L" + 0x08 "ST" + 0x0A "O" + 0x0B "OU" + 0x0C "T" + 0x0D "D" + 0x24 "userCertificate" + 0x29 "N" + 0x2A "G" + 0x2B "I" + 0x2D "ID" + 0x48 "role" OID_ROLE + 0x1D "id-ce" + 0x09 "subjectDirectoryAttrs" + 0x0E "subjectKeyIdentifier" OID_SUBJECT_KEY_ID + 0x0F "keyUsage" + 0x10 "privateKeyUsagePeriod" + 0x11 "subjectAltName" OID_SUBJECT_ALT_NAME + 0x12 "issuerAltName" + 0x13 "basicConstraints" OID_BASIC_CONSTRAINTS + 0x15 "reasonCode" OID_CRL_REASON_CODE + 0x1F "crlDistributionPoints" OID_CRL_DISTRIBUTION_POINTS + 0x20 "certificatePolicies" + 0x23 "authorityKeyIdentifier" OID_AUTHORITY_KEY_ID + 0x25 "extendedKeyUsage" OID_EXTENDED_KEY_USAGE + 0x37 "targetInformation" OID_TARGET_INFORMATION + 0x38 "noRevAvail" OID_NO_REV_AVAIL +0x2A "" + 0x86 "" + 0x48 "" + 0x86 "" + 0xF7 "" + 0x0D "RSADSI" + 0x01 "PKCS" + 0x01 "PKCS-1" + 0x01 "rsaEncryption" OID_RSA_ENCRYPTION + 0x02 "md2WithRSAEncryption" OID_MD2_WITH_RSA + 0x04 "md5WithRSAEncryption" OID_MD5_WITH_RSA + 0x05 "sha-1WithRSAEncryption" OID_SHA1_WITH_RSA + 0x0B "sha256WithRSAEncryption" OID_SHA256_WITH_RSA + 0x0C "sha384WithRSAEncryption" OID_SHA384_WITH_RSA + 0x0D "sha512WithRSAEncryption" OID_SHA512_WITH_RSA + 0x07 "PKCS-7" + 0x01 "data" OID_PKCS7_DATA + 0x02 "signedData" OID_PKCS7_SIGNED_DATA + 0x03 "envelopedData" OID_PKCS7_ENVELOPED_DATA + 0x04 "signedAndEnvelopedData" OID_PKCS7_SIGNED_ENVELOPED_DATA + 0x05 "digestedData" OID_PKCS7_DIGESTED_DATA + 0x06 "encryptedData" OID_PKCS7_ENCRYPTED_DATA + 0x09 "PKCS-9" + 0x01 "E" OID_PKCS9_EMAIL + 0x02 "unstructuredName" + 0x03 "contentType" OID_PKCS9_CONTENT_TYPE + 0x04 "messageDigest" OID_PKCS9_MESSAGE_DIGEST + 0x05 "signingTime" OID_PKCS9_SIGNING_TIME + 0x06 "counterSignature" + 0x07 "challengePassword" + 0x08 "unstructuredAddress" + 0x0E "extensionRequest" + 0x02 "digestAlgorithm" + 0x02 "md2" OID_MD2 + 0x05 "md5" OID_MD5 + 0x03 "encryptionAlgorithm" + 0x07 "3des-ede-cbc" OID_3DES_EDE_CBC +0x2B "" + 0x06 "dod" + 0x01 "internet" + 0x04 "private" + 0x01 "enterprise" + 0x82 "" + 0x37 "Microsoft" + 0x0A "" + 0x03 "" + 0x03 "msSGC" + 0x89 "" + 0x31 "" + 0x01 "" + 0x01 "" + 0x02 "" + 0x02 "" + 0x4B "TCGID" + 0x05 "security" + 0x05 "mechanisms" + 0x07 "id-pkix" + 0x01 "id-pe" + 0x01 "authorityInfoAccess" OID_AUTHORITY_INFO_ACCESS + 0x03 "id-kp" + 0x01 "serverAuth" + 0x02 "clientAuth" + 0x03 "codeSigning" + 0x04 "emailProtection" + 0x05 "ipsecEndSystem" + 0x06 "ipsecTunnel" + 0x07 "ipsecUser" + 0x08 "timeStamping" + 0x09 "ocspSigning" OID_OCSP_SIGNING + 0x08 "id-otherNames" + 0x05 "xmppAddr" OID_XMPP_ADDR + 0x0A "id-aca" + 0x01 "authenticationInfo" OID_AUTHENTICATION_INFO + 0x02 "accessIdentity" OID_ACCESS_IDENTITY + 0x03 "chargingIdentity" OID_CHARGING_IDENTITY + 0x04 "group" OID_GROUP + 0x30 "id-ad" + 0x01 "ocsp" OID_OCSP + 0x01 "basic" OID_BASIC + 0x02 "nonce" OID_NONCE + 0x03 "crl" OID_CRL + 0x04 "response" OID_RESPONSE + 0x05 "noCheck" OID_NO_CHECK + 0x06 "archiveCutoff" OID_ARCHIVE_CUTOFF + 0x07 "serviceLocator" OID_SERVICE_LOCATOR + 0x0E "oiw" + 0x03 "secsig" + 0x02 "algorithms" + 0x07 "des-cbc" OID_DES_CBC + 0x1A "sha-1" OID_SHA1 + 0x1D "sha-1WithRSASignature" OID_SHA1_WITH_RSA_OIW + 0x24 "TeleTrusT" + 0x03 "algorithm" + 0x03 "signatureAlgorithm" + 0x01 "rsaSignature" + 0x02 "rsaSigWithripemd160" + 0x03 "rsaSigWithripemd128" + 0x04 "rsaSigWithripemd256" +0x60 "" + 0x86 "" + 0x48 "" + 0x01 "organization" + 0x65 "gov" + 0x03 "csor" + 0x04 "nistalgorithm" + 0x02 "hashalgs" + 0x01 "id-SHA-256" + 0x02 "id-SHA-384" + 0x03 "id-SHA-512" + 0x86 "" + 0xf8 "" + 0x42 "netscape" + 0x01 "" + 0x01 "nsCertType" + 0x03 "nsRevocationUrl" OID_NS_REVOCATION_URL + 0x04 "nsCaRevocationUrl" OID_NS_CA_REVOCATION_URL + 0x08 "nsCaPolicyUrl" OID_NS_CA_POLICY_URL + 0x0d "nsComment" OID_NS_COMMENT + 0x04 "policy" + 0x01 "nsSGC" + 0x45 "verisign" + 0x01 "pki" + 0x09 "attributes" + 0x02 "messageType" OID_PKI_MESSAGE_TYPE + 0x03 "pkiStatus" OID_PKI_STATUS + 0x04 "failInfo" OID_PKI_FAIL_INFO + 0x05 "senderNonce" OID_PKI_SENDER_NONCE + 0x06 "recipientNonce" OID_PKI_RECIPIENT_NONCE + 0x07 "transID" OID_PKI_TRANS_ID + 0x08 "extensionReq" diff --git a/Source/lib/asn1/pem.c b/Source/lib/asn1/pem.c new file mode 100755 index 000000000..24c71c61f --- /dev/null +++ b/Source/lib/asn1/pem.c @@ -0,0 +1,343 @@ +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * 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 . + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "pem.h" +#include "ttodata.h" + +#include +#include + + +/* + * check the presence of a pattern in a character string + */ +static bool present(const char* pattern, chunk_t* ch) +{ + u_int pattern_len = strlen(pattern); + + if (ch->len >= pattern_len && strncmp(ch->ptr, pattern, pattern_len) == 0) + { + ch->ptr += pattern_len; + ch->len -= pattern_len; + return TRUE; + } + return FALSE; +} + +/* + * compare string with chunk + */ +static bool match(const char *pattern, const chunk_t *ch) +{ + return ch->len == strlen(pattern) && strncmp(pattern, ch->ptr, ch->len) == 0; +} + +/* + * find a boundary of the form -----tag name----- + */ +static bool find_boundary(const char* tag, chunk_t *line) +{ + chunk_t name = CHUNK_INITIALIZER; + + if (!present("-----", line)) + return FALSE; + if (!present(tag, line)) + return FALSE; + if (*line->ptr != ' ') + return FALSE; + line->ptr++; line->len--; + + /* extract name */ + name.ptr = line->ptr; + while (line->len > 0) + { + if (present("-----", line)) + { + return TRUE; + } + line->ptr++; line->len--; name.len++; + } + return FALSE; +} + +/* + * eat whitespace + */ +static void eat_whitespace(chunk_t *src) +{ + while (src->len > 0 && (*src->ptr == ' ' || *src->ptr == '\t')) + { + src->ptr++; src->len--; + } +} + +/* + * extracts a token ending with a given termination symbol + */ +static bool extract_token(chunk_t *token, char termination, chunk_t *src) +{ + u_char *eot = memchr(src->ptr, termination, src->len); + + /* initialize empty token */ + *token = CHUNK_INITIALIZER; + + if (eot == NULL) /* termination symbol not found */ + { + return FALSE; + } + + /* extract token */ + token->ptr = src->ptr; + token->len = (u_int)(eot - src->ptr); + + /* advance src pointer after termination symbol */ + src->ptr = eot + 1; + src->len -= (token->len + 1); + + return TRUE; +} + +/* + * extracts a name: value pair from the PEM header + */ +static bool extract_parameter(chunk_t *name, chunk_t *value, chunk_t *line) +{ + /* extract name */ + if (!extract_token(name,':', line)) + { + return FALSE; + } + + eat_whitespace(line); + + /* extract value */ + *value = *line; + return TRUE; +} + +/* + * fetches a new line terminated by \n or \r\n + */ +static bool fetchline(chunk_t *src, chunk_t *line) +{ + if (src->len == 0) /* end of src reached */ + return FALSE; + + if (extract_token(line, '\n', src)) + { + if (line->len > 0 && *(line->ptr + line->len -1) == '\r') + line->len--; /* remove optional \r */ + } + else /*last line ends without newline */ + { + *line = *src; + src->ptr += src->len; + src->len = 0; + } + return TRUE; +} + +/* + * decrypts a DES-EDE-CBC encrypted data block + */ +static status_t pem_decrypt(chunk_t *blob, chunk_t *iv, char *passphrase) +{ + hasher_t *hasher; + crypter_t *crypter; + chunk_t hash; + chunk_t decrypted; + chunk_t pass = {passphrase, strlen(passphrase)}; + chunk_t key = {alloca(24), 24}; + u_int8_t padding, *last_padding_pos, *first_padding_pos; + + /* build key from passphrase and IV */ + hasher = hasher_create(HASH_MD5); + hash.len = hasher->get_block_size(hasher); + hash.ptr = alloca(hash.len); + hasher->get_hash(hasher, pass, NULL); + hasher->get_hash(hasher, *iv, hash.ptr); + + memcpy(key.ptr, hash.ptr, hash.len); + + hasher->get_hash(hasher, hash, NULL); + hasher->get_hash(hasher, pass, NULL); + hasher->get_hash(hasher, *iv, hash.ptr); + + memcpy(key.ptr + hash.len, hash.ptr, key.len - hash.len); + + hasher->destroy(hasher); + + /* decrypt blob */ + crypter = crypter_create(ENCR_3DES, 0); + crypter->set_key(crypter, key); + crypter->decrypt(crypter, *blob, *iv, &decrypted); + memcpy(blob->ptr, decrypted.ptr, blob->len); + chunk_free(&decrypted); + + /* determine amount of padding */ + last_padding_pos = blob->ptr + blob->len - 1; + padding = *last_padding_pos; + first_padding_pos = (padding > blob->len) ? blob->ptr : last_padding_pos - padding; + + /* check the padding pattern */ + while (--last_padding_pos > first_padding_pos) + { + if (*last_padding_pos != padding) + return FALSE; + } + /* remove padding */ + blob->len -= padding; + return TRUE; +} + +/* Converts a PEM encoded file into its binary form + * + * RFC 1421 Privacy Enhancement for Electronic Mail, February 1993 + * RFC 934 Message Encapsulation, January 1985 + */ +status_t pemtobin(chunk_t *blob, char *pass) +{ + typedef enum { + PEM_PRE = 0, + PEM_MSG = 1, + PEM_HEADER = 2, + PEM_BODY = 3, + PEM_POST = 4, + PEM_ABORT = 5 + } state_t; + + bool encrypted = FALSE; + + state_t state = PEM_PRE; + + chunk_t src = *blob; + chunk_t dst = *blob; + chunk_t line = CHUNK_INITIALIZER; + chunk_t iv = CHUNK_INITIALIZER; + + u_char iv_buf[16]; /* MD5 digest size */ + + /* zero size of converted blob */ + dst.len = 0; + + /* zero size of IV */ + iv.ptr = iv_buf; + iv.len = 0; + + while (fetchline(&src, &line)) + { + if (state == PEM_PRE) + { + if (find_boundary("BEGIN", &line)) + { + state = PEM_MSG; + } + continue; + } + else + { + if (find_boundary("END", &line)) + { + state = PEM_POST; + break; + } + if (state == PEM_MSG) + { + state = (memchr(line.ptr, ':', line.len) == NULL) ? PEM_BODY : PEM_HEADER; + } + if (state == PEM_HEADER) + { + chunk_t name = CHUNK_INITIALIZER; + chunk_t value = CHUNK_INITIALIZER; + + /* an empty line separates HEADER and BODY */ + if (line.len == 0) + { + state = PEM_BODY; + continue; + } + + /* we are looking for a name: value pair */ + if (!extract_parameter(&name, &value, &line)) + continue; + + if (match("Proc-Type", &name) && *value.ptr == '4') + encrypted = TRUE; + else if (match("DEK-Info", &name)) + { + const char *ugh = NULL; + size_t len = 0; + chunk_t dek; + + if (!extract_token(&dek, ',', &value)) + dek = value; + + /* we support DES-EDE3-CBC encrypted files, only */ + if (!match("DES-EDE3-CBC", &dek)) + return NOT_SUPPORTED; + + eat_whitespace(&value); + ugh = ttodata(value.ptr, value.len, 16, iv.ptr, 16, &len); + if (ugh) + return PARSE_ERROR; + + iv.len = len; + } + } + else /* state is PEM_BODY */ + { + const char *ugh = NULL; + size_t len = 0; + chunk_t data; + + /* remove any trailing whitespace */ + if (!extract_token(&data ,' ', &line)) + { + data = line; + } + + ugh = ttodata(data.ptr, data.len, 64, dst.ptr, blob->len - dst.len, &len); + if (ugh) + { + state = PEM_ABORT; + break; + } + else + { + dst.ptr += len; + dst.len += len; + } + } + } + } + /* set length to size of binary blob */ + blob->len = dst.len; + + if (state != PEM_POST) + return PARSE_ERROR; + + if (encrypted) + return pem_decrypt(blob, &iv, pass); + else + return SUCCESS; +} diff --git a/Source/lib/asn1/pem.h b/Source/lib/asn1/pem.h new file mode 100755 index 000000000..a4332fd34 --- /dev/null +++ b/Source/lib/asn1/pem.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2006 Martin Willi + * 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 . + * + * 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. + */ + +#ifndef PEM_H_ +#define PEM_H_ + +#include + +#include + +status_t pemtobin(chunk_t *blob, char *pass); + +#endif /*PEM_H_*/ diff --git a/Source/lib/asn1/ttodata.c b/Source/lib/asn1/ttodata.c new file mode 100644 index 000000000..5e8149955 --- /dev/null +++ b/Source/lib/asn1/ttodata.c @@ -0,0 +1,374 @@ +/* + * 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 . + * + * 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 +#include + +/* 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)) + +/* + - ttodatav - 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. + */ +const char * /* NULL on success, else literal or errp */ +ttodatav(src, srclen, base, dst, dstlen, lenp, errp, errlen, flags) +const char *src; +size_t srclen; /* 0 means apply strlen() */ +int base; /* 0 means figure it out */ +char *dst; /* need not be valid if dstlen is 0 */ +size_t dstlen; +size_t *lenp; /* where to record length (NULL is nowhere) */ +char *errp; /* error buffer */ +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 == '_') { + /* 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; +} + +/* + - ttodata - convert text to data + */ +const char * /* NULL on success, else literal */ +ttodata(src, srclen, base, dst, dstlen, lenp) +const char *src; +size_t srclen; /* 0 means apply strlen() */ +int base; /* 0 means figure it out */ +char *dst; /* need not be valid if dstlen is 0 */ +size_t dstlen; +size_t *lenp; /* where to record length (NULL is nowhere) */ +{ + return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL, + (size_t)0, TTODATAV_SPACECOUNTS); +} + +/* + - atodata - convert ASCII to data + * backward-compatibility interface + */ +size_t /* 0 for failure, true length for success */ +atodata(src, srclen, dst, dstlen) +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); + if (err != NULL) + return 0; + return len; +} + +/* + - atobytes - convert ASCII to data bytes + * another backward-compatibility interface + */ +const char * +atobytes(src, srclen, dst, dstlen, lenp) +const char *src; +size_t srclen; +char *dst; +size_t dstlen; +size_t *lenp; +{ + return ttodata(src, srclen, 0, dst, dstlen, lenp); +} + +/* + - unhex - convert two ASCII hex digits to byte + */ +static int /* number of result bytes, or error code */ +unhex(src, dst, dstlen) +const char *src; /* known to be full length */ +char *dst; +size_t dstlen; /* not large enough is a failure */ +{ + 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; +} + +/* + - 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. + */ +static int /* number of result bytes, or error code */ +unb64(src, dst, dstlen) +const char *src; /* known to be full length */ +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; +} + +/* + - untext - convert one ASCII character to byte + */ +static int /* number of result bytes, or error code */ +untext(src, dst, dstlen) +const char *src; /* known to be full length */ +char *dst; +size_t dstlen; /* not large enough is a failure */ +{ + if (dstlen < 1) + return SHORT; + + *dst = *src; + return 1; +} + +/* + - 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. + */ +static const char * /* literal or errp */ +badch(src, errcode, errp, errlen) +const char *src; +int errcode; +char *errp; /* might be NULL */ +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/Source/lib/asn1/ttodata.h b/Source/lib/asn1/ttodata.h new file mode 100644 index 000000000..d57244ef5 --- /dev/null +++ b/Source/lib/asn1/ttodata.h @@ -0,0 +1,30 @@ +/* + * 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 . + * + * 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 + +#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 */ + +typedef const char *err_t; /* error message, or NULL for success */ + +err_t ttodata(const char *src, size_t srclen, int base, char *buf, size_t buflen, size_t *needed); + + +#endif /* TTODATA_H_ */ diff --git a/Source/lib/crypto/certificate.h b/Source/lib/crypto/certificate.h index 2b5459efb..8dc88e033 100755 --- a/Source/lib/crypto/certificate.h +++ b/Source/lib/crypto/certificate.h @@ -26,6 +26,8 @@ #include #include #include +#include +#include typedef struct certificate_t certificate_t; @@ -47,6 +49,14 @@ struct certificate_t { * @return public_key */ rsa_public_key_t *(*get_public_key) (certificate_t *this); + + identification_t *(*get_issuer) (certificate_t *this); + identification_t *(*get_subject) (certificate_t *this); + iterator_t *(*create_subjectaltname_iter) (certificate_t *this); + iterator_t *(*create_issueraltname_iter) (certificate_t *this); + bool (*belongs_to) (certificate_t *this, identification_t *subject); + bool (*issued_by) (certificate_t *this, identification_t *issuer); + bool (*validate) (certificate_t *this, rsa_public_key_t *signer); /** * @brief Destroys the private key. diff --git a/Source/lib/utils/identification.h b/Source/lib/utils/identification.h index b973da9a4..30796bd56 100644 --- a/Source/lib/utils/identification.h +++ b/Source/lib/utils/identification.h @@ -84,6 +84,21 @@ enum id_type_t { ID_KEY_ID = 11 }; +/** + * Old pluto id format + * + * @deprecated Do not use any more, only here for pluto. + */ +// struct id { +// /** ID_* value, pluto pendant to id_type_t */ +// int kind; +// /** ID_IPV4_ADDR, ID_IPV6_ADDR */ +// ip_address ip_addr; +// /** ID_FQDN, ID_USER_FQDN (with @) */ +// /** ID_KEY_ID, ID_DER_ASN_DN */ +// chunk_t name; +// }; + /** * String mappings for id_type_t. */ @@ -143,6 +158,17 @@ struct identification_t { */ char *(*get_string) (identification_t *this); + /** + * @brief Get the id in the format used in pluto. + * + * We do this in pluto style here, which means no memory + * is allocated. + * + * @param this the identification_t object + * @return string + */ + // void (*get_pluto_id) (identification_t *this, struct id *pluto_id); + /** * @brief Check if two identification_t objects are equal. * @@ -195,7 +221,6 @@ struct identification_t { */ identification_t * identification_create_from_string(id_type_t type, char *string); - /** * @brief Creates an identification_t object from an encoded chunk. * @@ -207,5 +232,18 @@ identification_t * identification_create_from_string(id_type_t type, char *strin */ identification_t * identification_create_from_encoding(id_type_t type, chunk_t encoded); +/** + * @brief Creates an identification_t object from the old pluto id format. + * + * Pluto uses struct id for identification stuff. Since we need to convert from + * this format to our identification_t, we need this special constructor. + * + * @param id old pluto format id + * @return identification_t object + * + * @ingroup utils + */ +// identification_t * identification_create_from_pluto_id(struct id *pluto_id); + #endif /* IDENTIFICATION_H_ */ diff --git a/Source/lib/utils/leak_detective.c b/Source/lib/utils/leak_detective.c index 67c123be2..0d90820ee 100644 --- a/Source/lib/utils/leak_detective.c +++ b/Source/lib/utils/leak_detective.c @@ -30,10 +30,12 @@ #include #include #include +#include #include "leak_detective.h" #include +#include #ifdef LEAK_DETECTIVE @@ -42,6 +44,10 @@ */ #define MEMORY_HEADER_MAGIC 0xF1367ADF +/** + * logger for the leak detective + */ +logger_t *logger; static void install_hooks(void); static void uninstall_hooks(void); @@ -103,37 +109,39 @@ memory_header_t first_header = { */ void *old_malloc_hook, *old_realloc_hook, *old_free_hook; - +/** + * Mutex to exclusivly uninstall hooks, access heap list + */ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +void (*__malloc_initialize_hook) (void) = install_hooks; /** * log stack frames queried by backtrace() * TODO: Dump symbols of static functions!!! */ -void log_stack_frames(void *stack_frames, int stack_frame_count) +void log_stack_frames(void **stack_frames, int stack_frame_count) { char **strings; size_t i; strings = backtrace_symbols (stack_frames, stack_frame_count); - printf(" dumping %d stack frames.\n", stack_frame_count); + logger->log(logger, ERROR, " dumping %d stack frame addresses.", stack_frame_count); for (i = 0; i < stack_frame_count; i++) { - printf (" %s\n", strings[i]); + logger->log(logger, ERROR, " %s", strings[i]); } free (strings); } -void (*__malloc_initialize_hook) (void) = install_hooks; - /** * Installs the malloc hooks, enables leak detection */ void install_hooks() { + logger = logger_manager->get_logger(logger_manager, LEAK_DETECT); old_malloc_hook = __malloc_hook; old_realloc_hook = __realloc_hook; old_free_hook = __free_hook; @@ -200,10 +208,10 @@ static void free_hook(void *ptr, const void *caller) pthread_mutex_unlock(&mutex); /* TODO: Since we get a lot of theses from the pthread lib, its deactivated for now... */ return; - printf("freeing of invalid memory (%p)\n", ptr); + logger->log(logger, ERROR, "freeing of invalid memory (%p)", ptr); stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); log_stack_frames(stack_frames, stack_frame_count); - kill(0, SIGSEGV); + kill(getpid(), SIGKILL); return; } /* remove magic from hdr */ @@ -239,10 +247,10 @@ static void *realloc_hook(void *old, size_t bytes, const void *caller) } if (hdr->magic != MEMORY_HEADER_MAGIC) { - printf("reallocation of invalid memory (%p)\n", old); + logger->log(logger, ERROR, "reallocation of invalid memory (%p)", old); stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); log_stack_frames(stack_frames, stack_frame_count); - kill(0, SIGSEGV); + kill(getpid(), SIGKILL); return NULL; } @@ -264,20 +272,20 @@ void __attribute__ ((destructor)) report_leaks() for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) { - printf("Leak (%d bytes at %p)\n", hdr->bytes, hdr + 1); + logger->log(logger, ERROR, "Leak (%d bytes at %p)", hdr->bytes, hdr + 1); log_stack_frames(hdr->stack_frames, hdr->stack_frame_count); leaks++; } switch (leaks) { case 0: - printf("No leaks detected\n"); + logger->log(logger, CONTROL, "No leaks detected"); break; case 1: - printf("One leak detected\n"); + logger->log(logger, ERROR, "One leak detected"); break; default: - printf("%d leaks detected\n", leaks); + logger->log(logger, ERROR, "%d leaks detected", leaks); break; } } @@ -304,13 +312,18 @@ char *inet_ntoa(struct in_addr in) handle = dlopen("libc.so.6", RTLD_LAZY); if (handle == NULL) { - kill(0, SIGSEGV); + install_hooks(); + pthread_mutex_unlock(&mutex); + kill(getpid(), SIGSEGV); } _inet_ntoa = dlsym(handle, "inet_ntoa"); if (_inet_ntoa == NULL) { - kill(0, SIGSEGV); + dlclose(handle); + install_hooks(); + pthread_mutex_unlock(&mutex); + kill(getpid(), SIGSEGV); } result = _inet_ntoa(in); dlclose(handle); @@ -336,13 +349,18 @@ int pthread_create(pthread_t *__restrict __threadp, __const pthread_attr_t *__re handle = dlopen("libpthread.so.0", RTLD_LAZY); if (handle == NULL) { - kill(0, SIGSEGV); + install_hooks(); + pthread_mutex_unlock(&mutex); + kill(getpid(), SIGSEGV); } _pthread_create = dlsym(handle, "pthread_create"); if (_pthread_create == NULL) { - kill(0, SIGSEGV); + dlclose(handle); + install_hooks(); + pthread_mutex_unlock(&mutex); + kill(getpid(), SIGSEGV); } result = _pthread_create(__threadp, __attr, __start_routine, __arg); dlclose(handle); @@ -364,13 +382,18 @@ time_t mktime(struct tm *tm) handle = dlopen("libc.so.6", RTLD_LAZY); if (handle == NULL) { - kill(0, SIGSEGV); + install_hooks(); + pthread_mutex_unlock(&mutex); + kill(getpid(), SIGSEGV); } _mktime = dlsym(handle, "mktime"); if (_mktime == NULL) { - kill(0, SIGSEGV); + dlclose(handle); + install_hooks(); + pthread_mutex_unlock(&mutex); + kill(getpid(), SIGSEGV); } result = _mktime(tm); dlclose(handle); -- cgit v1.2.3