- startet importing pluto ASN1 stuff

- der PKCS#1 key loading works (as it did with der_decoder)
This commit is contained in:
Martin Willi
2006-04-10 14:19:10 +00:00
parent 5113680f95
commit b5cb0210f7
21 changed files with 2647 additions and 12 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ MAIN_DIR= ./
LDFLAGS= -ldl -lgmp -lpthread -rdynamic
CFLAGS= -Icharon -Ilib -Istroke -Wall -g -fPIC -fomit-frame-pointer -DLEAK_DETECTIVE
CFLAGS= -Icharon -Ilib -Istroke -Wall -g -fPIC -DLEAK_DETECTIVE
# objects is extended by each included Makefile
CHARON_OBJS=
+2
View File
@@ -448,6 +448,8 @@ socket_t *socket_create(u_int16_t port)
if (build_interface_list(this, port) != SUCCESS)
{
this->interfaces->destroy(this->interfaces);
free(this);
charon->kill(charon, "could not bind any interface!");
}
+2 -2
View File
@@ -1,5 +1,5 @@
Known bugs in charon
======================
- intiating the same connection twice makes trouble.
-
- intiating the same connection twice makes trouble
- leak_detective gets confused from libpthread (invalid frees)
+6 -4
View File
@@ -22,12 +22,12 @@
+ new charon build - libstrong?
+ transforms
+ utils (plus host)
- doxygen fixes (two doxyfiles?)
- allocator cleanup (used in lib, charon and pluto(!))
- logger reimplementation? (one logger for lib, charon, pluto)
+ logger_manager instance in lib
+ leak detective usable for charon and pluto and anything else
- doxygen fixes (multiple doxyfiles?)
- integrate asn1 parser/oid (asn1/oid)
- integrate PEM loading (pem)
- ... (more to come, for sure)
- ... (more to come)
- ipsec.secrets parsing
@@ -42,3 +42,5 @@
- delete notify, when to send?
- notifys on connection setup failure
- create child sa message
- new build environment (autotools?)
+1
View File
@@ -25,3 +25,4 @@ $(BUILD_DIR)definitions.o : $(LIB_DIR)definitions.c $(LIB_DIR)definitions.h
include $(MAIN_DIR)lib/crypto/Makefile.transforms
include $(MAIN_DIR)lib/utils/Makefile.utils
include $(MAIN_DIR)lib/asn1/Makefile.asn1
include $(MAIN_DIR)lib/asn1-pluto/Makefile.asn1
+29
View File
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
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 $@ $<
+574
View File
@@ -0,0 +1,574 @@
/* 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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "asn1-pluto.h"
#include "oid.h"
#include <utils/logger_manager.h>
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;
}
+129
View File
@@ -0,0 +1,129 @@
/* 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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef _ASN1_H
#define _ASN1_H
#include <stdarg.h>
#include <gmp.h>
#include <types.h>
/* 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;
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);
#endif /* _ASN1_H */
+194
View File
@@ -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 <stdlib.h>
#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 */
};
+75
View File
@@ -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
+123
View File
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
$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, "<oid.txt")
or die "could not open 'oid.txt': $!";
$counter = 0;
$max_name = 0;
$max_order = 0;
while ($line = <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 <stdlib.h>\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;
+181
View File
@@ -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"
+343
View File
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stddef.h>
#include <sys/types.h>
#include "pem.h"
#include "ttodata.h"
#include <crypto/hashers/hasher.h>
#include <crypto/crypters/crypter.h>
/*
* 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;
}
+25
View File
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef PEM_H_
#define PEM_H_
#include <stdio.h>
#include <types.h>
status_t pemtobin(chunk_t *blob, char *pass);
#endif /*PEM_H_*/
+723
View File
@@ -0,0 +1,723 @@
/*
* convert from text form of arbitrary data (e.g., keys) to binary
* Copyright (C) 2000 Henry Spencer.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*/
#include "ttodata.h"
#include <string.h>
#include <ctype.h>
/* converters and misc */
static int unhex(const char *, char *, size_t);
static int unb64(const char *, char *, size_t);
static int untext(const char *, char *, size_t);
static const char *badch(const char *, int, char *, size_t);
/* internal error codes for converters */
#define SHORT (-2) /* internal buffer too short */
#define BADPAD (-3) /* bad base64 padding */
#define BADCH0 (-4) /* invalid character 0 */
#define BADCH1 (-5) /* invalid character 1 */
#define BADCH2 (-6) /* invalid character 2 */
#define BADCH3 (-7) /* invalid character 3 */
#define BADOFF(code) (BADCH0-(code))
/*
- 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;
}
#ifdef TTODATA_MAIN
#include <stdio.h>
struct artab;
static void check(struct artab *r, char *buf, size_t n, err_t oops, int *status);
static void regress(char *pgm);
static void hexout(const char *s, size_t len, FILE *f);
/*
- main - convert first argument to hex, or run regression
*/
int
main(int argc, char *argv[])
{
char buf[1024];
char buf2[1024];
char err[512];
size_t n;
size_t i;
char *p = buf;
char *p2 = buf2;
char *pgm = argv[0];
const char *oops;
if (argc < 2) {
fprintf(stderr, "Usage: %s {0x<hex>|0s<base64>|-r}\n", pgm);
exit(2);
}
if (strcmp(argv[1], "-r") == 0) {
regress(pgm); /* should not return */
fprintf(stderr, "%s: regress() returned?!?\n", pgm);
exit(1);
}
oops = ttodatav(argv[1], 0, 0, buf, sizeof(buf), &n,
err, sizeof(err), TTODATAV_IGNORESPACE);
if (oops != NULL) {
fprintf(stderr, "%s: ttodata error `%s' in `%s'\n", pgm,
oops, argv[1]);
exit(1);
}
if (n > sizeof(buf)) {
p = (char *)malloc((size_t)n);
if (p == NULL) {
fprintf(stderr,
"%s: unable to malloc %d bytes for result\n",
pgm, n);
exit(1);
}
oops = ttodata(argv[1], 0, 0, p, n, &n);
if (oops != NULL) {
fprintf(stderr, "%s: error `%s' in ttodata retry?!?\n",
pgm, oops);
exit(1);
}
}
hexout(p, n, stdout);
printf("\n");
i = datatot(buf, n, 'h', buf2, sizeof(buf2));
if (i == 0) {
fprintf(stderr, "%s: datatot reports error in `%s'\n", pgm,
argv[1]);
exit(1);
}
if (i > sizeof(buf2)) {
p2 = (char *)malloc((size_t)i);
if (p == NULL) {
fprintf(stderr,
"%s: unable to malloc %d bytes for result\n",
pgm, i);
exit(1);
}
i = datatot(buf, n, 'h', p2, i);
if (i == 0) {
fprintf(stderr, "%s: error in datatoa retry?!?\n", pgm);
exit(1);
}
}
printf("%s\n", p2);
exit(0);
}
/*
- hexout - output an arbitrary-length string in hex
*/
static void
hexout(s, len, f)
const char *s;
size_t len;
FILE *f;
{
size_t i;
fprintf(f, "0x");
for (i = 0; i < len; i++)
fprintf(f, "%02x", (unsigned char)s[i]);
}
struct artab {
int base;
# define IGNORESPACE_BIAS 1000
char *ascii; /* NULL for end */
char *data; /* NULL for error expected */
} atodatatab[] = {
{ 0, "", NULL, },
{ 0, "0", NULL, },
{ 0, "0x", NULL, },
{ 0, "0xa", NULL, },
{ 0, "0xab", "\xab", },
{ 0, "0xabc", NULL, },
{ 0, "0xabcd", "\xab\xcd", },
{ 0, "0x0123456789", "\x01\x23\x45\x67\x89", },
{ 0, "0x01x", NULL, },
{ 0, "0xabcdef", "\xab\xcd\xef", },
{ 0, "0xABCDEF", "\xab\xcd\xef", },
{ 0, "0XaBc0eEd81f", "\xab\xc0\xee\xd8\x1f", },
{ 0, "0XaBc0_eEd8", "\xab\xc0\xee\xd8", },
{ 0, "0XaBc0_", NULL, },
{ 0, "0X_aBc0", NULL, },
{ 0, "0Xa_Bc0", NULL, },
{ 16, "aBc0eEd8", "\xab\xc0\xee\xd8", },
{ 0, "0s", NULL, },
{ 0, "0sA", NULL, },
{ 0, "0sBA", NULL, },
{ 0, "0sCBA", NULL, },
{ 0, "0sDCBA", "\x0c\x20\x40", },
{ 0, "0SDCBA", "\x0c\x20\x40", },
{ 0, "0sDA==", "\x0c", },
{ 0, "0sDC==", NULL, },
{ 0, "0sDCA=", "\x0c\x20", },
{ 0, "0sDCB=", NULL, },
{ 0, "0sDCAZ", "\x0c\x20\x19", },
{ 0, "0sDCAa", "\x0c\x20\x1a", },
{ 0, "0sDCAz", "\x0c\x20\x33", },
{ 0, "0sDCA0", "\x0c\x20\x34", },
{ 0, "0sDCA9", "\x0c\x20\x3d", },
{ 0, "0sDCA+", "\x0c\x20\x3e", },
{ 0, "0sDCA/", "\x0c\x20\x3f", },
{ 0, "0sAbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0s AbraCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sA braCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAb raCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbr aCadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbra Cadabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraC adabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCa dabra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCad abra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCada bra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadab ra+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadabr a+", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadabra +", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ IGNORESPACE_BIAS + 0, "0sAbraCadabra+ ", "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", },
{ 0, "0t", NULL, },
{ 0, "0tabc_xyz", "abc_xyz", },
{ 256, "abc_xyz", "abc_xyz", },
{ 0, NULL, NULL, },
};
struct drtab {
char *data; /* input; NULL for end */
char format;
int buflen; /* -1 means big buffer */
int outlen; /* -1 means strlen(ascii)+1 */
char *ascii; /* NULL for error expected */
} datatoatab[] = {
{ "", 'x', -1, -1, NULL, },
{ "", 'X', -1, -1, NULL, },
{ "", 'n', -1, -1, NULL, },
{ "0", 'x', -1, -1, "0x30", },
{ "0", 'x', 0, 5, "---", },
{ "0", 'x', 1, 5, "", },
{ "0", 'x', 2, 5, "0", },
{ "0", 'x', 3, 5, "0x", },
{ "0", 'x', 4, 5, "0x3", },
{ "0", 'x', 5, 5, "0x30", },
{ "0", 'x', 6, 5, "0x30", },
{ "\xab\xcd", 'x', -1, -1, "0xabcd", },
{ "\x01\x23\x45\x67\x89", 'x', -1, -1, "0x0123456789", },
{ "\xab\xcd\xef", 'x', -1, -1, "0xabcdef", },
{ "\xab\xc0\xee\xd8\x1f", 'x', -1, -1, "0xabc0eed81f", },
{ "\x01\x02", 'h', -1, -1, "0x0102", },
{ "\x01\x02\x03\x04\x05\x06", 'h', -1, -1, "0x01020304_0506", },
{ "\xab\xc0\xee\xd8\x1f", 16, -1, -1, "abc0eed81f", },
{ "\x0c\x20\x40", 's', -1, -1, "0sDCBA", },
{ "\x0c\x20\x40", 's', 0, 7, "---", },
{ "\x0c\x20\x40", 's', 1, 7, "", },
{ "\x0c\x20\x40", 's', 2, 7, "0", },
{ "\x0c\x20\x40", 's', 3, 7, "0s", },
{ "\x0c\x20\x40", 's', 4, 7, "0sD", },
{ "\x0c\x20\x40", 's', 5, 7, "0sDC", },
{ "\x0c\x20\x40", 's', 6, 7, "0sDCB", },
{ "\x0c\x20\x40", 's', 7, 7, "0sDCBA", },
{ "\x0c\x20\x40", 's', 8, 7, "0sDCBA", },
{ "\x0c", 's', -1, -1, "0sDA==", },
{ "\x0c\x20", 's', -1, -1, "0sDCA=", },
{ "\x0c\x20\x19", 's', -1, -1, "0sDCAZ", },
{ "\x0c\x20\x1a", 's', -1, -1, "0sDCAa", },
{ "\x0c\x20\x33", 's', -1, -1, "0sDCAz", },
{ "\x0c\x20\x34", 's', -1, -1, "0sDCA0", },
{ "\x0c\x20\x3d", 's', -1, -1, "0sDCA9", },
{ "\x0c\x20\x3e", 's', -1, -1, "0sDCA+", },
{ "\x0c\x20\x3f", 's', -1, -1, "0sDCA/", },
{ "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 's', -1, -1, "0sAbraCadabra+", },
{ "\x01\xba\xda\x09\xa7\x5a\x6e\xb6\xbe", 64, -1, -1, "AbraCadabra+", },
{ NULL, 'x', -1, -1, NULL, },
};
/*
- regress - regression-test ttodata() and datatot()
*/
static void
check(r, buf, n, oops, status)
struct artab *r;
char *buf;
size_t n;
err_t oops;
int *status;
{
if (oops != NULL && r->data == NULL)
{} /* error expected */
else if (oops != NULL) {
printf("`%s' gave error `%s', expecting %d `", r->ascii,
oops, strlen(r->data));
hexout(r->data, strlen(r->data), stdout);
printf("'\n");
*status = 1;
} else if (r->data == NULL) {
printf("`%s' gave %d `", r->ascii, n);
hexout(buf, n, stdout);
printf("', expecting error\n");
*status = 1;
} else if (n != strlen(r->data)) {
printf("length wrong in `%s': got %d `", r->ascii, n);
hexout(buf, n, stdout);
printf("', expecting %d `", strlen(r->data));
hexout(r->data, strlen(r->data), stdout);
printf("'\n");
*status = 1;
} else if (memcmp(buf, r->data, n) != 0) {
printf("`%s' gave %d `", r->ascii, n);
hexout(buf, n, stdout);
printf("', expecting %d `", strlen(r->data));
hexout(r->data, strlen(r->data), stdout);
printf("'\n");
*status = 1;
}
fflush(stdout);
}
static void /* should not return at all, in fact */
regress(pgm)
char *pgm;
{
struct artab *r;
struct drtab *dr;
char buf[100];
size_t n;
int status = 0;
for (r = atodatatab; r->ascii != NULL; r++) {
int base = r->base;
int xbase = 0;
if ((base == 0 || base == IGNORESPACE_BIAS + 0) && r->ascii[0] == '0') {
switch (r->ascii[1]) {
case 'x':
case 'X':
xbase = 16;
break;
case 's':
case 'S':
xbase = 64;
break;
case 't':
case 'T':
xbase = 256;
break;
}
}
if (base >= IGNORESPACE_BIAS) {
base = base - IGNORESPACE_BIAS;
check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
if (xbase != 0)
check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
} else {
check(r, buf, n, ttodata(r->ascii, 0, base, buf, sizeof(buf), &n), &status);
if (base == 64 || xbase == 64)
check(r, buf, n, ttodatav(r->ascii, 0, base, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
if (xbase != 0) {
check(r, buf, n, ttodata(r->ascii+2, 0, xbase, buf, sizeof(buf), &n), &status);
if (base == 64 || xbase == 64)
check(r, buf, n, ttodatav(r->ascii+2, 0, xbase, buf, sizeof(buf), &n, NULL, 0, TTODATAV_IGNORESPACE), &status);
}
}
}
for (dr = datatoatab; dr->data != NULL; dr++) {
size_t should;
strcpy(buf, "---");
n = datatot(dr->data, strlen(dr->data), dr->format, buf,
(dr->buflen == -1) ? sizeof(buf) : dr->buflen);
should = (dr->ascii == NULL) ? 0 : strlen(dr->ascii) + 1;
if (dr->outlen != -1)
should = dr->outlen;
if (n == 0 && dr->ascii == NULL)
{} /* error expected */
else if (n == 0) {
printf("`");
hexout(dr->data, strlen(dr->data), stdout);
printf("' %c gave error, expecting %d `%s'\n",
dr->format, should, dr->ascii);
status = 1;
} else if (dr->ascii == NULL) {
printf("`");
hexout(dr->data, strlen(dr->data), stdout);
printf("' %c gave %d `%.*s', expecting error\n",
dr->format, n, (int)n, buf);
status = 1;
} else if (n != should) {
printf("length wrong in `");
hexout(dr->data, strlen(dr->data), stdout);
printf("': got %d `%s'", n, buf);
printf(", expecting %d `%s'\n", should, dr->ascii);
status = 1;
} else if (strcmp(buf, dr->ascii) != 0) {
printf("`");
hexout(dr->data, strlen(dr->data), stdout);
printf("' gave %d `%s'", n, buf);
printf(", expecting %d `%s'\n", should, dr->ascii);
status = 1;
}
fflush(stdout);
}
exit(status);
}
#endif /* TTODATA_MAIN */
+30
View File
@@ -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 <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*/
#ifndef TTODATA_H_
#define TTODATA_H_
#include <types.h>
#define TTODATAV_BUF 40 /* ttodatav's largest non-literal message */
#define TTODATAV_IGNORESPACE (1<<1) /* ignore spaces in base64 encodings*/
#define TTODATAV_SPACECOUNTS 0 /* do not ignore spaces in base64 */
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_ */
+197 -1
View File
@@ -28,7 +28,7 @@
#include "rsa_private_key.h"
#include <daemon.h>
#include <asn1/der_decoder.h>
#include <asn1-pluto/asn1-pluto.h>
/*
@@ -138,6 +138,8 @@ struct private_rsa_private_key_t {
};
#if 0
Not used yet, since we use plutos ASN1 stuff
/**
* Rules for de-/encoding of a private key from/in ASN1
*/
@@ -154,6 +156,51 @@ static asn1_rule_t rsa_private_key_rules[] = {
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, coeff), 0},
{ASN1_END, 0, 0, 0},
};
#endif
struct {
const char *name;
size_t offset;
} RSA_private_field[] = {
{ "Modulus", offsetof(private_rsa_private_key_t, n) },
{ "PublicExponent", offsetof(private_rsa_private_key_t, e) },
{ "PrivateExponent", offsetof(private_rsa_private_key_t, d) },
{ "Prime1", offsetof(private_rsa_private_key_t, p) },
{ "Prime2", offsetof(private_rsa_private_key_t, q) },
{ "Exponent1", offsetof(private_rsa_private_key_t, exp1) },
{ "Exponent2", offsetof(private_rsa_private_key_t, exp2) },
{ "Coefficient", offsetof(private_rsa_private_key_t, coeff) },
};
/* ASN.1 definition of a PKCS#1 RSA private key */
static const asn1Object_t privkeyObjects[] = {
{ 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
{ 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
{ 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
{ 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
{ 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
{ 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
{ 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
{ 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
{ 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
{ 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
{ 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
ASN1_LOOP }, /* 10 */
{ 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
{ 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
{ 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
{ 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
{ 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */
};
#define PKCS1_PRIV_KEY_VERSION 1
#define PKCS1_PRIV_KEY_MODULUS 2
#define PKCS1_PRIV_KEY_PUB_EXP 3
#define PKCS1_PRIV_KEY_COEFF 9
#define PKCS1_PRIV_KEY_ROOF 16
static private_rsa_private_key_t *rsa_private_key_create_empty();
@@ -548,6 +595,9 @@ rsa_private_key_t *rsa_private_key_create(size_t key_size)
return &this->public;
}
#if 0
NOT used yet, since we use plutos ASN1 parser for now
/*
* see header
*/
@@ -579,6 +629,152 @@ rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk)
this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
return &this->public;
}
#endif
static status_t check(private_rsa_private_key_t *this)
{
mpz_t t, u, q1;
status_t status = SUCCESS;
/* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets.
* We actually require more (for security).
*/
if (this->k < 512/8)
return FAILED;
/* we picked a max modulus size to simplify buffer allocation */
if (this->k > 8192/8)
return FAILED;
mpz_init(t);
mpz_init(u);
mpz_init(q1);
/* check that n == p * q */
mpz_mul(u, this->p, this->q);
if (mpz_cmp(u, this->n) != 0)
{
status = FAILED;
}
/* check that e divides neither p-1 nor q-1 */
mpz_sub_ui(t, this->p, 1);
mpz_mod(t, t, this->e);
if (mpz_cmp_ui(t, 0) == 0)
{
status = FAILED;
}
mpz_sub_ui(t, this->q, 1);
mpz_mod(t, t, this->e);
if (mpz_cmp_ui(t, 0) == 0)
{
status = FAILED;
}
/* check that d is e^-1 (mod lcm(p-1, q-1)) */
/* see PKCS#1v2, aka RFC 2437, for the "lcm" */
mpz_sub_ui(q1, this->q, 1);
mpz_sub_ui(u, this->p, 1);
mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */
mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */
mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */
mpz_mul(t, this->d, this->e);
mpz_mod(t, t, u);
if (mpz_cmp_ui(t, 1) != 0)
{
status = FAILED;
}
/* check that exp1 is d mod (p-1) */
mpz_sub_ui(u, this->p, 1);
mpz_mod(t, this->d, u);
if (mpz_cmp(t, this->exp1) != 0)
{
status = FAILED;
}
/* check that exp2 is d mod (q-1) */
mpz_sub_ui(u, this->q, 1);
mpz_mod(t, this->d, u);
if (mpz_cmp(t, this->exp2) != 0)
{
status = FAILED;
}
/* check that coeff is (q^-1) mod p */
mpz_mul(t, this->coeff, this->q);
mpz_mod(t, t, this->p);
if (mpz_cmp_ui(t, 1) != 0)
{
status = FAILED;
}
mpz_clear(t);
mpz_clear(u);
mpz_clear(q1);
return status;
}
/*
* Parses a PKCS#1 private key
*/
rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t blob)
{
asn1_ctx_t ctx;
chunk_t object;
u_int level;
int objectID = 0;
private_rsa_private_key_t *this;
this = rsa_private_key_create_empty();
mpz_init(this->n);
mpz_init(this->e);
mpz_init(this->p);
mpz_init(this->q);
mpz_init(this->d);
mpz_init(this->exp1);
mpz_init(this->exp2);
mpz_init(this->coeff);
asn1_init(&ctx, blob, 0, FALSE);
while (objectID < PKCS1_PRIV_KEY_ROOF)
{
if (!extract_object(privkeyObjects, &objectID, &object, &level, &ctx))
{
return FALSE;
}
if (objectID == PKCS1_PRIV_KEY_VERSION)
{
if (object.len > 0 && *object.ptr != 0)
{
destroy(this);
return NULL;
}
}
else if (objectID >= PKCS1_PRIV_KEY_MODULUS &&
objectID <= PKCS1_PRIV_KEY_COEFF)
{
mpz_t *u = (mpz_t *) ((char *)this
+ RSA_private_field[objectID - PKCS1_PRIV_KEY_MODULUS].offset);
mpz_import(*u, object.len, 1, 1, 1, 0, object.ptr);
}
objectID++;
}
if (check(this) != SUCCESS)
{
destroy(this);
return NULL;
}
else
{
return &this->public;
}
}
/*
* see header
+5
View File
@@ -145,6 +145,11 @@ struct chunk_t {
*/
extern chunk_t CHUNK_INITIALIZER;
/**
* Initialize a chunk to a static buffer
*/
#define chunk_from_buf(str) { str, sizeof(str) }
/**
* Clone chunk contents in a newly allocated chunk
*/
+4 -4
View File
@@ -220,11 +220,11 @@ static void log_bytes(private_logger_t *this, log_level_t loglevel, char *label,
buffer_pos = buffer;
if (this->output == NULL)
{
syslog(LOG_INFO, "[=>] [%5d ] %s %s", line_start, buffer, ascii_buffer);
syslog(LOG_INFO, "[=>] [%5d] %s %s", line_start, buffer, ascii_buffer);
}
else
{
fprintf(this->output, "[=>] [%5d ] %s %s\n", line_start, buffer, ascii_buffer);
fprintf(this->output, "[=>] [%5d] %s %s\n", line_start, buffer, ascii_buffer);
}
memset(ascii_buffer, 0, 16);
line_start += 16;
@@ -257,11 +257,11 @@ static void log_bytes(private_logger_t *this, log_level_t loglevel, char *label,
buffer_pos = buffer;
if (this->output == NULL)
{
syslog(LOG_INFO, "[=>] [%5d ] %s %16s", line_start, buffer, ascii_buffer);
syslog(LOG_INFO, "[=>] [%5d] %s %16s", line_start, buffer, ascii_buffer);
}
else
{
fprintf(this->output, "[=>] [%5d ] %s %16s\n", line_start, buffer, ascii_buffer);
fprintf(this->output, "[=>] [%5d] %s %16s\n", line_start, buffer, ascii_buffer);
}
}
pthread_mutex_unlock(&mutex);
+2
View File
@@ -50,6 +50,7 @@ mapping_t logger_context_t_mappings[] = {
{PAYLOAD, "PAYLOAD"},
{DER_DECODER, "DER_DECODER"},
{DER_ENCODER, "DER_ENCODER"},
{ASN1, "ASN1"},
{MAPPING_END, NULL},
};
@@ -77,6 +78,7 @@ struct {
{ "PAYLD", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* PAYLOAD */
{ "DERDC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* DER_DECODER */
{ "DEREC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* DER_ENCODER */
{ "ASN_1", ERROR|CONTROL|AUDIT|RAW|LEVEL3, TRUE }, /* ASN1 */
};
+1
View File
@@ -56,6 +56,7 @@ enum logger_context_t {
PAYLOAD,
DER_DECODER,
DER_ENCODER,
ASN1,
LOGGER_CONTEXT_ROOF,
};