This commit is contained in:
@@ -1,31 +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 <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.
|
||||
#
|
||||
|
||||
LIB_DIR= $(MAIN_DIR)lib/
|
||||
|
||||
include $(MAIN_DIR)lib/utils/Makefile.utils
|
||||
include $(MAIN_DIR)lib/crypto/Makefile.transforms
|
||||
include $(MAIN_DIR)lib/asn1/Makefile.asn1
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)types.o
|
||||
$(BUILD_DIR)types.o : $(LIB_DIR)types.c $(LIB_DIR)types.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)definitions.o
|
||||
$(BUILD_DIR)definitions.o : $(LIB_DIR)definitions.c $(LIB_DIR)definitions.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)library.o
|
||||
$(BUILD_DIR)library.o : $(LIB_DIR)library.c $(LIB_DIR)library.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
@@ -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 <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/
|
||||
|
||||
|
||||
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.o
|
||||
$(BUILD_DIR)asn1.o : $(ASN1_DIR)asn1.c $(ASN1_DIR)asn1.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 $@ $<
|
||||
@@ -1,751 +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 <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.h"
|
||||
|
||||
#include <utils/logger_manager.h>
|
||||
|
||||
/* 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
|
||||
|
||||
static logger_t *logger = NULL;
|
||||
|
||||
/**
|
||||
* initializes the ASN.1 logger
|
||||
*/
|
||||
static void asn1_init_logger(void)
|
||||
{
|
||||
if (logger == NULL)
|
||||
logger = logger_manager->get_logger(logger_manager, ASN1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 safe
|
||||
*/
|
||||
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)
|
||||
{
|
||||
asn1_init_logger();
|
||||
|
||||
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;
|
||||
|
||||
asn1_init_logger();
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -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 <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>
|
||||
#include <asn1/oid.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;
|
||||
|
||||
#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 */
|
||||
@@ -1,197 +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 <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, 174, 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 */
|
||||
{ 0x03, 172, 1, "directory" }, /* 169 */
|
||||
{ 0x01, 0, 1, "" }, /* 170 */
|
||||
{ 0x03, 0, 0, "employeeNumber" }, /* 171 */
|
||||
{ 0x04, 0, 1, "policy" }, /* 172 */
|
||||
{ 0x01, 0, 0, "nsSGC" }, /* 173 */
|
||||
{ 0x45, 0, 1, "verisign" }, /* 174 */
|
||||
{ 0x01, 0, 1, "pki" }, /* 175 */
|
||||
{ 0x09, 0, 1, "attributes" }, /* 176 */
|
||||
{ 0x02, 178, 0, "messageType" }, /* 177 */
|
||||
{ 0x03, 179, 0, "pkiStatus" }, /* 178 */
|
||||
{ 0x04, 180, 0, "failInfo" }, /* 179 */
|
||||
{ 0x05, 181, 0, "senderNonce" }, /* 180 */
|
||||
{ 0x06, 182, 0, "recipientNonce" }, /* 181 */
|
||||
{ 0x07, 183, 0, "transID" }, /* 182 */
|
||||
{ 0x08, 0, 0, "extensionReq" } /* 183 */
|
||||
};
|
||||
@@ -1,80 +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!
|
||||
*/
|
||||
|
||||
#ifndef OID_H_
|
||||
#define OID_H_
|
||||
|
||||
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 177
|
||||
#define OID_PKI_STATUS 178
|
||||
#define OID_PKI_FAIL_INFO 179
|
||||
#define OID_PKI_SENDER_NONCE 180
|
||||
#define OID_PKI_RECIPIENT_NONCE 181
|
||||
#define OID_PKI_TRANS_ID 182
|
||||
|
||||
#endif /* OID_H_ */
|
||||
@@ -1,127 +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 <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",
|
||||
"#ifndef OID_H_\n",
|
||||
"#define OID_H_\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++;
|
||||
}
|
||||
|
||||
print OID_H "\n#endif /* OID_H_ */\n";
|
||||
|
||||
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;
|
||||
@@ -1,184 +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
|
||||
0x03 "directory"
|
||||
0x01 ""
|
||||
0x03 "employeeNumber"
|
||||
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"
|
||||
@@ -1,344 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001-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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "asn1.h"
|
||||
#include "pem.h"
|
||||
#include "ttodata.h"
|
||||
|
||||
#include <utils/lexparser.h>
|
||||
#include <utils/logger_manager.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
#include <crypto/crypters/crypter.h>
|
||||
|
||||
static logger_t *logger = NULL;
|
||||
|
||||
/**
|
||||
* initializes the PEM logger
|
||||
*/
|
||||
static void pem_init_logger(void)
|
||||
{
|
||||
if (logger == NULL)
|
||||
logger = logger_manager->get_logger(logger_manager, ASN1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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))
|
||||
{
|
||||
logger->log(logger, CONTROL|LEVEL2,
|
||||
" -----%s %.*s-----", tag, (int)name.len, name.ptr);
|
||||
return TRUE;
|
||||
}
|
||||
line->ptr++; line->len--; name.len++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* decrypts a DES-EDE-CBC encrypted data block
|
||||
*/
|
||||
static err_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 = {(char*)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_hash_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 "invalid passphrase";
|
||||
}
|
||||
/* remove padding */
|
||||
blob->len -= padding;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Converts a PEM encoded file into its binary form
|
||||
*
|
||||
* RFC 1421 Privacy Enhancement for Electronic Mail, February 1993
|
||||
* RFC 934 Message Encapsulation, January 1985
|
||||
*/
|
||||
err_t pem_to_bin(chunk_t *blob, char *passphrase, bool *pgp)
|
||||
{
|
||||
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;
|
||||
|
||||
pem_init_logger();
|
||||
|
||||
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 parameter: value pair */
|
||||
logger->log(logger, CONTROL|LEVEL2, " %.*s", (int)line.len, line.ptr);
|
||||
if (!extract_parameter_value(&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 "encryption algorithm not supported";
|
||||
|
||||
eat_whitespace(&value);
|
||||
ugh = ttodata(value.ptr, value.len, 16, iv.ptr, 16, &len);
|
||||
if (ugh)
|
||||
return "error in IV";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* check for PGP armor checksum */
|
||||
if (*data.ptr == '=')
|
||||
{
|
||||
*pgp = TRUE;
|
||||
data.ptr++;
|
||||
data.len--;
|
||||
logger->log(logger, CONTROL|LEVEL2, " Armor checksum: %.*s",
|
||||
(int)data.len, data.ptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
ugh = ttodata(data.ptr, data.len, 64, dst.ptr, blob->len - dst.len, &len);
|
||||
if (ugh)
|
||||
{
|
||||
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 "file coded in unknown format, discarded";
|
||||
|
||||
return (encrypted)? pem_decrypt(blob, &iv, passphrase) : NULL;
|
||||
}
|
||||
|
||||
/* load a coded key or certificate file with autodetection
|
||||
* of binary DER or base64 PEM ASN.1 formats and armored PGP format
|
||||
*/
|
||||
bool pem_asn1_load_file(const char *filename, char *passphrase,
|
||||
const char *type, chunk_t *blob, bool *pgp)
|
||||
{
|
||||
err_t ugh = NULL;
|
||||
|
||||
FILE *fd = fopen(filename, "r");
|
||||
|
||||
pem_init_logger();
|
||||
|
||||
if (fd)
|
||||
{
|
||||
int bytes;
|
||||
fseek(fd, 0, SEEK_END );
|
||||
blob->len = ftell(fd);
|
||||
rewind(fd);
|
||||
blob->ptr = malloc(blob->len);
|
||||
bytes = fread(blob->ptr, 1, blob->len, fd);
|
||||
fclose(fd);
|
||||
logger->log(logger, CONTROL, "loaded %s file '%s' (%d bytes)", type, filename, bytes);
|
||||
|
||||
*pgp = FALSE;
|
||||
|
||||
/* try DER format */
|
||||
if (is_asn1(*blob))
|
||||
{
|
||||
logger->log(logger, CONTROL|LEVEL1, " file coded in DER format");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* try PEM format */
|
||||
ugh = pem_to_bin(blob, passphrase, pgp);
|
||||
|
||||
if (ugh == NULL)
|
||||
{
|
||||
if (*pgp)
|
||||
{
|
||||
logger->log(logger, CONTROL|LEVEL1, " file coded in armored PGP format");
|
||||
return TRUE;
|
||||
}
|
||||
if (is_asn1(*blob))
|
||||
{
|
||||
logger->log(logger, CONTROL|LEVEL1, " file coded in PEM format");
|
||||
return TRUE;
|
||||
}
|
||||
ugh = "file coded in unknown format, discarded";
|
||||
}
|
||||
|
||||
/* a conversion error has occured */
|
||||
logger->log(logger, ERROR, " %s", ugh);
|
||||
chunk_free(blob);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->log(logger, ERROR, "could not open %s file '%s'", type, filename);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2001-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.
|
||||
*/
|
||||
|
||||
#ifndef PEM_H_
|
||||
#define PEM_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
err_t pem_to_bin(chunk_t *blob, char *passphrase, bool *pgp);
|
||||
|
||||
bool pem_asn1_load_file(const char *filename, char *passphrase,
|
||||
const char *type, chunk_t *blob, bool *pgp);
|
||||
|
||||
#endif /*PEM_H_*/
|
||||
@@ -1,378 +0,0 @@
|
||||
/*
|
||||
* convert from text form of arbitrary data (e.g., keys) to binary
|
||||
* Copyright (C) 2000 Henry Spencer.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Library General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
||||
* License for more details.
|
||||
*/
|
||||
|
||||
#include "ttodata.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* converters and misc */
|
||||
static int unhex(const char *, char *, size_t);
|
||||
static int unb64(const char *, char *, size_t);
|
||||
static int untext(const char *, char *, size_t);
|
||||
static const char *badch(const char *, int, char *, size_t);
|
||||
|
||||
/* internal error codes for converters */
|
||||
#define SHORT (-2) /* internal buffer too short */
|
||||
#define BADPAD (-3) /* bad base64 padding */
|
||||
#define BADCH0 (-4) /* invalid character 0 */
|
||||
#define BADCH1 (-5) /* invalid character 1 */
|
||||
#define BADCH2 (-6) /* invalid character 2 */
|
||||
#define BADCH3 (-7) /* invalid character 3 */
|
||||
#define BADOFF(code) (BADCH0-(code))
|
||||
|
||||
/**
|
||||
* @brief convert text to data, with verbose error reports
|
||||
*
|
||||
* If some of this looks slightly odd, it's because it has changed
|
||||
* repeatedly (from the original atodata()) without a major rewrite.
|
||||
*
|
||||
* @param src
|
||||
* @param srclen 0 means apply strlen()
|
||||
* @param base 0 means figure it out
|
||||
* @param dst need not be valid if dstlen is 0
|
||||
* @param dstlen
|
||||
* @param lenp where to record length (NULL is nowhere)
|
||||
* @param errp error buffer
|
||||
* @param flags
|
||||
* @return NULL on success, else literal or errp
|
||||
*/
|
||||
const char *ttodatav(const char *src, size_t srclen, int base, char *dst, size_t dstlen, size_t *lenp, char *errp, size_t errlen, unsigned int flags)
|
||||
{
|
||||
size_t ingroup; /* number of input bytes converted at once */
|
||||
char buf[4]; /* output from conversion */
|
||||
int nbytes; /* size of output */
|
||||
int (*decode)(const char *, char *, size_t);
|
||||
char *stop;
|
||||
int ndone;
|
||||
int i;
|
||||
int underscoreok;
|
||||
int skipSpace = 0;
|
||||
|
||||
if (srclen == 0)
|
||||
srclen = strlen(src);
|
||||
if (dstlen == 0)
|
||||
dst = buf; /* point it somewhere valid */
|
||||
stop = dst + dstlen;
|
||||
|
||||
if (base == 0) {
|
||||
if (srclen < 2)
|
||||
return "input too short to be valid";
|
||||
if (*src++ != '0')
|
||||
return "input does not begin with format prefix";
|
||||
switch (*src++) {
|
||||
case 'x':
|
||||
case 'X':
|
||||
base = 16;
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
base = 64;
|
||||
break;
|
||||
case 't':
|
||||
case 'T':
|
||||
base = 256;
|
||||
break;
|
||||
default:
|
||||
return "unknown format prefix";
|
||||
}
|
||||
srclen -= 2;
|
||||
}
|
||||
switch (base) {
|
||||
case 16:
|
||||
decode = unhex;
|
||||
underscoreok = 1;
|
||||
ingroup = 2;
|
||||
break;
|
||||
case 64:
|
||||
decode = unb64;
|
||||
underscoreok = 0;
|
||||
ingroup = 4;
|
||||
if(flags & TTODATAV_IGNORESPACE) {
|
||||
skipSpace = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 256:
|
||||
decode = untext;
|
||||
ingroup = 1;
|
||||
underscoreok = 0;
|
||||
break;
|
||||
default:
|
||||
return "unknown base";
|
||||
}
|
||||
|
||||
/* proceed */
|
||||
ndone = 0;
|
||||
while (srclen > 0) {
|
||||
char stage[4]; /* staging area for group */
|
||||
size_t sl = 0;
|
||||
|
||||
/* Grab ingroup characters into stage,
|
||||
* squeezing out blanks if we are supposed to ignore them.
|
||||
*/
|
||||
for (sl = 0; sl < ingroup; src++, srclen--) {
|
||||
if (srclen == 0)
|
||||
return "input ends in mid-byte, perhaps truncated";
|
||||
else if (!(skipSpace && (*src == ' ' || *src == '\t')))
|
||||
stage[sl++] = *src;
|
||||
}
|
||||
|
||||
nbytes = (*decode)(stage, buf, sizeof(buf));
|
||||
switch (nbytes) {
|
||||
case BADCH0:
|
||||
case BADCH1:
|
||||
case BADCH2:
|
||||
case BADCH3:
|
||||
return badch(stage, nbytes, errp, errlen);
|
||||
case SHORT:
|
||||
return "internal buffer too short (\"can't happen\")";
|
||||
case BADPAD:
|
||||
return "bad (non-zero) padding at end of base64 input";
|
||||
}
|
||||
if (nbytes <= 0)
|
||||
return "unknown internal error";
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
if (dst < stop)
|
||||
*dst++ = buf[i];
|
||||
ndone++;
|
||||
}
|
||||
while (srclen >= 1 && skipSpace && (*src == ' ' || *src == '\t')){
|
||||
src++;
|
||||
srclen--;
|
||||
}
|
||||
if (underscoreok && srclen > 1 && *src == '_') {
|
||||
/* srclen > 1 means not last character */
|
||||
src++;
|
||||
srclen--;
|
||||
}
|
||||
}
|
||||
|
||||
if (ndone == 0)
|
||||
return "no data bytes specified by input";
|
||||
if (lenp != NULL)
|
||||
*lenp = ndone;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ttodata - convert text to data
|
||||
*
|
||||
* @param src
|
||||
* @param srclen 0 means apply strlen()
|
||||
* @param base 0 means figure it out
|
||||
* @param dst need not be valid if dstlen is 0
|
||||
* @param dstlen
|
||||
* @param lenp where to record length (NULL is nowhere)
|
||||
* @return NULL on success, else literal
|
||||
*/
|
||||
const char *ttodata(const char *src, size_t srclen, int base, char *dst, size_t dstlen, size_t *lenp)
|
||||
{
|
||||
return ttodatav(src, srclen, base, dst, dstlen, lenp, (char *)NULL,
|
||||
(size_t)0, TTODATAV_SPACECOUNTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief atodata - convert ASCII to data
|
||||
*
|
||||
* backward-compatibility interface
|
||||
*
|
||||
* @param src
|
||||
* @param srclen
|
||||
* @param dst
|
||||
* @param dstlen
|
||||
* @return 0 for failure, true length for success
|
||||
*/
|
||||
size_t atodata(const char *src, size_t srclen, char *dst, size_t dstlen)
|
||||
{
|
||||
size_t len;
|
||||
const char *err;
|
||||
|
||||
err = ttodata(src, srclen, 0, dst, dstlen, &len);
|
||||
if (err != NULL)
|
||||
return 0;
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief atobytes - convert ASCII to data bytes
|
||||
*
|
||||
* another backward-compatibility interface
|
||||
*/
|
||||
const char *atobytes(const char *src, size_t srclen, char *dst, size_t dstlen, size_t *lenp)
|
||||
{
|
||||
return ttodata(src, srclen, 0, dst, dstlen, lenp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unhex - convert two ASCII hex digits to byte
|
||||
*
|
||||
* @param src known to be full length
|
||||
* @param dstnumber of result bytes, or error code
|
||||
* @param dstlen not large enough is a failure
|
||||
* @return
|
||||
*/
|
||||
static int unhex(const char *src, char *dst, size_t dstlen)
|
||||
{
|
||||
char *p;
|
||||
unsigned byte;
|
||||
static char hex[] = "0123456789abcdef";
|
||||
|
||||
if (dstlen < 1)
|
||||
return SHORT;
|
||||
|
||||
p = strchr(hex, *src);
|
||||
if (p == NULL)
|
||||
p = strchr(hex, tolower(*src));
|
||||
if (p == NULL)
|
||||
return BADCH0;
|
||||
byte = (p - hex) << 4;
|
||||
src++;
|
||||
|
||||
p = strchr(hex, *src);
|
||||
if (p == NULL)
|
||||
p = strchr(hex, tolower(*src));
|
||||
if (p == NULL)
|
||||
return BADCH1;
|
||||
byte |= (p - hex);
|
||||
|
||||
*dst = byte;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief unb64 - convert four ASCII base64 digits to three bytes
|
||||
*
|
||||
* Note that a base64 digit group is padded out with '=' if it represents
|
||||
* less than three bytes: one byte is dd==, two is ddd=, three is dddd.
|
||||
*
|
||||
* @param src known to be full length
|
||||
* @param dst
|
||||
* @param dstlen
|
||||
* @return number of result bytes, or error code
|
||||
*/
|
||||
static int unb64(const char *src, char *dst, size_t dstlen)
|
||||
{
|
||||
char *p;
|
||||
unsigned byte1;
|
||||
unsigned byte2;
|
||||
static char base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
if (dstlen < 3)
|
||||
return SHORT;
|
||||
|
||||
p = strchr(base64, *src++);
|
||||
|
||||
if (p == NULL)
|
||||
return BADCH0;
|
||||
byte1 = (p - base64) << 2; /* first six bits */
|
||||
|
||||
p = strchr(base64, *src++);
|
||||
if (p == NULL) {
|
||||
return BADCH1;
|
||||
}
|
||||
|
||||
byte2 = p - base64; /* next six: two plus four */
|
||||
*dst++ = byte1 | (byte2 >> 4);
|
||||
byte1 = (byte2 & 0xf) << 4;
|
||||
|
||||
p = strchr(base64, *src++);
|
||||
if (p == NULL) {
|
||||
if (*(src-1) == '=' && *src == '=') {
|
||||
if (byte1 != 0) /* bad padding */
|
||||
return BADPAD;
|
||||
return 1;
|
||||
}
|
||||
return BADCH2;
|
||||
}
|
||||
|
||||
byte2 = p - base64; /* next six: four plus two */
|
||||
*dst++ = byte1 | (byte2 >> 2);
|
||||
byte1 = (byte2 & 0x3) << 6;
|
||||
|
||||
p = strchr(base64, *src++);
|
||||
if (p == NULL) {
|
||||
if (*(src-1) == '=') {
|
||||
if (byte1 != 0) /* bad padding */
|
||||
return BADPAD;
|
||||
return 2;
|
||||
}
|
||||
return BADCH3;
|
||||
}
|
||||
byte2 = p - base64; /* last six */
|
||||
*dst++ = byte1 | byte2;
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief untext - convert one ASCII character to byte
|
||||
*
|
||||
* @param src known to be full length
|
||||
* @param dst
|
||||
* @param dstlen not large enough is a failure
|
||||
* @return number of result bytes, or error code
|
||||
*/
|
||||
static int untext(const char *src, char *dst, size_t dstlen)
|
||||
{
|
||||
if (dstlen < 1)
|
||||
return SHORT;
|
||||
|
||||
*dst = *src;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief badch - produce a nice complaint about an unknown character
|
||||
*
|
||||
* If the compiler complains that the array bigenough[] has a negative
|
||||
* size, that means the TTODATAV_BUF constant has been set too small.
|
||||
*
|
||||
* @param src
|
||||
* @param errcode
|
||||
* @param errp might be NULL
|
||||
* @param errlen
|
||||
* @return literal or errp
|
||||
*/
|
||||
static const char *badch(const char *src, int errcode, char *errp, size_t errlen)
|
||||
{
|
||||
static const char pre[] = "unknown character (`";
|
||||
static const char suf[] = "') in input";
|
||||
char buf[5];
|
||||
# define REQD (sizeof(pre) - 1 + sizeof(buf) - 1 + sizeof(suf))
|
||||
struct sizecheck {
|
||||
char bigenough[TTODATAV_BUF - REQD]; /* see above */
|
||||
};
|
||||
char ch;
|
||||
|
||||
if (errp == NULL || errlen < REQD)
|
||||
return "unknown character in input";
|
||||
strcpy(errp, pre);
|
||||
ch = *(src + BADOFF(errcode));
|
||||
if (isprint(ch)) {
|
||||
buf[0] = ch;
|
||||
buf[1] = '\0';
|
||||
} else {
|
||||
buf[0] = '\\';
|
||||
buf[1] = ((ch & 0700) >> 6) + '0';
|
||||
buf[2] = ((ch & 0070) >> 3) + '0';
|
||||
buf[3] = ((ch & 0007) >> 0) + '0';
|
||||
buf[4] = '\0';
|
||||
}
|
||||
strcat(errp, buf);
|
||||
strcat(errp, suf);
|
||||
return (const char *)errp;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* convert from text form of arbitrary data (e.g., keys) to binary
|
||||
* Copyright (C) 2000 Henry Spencer.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Library General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
|
||||
* License for more details.
|
||||
*/
|
||||
|
||||
#ifndef TTODATA_H_
|
||||
#define TTODATA_H_
|
||||
|
||||
#include <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 */
|
||||
|
||||
err_t ttodata(const char *src, size_t srclen, int base, char *buf, size_t buflen, size_t *needed);
|
||||
|
||||
|
||||
#endif /* TTODATA_H_ */
|
||||
@@ -1,37 +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 <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.
|
||||
#
|
||||
|
||||
CRYPTO_DIR= $(LIB_DIR)crypto/
|
||||
|
||||
include $(CRYPTO_DIR)crypters/Makefile.crypters
|
||||
include $(CRYPTO_DIR)hashers/Makefile.hashers
|
||||
include $(CRYPTO_DIR)prfs/Makefile.prfs
|
||||
include $(CRYPTO_DIR)signers/Makefile.signers
|
||||
include $(CRYPTO_DIR)rsa/Makefile.rsa
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)diffie_hellman.o
|
||||
$(BUILD_DIR)diffie_hellman.o : $(CRYPTO_DIR)diffie_hellman.c $(CRYPTO_DIR)diffie_hellman.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)hmac.o
|
||||
$(BUILD_DIR)hmac.o : $(CRYPTO_DIR)hmac.c $(CRYPTO_DIR)hmac.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)prf_plus.o
|
||||
$(BUILD_DIR)prf_plus.o : $(CRYPTO_DIR)prf_plus.c $(CRYPTO_DIR)prf_plus.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)x509.o
|
||||
$(BUILD_DIR)x509.o : $(CRYPTO_DIR)x509.c $(CRYPTO_DIR)x509.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
@@ -1,23 +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 <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.
|
||||
#
|
||||
|
||||
CRYPTERS_DIR= $(CRYPTO_DIR)crypters/
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)crypter.o
|
||||
$(BUILD_DIR)crypter.o : $(CRYPTERS_DIR)crypter.c $(CRYPTERS_DIR)crypter.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)aes_cbc_crypter.o
|
||||
$(BUILD_DIR)aes_cbc_crypter.o : $(CRYPTERS_DIR)aes_cbc_crypter.c $(CRYPTERS_DIR)aes_cbc_crypter.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
* @file aes_cbc_crypter.h
|
||||
*
|
||||
* @brief Interface of aes_cbc_crypter_t
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Dr B. R. Gladman <[email protected]>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef AES_CBC_CRYPTER_H_
|
||||
#define AES_CBC_CRYPTER_H_
|
||||
|
||||
#include <crypto/crypters/crypter.h>
|
||||
|
||||
|
||||
typedef struct aes_cbc_crypter_t aes_cbc_crypter_t;
|
||||
|
||||
/**
|
||||
* @brief Class implementing the AES symmetric encryption algorithm.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - aes_cbc_crypter_create()
|
||||
*
|
||||
* @ingroup crypters
|
||||
*/
|
||||
struct aes_cbc_crypter_t {
|
||||
|
||||
/**
|
||||
* The crypter_t interface.
|
||||
*/
|
||||
crypter_t crypter_interface;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor to create aes_cbc_crypter_t objects.
|
||||
*
|
||||
* Supported key sizes are: 16, 24 or 32.
|
||||
*
|
||||
* @param key_size key size in bytes
|
||||
* @return
|
||||
* - aes_cbc_crypter_t object
|
||||
* - NULL if key size not supported
|
||||
*/
|
||||
aes_cbc_crypter_t *aes_cbc_crypter_create(size_t key_size);
|
||||
|
||||
|
||||
#endif /* AES_CBC_CRYPTER_H_ */
|
||||
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
* @file crypter.c
|
||||
*
|
||||
* @brief Generic constructor for crypter_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "crypter.h"
|
||||
|
||||
#include <crypto/crypters/aes_cbc_crypter.h>
|
||||
|
||||
|
||||
/**
|
||||
* String mappings for encryption_algorithm_t.
|
||||
*/
|
||||
mapping_t encryption_algorithm_m[] = {
|
||||
{ENCR_UNDEFINED, "ENCR_UNDEFINED"},
|
||||
{ENCR_DES_IV64, "ENCR_DES_IV64"},
|
||||
{ENCR_DES, "ENCR_DES"},
|
||||
{ENCR_3DES, "ENCR_3DES"},
|
||||
{ENCR_RC5, "ENCR_RC5"},
|
||||
{ENCR_IDEA, "ENCR_IDEA"},
|
||||
{ENCR_CAST, "ENCR_CAST"},
|
||||
{ENCR_BLOWFISH, "ENCR_BLOWFISH"},
|
||||
{ENCR_3IDEA, "ENCR_3IDEA"},
|
||||
{ENCR_DES_IV32, "ENCR_DES_IV32"},
|
||||
{ENCR_NULL, "ENCR_NULL"},
|
||||
{ENCR_AES_CBC, "ENCR_AES_CBC"},
|
||||
{ENCR_AES_CTR, "ENCR_AES_CTR"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
crypter_t *crypter_create(encryption_algorithm_t encryption_algorithm, size_t key_size)
|
||||
{
|
||||
switch (encryption_algorithm)
|
||||
{
|
||||
case ENCR_AES_CBC:
|
||||
{
|
||||
return (crypter_t*)aes_cbc_crypter_create(key_size);
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/**
|
||||
* @file crypter.h
|
||||
*
|
||||
* @brief Interface crypter_t
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTER_H_
|
||||
#define CRYPTER_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef enum encryption_algorithm_t encryption_algorithm_t;
|
||||
|
||||
/**
|
||||
* @brief Encryption algorithm, as in IKEv2 RFC 3.3.2.
|
||||
*
|
||||
* Currently only the following algorithms are implemented and therefore supported:
|
||||
* - ENCR_AES_CBC
|
||||
*
|
||||
* @todo Implement more enryption algorithms, such as 3DES
|
||||
*
|
||||
* @ingroup crypters
|
||||
*/
|
||||
enum encryption_algorithm_t {
|
||||
ENCR_UNDEFINED = 1024,
|
||||
ENCR_DES_IV64 = 1,
|
||||
ENCR_DES = 2,
|
||||
ENCR_3DES = 3,
|
||||
ENCR_RC5 = 4,
|
||||
ENCR_IDEA = 5,
|
||||
ENCR_CAST = 6,
|
||||
ENCR_BLOWFISH = 7,
|
||||
ENCR_3IDEA = 8,
|
||||
ENCR_DES_IV32 = 9,
|
||||
ENCR_NULL = 11,
|
||||
/**
|
||||
* Implemented in class aes_cbc_crypter_t.
|
||||
*/
|
||||
ENCR_AES_CBC = 12,
|
||||
ENCR_AES_CTR = 13
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for encryption_algorithm_t.
|
||||
*/
|
||||
extern mapping_t encryption_algorithm_m[];
|
||||
|
||||
|
||||
typedef struct crypter_t crypter_t;
|
||||
|
||||
/**
|
||||
* @brief Generic interface for symmetric encryption algorithms.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - crypter_create()
|
||||
*
|
||||
* @ingroup crypters
|
||||
*/
|
||||
struct crypter_t {
|
||||
/**
|
||||
* @brief Encrypt a chunk of data and allocate space for the encrypted value.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data data to encrypt
|
||||
* @param iv initializing vector
|
||||
* @param[out] encrypted pointer where the encrypted bytes will be written
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - INVALID_ARG if data size not a multiple of block size
|
||||
*/
|
||||
status_t (*encrypt) (crypter_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted);
|
||||
|
||||
/**
|
||||
* @brief Decrypt a chunk of data and allocate space for the decrypted value.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data data to decrypt
|
||||
* @param iv initializing vector
|
||||
* @param[out] encrypted pointer where the decrypted bytes will be written
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - INVALID_ARG if data size not a multiple of block size
|
||||
*/
|
||||
status_t (*decrypt) (crypter_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted);
|
||||
|
||||
/**
|
||||
* @brief Get the block size of this crypter_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return block size in bytes
|
||||
*/
|
||||
size_t (*get_block_size) (crypter_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the key size of this crypter_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return key size in bytes
|
||||
*/
|
||||
size_t (*get_key_size) (crypter_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set the key for this crypter_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param key key to set
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - INVALID_ARG if key length invalid
|
||||
*/
|
||||
status_t (*set_key) (crypter_t *this, chunk_t key);
|
||||
|
||||
/**
|
||||
* @brief Destroys a crypter_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (crypter_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generic constructor for crypter_t objects.
|
||||
*
|
||||
* Currently only the following algorithms are implemented and therefore supported:
|
||||
* - ENCR_AES_CBC
|
||||
*
|
||||
* The key_size is ignored for algorithms with fixed key size.
|
||||
*
|
||||
* @param encryption_algorithm Algorithm to use for crypter
|
||||
* @param key_size size of the key in bytes
|
||||
* @return
|
||||
* - crypter_t object
|
||||
* - NULL if encryption algorithm/key_size is not supported
|
||||
*/
|
||||
crypter_t *crypter_create(encryption_algorithm_t encryption_algorithm, size_t key_size);
|
||||
|
||||
#endif /*CRYPTER_H_*/
|
||||
@@ -1,615 +0,0 @@
|
||||
/**
|
||||
* @file diffie_hellman.c
|
||||
*
|
||||
* @brief Implementation of diffie_hellman_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
|
||||
* Copyright (C) 1999, 2000, 2001 Henry Spencer.
|
||||
* 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 <gmp.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "diffie_hellman.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <utils/randomizer.h>
|
||||
|
||||
|
||||
/**
|
||||
* String mappings for diffie_hellman_group_t.
|
||||
*/
|
||||
mapping_t diffie_hellman_group_m[] = {
|
||||
{MODP_UNDEFINED, "MODP_UNDEFINED"},
|
||||
{MODP_768_BIT, "MODP_768_BIT"},
|
||||
{MODP_1024_BIT, "MODP_1024_BIT"},
|
||||
{MODP_1536_BIT, "MODP_1536_BIT"},
|
||||
{MODP_2048_BIT, "MODP_2048_BIT"},
|
||||
{MODP_3072_BIT, "MODP_3072_BIT"},
|
||||
{MODP_4096_BIT, "MODP_4096_BIT"},
|
||||
{MODP_6144_BIT, "MODP_6144_BIT"},
|
||||
{MODP_8192_BIT, "MODP_8192_BIT"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Modulus of Group 1 (MODP_768_BIT).
|
||||
*/
|
||||
static u_int8_t group1_modulus[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
|
||||
0xC4,0xC6,0x62,0x8B,0x80 ,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
|
||||
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
|
||||
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
|
||||
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
|
||||
0xF4,0x4C,0x42,0xE9,0xA6,0x3A,0x36,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
* Modulus of Group 2 (MODP_1024_BIT).
|
||||
*/
|
||||
static u_int8_t group2_modulus[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
|
||||
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
|
||||
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
|
||||
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
|
||||
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
|
||||
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
|
||||
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
|
||||
0x49,0x28,0x66,0x51,0xEC,0xE6,0x53,0x81,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
* Modulus of Group 5 (MODP_1536_BIT).
|
||||
*/
|
||||
static u_int8_t group5_modulus[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
|
||||
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
|
||||
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
|
||||
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
|
||||
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
|
||||
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
|
||||
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
|
||||
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
|
||||
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
|
||||
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
|
||||
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
|
||||
0xF1,0x74,0x6C,0x08,0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
|
||||
};
|
||||
/**
|
||||
* Modulus of Group 14 (MODP_2048_BIT).
|
||||
*/
|
||||
static u_int8_t group14_modulus[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
|
||||
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
|
||||
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
|
||||
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
|
||||
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
|
||||
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
|
||||
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
|
||||
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
|
||||
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
|
||||
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
|
||||
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
|
||||
0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
|
||||
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
|
||||
0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
|
||||
0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
|
||||
0x15,0x72,0x8E,0x5A,0x8A,0xAC,0xAA,0x68,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
* Modulus of Group 15 (MODP_3072_BIT).
|
||||
*/
|
||||
static u_int8_t group15_modulus[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
|
||||
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
|
||||
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
|
||||
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
|
||||
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
|
||||
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
|
||||
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
|
||||
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
|
||||
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
|
||||
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
|
||||
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
|
||||
0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
|
||||
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
|
||||
0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
|
||||
0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
|
||||
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
|
||||
0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
|
||||
0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
|
||||
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
|
||||
0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
|
||||
0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
|
||||
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
|
||||
0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
|
||||
0x4B,0x82,0xD1,0x20,0xA9,0x3A,0xD2,0xCA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
* Modulus of Group 16 (MODP_4096_BIT).
|
||||
*/
|
||||
static u_int8_t group16_modulus[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
|
||||
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
|
||||
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
|
||||
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
|
||||
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
|
||||
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
|
||||
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
|
||||
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
|
||||
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
|
||||
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
|
||||
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
|
||||
0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
|
||||
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
|
||||
0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
|
||||
0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
|
||||
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
|
||||
0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
|
||||
0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
|
||||
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
|
||||
0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
|
||||
0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
|
||||
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
|
||||
0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
|
||||
0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
|
||||
0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
|
||||
0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
|
||||
0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
|
||||
0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
|
||||
0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
|
||||
0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
|
||||
0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
|
||||
0x4D,0xF4,0x35,0xC9,0x34,0x06,0x31,0x99,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
* Modulus of Group 17 (MODP_6144_BIT).
|
||||
*/
|
||||
static u_int8_t group17_modulus[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
|
||||
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
|
||||
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
|
||||
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
|
||||
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
|
||||
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
|
||||
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
|
||||
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
|
||||
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
|
||||
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
|
||||
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
|
||||
0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
|
||||
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
|
||||
0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
|
||||
0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
|
||||
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
|
||||
0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
|
||||
0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
|
||||
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
|
||||
0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
|
||||
0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
|
||||
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
|
||||
0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
|
||||
0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
|
||||
0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
|
||||
0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
|
||||
0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
|
||||
0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
|
||||
0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
|
||||
0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
|
||||
0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
|
||||
0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,
|
||||
0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
|
||||
0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE,
|
||||
0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,
|
||||
0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
|
||||
0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42,
|
||||
0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,
|
||||
0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
|
||||
0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E,
|
||||
0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,
|
||||
0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
|
||||
0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0,
|
||||
0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,
|
||||
0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
|
||||
0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68,
|
||||
0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,
|
||||
0xE6,0x94,0xF9,0x1E,0x6D,0xCC,0x40,0x24,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
* Modulus of Group 18 (MODP_8192_BIT).
|
||||
*/
|
||||
static u_int8_t group18_modulus[] = {
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2,0x21,0x68,0xC2,0x34,
|
||||
0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1,0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,
|
||||
0x02,0x0B,0xBE,0xA6,0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD,
|
||||
0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D,0xF2,0x5F,0x14,0x37,
|
||||
0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45,0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,
|
||||
0xF4,0x4C,0x42,0xE9,0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED,
|
||||
0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11,0x7C,0x4B,0x1F,0xE6,
|
||||
0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D,0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,
|
||||
0x98,0xDA,0x48,0x36,0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F,
|
||||
0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56,0x20,0x85,0x52,0xBB,
|
||||
0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D,0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,
|
||||
0xF1,0x74,0x6C,0x08,0xCA,0x18,0x21,0x7C,0x32,0x90,0x5E,0x46,0x2E,0x36,0xCE,0x3B,
|
||||
0xE3,0x9E,0x77,0x2C,0x18,0x0E,0x86,0x03,0x9B,0x27,0x83,0xA2,0xEC,0x07,0xA2,0x8F,
|
||||
0xB5,0xC5,0x5D,0xF0,0x6F,0x4C,0x52,0xC9,0xDE,0x2B,0xCB,0xF6,0x95,0x58,0x17,0x18,
|
||||
0x39,0x95,0x49,0x7C,0xEA,0x95,0x6A,0xE5,0x15,0xD2,0x26,0x18,0x98,0xFA,0x05,0x10,
|
||||
0x15,0x72,0x8E,0x5A,0x8A,0xAA,0xC4,0x2D,0xAD,0x33,0x17,0x0D,0x04,0x50,0x7A,0x33,
|
||||
0xA8,0x55,0x21,0xAB,0xDF,0x1C,0xBA,0x64,0xEC,0xFB,0x85,0x04,0x58,0xDB,0xEF,0x0A,
|
||||
0x8A,0xEA,0x71,0x57,0x5D,0x06,0x0C,0x7D,0xB3,0x97,0x0F,0x85,0xA6,0xE1,0xE4,0xC7,
|
||||
0xAB,0xF5,0xAE,0x8C,0xDB,0x09,0x33,0xD7,0x1E,0x8C,0x94,0xE0,0x4A,0x25,0x61,0x9D,
|
||||
0xCE,0xE3,0xD2,0x26,0x1A,0xD2,0xEE,0x6B,0xF1,0x2F,0xFA,0x06,0xD9,0x8A,0x08,0x64,
|
||||
0xD8,0x76,0x02,0x73,0x3E,0xC8,0x6A,0x64,0x52,0x1F,0x2B,0x18,0x17,0x7B,0x20,0x0C,
|
||||
0xBB,0xE1,0x17,0x57,0x7A,0x61,0x5D,0x6C,0x77,0x09,0x88,0xC0,0xBA,0xD9,0x46,0xE2,
|
||||
0x08,0xE2,0x4F,0xA0,0x74,0xE5,0xAB,0x31,0x43,0xDB,0x5B,0xFC,0xE0,0xFD,0x10,0x8E,
|
||||
0x4B,0x82,0xD1,0x20,0xA9,0x21,0x08,0x01,0x1A,0x72,0x3C,0x12,0xA7,0x87,0xE6,0xD7,
|
||||
0x88,0x71,0x9A,0x10,0xBD,0xBA,0x5B,0x26,0x99,0xC3,0x27,0x18,0x6A,0xF4,0xE2,0x3C,
|
||||
0x1A,0x94,0x68,0x34,0xB6,0x15,0x0B,0xDA,0x25,0x83,0xE9,0xCA,0x2A,0xD4,0x4C,0xE8,
|
||||
0xDB,0xBB,0xC2,0xDB,0x04,0xDE,0x8E,0xF9,0x2E,0x8E,0xFC,0x14,0x1F,0xBE,0xCA,0xA6,
|
||||
0x28,0x7C,0x59,0x47,0x4E,0x6B,0xC0,0x5D,0x99,0xB2,0x96,0x4F,0xA0,0x90,0xC3,0xA2,
|
||||
0x23,0x3B,0xA1,0x86,0x51,0x5B,0xE7,0xED,0x1F,0x61,0x29,0x70,0xCE,0xE2,0xD7,0xAF,
|
||||
0xB8,0x1B,0xDD,0x76,0x21,0x70,0x48,0x1C,0xD0,0x06,0x91,0x27,0xD5,0xB0,0x5A,0xA9,
|
||||
0x93,0xB4,0xEA,0x98,0x8D,0x8F,0xDD,0xC1,0x86,0xFF,0xB7,0xDC,0x90,0xA6,0xC0,0x8F,
|
||||
0x4D,0xF4,0x35,0xC9,0x34,0x02,0x84,0x92,0x36,0xC3,0xFA,0xB4,0xD2,0x7C,0x70,0x26,
|
||||
0xC1,0xD4,0xDC,0xB2,0x60,0x26,0x46,0xDE,0xC9,0x75,0x1E,0x76,0x3D,0xBA,0x37,0xBD,
|
||||
0xF8,0xFF,0x94,0x06,0xAD,0x9E,0x53,0x0E,0xE5,0xDB,0x38,0x2F,0x41,0x30,0x01,0xAE,
|
||||
0xB0,0x6A,0x53,0xED,0x90,0x27,0xD8,0x31,0x17,0x97,0x27,0xB0,0x86,0x5A,0x89,0x18,
|
||||
0xDA,0x3E,0xDB,0xEB,0xCF,0x9B,0x14,0xED,0x44,0xCE,0x6C,0xBA,0xCE,0xD4,0xBB,0x1B,
|
||||
0xDB,0x7F,0x14,0x47,0xE6,0xCC,0x25,0x4B,0x33,0x20,0x51,0x51,0x2B,0xD7,0xAF,0x42,
|
||||
0x6F,0xB8,0xF4,0x01,0x37,0x8C,0xD2,0xBF,0x59,0x83,0xCA,0x01,0xC6,0x4B,0x92,0xEC,
|
||||
0xF0,0x32,0xEA,0x15,0xD1,0x72,0x1D,0x03,0xF4,0x82,0xD7,0xCE,0x6E,0x74,0xFE,0xF6,
|
||||
0xD5,0x5E,0x70,0x2F,0x46,0x98,0x0C,0x82,0xB5,0xA8,0x40,0x31,0x90,0x0B,0x1C,0x9E,
|
||||
0x59,0xE7,0xC9,0x7F,0xBE,0xC7,0xE8,0xF3,0x23,0xA9,0x7A,0x7E,0x36,0xCC,0x88,0xBE,
|
||||
0x0F,0x1D,0x45,0xB7,0xFF,0x58,0x5A,0xC5,0x4B,0xD4,0x07,0xB2,0x2B,0x41,0x54,0xAA,
|
||||
0xCC,0x8F,0x6D,0x7E,0xBF,0x48,0xE1,0xD8,0x14,0xCC,0x5E,0xD2,0x0F,0x80,0x37,0xE0,
|
||||
0xA7,0x97,0x15,0xEE,0xF2,0x9B,0xE3,0x28,0x06,0xA1,0xD5,0x8B,0xB7,0xC5,0xDA,0x76,
|
||||
0xF5,0x50,0xAA,0x3D,0x8A,0x1F,0xBF,0xF0,0xEB,0x19,0xCC,0xB1,0xA3,0x13,0xD5,0x5C,
|
||||
0xDA,0x56,0xC9,0xEC,0x2E,0xF2,0x96,0x32,0x38,0x7F,0xE8,0xD7,0x6E,0x3C,0x04,0x68,
|
||||
0x04,0x3E,0x8F,0x66,0x3F,0x48,0x60,0xEE,0x12,0xBF,0x2D,0x5B,0x0B,0x74,0x74,0xD6,
|
||||
0xE6,0x94,0xF9,0x1E,0x6D,0xBE,0x11,0x59,0x74,0xA3,0x92,0x6F,0x12,0xFE,0xE5,0xE4,
|
||||
0x38,0x77,0x7C,0xB6,0xA9,0x32,0xDF,0x8C,0xD8,0xBE,0xC4,0xD0,0x73,0xB9,0x31,0xBA,
|
||||
0x3B,0xC8,0x32,0xB6,0x8D,0x9D,0xD3,0x00,0x74,0x1F,0xA7,0xBF,0x8A,0xFC,0x47,0xED,
|
||||
0x25,0x76,0xF6,0x93,0x6B,0xA4,0x24,0x66,0x3A,0xAB,0x63,0x9C,0x5A,0xE4,0xF5,0x68,
|
||||
0x34,0x23,0xB4,0x74,0x2B,0xF1,0xC9,0x78,0x23,0x8F,0x16,0xCB,0xE3,0x9D,0x65,0x2D,
|
||||
0xE3,0xFD,0xB8,0xBE,0xFC,0x84,0x8A,0xD9,0x22,0x22,0x2E,0x04,0xA4,0x03,0x7C,0x07,
|
||||
0x13,0xEB,0x57,0xA8,0x1A,0x23,0xF0,0xC7,0x34,0x73,0xFC,0x64,0x6C,0xEA,0x30,0x6B,
|
||||
0x4B,0xCB,0xC8,0x86,0x2F,0x83,0x85,0xDD,0xFA,0x9D,0x4B,0x7F,0xA2,0xC0,0x87,0xE8,
|
||||
0x79,0x68,0x33,0x03,0xED,0x5B,0xDD,0x3A,0x06,0x2B,0x3C,0xF5,0xB3,0xA2,0x78,0xA6,
|
||||
0x6D,0x2A,0x13,0xF8,0x3F,0x44,0xF8,0x2D,0xDF,0x31,0x0E,0xE0,0x74,0xAB,0x6A,0x36,
|
||||
0x45,0x97,0xE8,0x99,0xA0,0x25,0x5D,0xC1,0x64,0xF3,0x1C,0xC5,0x08,0x46,0x85,0x1D,
|
||||
0xF9,0xAB,0x48,0x19,0x5D,0xED,0x7E,0xA1,0xB1,0xD5,0x10,0xBD,0x7E,0xE7,0x4D,0x73,
|
||||
0xFA,0xF3,0x6B,0xC3,0x1E,0xCF,0xA2,0x68,0x35,0x90,0x46,0xF4,0xEB,0x87,0x9F,0x92,
|
||||
0x40,0x09,0x43,0x8B,0x48,0x1C,0x6C,0xD7,0x88,0x9A,0x00,0x2E,0xD5,0xEE,0x38,0x2B,
|
||||
0xC9,0x19,0x0D,0xA6,0xFC,0x02,0x6E,0x47,0x95,0x58,0xE4,0x47,0x56,0x77,0xE9,0xAA,
|
||||
0x9E,0x30,0x50,0xE2,0x76,0x56,0x94,0xDF,0xC8,0x1F,0x56,0xE8,0x80,0xB9,0x6E,0x71,
|
||||
0x60,0xC9,0x80,0xDD,0x98,0xED,0xD3,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
};
|
||||
|
||||
typedef struct modulus_info_entry_t modulus_info_entry_t;
|
||||
|
||||
/**
|
||||
* Entry of the modulus list.
|
||||
*/
|
||||
struct modulus_info_entry_t {
|
||||
/**
|
||||
* Group number as it is defined in file transform_substructure.h.
|
||||
*/
|
||||
diffie_hellman_group_t group;
|
||||
|
||||
/**
|
||||
* Pointer to first byte of modulus (network order).
|
||||
*/
|
||||
u_int8_t *modulus;
|
||||
|
||||
/*
|
||||
* Length of modulus in bytes.
|
||||
*/
|
||||
size_t modulus_length;
|
||||
|
||||
/*
|
||||
* Generator value.
|
||||
*/
|
||||
u_int16_t generator;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* All supported modulus values.
|
||||
*/
|
||||
static modulus_info_entry_t modulus_info_entries[] = {
|
||||
{MODP_768_BIT,group1_modulus,sizeof(group1_modulus),2},
|
||||
{MODP_1024_BIT,group2_modulus,sizeof(group2_modulus),2},
|
||||
{MODP_1536_BIT,group5_modulus,sizeof(group5_modulus),2},
|
||||
{MODP_2048_BIT,group14_modulus,sizeof(group14_modulus),2},
|
||||
{MODP_3072_BIT,group15_modulus,sizeof(group15_modulus),2},
|
||||
{MODP_4096_BIT,group16_modulus,sizeof(group16_modulus),2},
|
||||
{MODP_6144_BIT,group17_modulus,sizeof(group17_modulus),2},
|
||||
{MODP_8192_BIT,group18_modulus,sizeof(group18_modulus),2},
|
||||
};
|
||||
|
||||
typedef struct private_diffie_hellman_t private_diffie_hellman_t;
|
||||
|
||||
/**
|
||||
* Private data of an diffie_hellman_t object.
|
||||
*
|
||||
*/
|
||||
struct private_diffie_hellman_t {
|
||||
/**
|
||||
* Public diffie_hellman_t interface.
|
||||
*/
|
||||
diffie_hellman_t public;
|
||||
|
||||
/**
|
||||
* Diffie Hellman group number.
|
||||
*/
|
||||
u_int16_t dh_group_number;
|
||||
|
||||
/**
|
||||
* Modulus.
|
||||
*/
|
||||
mpz_t modulus;
|
||||
|
||||
/**
|
||||
* Modulus length.
|
||||
*/
|
||||
size_t modulus_length;
|
||||
|
||||
/*
|
||||
* Generator value.
|
||||
*/
|
||||
u_int16_t generator;
|
||||
|
||||
/**
|
||||
* My private value .
|
||||
*/
|
||||
mpz_t my_private_value;
|
||||
|
||||
/**
|
||||
* My public value.
|
||||
*/
|
||||
mpz_t my_public_value;
|
||||
|
||||
/**
|
||||
* Other public value.
|
||||
*/
|
||||
mpz_t other_public_value;
|
||||
|
||||
/**
|
||||
* Shared secret.
|
||||
*/
|
||||
mpz_t shared_secret;
|
||||
|
||||
/**
|
||||
* True if shared secret is computed and stored in my_public_value.
|
||||
*/
|
||||
bool shared_secret_is_computed;
|
||||
|
||||
/**
|
||||
* Sets the modulus for a specific diffie hellman group.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return
|
||||
* SUCCESS if modulus could be found
|
||||
* NOT_FOUND if modulus not supported
|
||||
*/
|
||||
status_t (*set_modulus) (private_diffie_hellman_t *this);
|
||||
|
||||
/**
|
||||
* Makes sure my public value is computed.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*compute_public_value) (private_diffie_hellman_t *this);
|
||||
|
||||
/**
|
||||
* Computes shared secret (other public value must be available).
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*compute_shared_secret) (private_diffie_hellman_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of private_diffie_hellman_t.set_modulus.
|
||||
*/
|
||||
static status_t set_modulus(private_diffie_hellman_t *this)
|
||||
{
|
||||
int i;
|
||||
status_t status = NOT_FOUND;
|
||||
|
||||
for (i = 0; i < (sizeof(modulus_info_entries) / sizeof(modulus_info_entry_t)); i++)
|
||||
{
|
||||
if (modulus_info_entries[i].group == this->dh_group_number)
|
||||
{
|
||||
chunk_t modulus_chunk;
|
||||
modulus_chunk.ptr = modulus_info_entries[i].modulus;
|
||||
modulus_chunk.len = modulus_info_entries[i].modulus_length;
|
||||
mpz_import(this->modulus, modulus_chunk.len, 1, 1, 1, 0, modulus_chunk.ptr);
|
||||
this->modulus_length = modulus_chunk.len;
|
||||
this->generator = modulus_info_entries[i].generator;
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of diffie_hellman_t.set_other_public_value.
|
||||
*/
|
||||
static void set_other_public_value(private_diffie_hellman_t *this,chunk_t public_value)
|
||||
{
|
||||
mpz_import(this->other_public_value, public_value.len, 1, 1, 1, 0, public_value.ptr);
|
||||
this->compute_shared_secret(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of diffie_hellman_t.get_other_public_value.
|
||||
*/
|
||||
static status_t get_other_public_value(private_diffie_hellman_t *this,chunk_t *public_value)
|
||||
{
|
||||
if (!this->shared_secret_is_computed)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
public_value->len = this->modulus_length;
|
||||
public_value->ptr = mpz_export(NULL, NULL, 1, public_value->len, 1, 0, this->other_public_value);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_diffie_hellman_t.compute_shared_secret.
|
||||
*/
|
||||
static void compute_shared_secret (private_diffie_hellman_t *this)
|
||||
{
|
||||
/* initialize my public value */
|
||||
mpz_init(this->shared_secret);
|
||||
/* calculate my public value */
|
||||
mpz_powm(this->shared_secret,this->other_public_value,this->my_private_value,this->modulus);
|
||||
|
||||
this->shared_secret_is_computed = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_diffie_hellman_t.compute_public_value.
|
||||
*/
|
||||
static void compute_public_value (private_diffie_hellman_t *this)
|
||||
{
|
||||
mpz_t generator;
|
||||
/* initialize generator and set it*/
|
||||
mpz_init_set_ui (generator,this->generator);
|
||||
/* initialize my public value */
|
||||
mpz_init(this->my_public_value);
|
||||
/* calculate my public value */
|
||||
mpz_powm(this->my_public_value,generator,this->my_private_value,this->modulus);
|
||||
/* generator not used anymore */
|
||||
mpz_clear(generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of diffie_hellman_t.get_my_public_value.
|
||||
*/
|
||||
static void get_my_public_value(private_diffie_hellman_t *this,chunk_t *public_value)
|
||||
{
|
||||
public_value->len = this->modulus_length;
|
||||
public_value->ptr = mpz_export(NULL, NULL, 1, public_value->len, 1, 0, this->my_public_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of diffie_hellman_t.get_shared_secret.
|
||||
*/
|
||||
static status_t get_shared_secret(private_diffie_hellman_t *this,chunk_t *secret)
|
||||
{
|
||||
if (!this->shared_secret_is_computed)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
secret->len = this->modulus_length;
|
||||
secret->ptr = mpz_export(NULL, NULL, 1, secret->len, 1, 0, this->shared_secret);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of diffie_hellman_t.get_dh_group.
|
||||
*/
|
||||
static diffie_hellman_group_t get_dh_group(private_diffie_hellman_t *this)
|
||||
{
|
||||
return this->dh_group_number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of diffie_hellman_t.destroy.
|
||||
*/
|
||||
static void destroy(private_diffie_hellman_t *this)
|
||||
{
|
||||
mpz_clear(this->modulus);
|
||||
mpz_clear(this->my_private_value);
|
||||
mpz_clear(this->my_public_value);
|
||||
mpz_clear(this->other_public_value);
|
||||
|
||||
if (this->shared_secret_is_computed)
|
||||
{
|
||||
/* other public value gets initialized together with shared secret */
|
||||
mpz_clear(this->shared_secret);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t dh_group_number)
|
||||
{
|
||||
private_diffie_hellman_t *this = malloc_thing(private_diffie_hellman_t);
|
||||
randomizer_t *randomizer;
|
||||
chunk_t random_bytes;
|
||||
|
||||
/* public functions */
|
||||
this->public.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret;
|
||||
this->public.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value;
|
||||
this->public.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value;
|
||||
this->public.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value;
|
||||
this->public.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group;
|
||||
this->public.destroy = (void (*)(diffie_hellman_t *)) destroy;
|
||||
|
||||
/* private functions */
|
||||
this->set_modulus = set_modulus;
|
||||
this->compute_public_value = compute_public_value;
|
||||
this->compute_shared_secret = compute_shared_secret;
|
||||
|
||||
/* private variables */
|
||||
this->dh_group_number = dh_group_number;
|
||||
mpz_init(this->modulus);
|
||||
mpz_init(this->other_public_value);
|
||||
mpz_init(this->my_private_value);
|
||||
|
||||
/* set this->modulus */
|
||||
if (this->set_modulus(this) != SUCCESS)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
randomizer = randomizer_create();
|
||||
if (randomizer == NULL)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
if (randomizer->allocate_pseudo_random_bytes(randomizer, this->modulus_length, &random_bytes) != SUCCESS)
|
||||
{
|
||||
randomizer->destroy(randomizer);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mpz_import(this->my_private_value, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
|
||||
chunk_free(&random_bytes);
|
||||
|
||||
randomizer->destroy(randomizer);
|
||||
|
||||
this->compute_public_value(this);
|
||||
|
||||
this->shared_secret_is_computed = FALSE;
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
/**
|
||||
* @file diffie_hellman.h
|
||||
*
|
||||
* @brief Interface of diffie_hellman_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef DIFFIE_HELLMAN_H_
|
||||
#define DIFFIE_HELLMAN_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
|
||||
typedef enum diffie_hellman_group_t diffie_hellman_group_t;
|
||||
|
||||
/**
|
||||
* @brief Diffie-Hellman group.
|
||||
*
|
||||
* The modulus (or group) to use for a Diffie-Hellman calculation.
|
||||
*
|
||||
* See IKEv2 RFC 3.3.2 and RFC 3526.
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
enum diffie_hellman_group_t {
|
||||
MODP_UNDEFINED = 1024,
|
||||
MODP_768_BIT = 1,
|
||||
MODP_1024_BIT = 2,
|
||||
MODP_1536_BIT = 5,
|
||||
MODP_2048_BIT = 14,
|
||||
MODP_3072_BIT = 15,
|
||||
MODP_4096_BIT = 16,
|
||||
MODP_6144_BIT = 17,
|
||||
MODP_8192_BIT = 18
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for diffie_hellman_group_t.
|
||||
*/
|
||||
extern mapping_t diffie_hellman_group_m[];
|
||||
|
||||
|
||||
typedef struct diffie_hellman_t diffie_hellman_t;
|
||||
|
||||
/**
|
||||
* @brief Implementation of the widely used Diffie-Hellman algorithm.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - diffie_hellman_create()
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
struct diffie_hellman_t {
|
||||
|
||||
/**
|
||||
* @brief Returns the shared secret of this diffie hellman exchange.
|
||||
*
|
||||
* @warning Space for returned secret is allocated and must be
|
||||
* freed by the caller.
|
||||
*
|
||||
* @param this calling diffie_hellman_t object
|
||||
* @param[out] secret shared secret will be written into this chunk
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - FAILED if not both DH values are set
|
||||
*/
|
||||
status_t (*get_shared_secret) (diffie_hellman_t *this, chunk_t *secret);
|
||||
|
||||
/**
|
||||
* @brief Sets the public value of partner.
|
||||
*
|
||||
* chunk gets cloned and can be destroyed afterwards.
|
||||
*
|
||||
* @param this calling diffie_hellman_t object
|
||||
* @param public_value public value of partner
|
||||
*/
|
||||
void (*set_other_public_value) (diffie_hellman_t *this, chunk_t public_value);
|
||||
|
||||
/**
|
||||
* @brief Gets the public value of partner.
|
||||
*
|
||||
* @warning Space for returned chunk is allocated and must be
|
||||
* freed by the caller.
|
||||
*
|
||||
* @param this calling diffie_hellman_t object
|
||||
* @param[out] public_value public value of partner is stored at this location
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - FAILED if other public value not set
|
||||
*/
|
||||
status_t (*get_other_public_value) (diffie_hellman_t *this, chunk_t *public_value);
|
||||
|
||||
/**
|
||||
* @brief Gets the public value of caller
|
||||
*
|
||||
* @warning Space for returned chunk is allocated and must be
|
||||
* freed by the caller.
|
||||
*
|
||||
* @param this calling diffie_hellman_t object
|
||||
* @param[out] public_value public value of caller is stored at this location
|
||||
*/
|
||||
void (*get_my_public_value) (diffie_hellman_t *this, chunk_t *public_value);
|
||||
|
||||
/**
|
||||
* @brief Get the DH group used.
|
||||
*
|
||||
* @param this calling diffie_hellman_t object
|
||||
* @return DH group set in construction
|
||||
*/
|
||||
diffie_hellman_group_t (*get_dh_group) (diffie_hellman_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys an diffie_hellman_t object.
|
||||
*
|
||||
* @param this diffie_hellman_t object to destroy
|
||||
*/
|
||||
void (*destroy) (diffie_hellman_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new diffie_hellman_t object.
|
||||
*
|
||||
* The first diffie hellman public value gets automatically created.
|
||||
*
|
||||
* @param dh_group_number Diffie Hellman group number to use
|
||||
* @return
|
||||
* - diffie_hellman_t object
|
||||
* - NULL if dh group not supported
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t dh_group_number);
|
||||
|
||||
#endif /*DIFFIE_HELLMAN_H_*/
|
||||
@@ -1,27 +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 <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.
|
||||
#
|
||||
|
||||
HASHERS_DIR= $(CRYPTO_DIR)hashers/
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)hasher.o
|
||||
$(BUILD_DIR)hasher.o : $(HASHERS_DIR)hasher.c $(HASHERS_DIR)hasher.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)sha1_hasher.o
|
||||
$(BUILD_DIR)sha1_hasher.o : $(HASHERS_DIR)sha1_hasher.c $(HASHERS_DIR)sha1_hasher.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)md5_hasher.o
|
||||
$(BUILD_DIR)md5_hasher.o : $(HASHERS_DIR)md5_hasher.c $(HASHERS_DIR)md5_hasher.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* @file hasher.c
|
||||
*
|
||||
* @brief Generic constructor for hasher_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "hasher.h"
|
||||
|
||||
#include <crypto/hashers/sha1_hasher.h>
|
||||
#include <crypto/hashers/md5_hasher.h>
|
||||
|
||||
/**
|
||||
* String mappings for hash_algorithm_t.
|
||||
*/
|
||||
mapping_t hash_algorithm_m[] = {
|
||||
{HASH_MD2,"HASH_MD2"},
|
||||
{HASH_MD5,"HASH_MD5"},
|
||||
{HASH_SHA1,"HASH_SHA1"},
|
||||
{HASH_SHA256,"HASH_SHA256"},
|
||||
{HASH_SHA384,"HASH_SHA384"},
|
||||
{HASH_SHA512,"HASH_SHA512"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
hasher_t *hasher_create(hash_algorithm_t hash_algorithm)
|
||||
{
|
||||
switch (hash_algorithm)
|
||||
{
|
||||
case HASH_SHA1:
|
||||
{
|
||||
return (hasher_t*)sha1_hasher_create();
|
||||
}
|
||||
case HASH_MD5:
|
||||
{
|
||||
return (hasher_t*)md5_hasher_create();
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
/**
|
||||
* @file hasher.h
|
||||
*
|
||||
* @brief Interface hasher_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HASHER_H_
|
||||
#define HASHER_H_
|
||||
|
||||
|
||||
#include <types.h>
|
||||
|
||||
|
||||
typedef enum hash_algorithm_t hash_algorithm_t;
|
||||
|
||||
/**
|
||||
* @brief Algorithms to use for hashing.
|
||||
*
|
||||
* Currently only the following algorithms are implemented and therefore supported:
|
||||
* - HASH_MD5
|
||||
* - HASH_SHA1
|
||||
*
|
||||
* @ingroup hashers
|
||||
*
|
||||
*/
|
||||
enum hash_algorithm_t {
|
||||
HASH_MD2,
|
||||
/**
|
||||
* Implemented in class md5_hasher_t.
|
||||
*/
|
||||
HASH_MD5,
|
||||
/**
|
||||
* Implemented in class sha1_hasher_t.
|
||||
*/
|
||||
HASH_SHA1,
|
||||
HASH_SHA256,
|
||||
HASH_SHA384,
|
||||
HASH_SHA512,
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for hash_algorithm_t.
|
||||
*/
|
||||
extern mapping_t hash_algorithm_m[];
|
||||
|
||||
|
||||
typedef struct hasher_t hasher_t;
|
||||
|
||||
/**
|
||||
* @brief Generic interface for all hash functions.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - hasher_create()
|
||||
* - md5_hasher_create()
|
||||
* - sha1_hasher_create()
|
||||
*
|
||||
* @see
|
||||
* - md5_hasher_t
|
||||
* - sha1_hasher_t
|
||||
*
|
||||
* @todo Implement more hash algorithms
|
||||
*
|
||||
* @ingroup hashers
|
||||
*/
|
||||
struct hasher_t {
|
||||
/**
|
||||
* @brief Hash data and write it in the buffer.
|
||||
*
|
||||
* If the parameter hash is NULL, no result is written back
|
||||
* an more data can be appended to already hashed data.
|
||||
* If not, the result is written back and the hasher is reseted.
|
||||
*
|
||||
* @warning: the hash output parameter must hold at least
|
||||
* hash_t.get_block_size bytes.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data data to hash
|
||||
* @param[out] hash pointer where the hash will be written
|
||||
*/
|
||||
void (*get_hash) (hasher_t *this, chunk_t data, u_int8_t *hash);
|
||||
|
||||
/**
|
||||
* @brief Hash data and allocate space for the hash.
|
||||
*
|
||||
* If the parameter hash is NULL, no result is written back
|
||||
* an more data can be appended to already hashed data.
|
||||
* If not, the result is written back and the hasher is reseted.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data chunk with data to hash
|
||||
* @param[out] hash chunk which will hold allocated hash
|
||||
*/
|
||||
void (*allocate_hash) (hasher_t *this, chunk_t data, chunk_t *hash);
|
||||
|
||||
/**
|
||||
* @brief Get the size of the resulting hash.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return hash size in bytes
|
||||
*/
|
||||
size_t (*get_hash_size) (hasher_t *this);
|
||||
|
||||
/**
|
||||
* @brief Resets the hashers state, which allows
|
||||
* computation of a completely new hash.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*reset) (hasher_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys a hasher object.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (hasher_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generic interface to create a hasher_t.
|
||||
*
|
||||
* @param hash_algorithm Algorithm to use for hashing
|
||||
* @return
|
||||
* - hasher_t object
|
||||
* - NULL if algorithm not supported
|
||||
*
|
||||
* @ingroup hashers
|
||||
*/
|
||||
hasher_t *hasher_create(hash_algorithm_t hash_algorithm);
|
||||
|
||||
#endif /*HASHER_H_*/
|
||||
@@ -1,394 +0,0 @@
|
||||
/**
|
||||
* @file md5_hasher.c
|
||||
*
|
||||
* @brief Implementation of md5_hasher_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Jan Hutter, Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* Copyright (C) 1991-1992, RSA Data Security, Inc. Created 1991.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
|
||||
* Ported to fulfill hasher_t interface.
|
||||
*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "md5_hasher.h"
|
||||
|
||||
#include <definitions.h>
|
||||
|
||||
#define BLOCK_SIZE_MD5 16
|
||||
|
||||
|
||||
/* Constants for MD5Transform routine. */
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
|
||||
static u_int8_t PADDING[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* ugly macro stuff
|
||||
*/
|
||||
/* F, G, H and I are basic MD5 functions.
|
||||
*/
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
/* ROTATE_LEFT rotates x left n bits.
|
||||
*/
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||
Rotation is separate from addition to prevent recomputation.
|
||||
*/
|
||||
#define FF(a, b, c, d, x, s, ac) { \
|
||||
(a) += F ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) { \
|
||||
(a) += G ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) { \
|
||||
(a) += H ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) { \
|
||||
(a) += I ((b), (c), (d)) + (x) + (u_int32_t)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef struct private_md5_hasher_t private_md5_hasher_t;
|
||||
|
||||
/**
|
||||
* Private data structure with hasing context.
|
||||
*/
|
||||
struct private_md5_hasher_t {
|
||||
/**
|
||||
* Public interface for this hasher.
|
||||
*/
|
||||
md5_hasher_t public;
|
||||
|
||||
/*
|
||||
* State of the hasher.
|
||||
*/
|
||||
u_int32_t state[5];
|
||||
u_int32_t count[2];
|
||||
u_int8_t buffer[64];
|
||||
};
|
||||
|
||||
|
||||
#if BYTE_ORDER != LITTLE_ENDIAN
|
||||
|
||||
/* Encodes input (u_int32_t) into output (u_int8_t). Assumes len is
|
||||
* a multiple of 4.
|
||||
*/
|
||||
static void Encode (u_int8_t *output, u_int32_t *input, size_t *len)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
{
|
||||
output[j] = (u_int8_t)(input[i] & 0xff);
|
||||
output[j+1] = (u_int8_t)((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (u_int8_t)((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (u_int8_t)((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decodes input (u_int8_t) into output (u_int32_t). Assumes len is
|
||||
* a multiple of 4.
|
||||
*/
|
||||
static void Decode(u_int32_t *output, u_int8_t *input, size_t len)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
{
|
||||
output[i] = ((u_int32_t)input[j]) | (((u_int32_t)input[j+1]) << 8) |
|
||||
(((u_int32_t)input[j+2]) << 16) | (((u_int32_t)input[j+3]) << 24);
|
||||
}
|
||||
}
|
||||
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define Encode memcpy
|
||||
#define Decode memcpy
|
||||
#endif
|
||||
|
||||
/* MD5 basic transformation. Transforms state based on block.
|
||||
*/
|
||||
static void MD5Transform(u_int32_t state[4], u_int8_t block[64])
|
||||
{
|
||||
u_int32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
|
||||
Decode(x, block, 64);
|
||||
|
||||
/* Round 1 */
|
||||
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
|
||||
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 2 */
|
||||
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 3 */
|
||||
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
|
||||
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 4 */
|
||||
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
|
||||
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
|
||||
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
|
||||
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
}
|
||||
|
||||
/* MD5 block update operation. Continues an MD5 message-digest
|
||||
* operation, processing another message block, and updating the
|
||||
* context.
|
||||
*/
|
||||
static void MD5Update(private_md5_hasher_t *this, u_int8_t *input, size_t inputLen)
|
||||
{
|
||||
u_int32_t i;
|
||||
size_t index, partLen;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
index = (u_int8_t)((this->count[0] >> 3) & 0x3F);
|
||||
|
||||
/* Update number of bits */
|
||||
if ((this->count[0] += (inputLen << 3)) < (inputLen << 3))
|
||||
{
|
||||
this->count[1]++;
|
||||
}
|
||||
this->count[1] += (inputLen >> 29);
|
||||
|
||||
partLen = 64 - index;
|
||||
|
||||
/* Transform as many times as possible. */
|
||||
if (inputLen >= partLen)
|
||||
{
|
||||
memcpy(&this->buffer[index], input, partLen);
|
||||
MD5Transform (this->state, this->buffer);
|
||||
|
||||
for (i = partLen; i + 63 < inputLen; i += 64)
|
||||
{
|
||||
MD5Transform (this->state, &input[i]);
|
||||
}
|
||||
index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
|
||||
/* Buffer remaining input */
|
||||
memcpy(&this->buffer[index], &input[i], inputLen-i);
|
||||
}
|
||||
|
||||
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
|
||||
* the message digest and zeroizing the context.
|
||||
*/
|
||||
static void MD5Final (private_md5_hasher_t *this, u_int8_t digest[16])
|
||||
{
|
||||
u_int8_t bits[8];
|
||||
size_t index, padLen;
|
||||
|
||||
/* Save number of bits */
|
||||
Encode (bits, this->count, 8);
|
||||
|
||||
/* Pad out to 56 mod 64. */
|
||||
index = (size_t)((this->count[0] >> 3) & 0x3f);
|
||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
MD5Update (this, PADDING, padLen);
|
||||
|
||||
/* Append length (before padding) */
|
||||
MD5Update (this, bits, 8);
|
||||
|
||||
if (digest != NULL) /* Bill Simpson's padding */
|
||||
{
|
||||
/* store state in digest */
|
||||
Encode (digest, this->state, 16);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of hasher_t.get_hash.
|
||||
*/
|
||||
static void get_hash(private_md5_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
|
||||
{
|
||||
MD5Update(this, chunk.ptr, chunk.len);
|
||||
if (buffer != NULL)
|
||||
{
|
||||
MD5Final(this, buffer);
|
||||
this->public.hasher_interface.reset(&(this->public.hasher_interface));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of hasher_t.allocate_hash.
|
||||
*/
|
||||
static void allocate_hash(private_md5_hasher_t *this, chunk_t chunk, chunk_t *hash)
|
||||
{
|
||||
chunk_t allocated_hash;
|
||||
|
||||
MD5Update(this, chunk.ptr, chunk.len);
|
||||
if (hash != NULL)
|
||||
{
|
||||
allocated_hash.ptr = malloc(BLOCK_SIZE_MD5);
|
||||
allocated_hash.len = BLOCK_SIZE_MD5;
|
||||
|
||||
MD5Final(this, allocated_hash.ptr);
|
||||
this->public.hasher_interface.reset(&(this->public.hasher_interface));
|
||||
|
||||
*hash = allocated_hash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hasher_t.get_hash_size.
|
||||
*/
|
||||
static size_t get_hash_size(private_md5_hasher_t *this)
|
||||
{
|
||||
return BLOCK_SIZE_MD5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hasher_t.reset.
|
||||
*/
|
||||
static void reset(private_md5_hasher_t *this)
|
||||
{
|
||||
this->state[0] = 0x67452301;
|
||||
this->state[1] = 0xefcdab89;
|
||||
this->state[2] = 0x98badcfe;
|
||||
this->state[3] = 0x10325476;
|
||||
this->count[0] = 0;
|
||||
this->count[1] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hasher_t.destroy.
|
||||
*/
|
||||
static void destroy(private_md5_hasher_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
md5_hasher_t *md5_hasher_create(void)
|
||||
{
|
||||
private_md5_hasher_t *this = malloc_thing(private_md5_hasher_t);
|
||||
|
||||
this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash;
|
||||
this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash;
|
||||
this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size;
|
||||
this->public.hasher_interface.reset = (void (*) (hasher_t*))reset;
|
||||
this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy;
|
||||
|
||||
/* initialize */
|
||||
this->public.hasher_interface.reset(&(this->public.hasher_interface));
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* @file md5_hasher.h
|
||||
*
|
||||
* @brief Interface for md5_hasher_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MD5_HASHER_H_
|
||||
#define MD5_HASHER_H_
|
||||
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
|
||||
typedef struct md5_hasher_t md5_hasher_t;
|
||||
|
||||
/**
|
||||
* @brief Implementation of hasher_t interface using the
|
||||
* MD5 algorithm.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - hasher_create() using HASH_MD5 as algorithm
|
||||
* - md5_hasher_create()
|
||||
*
|
||||
* @see hasher_t
|
||||
*
|
||||
* @ingroup hashers
|
||||
*/
|
||||
struct md5_hasher_t {
|
||||
|
||||
/**
|
||||
* Generic hasher_t interface for this hasher.
|
||||
*/
|
||||
hasher_t hasher_interface;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new md5_hasher_t.
|
||||
*
|
||||
* @return md5_hasher_t object
|
||||
*
|
||||
* @ingroup hashers
|
||||
*/
|
||||
md5_hasher_t *md5_hasher_create(void);
|
||||
|
||||
#endif /*MD5_HASHER_H_*/
|
||||
@@ -1,269 +0,0 @@
|
||||
/**
|
||||
* @file sha1_hasher.c
|
||||
*
|
||||
* @brief Implementation of hasher_sha_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Jan Hutter, Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* Ported from Steve Reid's <[email protected]> implementation
|
||||
* "SHA1 in C" found in strongSwan.
|
||||
*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "sha1_hasher.h"
|
||||
|
||||
#include <definitions.h>
|
||||
|
||||
#define BLOCK_SIZE_SHA1 20
|
||||
|
||||
/*
|
||||
* ugly macro stuff
|
||||
*/
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) |(rol(block->l[i],8)&0x00FF00FF))
|
||||
#elif BYTE_ORDER == BIG_ENDIAN
|
||||
#define blk0(i) block->l[i]
|
||||
#else
|
||||
#error "Endianness not defined!"
|
||||
#endif
|
||||
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] ^block->l[(i+2)&15]^block->l[i&15],1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||
|
||||
|
||||
typedef struct private_sha1_hasher_t private_sha1_hasher_t;
|
||||
|
||||
/**
|
||||
* Private data structure with hasing context.
|
||||
*/
|
||||
struct private_sha1_hasher_t {
|
||||
/**
|
||||
* Public interface for this hasher.
|
||||
*/
|
||||
sha1_hasher_t public;
|
||||
|
||||
/*
|
||||
* State of the hasher.
|
||||
*/
|
||||
u_int32_t state[5];
|
||||
u_int32_t count[2];
|
||||
u_int8_t buffer[64];
|
||||
};
|
||||
|
||||
/*
|
||||
* Hash a single 512-bit block. This is the core of the algorithm. *
|
||||
*/
|
||||
static void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64])
|
||||
{
|
||||
u_int32_t a, b, c, d, e;
|
||||
typedef union {
|
||||
u_int8_t c[64];
|
||||
u_int32_t l[16];
|
||||
} CHAR64LONG16;
|
||||
CHAR64LONG16 block[1]; /* use array to appear as a pointer */
|
||||
memcpy(block, buffer, 64);
|
||||
|
||||
/* Copy context->state[] to working vars */
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
memset(block, '\0', sizeof(block));
|
||||
}
|
||||
|
||||
/*
|
||||
* Run your data through this.
|
||||
*/
|
||||
static void SHA1Update(private_sha1_hasher_t* this, u_int8_t *data, u_int32_t len)
|
||||
{
|
||||
u_int32_t i;
|
||||
u_int32_t j;
|
||||
|
||||
j = this->count[0];
|
||||
if ((this->count[0] += len << 3) < j)
|
||||
{
|
||||
this->count[1]++;
|
||||
}
|
||||
this->count[1] += (len>>29);
|
||||
j = (j >> 3) & 63;
|
||||
if ((j + len) > 63)
|
||||
{
|
||||
memcpy(&this->buffer[j], data, (i = 64-j));
|
||||
SHA1Transform(this->state, this->buffer);
|
||||
for ( ; i + 63 < len; i += 64)
|
||||
{
|
||||
SHA1Transform(this->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
}
|
||||
memcpy(&this->buffer[j], &data[i], len - i);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Add padding and return the message digest.
|
||||
*/
|
||||
static void SHA1Final(private_sha1_hasher_t *this, u_int8_t *digest)
|
||||
{
|
||||
u_int32_t i;
|
||||
u_int8_t finalcount[8];
|
||||
u_int8_t c;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
finalcount[i] = (u_int8_t)((this->count[(i >= 4 ? 0 : 1)]
|
||||
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||
}
|
||||
c = 0200;
|
||||
SHA1Update(this, &c, 1);
|
||||
while ((this->count[0] & 504) != 448)
|
||||
{
|
||||
c = 0000;
|
||||
SHA1Update(this, &c, 1);
|
||||
}
|
||||
SHA1Update(this, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
digest[i] = (u_int8_t)((this->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of hasher_t.get_hash.
|
||||
*/
|
||||
static void get_hash(private_sha1_hasher_t *this, chunk_t chunk, u_int8_t *buffer)
|
||||
{
|
||||
SHA1Update(this, chunk.ptr, chunk.len);
|
||||
if (buffer != NULL)
|
||||
{
|
||||
SHA1Final(this, buffer);
|
||||
this->public.hasher_interface.reset(&(this->public.hasher_interface));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of hasher_t.allocate_hash.
|
||||
*/
|
||||
static void allocate_hash(private_sha1_hasher_t *this, chunk_t chunk, chunk_t *hash)
|
||||
{
|
||||
chunk_t allocated_hash;
|
||||
|
||||
SHA1Update(this, chunk.ptr, chunk.len);
|
||||
if (hash != NULL)
|
||||
{
|
||||
allocated_hash.ptr = malloc(BLOCK_SIZE_SHA1);
|
||||
allocated_hash.len = BLOCK_SIZE_SHA1;
|
||||
|
||||
SHA1Final(this, allocated_hash.ptr);
|
||||
this->public.hasher_interface.reset(&(this->public.hasher_interface));
|
||||
|
||||
*hash = allocated_hash;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hasher_t.get_hash_size.
|
||||
*/
|
||||
static size_t get_hash_size(private_sha1_hasher_t *this)
|
||||
{
|
||||
return BLOCK_SIZE_SHA1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hasher_t.reset.
|
||||
*/
|
||||
static void reset(private_sha1_hasher_t *this)
|
||||
{
|
||||
this->state[0] = 0x67452301;
|
||||
this->state[1] = 0xEFCDAB89;
|
||||
this->state[2] = 0x98BADCFE;
|
||||
this->state[3] = 0x10325476;
|
||||
this->state[4] = 0xC3D2E1F0;
|
||||
this->count[0] = 0;
|
||||
this->count[1] = 0;
|
||||
}
|
||||
/**
|
||||
* Implementation of hasher_t.destroy.
|
||||
*/
|
||||
static void destroy(private_sha1_hasher_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
sha1_hasher_t *sha1_hasher_create(void)
|
||||
{
|
||||
private_sha1_hasher_t *this = malloc_thing(private_sha1_hasher_t);
|
||||
|
||||
this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash;
|
||||
this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash;
|
||||
this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size;
|
||||
this->public.hasher_interface.reset = (void (*) (hasher_t*))reset;
|
||||
this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy;
|
||||
|
||||
/* initialize */
|
||||
this->public.hasher_interface.reset(&(this->public.hasher_interface));
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
/**
|
||||
* @file sha1_hasher.h
|
||||
*
|
||||
* @brief Interface of sha1_hasher_t
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SHA1_HASHER_H_
|
||||
#define SHA1_HASHER_H_
|
||||
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
|
||||
typedef struct sha1_hasher_t sha1_hasher_t;
|
||||
|
||||
/**
|
||||
* @brief Implementation of hasher_t interface using the
|
||||
* SHA1 algorithm.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - hasher_create() using HASH_SHA1 as algorithm
|
||||
* - sha1_hasher_create()
|
||||
*
|
||||
* @see hasher_t
|
||||
*
|
||||
* @ingroup hashers
|
||||
*/
|
||||
struct sha1_hasher_t {
|
||||
|
||||
/**
|
||||
* Generic hasher_t interface for this hasher.
|
||||
*/
|
||||
hasher_t hasher_interface;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new sha1_hasher_t.
|
||||
*
|
||||
* @return sha1_hasher_t object
|
||||
*
|
||||
* @ingroup hashers
|
||||
*/
|
||||
sha1_hasher_t *sha1_hasher_create(void);
|
||||
|
||||
#endif /*SHA1_HASHER_H_*/
|
||||
@@ -1,209 +0,0 @@
|
||||
/**
|
||||
* @file hmac.c
|
||||
*
|
||||
* @brief Implementation of hmac_t.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 hmac 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 hmac License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "hmac.h"
|
||||
|
||||
|
||||
typedef struct private_hmac_t private_hmac_t;
|
||||
|
||||
/**
|
||||
* Private data of a hmac_t object.
|
||||
*
|
||||
* The variable names are the same as in the RFC.
|
||||
*/
|
||||
struct private_hmac_t {
|
||||
/**
|
||||
* Public hmac_t interface.
|
||||
*/
|
||||
hmac_t hmac;
|
||||
|
||||
/**
|
||||
* Block size, as in RFC.
|
||||
*/
|
||||
u_int8_t b;
|
||||
|
||||
/**
|
||||
* Hash function.
|
||||
*/
|
||||
hasher_t *h;
|
||||
|
||||
/**
|
||||
* Previously xor'ed key using opad.
|
||||
*/
|
||||
chunk_t opaded_key;
|
||||
|
||||
/**
|
||||
* Previously xor'ed key using ipad.
|
||||
*/
|
||||
chunk_t ipaded_key;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of hmac_t.get_mac.
|
||||
*/
|
||||
static void get_mac(private_hmac_t *this, chunk_t data, u_int8_t *out)
|
||||
{
|
||||
/* H(K XOR opad, H(K XOR ipad, text))
|
||||
*
|
||||
* if out is NULL, we append text to the inner hash.
|
||||
* else, we complete the inner and do the outer.
|
||||
*
|
||||
*/
|
||||
|
||||
u_int8_t buffer[this->h->get_hash_size(this->h)];
|
||||
chunk_t inner;
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
/* append data to inner */
|
||||
this->h->get_hash(this->h, data, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* append and do outer hash */
|
||||
inner.ptr = buffer;
|
||||
inner.len = this->h->get_hash_size(this->h);
|
||||
|
||||
/* complete inner */
|
||||
this->h->get_hash(this->h, data, buffer);
|
||||
|
||||
/* do outer */
|
||||
this->h->get_hash(this->h, this->opaded_key, NULL);
|
||||
this->h->get_hash(this->h, inner, out);
|
||||
|
||||
/* reinit for next call */
|
||||
this->h->get_hash(this->h, this->ipaded_key, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hmac_t.allocate_mac.
|
||||
*/
|
||||
static void allocate_mac(private_hmac_t *this, chunk_t data, chunk_t *out)
|
||||
{
|
||||
/* allocate space and use get_mac */
|
||||
if (out == NULL)
|
||||
{
|
||||
/* append mode */
|
||||
this->hmac.get_mac(&(this->hmac), data, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
out->len = this->h->get_hash_size(this->h);
|
||||
out->ptr = malloc(out->len);
|
||||
this->hmac.get_mac(&(this->hmac), data, out->ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hmac_t.get_block_size.
|
||||
*/
|
||||
static size_t get_block_size(private_hmac_t *this)
|
||||
{
|
||||
return this->h->get_hash_size(this->h);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hmac_t.set_key.
|
||||
*/
|
||||
static void set_key(private_hmac_t *this, chunk_t key)
|
||||
{
|
||||
int i;
|
||||
u_int8_t buffer[this->b];
|
||||
|
||||
memset(buffer, 0, this->b);
|
||||
|
||||
if (key.len > this->b)
|
||||
{
|
||||
/* if key is too long, it will be hashed */
|
||||
this->h->get_hash(this->h, key, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if not, just copy it in our pre-padded k */
|
||||
memcpy(buffer, key.ptr, key.len);
|
||||
}
|
||||
|
||||
/* apply ipad and opad to key */
|
||||
for (i = 0; i < this->b; i++)
|
||||
{
|
||||
this->ipaded_key.ptr[i] = buffer[i] ^ 0x36;
|
||||
this->opaded_key.ptr[i] = buffer[i] ^ 0x5C;
|
||||
}
|
||||
|
||||
/* begin hashing of inner pad */
|
||||
this->h->reset(this->h);
|
||||
this->h->get_hash(this->h, this->ipaded_key, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hmac_t.destroy.
|
||||
*/
|
||||
static void destroy(private_hmac_t *this)
|
||||
{
|
||||
this->h->destroy(this->h);
|
||||
free(this->opaded_key.ptr);
|
||||
free(this->ipaded_key.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
hmac_t *hmac_create(hash_algorithm_t hash_algorithm)
|
||||
{
|
||||
private_hmac_t *this;
|
||||
|
||||
this = malloc_thing(private_hmac_t);
|
||||
|
||||
/* set hmac_t methods */
|
||||
this->hmac.get_mac = (void (*)(hmac_t *,chunk_t,u_int8_t*))get_mac;
|
||||
this->hmac.allocate_mac = (void (*)(hmac_t *,chunk_t,chunk_t*))allocate_mac;
|
||||
this->hmac.get_block_size = (size_t (*)(hmac_t *))get_block_size;
|
||||
this->hmac.set_key = (void (*)(hmac_t *,chunk_t))set_key;
|
||||
this->hmac.destroy = (void (*)(hmac_t *))destroy;
|
||||
|
||||
/* set b, according to hasher */
|
||||
switch (hash_algorithm)
|
||||
{
|
||||
case HASH_SHA1:
|
||||
case HASH_MD5:
|
||||
this->b = 64;
|
||||
break;
|
||||
default:
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* build the hasher */
|
||||
this->h = hasher_create(hash_algorithm);
|
||||
|
||||
/* build ipad and opad */
|
||||
this->opaded_key.ptr = malloc(this->b);
|
||||
this->opaded_key.len = this->b;
|
||||
|
||||
this->ipaded_key.ptr = malloc(this->b);
|
||||
this->ipaded_key.len = this->b;
|
||||
|
||||
return &(this->hmac);
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/**
|
||||
* @file hmac.h
|
||||
*
|
||||
* @brief Interface of hmac_t.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HMAC_H_
|
||||
#define HMAC_H_
|
||||
|
||||
#include <crypto/hashers/hasher.h>
|
||||
#include <definitions.h>
|
||||
|
||||
|
||||
typedef struct hmac_t hmac_t;
|
||||
|
||||
/**
|
||||
* @brief Message authentication using hash functions.
|
||||
*
|
||||
* This class implements the message authenticaion algorithm
|
||||
* described in RFC2104. It uses a hash function, wich must
|
||||
* be implemented as a hasher_t class.
|
||||
*
|
||||
* See http://www.faqs.org/rfcs/rfc2104.html for RFC.
|
||||
* @see
|
||||
* - hasher_t
|
||||
* - prf_hmac_t
|
||||
*
|
||||
* @b Constructors:
|
||||
* - hmac_create()
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
struct hmac_t {
|
||||
/**
|
||||
* @brief Generate message authentication code.
|
||||
*
|
||||
* If buffer is NULL, no result is given back. A next call will
|
||||
* append the data to already supplied data. If buffer is not NULL,
|
||||
* the mac of all apended data is calculated, returned and the
|
||||
* state of the hmac_t is reseted.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data chunk of data to authenticate
|
||||
* @param[out] buffer pointer where the generated bytes will be written
|
||||
*/
|
||||
void (*get_mac) (hmac_t *this, chunk_t data, u_int8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief Generates message authentication code and
|
||||
* allocate space for them.
|
||||
*
|
||||
* If chunk is NULL, no result is given back. A next call will
|
||||
* append the data to already supplied. If chunk is not NULL,
|
||||
* the mac of all apended data is calculated, returned and the
|
||||
* state of the hmac_t reset;
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data chunk of data to authenticate
|
||||
* @param[out] chunk chunk which will hold generated bytes
|
||||
*/
|
||||
void (*allocate_mac) (hmac_t *this, chunk_t data, chunk_t *chunk);
|
||||
|
||||
/**
|
||||
* @brief Get the block size of this hmac_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return block size in bytes
|
||||
*/
|
||||
size_t (*get_block_size) (hmac_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set the key for this hmac_t object.
|
||||
*
|
||||
* Any key length is accepted.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param key key to set
|
||||
*/
|
||||
void (*set_key) (hmac_t *this, chunk_t key);
|
||||
|
||||
/**
|
||||
* @brief Destroys a hmac_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (hmac_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new hmac_t object.
|
||||
*
|
||||
* Creates a hasher_t object internally.
|
||||
*
|
||||
* @param hash_algorithm hash algorithm to use
|
||||
* @return
|
||||
* - hmac_t object
|
||||
* - NULL if hash algorithm is not supported
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
hmac_t *hmac_create(hash_algorithm_t hash_algorithm);
|
||||
|
||||
#endif /*HMAC_H_*/
|
||||
@@ -1,157 +0,0 @@
|
||||
/**
|
||||
* @file prf_plus.c
|
||||
*
|
||||
* @brief Implementation of prf_plus_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "prf_plus.h"
|
||||
|
||||
#include <definitions.h>
|
||||
|
||||
typedef struct private_prf_plus_t private_prf_plus_t;
|
||||
|
||||
/**
|
||||
* Private data of an prf_plus_t object.
|
||||
*
|
||||
*/
|
||||
struct private_prf_plus_t {
|
||||
/**
|
||||
* Public interface of prf_plus_t.
|
||||
*/
|
||||
prf_plus_t public;
|
||||
|
||||
/**
|
||||
* PRF to use.
|
||||
*/
|
||||
prf_t *prf;
|
||||
|
||||
/**
|
||||
* Initial seed.
|
||||
*/
|
||||
chunk_t seed;
|
||||
|
||||
/**
|
||||
* Buffer to store current PRF result.
|
||||
*/
|
||||
chunk_t buffer;
|
||||
|
||||
/**
|
||||
* Already given out bytes in current buffer.
|
||||
*/
|
||||
size_t given_out;
|
||||
|
||||
/**
|
||||
* Octet which will be appended to the seed.
|
||||
*/
|
||||
u_int8_t appending_octet;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of prf_plus_t.get_bytes.
|
||||
*/
|
||||
static void get_bytes(private_prf_plus_t *this, size_t length, u_int8_t *buffer)
|
||||
{
|
||||
chunk_t appending_chunk;
|
||||
size_t bytes_in_round;
|
||||
size_t total_bytes_written = 0;
|
||||
|
||||
appending_chunk.ptr = &(this->appending_octet);
|
||||
appending_chunk.len = 1;
|
||||
|
||||
while (length > 0)
|
||||
{ /* still more to do... */
|
||||
if (this->buffer.len == this->given_out)
|
||||
{ /* no bytes left in buffer, get next*/
|
||||
this->prf->get_bytes(this->prf, this->buffer, NULL);
|
||||
this->prf->get_bytes(this->prf, this->seed, NULL);
|
||||
this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr);
|
||||
this->given_out = 0;
|
||||
this->appending_octet++;
|
||||
}
|
||||
/* how many bytes can we write in this round ? */
|
||||
bytes_in_round = min(length, this->buffer.len - this->given_out);
|
||||
/* copy bytes from buffer with offset */
|
||||
memcpy(buffer + total_bytes_written, this->buffer.ptr + this->given_out, bytes_in_round);
|
||||
|
||||
length -= bytes_in_round;
|
||||
this->given_out += bytes_in_round;
|
||||
total_bytes_written += bytes_in_round;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of prf_plus_t.allocate_bytes.
|
||||
*/
|
||||
static void allocate_bytes(private_prf_plus_t *this, size_t length, chunk_t *chunk)
|
||||
{
|
||||
chunk->ptr = malloc(length);
|
||||
chunk->len = length;
|
||||
this->public.get_bytes(&(this->public), length, chunk->ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of prf_plus_t.destroy.
|
||||
*/
|
||||
static void destroy(private_prf_plus_t *this)
|
||||
{
|
||||
free(this->buffer.ptr);
|
||||
free(this->seed.ptr);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Description in header.
|
||||
*/
|
||||
prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed)
|
||||
{
|
||||
private_prf_plus_t *this;
|
||||
chunk_t appending_chunk;
|
||||
|
||||
this = malloc_thing(private_prf_plus_t);
|
||||
|
||||
/* set public methods */
|
||||
this->public.get_bytes = (void (*)(prf_plus_t *,size_t,u_int8_t*))get_bytes;
|
||||
this->public.allocate_bytes = (void (*)(prf_plus_t *,size_t,chunk_t*))allocate_bytes;
|
||||
this->public.destroy = (void (*)(prf_plus_t *))destroy;
|
||||
|
||||
/* take over prf */
|
||||
this->prf = prf;
|
||||
|
||||
/* allocate buffer for prf output */
|
||||
this->buffer.len = prf->get_block_size(prf);
|
||||
this->buffer.ptr = malloc(this->buffer.len);
|
||||
|
||||
this->appending_octet = 0x01;
|
||||
|
||||
/* clone seed */
|
||||
this->seed.ptr = clalloc(seed.ptr, seed.len);
|
||||
this->seed.len = seed.len;
|
||||
|
||||
/* do the first run */
|
||||
appending_chunk.ptr = &(this->appending_octet);
|
||||
appending_chunk.len = 1;
|
||||
this->prf->get_bytes(this->prf, this->seed, NULL);
|
||||
this->prf->get_bytes(this->prf, appending_chunk, this->buffer.ptr);
|
||||
this->given_out = 0;
|
||||
this->appending_octet++;
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/**
|
||||
* @file prf_plus.h
|
||||
*
|
||||
* @brief Interface for prf_plus.h.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PRF_PLUS_H_
|
||||
#define PRF_PLUS_H_
|
||||
|
||||
|
||||
#include <crypto/prfs/prf.h>
|
||||
|
||||
|
||||
typedef struct prf_plus_t prf_plus_t;
|
||||
|
||||
/**
|
||||
* @brief Implementation of the prf+ function described in IKEv2 RFC.
|
||||
*
|
||||
* This class implements the prf+ algorithm. Internally it uses a pseudo random
|
||||
* function, which implements the prf_t interface.
|
||||
*
|
||||
* See IKEv2 RFC 2.13.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - prf_plus_create()
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
struct prf_plus_t {
|
||||
/**
|
||||
* @brief Get pseudo random bytes.
|
||||
*
|
||||
* Get the next few bytes of the prf+ output. Space
|
||||
* must be allocated by the caller.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param length number of bytes to get
|
||||
* @param[out] buffer pointer where the generated bytes will be written
|
||||
*/
|
||||
void (*get_bytes) (prf_plus_t *this, size_t length, u_int8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief Allocate pseudo random bytes.
|
||||
*
|
||||
* Get the next few bytes of the prf+ output. This function
|
||||
* will allocate the required space.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param length number of bytes to get
|
||||
* @param[out] chunk chunk which will hold generated bytes
|
||||
*/
|
||||
void (*allocate_bytes) (prf_plus_t *this, size_t length, chunk_t *chunk);
|
||||
|
||||
/**
|
||||
* @brief Destroys a prf_plus_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (prf_plus_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new prf_plus_t object.
|
||||
*
|
||||
* Seed will be cloned. prf will
|
||||
* not be cloned, must be destroyed outside after
|
||||
* prf_plus_t usage.
|
||||
*
|
||||
* @param prf prf object to use
|
||||
* @param seed input seed for prf
|
||||
* @return prf_plus_t object
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
prf_plus_t *prf_plus_create(prf_t *prf, chunk_t seed);
|
||||
|
||||
#endif /*PRF_PLUS_H_*/
|
||||
@@ -1,23 +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 <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.
|
||||
#
|
||||
|
||||
PRFS_DIR= $(CRYPTO_DIR)prfs/
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)prf.o
|
||||
$(BUILD_DIR)prf.o : $(PRFS_DIR)prf.c $(PRFS_DIR)prf.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)hmac_prf.o
|
||||
$(BUILD_DIR)hmac_prf.o : $(PRFS_DIR)hmac_prf.c $(PRFS_DIR)hmac_prf.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
@@ -1,117 +0,0 @@
|
||||
/**
|
||||
* @file hmac_prf.c
|
||||
*
|
||||
* @brief Implementation for hmac_prf_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "hmac_prf.h"
|
||||
|
||||
#include <crypto/hmac.h>
|
||||
|
||||
|
||||
typedef struct private_hmac_prf_t private_hmac_prf_t;
|
||||
|
||||
/**
|
||||
* Private data of a hma_prf_t object.
|
||||
*/
|
||||
struct private_hmac_prf_t {
|
||||
/**
|
||||
* Public hmac_prf_t interface.
|
||||
*/
|
||||
hmac_prf_t public;
|
||||
|
||||
/**
|
||||
* Hmac to use for generation.
|
||||
*/
|
||||
hmac_t *hmac;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of prf_t.get_bytes.
|
||||
*/
|
||||
static void get_bytes(private_hmac_prf_t *this, chunk_t seed, u_int8_t *buffer)
|
||||
{
|
||||
this->hmac->get_mac(this->hmac, seed, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of prf_t.allocate_bytes.
|
||||
*/
|
||||
static void allocate_bytes(private_hmac_prf_t *this, chunk_t seed, chunk_t *chunk)
|
||||
{
|
||||
this->hmac->allocate_mac(this->hmac, seed, chunk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of prf_t.get_block_size.
|
||||
*/
|
||||
static size_t get_block_size(private_hmac_prf_t *this)
|
||||
{
|
||||
return this->hmac->get_block_size(this->hmac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of prf_t.get_block_size.
|
||||
*/
|
||||
static size_t get_key_size(private_hmac_prf_t *this)
|
||||
{
|
||||
/* for HMAC prfs, IKEv2 uses block size as key size */
|
||||
return this->hmac->get_block_size(this->hmac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of prf_t.set_key.
|
||||
*/
|
||||
static void set_key(private_hmac_prf_t *this, chunk_t key)
|
||||
{
|
||||
this->hmac->set_key(this->hmac, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of prf_t.destroy.
|
||||
*/
|
||||
static void destroy(private_hmac_prf_t *this)
|
||||
{
|
||||
free(this);
|
||||
this->hmac->destroy(this->hmac);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
hmac_prf_t *hmac_prf_create(hash_algorithm_t hash_algorithm)
|
||||
{
|
||||
private_hmac_prf_t *this = malloc_thing(private_hmac_prf_t);
|
||||
|
||||
this->public.prf_interface.get_bytes = (void (*) (prf_t *,chunk_t,u_int8_t*))get_bytes;
|
||||
this->public.prf_interface.allocate_bytes = (void (*) (prf_t*,chunk_t,chunk_t*))allocate_bytes;
|
||||
this->public.prf_interface.get_block_size = (size_t (*) (prf_t*))get_block_size;
|
||||
this->public.prf_interface.get_key_size = (size_t (*) (prf_t*))get_key_size;
|
||||
this->public.prf_interface.set_key = (void (*) (prf_t *,chunk_t))set_key;
|
||||
this->public.prf_interface.destroy = (void (*) (prf_t *))destroy;
|
||||
|
||||
this->hmac = hmac_create(hash_algorithm);
|
||||
if (this->hmac == NULL)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/**
|
||||
* @file hmac_prf.h
|
||||
*
|
||||
* @brief Interface of hmac_prf_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PRF_HMAC_H_
|
||||
#define PRF_HMAC_H_
|
||||
|
||||
#include <types.h>
|
||||
#include <crypto/prfs/prf.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
typedef struct hmac_prf_t hmac_prf_t;
|
||||
|
||||
/**
|
||||
* @brief Implementation of prf_t interface using the
|
||||
* HMAC algorithm.
|
||||
*
|
||||
* This simply wraps a hmac_t in a prf_t. More a question of
|
||||
* interface matching.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - hmac_prf_create()
|
||||
*
|
||||
* @ingroup prfs
|
||||
*/
|
||||
struct hmac_prf_t {
|
||||
|
||||
/**
|
||||
* Generic prf_t interface for this hmac_prf_t class.
|
||||
*/
|
||||
prf_t prf_interface;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new hmac_prf_t object.
|
||||
*
|
||||
* @param hash_algorithm hmac's hash algorithm
|
||||
* @return
|
||||
* - hmac_prf_t object
|
||||
* - NULL if hash not supported
|
||||
*
|
||||
* @ingroup prfs
|
||||
*/
|
||||
hmac_prf_t *hmac_prf_create(hash_algorithm_t hash_algorithm);
|
||||
|
||||
#endif /*PRF_HMAC_SHA1_H_*/
|
||||
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
* @file prf.c
|
||||
*
|
||||
* @brief Generic constructor for all prf_t
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "prf.h"
|
||||
|
||||
#include <crypto/hashers/hasher.h>
|
||||
#include <crypto/prfs/hmac_prf.h>
|
||||
|
||||
|
||||
/**
|
||||
* String mappings for encryption_algorithm_t.
|
||||
*/
|
||||
mapping_t pseudo_random_function_m[] = {
|
||||
{PRF_UNDEFINED, "PRF_UNDEFINED"},
|
||||
{PRF_HMAC_MD5, "PRF_HMAC_MD5"},
|
||||
{PRF_HMAC_SHA1, "PRF_HMAC_SHA1"},
|
||||
{PRF_HMAC_TIGER, "PRF_HMAC_TIGER"},
|
||||
{PRF_AES128_CBC, "PRF_AES128_CBC"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
prf_t *prf_create(pseudo_random_function_t pseudo_random_function)
|
||||
{
|
||||
switch (pseudo_random_function)
|
||||
{
|
||||
case PRF_HMAC_SHA1:
|
||||
{
|
||||
return (prf_t*)hmac_prf_create(HASH_SHA1);
|
||||
}
|
||||
case PRF_HMAC_MD5:
|
||||
{
|
||||
return (prf_t*)hmac_prf_create(HASH_MD5);
|
||||
}
|
||||
case PRF_HMAC_TIGER:
|
||||
case PRF_AES128_CBC:
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
/**
|
||||
* @file prf.h
|
||||
*
|
||||
* @brief Interface prf_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef PRF_H_
|
||||
#define PRF_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef enum pseudo_random_function_t pseudo_random_function_t;
|
||||
|
||||
/**
|
||||
* @brief Pseudo random function, as in IKEv2 RFC 3.3.2.
|
||||
*
|
||||
* Currently only the following algorithms are implemented and therefore supported:
|
||||
* - PRF_HMAC_MD5
|
||||
* - PRF_HMAC_SHA1
|
||||
*
|
||||
* @ingroup prfs
|
||||
*/
|
||||
enum pseudo_random_function_t {
|
||||
PRF_UNDEFINED = 1024,
|
||||
/**
|
||||
* Implemented in class hmac_prf_t.
|
||||
*/
|
||||
PRF_HMAC_MD5 = 1,
|
||||
/**
|
||||
* Implemented in class hmac_prf_t.
|
||||
*/
|
||||
PRF_HMAC_SHA1 = 2,
|
||||
PRF_HMAC_TIGER = 3,
|
||||
PRF_AES128_CBC = 4
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for encryption_algorithm_t.
|
||||
*/
|
||||
extern mapping_t pseudo_random_function_m[];
|
||||
|
||||
|
||||
typedef struct prf_t prf_t;
|
||||
|
||||
/**
|
||||
* @brief Generic interface for pseudo-random-functions.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - prf_create()
|
||||
* - hmac_prf_create()
|
||||
*
|
||||
* @todo Implement more prf algorithms
|
||||
*
|
||||
* @ingroup prfs
|
||||
*/
|
||||
struct prf_t {
|
||||
/**
|
||||
* @brief Generates pseudo random bytes and writes them
|
||||
* in the buffer.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param seed a chunk containing the seed for the next bytes
|
||||
* @param[out] buffer pointer where the generated bytes will be written
|
||||
*/
|
||||
void (*get_bytes) (prf_t *this, chunk_t seed, u_int8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief Generates pseudo random bytes and allocate space for them.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param seed a chunk containing the seed for the next bytes
|
||||
* @param[out] chunk chunk which will hold generated bytes
|
||||
*/
|
||||
void (*allocate_bytes) (prf_t *this, chunk_t seed, chunk_t *chunk);
|
||||
|
||||
/**
|
||||
* @brief Get the block size of this prf_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return block size in bytes
|
||||
*/
|
||||
size_t (*get_block_size) (prf_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the key size of this prf_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return key size in bytes
|
||||
*/
|
||||
size_t (*get_key_size) (prf_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set the key for this prf_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param key key to set
|
||||
*/
|
||||
void (*set_key) (prf_t *this, chunk_t key);
|
||||
|
||||
/**
|
||||
* @brief Destroys a prf object.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (prf_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generic constructor for a prf_t oject.
|
||||
*
|
||||
* @param pseudo_random_function Algorithm to use
|
||||
* @return
|
||||
* - prf_t object
|
||||
* - NULL if prf algorithm not supported
|
||||
*
|
||||
* @ingroup prfs
|
||||
*/
|
||||
prf_t *prf_create(pseudo_random_function_t pseudo_random_function);
|
||||
|
||||
#endif /*PRF_H_*/
|
||||
@@ -1,23 +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 <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.
|
||||
#
|
||||
|
||||
RSA_DIR= $(CRYPTO_DIR)rsa/
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)rsa_private_key.o
|
||||
$(BUILD_DIR)rsa_private_key.o : $(RSA_DIR)rsa_private_key.c $(RSA_DIR)rsa_private_key.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)rsa_public_key.o
|
||||
$(BUILD_DIR)rsa_public_key.o : $(RSA_DIR)rsa_public_key.c $(RSA_DIR)rsa_public_key.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
@@ -1,753 +0,0 @@
|
||||
/**
|
||||
* @file rsa_private_key.c
|
||||
*
|
||||
* @brief Implementation of rsa_private_key_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <gmp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rsa_private_key.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/pem.h>
|
||||
|
||||
/*
|
||||
* Oids for hash algorithms are defined in
|
||||
* rsa_public_key.c.
|
||||
*/
|
||||
extern u_int8_t md2_oid[18];
|
||||
extern u_int8_t md5_oid[18];
|
||||
extern u_int8_t sha1_oid[15];
|
||||
extern u_int8_t sha256_oid[19];
|
||||
extern u_int8_t sha384_oid[19];
|
||||
extern u_int8_t sha512_oid[19];
|
||||
|
||||
|
||||
/**
|
||||
* Public exponent to use for key generation.
|
||||
*/
|
||||
#define PUBLIC_EXPONENT 0x10001
|
||||
|
||||
|
||||
typedef struct private_rsa_private_key_t private_rsa_private_key_t;
|
||||
|
||||
/**
|
||||
* Private data of a rsa_private_key_t object.
|
||||
*/
|
||||
struct private_rsa_private_key_t {
|
||||
/**
|
||||
* Public interface for this signer.
|
||||
*/
|
||||
rsa_private_key_t public;
|
||||
|
||||
/**
|
||||
* Version of key, as encoded in PKCS#1
|
||||
*/
|
||||
u_int version;
|
||||
|
||||
/**
|
||||
* Public modulus.
|
||||
*/
|
||||
mpz_t n;
|
||||
|
||||
/**
|
||||
* Public exponent.
|
||||
*/
|
||||
mpz_t e;
|
||||
|
||||
/**
|
||||
* Private prime 1.
|
||||
*/
|
||||
mpz_t p;
|
||||
|
||||
/**
|
||||
* Private Prime 2.
|
||||
*/
|
||||
mpz_t q;
|
||||
|
||||
/**
|
||||
* Private exponent.
|
||||
*/
|
||||
mpz_t d;
|
||||
|
||||
/**
|
||||
* Private exponent 1.
|
||||
*/
|
||||
mpz_t exp1;
|
||||
|
||||
/**
|
||||
* Private exponent 2.
|
||||
*/
|
||||
mpz_t exp2;
|
||||
|
||||
/**
|
||||
* Private coefficient.
|
||||
*/
|
||||
mpz_t coeff;
|
||||
|
||||
/**
|
||||
* Keysize in bytes.
|
||||
*/
|
||||
size_t k;
|
||||
|
||||
/**
|
||||
* @brief Implements the RSADP algorithm specified in PKCS#1.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data data to process
|
||||
* @return processed data
|
||||
*/
|
||||
chunk_t (*rsadp) (private_rsa_private_key_t *this, chunk_t data);
|
||||
|
||||
/**
|
||||
* @brief Implements the RSASP1 algorithm specified in PKCS#1.
|
||||
* @param this calling object
|
||||
* @param data data to process
|
||||
* @return processed data
|
||||
*/
|
||||
chunk_t (*rsasp1) (private_rsa_private_key_t *this, chunk_t data);
|
||||
|
||||
/**
|
||||
* @brief Generate a prime value.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param prime_size size of the prime, in bytes
|
||||
* @param[out] prime uninitialized mpz
|
||||
*/
|
||||
status_t (*compute_prime) (private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime);
|
||||
|
||||
};
|
||||
|
||||
/* ASN.1 definition of a PKCS#1 RSA private key */
|
||||
static const asn1Object_t privkey_objects[] = {
|
||||
{ 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 PRIV_KEY_VERSION 1
|
||||
#define PRIV_KEY_MODULUS 2
|
||||
#define PRIV_KEY_PUB_EXP 3
|
||||
#define PRIV_KEY_PRIV_EXP 4
|
||||
#define PRIV_KEY_PRIME1 5
|
||||
#define PRIV_KEY_PRIME2 6
|
||||
#define PRIV_KEY_EXP1 7
|
||||
#define PRIV_KEY_EXP2 8
|
||||
#define PRIV_KEY_COEFF 9
|
||||
#define PRIV_KEY_ROOF 16
|
||||
|
||||
static private_rsa_private_key_t *rsa_private_key_create_empty(void);
|
||||
|
||||
/**
|
||||
* Implementation of private_rsa_private_key_t.compute_prime.
|
||||
*/
|
||||
static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_size, mpz_t *prime)
|
||||
{
|
||||
randomizer_t *randomizer;
|
||||
chunk_t random_bytes;
|
||||
status_t status;
|
||||
|
||||
randomizer = randomizer_create();
|
||||
mpz_init(*prime);
|
||||
|
||||
do
|
||||
{
|
||||
status = randomizer->allocate_random_bytes(randomizer, prime_size, &random_bytes);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
randomizer->destroy(randomizer);
|
||||
mpz_clear(*prime);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* make sure most significant bit is set */
|
||||
random_bytes.ptr[0] = random_bytes.ptr[0] | 0x80;
|
||||
|
||||
/* convert chunk to mpz value */
|
||||
mpz_import(*prime, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
|
||||
|
||||
/* get next prime */
|
||||
mpz_nextprime (*prime, *prime);
|
||||
|
||||
free(random_bytes.ptr);
|
||||
}
|
||||
/* check if it isnt too large */
|
||||
while (((mpz_sizeinbase(*prime, 2) + 7) / 8) > prime_size);
|
||||
|
||||
randomizer->destroy(randomizer);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_rsa_private_key_t.rsadp and private_rsa_private_key_t.rsasp1.
|
||||
*/
|
||||
static chunk_t rsadp(private_rsa_private_key_t *this, chunk_t data)
|
||||
{
|
||||
mpz_t t1, t2;
|
||||
chunk_t decrypted;
|
||||
|
||||
mpz_init(t1);
|
||||
mpz_init(t2);
|
||||
|
||||
mpz_import(t1, data.len, 1, 1, 1, 0, data.ptr);
|
||||
|
||||
mpz_powm(t2, t1, this->exp1, this->p); /* m1 = c^dP mod p */
|
||||
mpz_powm(t1, t1, this->exp2, this->q); /* m2 = c^dQ mod Q */
|
||||
mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */
|
||||
mpz_mod(t2, t2, this->p);
|
||||
mpz_mul(t2, t2, this->coeff);
|
||||
mpz_mod(t2, t2, this->p);
|
||||
|
||||
mpz_mul(t2, t2, this->q); /* m = m2 + h q */
|
||||
mpz_add(t1, t1, t2);
|
||||
|
||||
decrypted.len = this->k;
|
||||
decrypted.ptr = mpz_export(NULL, NULL, 1, decrypted.len, 1, 0, t1);
|
||||
|
||||
mpz_clear(t1);
|
||||
mpz_clear(t2);
|
||||
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.build_emsa_signature.
|
||||
*/
|
||||
static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, hash_algorithm_t hash_algorithm, chunk_t data, chunk_t *signature)
|
||||
{
|
||||
hasher_t *hasher;
|
||||
chunk_t hash;
|
||||
chunk_t oid;
|
||||
chunk_t em;
|
||||
|
||||
/* get oid string prepended to hash */
|
||||
switch (hash_algorithm)
|
||||
{
|
||||
case HASH_MD2:
|
||||
{
|
||||
oid.ptr = md2_oid;
|
||||
oid.len = sizeof(md2_oid);
|
||||
break;
|
||||
}
|
||||
case HASH_MD5:
|
||||
{
|
||||
oid.ptr = md5_oid;
|
||||
oid.len = sizeof(md5_oid);
|
||||
break;
|
||||
}
|
||||
case HASH_SHA1:
|
||||
{
|
||||
oid.ptr = sha1_oid;
|
||||
oid.len = sizeof(sha1_oid);
|
||||
break;
|
||||
}
|
||||
case HASH_SHA256:
|
||||
{
|
||||
oid.ptr = sha256_oid;
|
||||
oid.len = sizeof(sha256_oid);
|
||||
break;
|
||||
}
|
||||
case HASH_SHA384:
|
||||
{
|
||||
oid.ptr = sha384_oid;
|
||||
oid.len = sizeof(sha384_oid);
|
||||
break;
|
||||
}
|
||||
case HASH_SHA512:
|
||||
{
|
||||
oid.ptr = sha512_oid;
|
||||
oid.len = sizeof(sha512_oid);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
/* get hasher */
|
||||
hasher = hasher_create(hash_algorithm);
|
||||
if (hasher == NULL)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* build hash */
|
||||
hasher->allocate_hash(hasher, data, &hash);
|
||||
hasher->destroy(hasher);
|
||||
|
||||
/* build chunk to rsa-decrypt:
|
||||
* EM = 0x00 || 0x01 || PS || 0x00 || T.
|
||||
* PS = 0xFF padding, with length to fill em
|
||||
* T = oid || hash
|
||||
*/
|
||||
em.len = this->k;
|
||||
em.ptr = malloc(em.len);
|
||||
|
||||
/* fill em with padding */
|
||||
memset(em.ptr, 0xFF, em.len);
|
||||
/* set magic bytes */
|
||||
*(em.ptr) = 0x00;
|
||||
*(em.ptr+1) = 0x01;
|
||||
*(em.ptr + em.len - hash.len - oid.len - 1) = 0x00;
|
||||
/* set hash */
|
||||
memcpy(em.ptr + em.len - hash.len, hash.ptr, hash.len);
|
||||
/* set oid */
|
||||
memcpy(em.ptr + em.len - hash.len - oid.len, oid.ptr, oid.len);
|
||||
|
||||
/* build signature */
|
||||
*signature = this->rsasp1(this, em);
|
||||
|
||||
free(hash.ptr);
|
||||
free(em.ptr);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.get_key.
|
||||
*/
|
||||
static status_t get_key(private_rsa_private_key_t *this, chunk_t *key)
|
||||
{
|
||||
chunk_t n, e, p, q, d, exp1, exp2, coeff;
|
||||
|
||||
n.len = this->k;
|
||||
n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, this->n);
|
||||
e.len = this->k;
|
||||
e.ptr = mpz_export(NULL, NULL, 1, e.len, 1, 0, this->e);
|
||||
p.len = this->k;
|
||||
p.ptr = mpz_export(NULL, NULL, 1, p.len, 1, 0, this->p);
|
||||
q.len = this->k;
|
||||
q.ptr = mpz_export(NULL, NULL, 1, q.len, 1, 0, this->q);
|
||||
d.len = this->k;
|
||||
d.ptr = mpz_export(NULL, NULL, 1, d.len, 1, 0, this->d);
|
||||
exp1.len = this->k;
|
||||
exp1.ptr = mpz_export(NULL, NULL, 1, exp1.len, 1, 0, this->exp1);
|
||||
exp2.len = this->k;
|
||||
exp2.ptr = mpz_export(NULL, NULL, 1, exp2.len, 1, 0, this->exp2);
|
||||
coeff.len = this->k;
|
||||
coeff.ptr = mpz_export(NULL, NULL, 1, coeff.len, 1, 0, this->coeff);
|
||||
|
||||
key->len = this->k * 8;
|
||||
key->ptr = malloc(key->len);
|
||||
memcpy(key->ptr + this->k * 0, n.ptr , n.len);
|
||||
memcpy(key->ptr + this->k * 1, e.ptr, e.len);
|
||||
memcpy(key->ptr + this->k * 2, p.ptr, p.len);
|
||||
memcpy(key->ptr + this->k * 3, q.ptr, q.len);
|
||||
memcpy(key->ptr + this->k * 4, d.ptr, d.len);
|
||||
memcpy(key->ptr + this->k * 5, exp1.ptr, exp1.len);
|
||||
memcpy(key->ptr + this->k * 6, exp2.ptr, exp2.len);
|
||||
memcpy(key->ptr + this->k * 7, coeff.ptr, coeff.len);
|
||||
|
||||
free(n.ptr);
|
||||
free(e.ptr);
|
||||
free(p.ptr);
|
||||
free(q.ptr);
|
||||
free(d.ptr);
|
||||
free(exp1.ptr);
|
||||
free(exp2.ptr);
|
||||
free(coeff.ptr);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.save_key.
|
||||
*/
|
||||
static status_t save_key(private_rsa_private_key_t *this, char *file)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.get_public_key.
|
||||
*/
|
||||
rsa_public_key_t *get_public_key(private_rsa_private_key_t *this)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.belongs_to.
|
||||
*/
|
||||
static bool belongs_to(private_rsa_private_key_t *this, rsa_public_key_t *public)
|
||||
{
|
||||
if (mpz_cmp(this->n, *public->get_modulus(public)) == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the loaded key if it is valid and usable
|
||||
* TODO: Log errors
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.clone.
|
||||
*/
|
||||
static rsa_private_key_t* _clone(private_rsa_private_key_t *this)
|
||||
{
|
||||
private_rsa_private_key_t *clone = rsa_private_key_create_empty();
|
||||
|
||||
mpz_init_set(clone->n, this->n);
|
||||
mpz_init_set(clone->e, this->e);
|
||||
mpz_init_set(clone->p, this->p);
|
||||
mpz_init_set(clone->q, this->q);
|
||||
mpz_init_set(clone->d, this->d);
|
||||
mpz_init_set(clone->exp1, this->exp1);
|
||||
mpz_init_set(clone->exp2, this->exp2);
|
||||
mpz_init_set(clone->coeff, this->coeff);
|
||||
clone->k = this->k;
|
||||
|
||||
return &clone->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.destroy.
|
||||
*/
|
||||
static void destroy(private_rsa_private_key_t *this)
|
||||
{
|
||||
mpz_clear(this->n);
|
||||
mpz_clear(this->e);
|
||||
mpz_clear(this->p);
|
||||
mpz_clear(this->q);
|
||||
mpz_clear(this->d);
|
||||
mpz_clear(this->exp1);
|
||||
mpz_clear(this->exp2);
|
||||
mpz_clear(this->coeff);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal generic constructor
|
||||
*/
|
||||
static private_rsa_private_key_t *rsa_private_key_create_empty(void)
|
||||
{
|
||||
private_rsa_private_key_t *this = malloc_thing(private_rsa_private_key_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.build_emsa_pkcs1_signature = (status_t (*) (rsa_private_key_t*,hash_algorithm_t,chunk_t,chunk_t*))build_emsa_pkcs1_signature;
|
||||
this->public.get_key = (status_t (*) (rsa_private_key_t*,chunk_t*))get_key;
|
||||
this->public.save_key = (status_t (*) (rsa_private_key_t*,char*))save_key;
|
||||
this->public.get_public_key = (rsa_public_key_t *(*) (rsa_private_key_t*))get_public_key;
|
||||
this->public.belongs_to = (bool (*) (rsa_private_key_t*,rsa_public_key_t*))belongs_to;
|
||||
this->public.clone = (rsa_private_key_t*(*)(rsa_private_key_t*))_clone;
|
||||
this->public.destroy = (void (*) (rsa_private_key_t*))destroy;
|
||||
|
||||
/* private functions */
|
||||
this->rsadp = rsadp;
|
||||
this->rsasp1 = rsadp; /* same algorithm */
|
||||
this->compute_prime = compute_prime;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* See header
|
||||
*/
|
||||
rsa_private_key_t *rsa_private_key_create(size_t key_size)
|
||||
{
|
||||
mpz_t p, q, n, e, d, exp1, exp2, coeff;
|
||||
mpz_t m, q1, t;
|
||||
private_rsa_private_key_t *this;
|
||||
|
||||
this = rsa_private_key_create_empty();
|
||||
key_size = key_size / 8;
|
||||
|
||||
/* Get values of primes p and q */
|
||||
if (this->compute_prime(this, key_size/2, &p) != SUCCESS)
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
if (this->compute_prime(this, key_size/2, &q) != SUCCESS)
|
||||
{
|
||||
mpz_clear(p);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mpz_init(t);
|
||||
mpz_init(n);
|
||||
mpz_init(d);
|
||||
mpz_init(exp1);
|
||||
mpz_init(exp2);
|
||||
mpz_init(coeff);
|
||||
|
||||
/* Swapping Primes so p is larger then q */
|
||||
if (mpz_cmp(p, q) < 0)
|
||||
{
|
||||
mpz_set(t, p);
|
||||
mpz_set(p, q);
|
||||
mpz_set(q, t);
|
||||
}
|
||||
|
||||
mpz_mul(n, p, q); /* n = p*q */
|
||||
mpz_init_set_ui(e, PUBLIC_EXPONENT); /* assign public exponent */
|
||||
mpz_init_set(m, p); /* m = p */
|
||||
mpz_sub_ui(m, m, 1); /* m = m -1 */
|
||||
mpz_init_set(q1, q); /* q1 = q */
|
||||
mpz_sub_ui(q1, q1, 1); /* q1 = q1 -1 */
|
||||
mpz_gcd(t, m, q1); /* t = gcd(p-1, q-1) */
|
||||
mpz_mul(m, m, q1); /* m = (p-1)*(q-1) */
|
||||
mpz_divexact(m, m, t); /* m = m / t */
|
||||
mpz_gcd(t, m, e); /* t = gcd(m, e) (greatest common divisor) */
|
||||
|
||||
mpz_invert(d, e, m); /* e has an inverse mod m */
|
||||
if (mpz_cmp_ui(d, 0) < 0) /* make sure d is positive */
|
||||
{
|
||||
mpz_add(d, d, m);
|
||||
}
|
||||
mpz_sub_ui(t, p, 1); /* t = p-1 */
|
||||
mpz_mod(exp1, d, t); /* exp1 = d mod p-1 */
|
||||
mpz_sub_ui(t, q, 1); /* t = q-1 */
|
||||
mpz_mod(exp2, d, t); /* exp2 = d mod q-1 */
|
||||
|
||||
mpz_invert(coeff, q, p); /* coeff = q^-1 mod p */
|
||||
if (mpz_cmp_ui(coeff, 0) < 0) /* make coeff d is positive */
|
||||
{
|
||||
mpz_add(coeff, coeff, p);
|
||||
}
|
||||
|
||||
mpz_clear(q1);
|
||||
mpz_clear(m);
|
||||
mpz_clear(t);
|
||||
|
||||
/* apply values */
|
||||
*(this->p) = *p;
|
||||
*(this->q) = *q;
|
||||
*(this->n) = *n;
|
||||
*(this->e) = *e;
|
||||
*(this->d) = *d;
|
||||
*(this->exp1) = *exp1;
|
||||
*(this->exp2) = *exp2;
|
||||
*(this->coeff) = *coeff;
|
||||
|
||||
/* set key size in bytes */
|
||||
this->k = key_size;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* see header
|
||||
*/
|
||||
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 < PRIV_KEY_ROOF)
|
||||
{
|
||||
if (!extract_object(privkey_objects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
destroy(this);
|
||||
return FALSE;
|
||||
}
|
||||
switch (objectID)
|
||||
{
|
||||
case PRIV_KEY_VERSION:
|
||||
if (object.len > 0 && *object.ptr != 0)
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case PRIV_KEY_MODULUS:
|
||||
mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
case PRIV_KEY_PUB_EXP:
|
||||
mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
case PRIV_KEY_PRIV_EXP:
|
||||
mpz_import(this->d, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
case PRIV_KEY_PRIME1:
|
||||
mpz_import(this->p, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
case PRIV_KEY_PRIME2:
|
||||
mpz_import(this->q, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
case PRIV_KEY_EXP1:
|
||||
mpz_import(this->exp1, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
case PRIV_KEY_EXP2:
|
||||
mpz_import(this->exp2, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
case PRIV_KEY_COEFF:
|
||||
mpz_import(this->coeff, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
|
||||
this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
|
||||
|
||||
if (check(this) != SUCCESS)
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &this->public;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* see header
|
||||
*/
|
||||
rsa_private_key_t *rsa_private_key_create_from_file(char *filename, char *passphrase)
|
||||
{
|
||||
bool pgp = FALSE;
|
||||
chunk_t chunk = CHUNK_INITIALIZER;
|
||||
rsa_private_key_t *key = NULL;
|
||||
|
||||
if (!pem_asn1_load_file(filename, passphrase, "private key", &chunk, &pgp))
|
||||
return NULL;
|
||||
|
||||
key = rsa_private_key_create_from_chunk(chunk);
|
||||
free(chunk.ptr);
|
||||
return key;
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
/**
|
||||
* @file rsa_private_key.h
|
||||
*
|
||||
* @brief Interface of rsa_private_key_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RSA_PRIVATE_KEY_H_
|
||||
#define RSA_PRIVATE_KEY_H_
|
||||
|
||||
#include <types.h>
|
||||
#include <definitions.h>
|
||||
#include <crypto/rsa/rsa_public_key.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
|
||||
typedef struct rsa_private_key_t rsa_private_key_t;
|
||||
|
||||
/**
|
||||
* @brief RSA private key with associated functions.
|
||||
*
|
||||
* Currently only supports signing using EMSA encoding.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - rsa_private_key_create()
|
||||
* - rsa_private_key_create_from_chunk()
|
||||
* - rsa_private_key_create_from_file()
|
||||
*
|
||||
* @see rsa_public_key_t
|
||||
*
|
||||
* @todo Implement get_key(), save_key(), get_public_key()
|
||||
*
|
||||
* @ingroup rsa
|
||||
*/
|
||||
struct rsa_private_key_t {
|
||||
|
||||
/**
|
||||
* @brief Build a signature over a chunk using EMSA-PKCS1 encoding.
|
||||
*
|
||||
* This signature creates a hash using the specified hash algorithm, concatenates
|
||||
* it with an ASN1-OID of the hash algorithm and runs the RSASP1 function
|
||||
* on it.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param hash_algorithm hash algorithm to use for hashing
|
||||
* @param data data to sign
|
||||
* @param[out] signature allocated signature
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - INVALID_STATE, if key not set
|
||||
* - NOT_SUPPORTED, if hash algorithm not supported
|
||||
*/
|
||||
status_t (*build_emsa_pkcs1_signature) (rsa_private_key_t *this, hash_algorithm_t hash_algorithm, chunk_t data, chunk_t *signature);
|
||||
|
||||
/**
|
||||
* @brief Gets the key.
|
||||
*
|
||||
* UNIMPLEMENTED!
|
||||
*
|
||||
* @param this calling object
|
||||
* @param key key (in a propriarity format)
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - INVALID_STATE, if key not set
|
||||
*/
|
||||
status_t (*get_key) (rsa_private_key_t *this, chunk_t *key);
|
||||
|
||||
/**
|
||||
* @brief Saves a key to a file.
|
||||
*
|
||||
* Not implemented!
|
||||
*
|
||||
* @param this calling object
|
||||
* @param file file to which the key should be written.
|
||||
* @return NOT_SUPPORTED
|
||||
*/
|
||||
status_t (*save_key) (rsa_private_key_t *this, char *file);
|
||||
|
||||
/**
|
||||
* @brief Generate a new key.
|
||||
*
|
||||
* Generates a new private_key with specified key size
|
||||
*
|
||||
* @param this calling object
|
||||
* @param key_size size of the key in bits
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - INVALID_ARG if key_size invalid
|
||||
*/
|
||||
status_t (*generate_key) (rsa_private_key_t *this, size_t key_size);
|
||||
|
||||
/**
|
||||
* @brief Create a rsa_public_key_t with the public
|
||||
* parts of the key.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return public_key
|
||||
*/
|
||||
rsa_public_key_t *(*get_public_key) (rsa_private_key_t *this);
|
||||
|
||||
/**
|
||||
* @brief Check if a private key belongs to a public key.
|
||||
*
|
||||
* Compares the public part of the private key with the
|
||||
* public key, return TRUE if it equals.
|
||||
*
|
||||
* @param this private key
|
||||
* @param public public key
|
||||
* @return TRUE, if keys belong together
|
||||
*/
|
||||
bool (*belongs_to) (rsa_private_key_t *this, rsa_public_key_t *public);
|
||||
|
||||
/**
|
||||
* @brief Clone the private key.
|
||||
*
|
||||
* @param this private key to clone
|
||||
* @return clone of this
|
||||
*/
|
||||
rsa_private_key_t *(*clone) (rsa_private_key_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys the private key.
|
||||
*
|
||||
* @param this private key to destroy
|
||||
*/
|
||||
void (*destroy) (rsa_private_key_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generate a new RSA key with specified key lenght.
|
||||
*
|
||||
* @param key_size size of the key in bits
|
||||
* @return generated rsa_private_key_t.
|
||||
*
|
||||
* @ingroup rsa
|
||||
*/
|
||||
rsa_private_key_t *rsa_private_key_create(size_t key_size);
|
||||
|
||||
/**
|
||||
* @brief Load an RSA private key from a chunk.
|
||||
*
|
||||
* Load a key from a chunk, encoded as described in PKCS#1
|
||||
* (ASN1 DER encoded).
|
||||
*
|
||||
* @param chunk chunk containing the DER encoded key
|
||||
* @return loaded rsa_private_key_t, or NULL
|
||||
*
|
||||
* @ingroup rsa
|
||||
*/
|
||||
rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk);
|
||||
|
||||
/**
|
||||
* @brief Load an RSA private key from a file.
|
||||
*
|
||||
* Load a key from a file, which is either in a unencrypted binary
|
||||
* format (DER), or in a (encrypted) PEM format. The supplied
|
||||
* passphrase is used to decrypt an ecrypted key.
|
||||
*
|
||||
* @param filename filename which holds the key
|
||||
* @param passphrase optional passphase for decryption
|
||||
* @return loaded rsa_private_key_t, or NULL
|
||||
*
|
||||
* @todo Implement PEM file loading
|
||||
* @todo Implement key decryption
|
||||
*
|
||||
* @ingroup rsa
|
||||
*/
|
||||
rsa_private_key_t *rsa_private_key_create_from_file(char *filename, char *passphrase);
|
||||
|
||||
#endif /*RSA_PRIVATE_KEY_H_*/
|
||||
@@ -1,458 +0,0 @@
|
||||
/**
|
||||
* @file rsa_public_key.c
|
||||
*
|
||||
* @brief Implementation of rsa_public_key_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <gmp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rsa_public_key.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
#include <asn1/asn1.h>
|
||||
|
||||
/*
|
||||
* For simplicity,
|
||||
* we use these predefined values for
|
||||
* hash algorithm OIDs. These also contain
|
||||
* the length of the following hash.
|
||||
* These values are also used in rsa_private_key.c.
|
||||
* TODO: We may move them in asn1 sometime...
|
||||
*/
|
||||
|
||||
u_int8_t md2_oid[] = {
|
||||
0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,
|
||||
0x48,0x86,0xf7,0x0d,0x02,0x02,0x05,0x00,
|
||||
0x04,0x10
|
||||
};
|
||||
|
||||
u_int8_t md5_oid[] = {
|
||||
0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,
|
||||
0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,
|
||||
0x04,0x10
|
||||
};
|
||||
|
||||
u_int8_t sha1_oid[] = {
|
||||
0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,
|
||||
0x03,0x02,0x1a,0x05,0x00,0x04,0x14
|
||||
};
|
||||
|
||||
u_int8_t sha256_oid[] = {
|
||||
0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,
|
||||
0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,
|
||||
0x00,0x04,0x20
|
||||
};
|
||||
|
||||
u_int8_t sha384_oid[] = {
|
||||
0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,
|
||||
0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,
|
||||
0x00,0x04,0x30
|
||||
};
|
||||
|
||||
u_int8_t sha512_oid[] = {
|
||||
0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,
|
||||
0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,
|
||||
0x00,0x04,0x40
|
||||
};
|
||||
|
||||
/* ASN.1 definition public key */
|
||||
static const asn1Object_t pubkey_objects[] = {
|
||||
{ 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
|
||||
{ 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
|
||||
{ 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
|
||||
};
|
||||
|
||||
#define PUB_KEY_RSA_PUBLIC_KEY 0
|
||||
#define PUB_KEY_MODULUS 1
|
||||
#define PUB_KEY_EXPONENT 2
|
||||
#define PUB_KEY_ROOF 3
|
||||
|
||||
typedef struct private_rsa_public_key_t private_rsa_public_key_t;
|
||||
|
||||
/**
|
||||
* Private data structure with signing context.
|
||||
*/
|
||||
struct private_rsa_public_key_t {
|
||||
/**
|
||||
* Public interface for this signer.
|
||||
*/
|
||||
rsa_public_key_t public;
|
||||
|
||||
/**
|
||||
* Public modulus.
|
||||
*/
|
||||
mpz_t n;
|
||||
|
||||
/**
|
||||
* Public exponent.
|
||||
*/
|
||||
mpz_t e;
|
||||
|
||||
/**
|
||||
* Keysize in bytes.
|
||||
*/
|
||||
size_t k;
|
||||
|
||||
/**
|
||||
* @brief Implements the RSAEP algorithm specified in PKCS#1.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data data to process
|
||||
* @return processed data
|
||||
*/
|
||||
chunk_t (*rsaep) (private_rsa_public_key_t *this, chunk_t data);
|
||||
|
||||
/**
|
||||
* @brief Implements the RSASVP1 algorithm specified in PKCS#1.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data data to process
|
||||
* @return processed data
|
||||
*/
|
||||
chunk_t (*rsavp1) (private_rsa_public_key_t *this, chunk_t data);
|
||||
};
|
||||
|
||||
|
||||
typedef struct rsa_public_key_info_t rsa_public_key_info_t;
|
||||
|
||||
/**
|
||||
* KeyInfo, as it appears in a public key file
|
||||
*/
|
||||
struct rsa_public_key_info_t {
|
||||
/**
|
||||
* Algorithm for this key
|
||||
*/
|
||||
chunk_t algorithm_oid;
|
||||
|
||||
/**
|
||||
* Public key, parseable with rsa_public_key_rules
|
||||
*/
|
||||
chunk_t public_key;
|
||||
};
|
||||
|
||||
private_rsa_public_key_t *rsa_public_key_create_empty(void);
|
||||
|
||||
/**
|
||||
* Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1
|
||||
*/
|
||||
static chunk_t rsaep(private_rsa_public_key_t *this, chunk_t data)
|
||||
{
|
||||
mpz_t m, c;
|
||||
chunk_t encrypted;
|
||||
|
||||
mpz_init(c);
|
||||
mpz_init(m);
|
||||
|
||||
mpz_import(m, data.len, 1, 1, 1, 0, data.ptr);
|
||||
|
||||
mpz_powm(c, m, this->e, this->n);
|
||||
|
||||
encrypted.len = this->k;
|
||||
encrypted.ptr = mpz_export(NULL, NULL, 1, encrypted.len, 1, 0, c);
|
||||
|
||||
mpz_clear(c);
|
||||
mpz_clear(m);
|
||||
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_public_key.verify_emsa_pkcs1_signature.
|
||||
*/
|
||||
static status_t verify_emsa_pkcs1_signature(private_rsa_public_key_t *this, chunk_t data, chunk_t signature)
|
||||
{
|
||||
hasher_t *hasher = NULL;
|
||||
chunk_t hash;
|
||||
chunk_t em;
|
||||
u_int8_t *pos;
|
||||
|
||||
if (signature.len > this->k)
|
||||
{
|
||||
return INVALID_ARG;
|
||||
}
|
||||
|
||||
/* unpack signature */
|
||||
em = this->rsavp1(this, signature);
|
||||
|
||||
/* result should look like this:
|
||||
* EM = 0x00 || 0x01 || PS || 0x00 || T.
|
||||
* PS = 0xFF padding, with length to fill em
|
||||
* T = oid || hash
|
||||
*/
|
||||
|
||||
/* check magic bytes */
|
||||
if ((*(em.ptr) != 0x00) ||
|
||||
(*(em.ptr+1) != 0x01))
|
||||
{
|
||||
free(em.ptr);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* find magic 0x00 */
|
||||
pos = em.ptr + 2;
|
||||
while (pos <= em.ptr + em.len)
|
||||
{
|
||||
if (*pos == 0x00)
|
||||
{
|
||||
/* found magic byte, stop */
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
else if (*pos != 0xFF)
|
||||
{
|
||||
/* bad padding, decryption failed ?!*/
|
||||
free(em.ptr);
|
||||
return FAILED;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (pos + 20 > em.ptr + em.len)
|
||||
{
|
||||
/* not enought room for oid compare */
|
||||
free(em.ptr);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
if (memcmp(md2_oid, pos, sizeof(md2_oid)) == 0)
|
||||
{
|
||||
hasher = hasher_create(HASH_MD2);
|
||||
pos += sizeof(md2_oid);
|
||||
}
|
||||
else if (memcmp(md5_oid, pos, sizeof(md5_oid)) == 0)
|
||||
{
|
||||
hasher = hasher_create(HASH_MD5);
|
||||
pos += sizeof(md5_oid);
|
||||
}
|
||||
else if (memcmp(sha1_oid, pos, sizeof(sha1_oid)) == 0)
|
||||
{
|
||||
hasher = hasher_create(HASH_SHA1);
|
||||
pos += sizeof(sha1_oid);
|
||||
}
|
||||
else if (memcmp(sha256_oid, pos, sizeof(sha256_oid)) == 0)
|
||||
{
|
||||
hasher = hasher_create(HASH_SHA256);
|
||||
pos += sizeof(sha256_oid);
|
||||
}
|
||||
else if (memcmp(sha384_oid, pos, sizeof(sha384_oid)) == 0)
|
||||
{
|
||||
hasher = hasher_create(HASH_SHA384);
|
||||
pos += sizeof(sha384_oid);
|
||||
}
|
||||
else if (memcmp(sha512_oid, pos, sizeof(sha512_oid)) == 0)
|
||||
{
|
||||
hasher = hasher_create(HASH_SHA512);
|
||||
pos += sizeof(sha512_oid);
|
||||
}
|
||||
|
||||
if (hasher == NULL)
|
||||
{
|
||||
/* not supported hash algorithm */
|
||||
free(em.ptr);
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (pos + hasher->get_hash_size(hasher) != em.ptr + em.len)
|
||||
{
|
||||
/* bad length */
|
||||
free(em.ptr);
|
||||
hasher->destroy(hasher);
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
/* build own hash for a compare */
|
||||
hasher->allocate_hash(hasher, data, &hash);
|
||||
hasher->destroy(hasher);
|
||||
|
||||
if (memcmp(hash.ptr, pos, hash.len) != 0)
|
||||
{
|
||||
/* hash does not equal */
|
||||
free(hash.ptr);
|
||||
free(em.ptr);
|
||||
return FAILED;
|
||||
|
||||
}
|
||||
|
||||
/* seems good */
|
||||
free(hash.ptr);
|
||||
free(em.ptr);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_public_key.get_key.
|
||||
*/
|
||||
static status_t get_key(private_rsa_public_key_t *this, chunk_t *key)
|
||||
{
|
||||
chunk_t n, e;
|
||||
|
||||
n.len = this->k;
|
||||
n.ptr = mpz_export(NULL, NULL, 1, n.len, 1, 0, this->n);
|
||||
e.len = this->k;
|
||||
e.ptr = mpz_export(NULL, NULL, 1, e.len, 1, 0, this->e);
|
||||
|
||||
key->len = this->k * 2;
|
||||
key->ptr = malloc(key->len);
|
||||
memcpy(key->ptr, n.ptr, n.len);
|
||||
memcpy(key->ptr + n.len, e.ptr, e.len);
|
||||
free(n.ptr);
|
||||
free(e.ptr);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_public_key.save_key.
|
||||
*/
|
||||
static status_t save_key(private_rsa_public_key_t *this, char *file)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_public_key.get_modulus.
|
||||
*/
|
||||
static mpz_t *get_modulus(private_rsa_public_key_t *this)
|
||||
{
|
||||
return &this->n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_public_key.clone.
|
||||
*/
|
||||
static rsa_public_key_t* _clone(private_rsa_public_key_t *this)
|
||||
{
|
||||
private_rsa_public_key_t *clone = rsa_public_key_create_empty();
|
||||
|
||||
mpz_init_set(clone->n, this->n);
|
||||
mpz_init_set(clone->e, this->e);
|
||||
clone->k = this->k;
|
||||
|
||||
return &clone->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_public_key.destroy.
|
||||
*/
|
||||
static void destroy(private_rsa_public_key_t *this)
|
||||
{
|
||||
mpz_clear(this->n);
|
||||
mpz_clear(this->e);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic private constructor
|
||||
*/
|
||||
private_rsa_public_key_t *rsa_public_key_create_empty(void)
|
||||
{
|
||||
private_rsa_public_key_t *this = malloc_thing(private_rsa_public_key_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.verify_emsa_pkcs1_signature = (status_t (*) (rsa_public_key_t*,chunk_t,chunk_t))verify_emsa_pkcs1_signature;
|
||||
this->public.get_key = (status_t (*) (rsa_public_key_t*,chunk_t*))get_key;
|
||||
this->public.save_key = (status_t (*) (rsa_public_key_t*,char*))save_key;
|
||||
this->public.get_modulus = (mpz_t *(*) (rsa_public_key_t*))get_modulus;
|
||||
this->public.clone = (rsa_public_key_t* (*) (rsa_public_key_t*))_clone;
|
||||
this->public.destroy = (void (*) (rsa_public_key_t*))destroy;
|
||||
|
||||
/* private functions */
|
||||
this->rsaep = rsaep;
|
||||
this->rsavp1 = rsaep; /* same algorithm */
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* See header
|
||||
*/
|
||||
rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t blob)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
private_rsa_public_key_t *this;
|
||||
|
||||
this = rsa_public_key_create_empty();
|
||||
mpz_init(this->n);
|
||||
mpz_init(this->e);
|
||||
|
||||
asn1_init(&ctx, blob, 0, FALSE);
|
||||
|
||||
while (objectID < PUB_KEY_ROOF)
|
||||
{
|
||||
if (!extract_object(pubkey_objects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
destroy(this);
|
||||
return FALSE;
|
||||
}
|
||||
switch (objectID)
|
||||
{
|
||||
case PUB_KEY_MODULUS:
|
||||
mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
case PUB_KEY_EXPONENT:
|
||||
mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
|
||||
this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* See header
|
||||
*/
|
||||
rsa_public_key_t *rsa_public_key_create_from_file(char *filename)
|
||||
{
|
||||
struct stat stb;
|
||||
FILE *file;
|
||||
char *buffer;
|
||||
chunk_t chunk;
|
||||
|
||||
if (stat(filename, &stb) == -1)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer = alloca(stb.st_size);
|
||||
|
||||
file = fopen(filename, "r");
|
||||
if (file == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fread(buffer, stb.st_size, 1, file) != 1)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chunk.ptr = buffer;
|
||||
chunk.len = stb.st_size;
|
||||
|
||||
return rsa_public_key_create_from_chunk(chunk);
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/**
|
||||
* @file rsa_public_key.h
|
||||
*
|
||||
* @brief Interface of rsa_public_key_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RSA_PUBLIC_KEY_H_
|
||||
#define RSA_PUBLIC_KEY_H_
|
||||
|
||||
#include <gmp.h>
|
||||
|
||||
#include <types.h>
|
||||
#include <definitions.h>
|
||||
|
||||
|
||||
typedef struct rsa_public_key_t rsa_public_key_t;
|
||||
|
||||
/**
|
||||
* @brief RSA public key with associated functions.
|
||||
*
|
||||
* Currently only supports signature verification using
|
||||
* the EMSA encoding (see PKCS1)
|
||||
*
|
||||
* @b Constructors:
|
||||
* - rsa_public_key_create_from_chunk()
|
||||
* - rsa_public_key_create_from_file()
|
||||
* - rsa_private_key_t.get_public_key()
|
||||
*
|
||||
* @see rsa_private_key_t
|
||||
*
|
||||
* @todo Implement getkey() and savekey()
|
||||
*
|
||||
* @ingroup rsa
|
||||
*/
|
||||
struct rsa_public_key_t {
|
||||
|
||||
/**
|
||||
* @brief Verify a EMSA-PKCS1 encodined signature.
|
||||
*
|
||||
* Processes the supplied signature with the RSAVP1 function,
|
||||
* selects the hash algorithm form the resultign ASN1-OID and
|
||||
* verifies the hash against the supplied data.
|
||||
*
|
||||
* @param this rsa_public_key to use
|
||||
* @param data data to sign
|
||||
* @param signature signature to verify
|
||||
* @return
|
||||
* - SUCCESS, if signature ok
|
||||
* - INVALID_STATE, if key not set
|
||||
* - NOT_SUPPORTED, if hash algorithm not supported
|
||||
* - INVALID_ARG, if signature is not a signature
|
||||
* - FAILED if signature invalid or unable to verify
|
||||
*/
|
||||
status_t (*verify_emsa_pkcs1_signature) (rsa_public_key_t *this, chunk_t data, chunk_t signature);
|
||||
|
||||
/**
|
||||
* @brief Gets the key.
|
||||
*
|
||||
* Currently uses a proprietary format which is only inteded
|
||||
* for testing. This should be replaced with a proper
|
||||
* ASN1 encoded key format, when charon gets the ASN1
|
||||
* capabilities.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param key key (in a propriarity format)
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - INVALID_STATE, if key not set
|
||||
*/
|
||||
status_t (*get_key) (rsa_public_key_t *this, chunk_t *key);
|
||||
|
||||
/**
|
||||
* @brief Saves a key to a file.
|
||||
*
|
||||
* Not implemented!
|
||||
*
|
||||
* @param this calling object
|
||||
* @param file file to which the key should be written.
|
||||
* @return NOT_SUPPORTED
|
||||
*/
|
||||
status_t (*save_key) (rsa_public_key_t *this, char *file);
|
||||
|
||||
/**
|
||||
* @brief Get the modulus of the key.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return modulus (n) of the key
|
||||
*/
|
||||
mpz_t *(*get_modulus) (rsa_public_key_t *this);
|
||||
|
||||
/**
|
||||
* @brief Clone the public key.
|
||||
*
|
||||
* @param this public key to clone
|
||||
* @return clone of this
|
||||
*/
|
||||
rsa_public_key_t *(*clone) (rsa_public_key_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys the public key.
|
||||
*
|
||||
* @param this public key to destroy
|
||||
*/
|
||||
void (*destroy) (rsa_public_key_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Load an RSA public key from a chunk.
|
||||
*
|
||||
* Load a key from a chunk, encoded in the more frequently
|
||||
* used PublicKeyInfo struct (ASN1 DER encoded).
|
||||
*
|
||||
* @param chunk chunk containing the DER encoded key
|
||||
* @return loaded rsa_public_key_t, or NULL
|
||||
*
|
||||
* @todo Check OID in PublicKeyInfo
|
||||
*
|
||||
* @ingroup rsa
|
||||
*/
|
||||
rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t chunk);
|
||||
|
||||
/**
|
||||
* @brief Load an RSA public key from a file.
|
||||
*
|
||||
* Load a key from a file, which is either in binary
|
||||
* format (DER), or in PEM format.
|
||||
*
|
||||
* @param filename filename which holds the key
|
||||
* @return loaded rsa_public_key_t, or NULL
|
||||
*
|
||||
* @todo Implement PEM file loading
|
||||
*
|
||||
* @ingroup rsa
|
||||
*/
|
||||
rsa_public_key_t *rsa_public_key_create_from_file(char *filename);
|
||||
|
||||
#endif /*RSA_PUBLIC_KEY_H_*/
|
||||
@@ -1,23 +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 <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.
|
||||
#
|
||||
|
||||
SIGNERS_DIR= $(CRYPTO_DIR)signers/
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)signer.o
|
||||
$(BUILD_DIR)signer.o : $(SIGNERS_DIR)signer.c $(SIGNERS_DIR)signer.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)hmac_signer.o
|
||||
$(BUILD_DIR)hmac_signer.o : $(SIGNERS_DIR)hmac_signer.c $(SIGNERS_DIR)hmac_signer.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
@@ -1,169 +0,0 @@
|
||||
/**
|
||||
* @file hmac_signer.c
|
||||
*
|
||||
* @brief Implementation of hmac_signer_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "hmac_signer.h"
|
||||
|
||||
#include <crypto/prfs/hmac_prf.h>
|
||||
|
||||
/**
|
||||
* This class represents a hmac signer with 12 byte (96 bit) output.
|
||||
*/
|
||||
#define BLOCK_SIZE 12
|
||||
|
||||
typedef struct private_hmac_signer_t private_hmac_signer_t;
|
||||
|
||||
/**
|
||||
* Private data structure with signing context.
|
||||
*/
|
||||
struct private_hmac_signer_t {
|
||||
/**
|
||||
* Public interface of hmac_signer_t.
|
||||
*/
|
||||
hmac_signer_t public;
|
||||
|
||||
/*
|
||||
* Assigned hmac function.
|
||||
*/
|
||||
prf_t *hmac_prf;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of signer_t.get_signature.
|
||||
*/
|
||||
static void get_signature (private_hmac_signer_t *this, chunk_t data, u_int8_t *buffer)
|
||||
{
|
||||
u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)];
|
||||
|
||||
this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac);
|
||||
|
||||
/* copy mac aka signature :-) */
|
||||
memcpy(buffer,full_mac,BLOCK_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of signer_t.allocate_signature.
|
||||
*/
|
||||
static void allocate_signature (private_hmac_signer_t *this, chunk_t data, chunk_t *chunk)
|
||||
{
|
||||
chunk_t signature;
|
||||
u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)];
|
||||
|
||||
this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac);
|
||||
|
||||
signature.ptr = malloc(BLOCK_SIZE);
|
||||
signature.len = BLOCK_SIZE;
|
||||
|
||||
/* copy signature */
|
||||
memcpy(signature.ptr,full_mac,BLOCK_SIZE);
|
||||
|
||||
*chunk = signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of signer_t.verify_signature.
|
||||
*/
|
||||
static bool verify_signature (private_hmac_signer_t *this, chunk_t data, chunk_t signature)
|
||||
{
|
||||
u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)];
|
||||
|
||||
this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac);
|
||||
|
||||
if (signature.len != BLOCK_SIZE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* compare mac aka signature :-) */
|
||||
if (memcmp(signature.ptr,full_mac,BLOCK_SIZE) == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of signer_t.get_key_size.
|
||||
*/
|
||||
static size_t get_key_size (private_hmac_signer_t *this)
|
||||
{
|
||||
/* for HMAC signer, IKEv2 uses block size as key size */
|
||||
return this->hmac_prf->get_block_size(this->hmac_prf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of signer_t.get_block_size.
|
||||
*/
|
||||
static size_t get_block_size (private_hmac_signer_t *this)
|
||||
{
|
||||
return BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of signer_t.set_key.
|
||||
*/
|
||||
static void set_key (private_hmac_signer_t *this, chunk_t key)
|
||||
{
|
||||
this->hmac_prf->set_key(this->hmac_prf,key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of signer_t.destroy.
|
||||
*/
|
||||
static status_t destroy(private_hmac_signer_t *this)
|
||||
{
|
||||
this->hmac_prf->destroy(this->hmac_prf);
|
||||
free(this);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
hmac_signer_t *hmac_signer_create(hash_algorithm_t hash_algoritm)
|
||||
{
|
||||
private_hmac_signer_t *this = malloc_thing(private_hmac_signer_t);
|
||||
|
||||
this->hmac_prf = (prf_t *) hmac_prf_create(hash_algoritm);
|
||||
|
||||
if (this->hmac_prf == NULL)
|
||||
{
|
||||
/* algorithm not supported */
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* interface functions */
|
||||
this->public.signer_interface.get_signature = (void (*) (signer_t*, chunk_t, u_int8_t*))get_signature;
|
||||
this->public.signer_interface.allocate_signature = (void (*) (signer_t*, chunk_t, chunk_t*))allocate_signature;
|
||||
this->public.signer_interface.verify_signature = (bool (*) (signer_t*, chunk_t, chunk_t))verify_signature;
|
||||
this->public.signer_interface.get_key_size = (size_t (*) (signer_t*))get_key_size;
|
||||
this->public.signer_interface.get_block_size = (size_t (*) (signer_t*))get_block_size;
|
||||
this->public.signer_interface.set_key = (void (*) (signer_t*,chunk_t))set_key;
|
||||
this->public.signer_interface.destroy = (void (*) (signer_t*))destroy;
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* @file hmac_signer.h
|
||||
*
|
||||
* @brief Interface of hmac_signer_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HMAC_SIGNER_H_
|
||||
#define HMAC_SIGNER_H_
|
||||
|
||||
#include <crypto/signers/signer.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
typedef struct hmac_signer_t hmac_signer_t;
|
||||
|
||||
/**
|
||||
* @brief Implementation of signer_t interface using the
|
||||
* HMAC algorithm in combination with either MD5 or SHA1.
|
||||
*
|
||||
* @ingroup signers
|
||||
*/
|
||||
struct hmac_signer_t {
|
||||
|
||||
/**
|
||||
* generic signer_t interface for this signer
|
||||
*/
|
||||
signer_t signer_interface;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new hmac_signer_t.
|
||||
*
|
||||
* @param hash_algoritm Hash algorithm to use with signer
|
||||
* @return
|
||||
* - hmac_signer_t
|
||||
* - NULL if hash algorithm not supported
|
||||
*
|
||||
* @ingroup signers
|
||||
*/
|
||||
hmac_signer_t *hmac_signer_create(hash_algorithm_t hash_algoritm);
|
||||
|
||||
|
||||
#endif /*HMAC_SIGNER_H_*/
|
||||
@@ -1,59 +0,0 @@
|
||||
/**
|
||||
* @file signer.c
|
||||
*
|
||||
* @brief Implementation of generic signer_t constructor.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "signer.h"
|
||||
|
||||
#include <crypto/signers/hmac_signer.h>
|
||||
|
||||
/**
|
||||
* String mappings for integrity_algorithm_t.
|
||||
*/
|
||||
mapping_t integrity_algorithm_m[] = {
|
||||
{AUTH_UNDEFINED, "AUTH_UNDEFINED"},
|
||||
{AUTH_HMAC_MD5_96, "AUTH_HMAC_MD5_96"},
|
||||
{AUTH_HMAC_SHA1_96, "AUTH_HMAC_SHA1_96"},
|
||||
{AUTH_DES_MAC, "AUTH_DES_MAC"},
|
||||
{AUTH_KPDK_MD5, "AUTH_KPDK_MD5"},
|
||||
{AUTH_AES_XCBC_96, "AUTH_AES_XCBC_96"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
signer_t *signer_create(integrity_algorithm_t integrity_algorithm)
|
||||
{
|
||||
switch(integrity_algorithm)
|
||||
{
|
||||
case AUTH_HMAC_SHA1_96:
|
||||
{
|
||||
return ((signer_t *) hmac_signer_create(HASH_SHA1));
|
||||
}
|
||||
case AUTH_HMAC_MD5_96:
|
||||
{
|
||||
return ((signer_t *) hmac_signer_create(HASH_MD5));
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
/**
|
||||
* @file signer.h
|
||||
*
|
||||
* @brief Interface for signer_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef SIGNER_H_
|
||||
#define SIGNER_H_
|
||||
|
||||
#include <types.h>
|
||||
#include <definitions.h>
|
||||
|
||||
typedef enum integrity_algorithm_t integrity_algorithm_t;
|
||||
|
||||
/**
|
||||
* @brief Integrity algorithm, as in IKEv2 RFC 3.3.2.
|
||||
*
|
||||
* Currently only the following algorithms are implemented and therefore supported:
|
||||
* - AUTH_HMAC_MD5_96
|
||||
* - AUTH_HMAC_SHA1_96
|
||||
*
|
||||
* @ingroup signers
|
||||
*/
|
||||
enum integrity_algorithm_t {
|
||||
AUTH_UNDEFINED = 1024,
|
||||
/**
|
||||
* Implemented in class hmac_signer_t.
|
||||
*/
|
||||
AUTH_HMAC_MD5_96 = 1,
|
||||
/**
|
||||
* Implemented in class hmac_signer_t.
|
||||
*/
|
||||
AUTH_HMAC_SHA1_96 = 2,
|
||||
AUTH_DES_MAC = 3,
|
||||
AUTH_KPDK_MD5 = 4,
|
||||
AUTH_AES_XCBC_96 = 5
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for integrity_algorithm_t.
|
||||
*/
|
||||
extern mapping_t integrity_algorithm_m[];
|
||||
|
||||
|
||||
typedef struct signer_t signer_t;
|
||||
|
||||
/**
|
||||
* @brief Generig interface for a symmetric signature algorithm.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - signer_create()
|
||||
* - hmac_signer_create()
|
||||
*
|
||||
* @todo Implement more integrity algorithms
|
||||
*
|
||||
* @ingroup signers
|
||||
*/
|
||||
struct signer_t {
|
||||
/**
|
||||
* @brief Generate a signature.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data a chunk containing the data to sign
|
||||
* @param[out] buffer pointer where the signature will be written
|
||||
*/
|
||||
void (*get_signature) (signer_t *this, chunk_t data, u_int8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief Generate a signature and allocate space for it.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data a chunk containing the data to sign
|
||||
* @param[out] chunk chunk which will hold the allocated signature
|
||||
*/
|
||||
void (*allocate_signature) (signer_t *this, chunk_t data, chunk_t *chunk);
|
||||
|
||||
/**
|
||||
* @brief Verify a signature.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param data a chunk containing the data to verify
|
||||
* @param signature a chunk containing the signature
|
||||
* @return TRUE, if signature is valid, FALSE otherwise
|
||||
*/
|
||||
bool (*verify_signature) (signer_t *this, chunk_t data, chunk_t signature);
|
||||
|
||||
/**
|
||||
* @brief Get the block size of this signature algorithm.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return block size in bytes
|
||||
*/
|
||||
size_t (*get_block_size) (signer_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the key size of the signature algorithm.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return key size in bytes
|
||||
*/
|
||||
size_t (*get_key_size) (signer_t *this);
|
||||
|
||||
/**
|
||||
* @brief Set the key for this object.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param key key to set
|
||||
*/
|
||||
void (*set_key) (signer_t *this, chunk_t key);
|
||||
|
||||
/**
|
||||
* @brief Destroys a signer_t object.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*destroy) (signer_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a new signer_t object.
|
||||
*
|
||||
* @param integrity_algorithm Algorithm to use for signing and verifying.
|
||||
* @return
|
||||
* - signer_t object
|
||||
* - NULL if signer not supported
|
||||
*
|
||||
* @ingroup signers
|
||||
*/
|
||||
signer_t *signer_create(integrity_algorithm_t integrity_algorithm);
|
||||
|
||||
#endif /*SIGNER_H_*/
|
||||
@@ -1,916 +0,0 @@
|
||||
/**
|
||||
* @file x509.c
|
||||
*
|
||||
* @brief Implementation of x509_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <gmp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "x509.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <asn1/oid.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/pem.h>
|
||||
#include <utils/logger_manager.h>
|
||||
|
||||
#define BUF_LEN 512
|
||||
#define RSA_MIN_OCTETS (512 / 8)
|
||||
#define RSA_MIN_OCTETS_UGH "RSA modulus too small for security: less than 512 bits"
|
||||
#define RSA_MAX_OCTETS (8192 / 8)
|
||||
#define RSA_MAX_OCTETS_UGH "RSA modulus too large: more than 8192 bits"
|
||||
|
||||
logger_t *logger;
|
||||
|
||||
typedef enum generalNames_t generalNames_t;
|
||||
|
||||
/**
|
||||
* Different kinds of generalNames
|
||||
*/
|
||||
enum generalNames_t {
|
||||
GN_OTHER_NAME = 0,
|
||||
GN_RFC822_NAME = 1,
|
||||
GN_DNS_NAME = 2,
|
||||
GN_X400_ADDRESS = 3,
|
||||
GN_DIRECTORY_NAME = 4,
|
||||
GN_EDI_PARTY_NAME = 5,
|
||||
GN_URI = 6,
|
||||
GN_IP_ADDRESS = 7,
|
||||
GN_REGISTERED_ID = 8,
|
||||
};
|
||||
|
||||
typedef struct generalName_t generalName_t;
|
||||
|
||||
/**
|
||||
* A generalName, chainable in a list
|
||||
*/
|
||||
struct generalName_t {
|
||||
generalName_t *next;
|
||||
generalNames_t kind;
|
||||
chunk_t name;
|
||||
};
|
||||
|
||||
typedef struct private_x509_t private_x509_t;
|
||||
|
||||
/**
|
||||
* Private data of a x509_t object.
|
||||
*/
|
||||
struct private_x509_t {
|
||||
/**
|
||||
* Public interface for this certificate.
|
||||
*/
|
||||
x509_t public;
|
||||
|
||||
/**
|
||||
* Version of the X509 certificate
|
||||
*/
|
||||
u_int version;
|
||||
|
||||
/**
|
||||
* ID representing the certificates subject
|
||||
*/
|
||||
identification_t *subject;
|
||||
|
||||
/**
|
||||
* ID representing the certificate issuer
|
||||
*/
|
||||
identification_t *issuer;
|
||||
|
||||
/**
|
||||
* List of identification_t's representing subjectAltNames
|
||||
*/
|
||||
linked_list_t *subjectAltNames;
|
||||
|
||||
/**
|
||||
* List of identification_t's representing issuerAltNames
|
||||
*/
|
||||
linked_list_t *issuerAltNames;
|
||||
|
||||
/**
|
||||
* List of identification_t's representing crlDistributionPoints
|
||||
*/
|
||||
linked_list_t *crlDistributionPoints;
|
||||
|
||||
/**
|
||||
* Type of the subjects Key (currently RSA only)
|
||||
*/
|
||||
auth_method_t subjectPublicKeyAlgorithm;
|
||||
|
||||
|
||||
/**
|
||||
* Subjects RSA public key, if subjectPublicKeyAlgorithm == RSA
|
||||
*/
|
||||
rsa_public_key_t *public_key;
|
||||
|
||||
|
||||
|
||||
|
||||
time_t installed;
|
||||
u_char authority_flags;
|
||||
chunk_t x509;
|
||||
chunk_t tbsCertificate;
|
||||
chunk_t serialNumber;
|
||||
/* signature */
|
||||
int sigAlg;
|
||||
/* validity */
|
||||
time_t notBefore;
|
||||
time_t notAfter;
|
||||
/* subjectPublicKeyInfo */
|
||||
chunk_t subjectPublicKey;
|
||||
/* issuerUniqueID */
|
||||
/* subjectUniqueID */
|
||||
/* v3 extensions */
|
||||
/* extension */
|
||||
/* extension */
|
||||
/* extnID */
|
||||
/* critical */
|
||||
/* extnValue */
|
||||
bool isCA;
|
||||
bool isOcspSigner; /* ocsp */
|
||||
chunk_t subjectKeyID;
|
||||
chunk_t authKeyID;
|
||||
chunk_t authKeySerialNumber;
|
||||
chunk_t accessLocation; /* ocsp */
|
||||
/* signatureAlgorithm */
|
||||
int algorithm;
|
||||
chunk_t signature;
|
||||
};
|
||||
|
||||
/**
|
||||
* ASN.1 definition of a basicConstraints extension
|
||||
*/
|
||||
static const asn1Object_t basicConstraintsObjects[] = {
|
||||
{ 0, "basicConstraints", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
|
||||
{ 1, "CA", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 1 */
|
||||
{ 1, "pathLenConstraint", ASN1_INTEGER, ASN1_OPT|ASN1_BODY }, /* 2 */
|
||||
{ 1, "end opt", ASN1_EOC, ASN1_END } /* 3 */
|
||||
};
|
||||
#define BASIC_CONSTRAINTS_CA 1
|
||||
#define BASIC_CONSTRAINTS_ROOF 4
|
||||
|
||||
/**
|
||||
* ASN.1 definition of time
|
||||
*/
|
||||
static const asn1Object_t timeObjects[] = {
|
||||
{ 0, "utcTime", ASN1_UTCTIME, ASN1_OPT|ASN1_BODY }, /* 0 */
|
||||
{ 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */
|
||||
{ 0, "generalizeTime",ASN1_GENERALIZEDTIME, ASN1_OPT|ASN1_BODY }, /* 2 */
|
||||
{ 0, "end opt", ASN1_EOC, ASN1_END } /* 3 */
|
||||
};
|
||||
#define TIME_UTC 0
|
||||
#define TIME_GENERALIZED 2
|
||||
#define TIME_ROOF 4
|
||||
|
||||
/**
|
||||
* ASN.1 definition of a keyIdentifier
|
||||
*/
|
||||
static const asn1Object_t keyIdentifierObjects[] = {
|
||||
{ 0, "keyIdentifier", ASN1_OCTET_STRING, ASN1_BODY } /* 0 */
|
||||
};
|
||||
|
||||
/**
|
||||
* ASN.1 definition of a authorityKeyIdentifier extension
|
||||
*/
|
||||
static const asn1Object_t authorityKeyIdentifierObjects[] = {
|
||||
{ 0, "authorityKeyIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
|
||||
{ 1, "keyIdentifier", ASN1_CONTEXT_S_0, ASN1_OPT|ASN1_OBJ }, /* 1 */
|
||||
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
|
||||
{ 1, "authorityCertIssuer", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_OBJ }, /* 3 */
|
||||
{ 1, "end opt", ASN1_EOC, ASN1_END }, /* 4 */
|
||||
{ 1, "authorityCertSerialNumber",ASN1_CONTEXT_S_2, ASN1_OPT|ASN1_BODY }, /* 5 */
|
||||
{ 1, "end opt", ASN1_EOC, ASN1_END } /* 6 */
|
||||
};
|
||||
#define AUTH_KEY_ID_KEY_ID 1
|
||||
#define AUTH_KEY_ID_CERT_ISSUER 3
|
||||
#define AUTH_KEY_ID_CERT_SERIAL 5
|
||||
#define AUTH_KEY_ID_ROOF 7
|
||||
|
||||
/**
|
||||
* ASN.1 definition of a authorityInfoAccess extension
|
||||
*/
|
||||
static const asn1Object_t authorityInfoAccessObjects[] = {
|
||||
{ 0, "authorityInfoAccess", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
||||
{ 1, "accessDescription", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
|
||||
{ 2, "accessMethod", ASN1_OID, ASN1_BODY }, /* 2 */
|
||||
{ 2, "accessLocation", ASN1_EOC, ASN1_RAW }, /* 3 */
|
||||
{ 0, "end loop", ASN1_EOC, ASN1_END } /* 4 */
|
||||
};
|
||||
#define AUTH_INFO_ACCESS_METHOD 2
|
||||
#define AUTH_INFO_ACCESS_LOCATION 3
|
||||
#define AUTH_INFO_ACCESS_ROOF 5
|
||||
|
||||
/**
|
||||
* ASN.1 definition of a extendedKeyUsage extension
|
||||
*/
|
||||
static const asn1Object_t extendedKeyUsageObjects[] = {
|
||||
{ 0, "extendedKeyUsage", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
||||
{ 1, "keyPurposeID", ASN1_OID, ASN1_BODY }, /* 1 */
|
||||
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */
|
||||
};
|
||||
|
||||
#define EXT_KEY_USAGE_PURPOSE_ID 1
|
||||
#define EXT_KEY_USAGE_ROOF 3
|
||||
|
||||
/**
|
||||
* ASN.1 definition of generalNames
|
||||
*/
|
||||
static const asn1Object_t generalNamesObjects[] = {
|
||||
{ 0, "generalNames", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
||||
{ 1, "generalName", ASN1_EOC, ASN1_RAW }, /* 1 */
|
||||
{ 0, "end loop", ASN1_EOC, ASN1_END } /* 2 */
|
||||
};
|
||||
#define GENERAL_NAMES_GN 1
|
||||
#define GENERAL_NAMES_ROOF 3
|
||||
|
||||
|
||||
/**
|
||||
* ASN.1 definition of crlDistributionPoints
|
||||
*/
|
||||
static const asn1Object_t crlDistributionPointsObjects[] = {
|
||||
{ 0, "crlDistributionPoints", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
||||
{ 1, "DistributionPoint", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
|
||||
{ 2, "distributionPoint", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_LOOP }, /* 2 */
|
||||
{ 3, "fullName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ }, /* 3 */
|
||||
{ 3, "end choice", ASN1_EOC, ASN1_END }, /* 4 */
|
||||
{ 3, "nameRelToCRLIssuer",ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 5 */
|
||||
{ 3, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
|
||||
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
|
||||
{ 2, "reasons", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 8 */
|
||||
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
|
||||
{ 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_BODY }, /* 10 */
|
||||
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
|
||||
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 12 */
|
||||
};
|
||||
#define CRL_DIST_POINTS_FULLNAME 3
|
||||
#define CRL_DIST_POINTS_ROOF 13
|
||||
|
||||
/**
|
||||
* ASN.1 definition of an X.509v3 x509
|
||||
*/
|
||||
static const asn1Object_t certObjects[] = {
|
||||
{ 0, "x509", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
|
||||
{ 1, "tbsCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
|
||||
{ 2, "DEFAULT v1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 2 */
|
||||
{ 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */
|
||||
{ 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 4 */
|
||||
{ 2, "signature", ASN1_EOC, ASN1_RAW }, /* 5 */
|
||||
{ 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */
|
||||
{ 2, "validity", ASN1_SEQUENCE, ASN1_NONE }, /* 7 */
|
||||
{ 3, "notBefore", ASN1_EOC, ASN1_RAW }, /* 8 */
|
||||
{ 3, "notAfter", ASN1_EOC, ASN1_RAW }, /* 9 */
|
||||
{ 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */
|
||||
{ 2, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
|
||||
{ 3, "algorithm", ASN1_EOC, ASN1_RAW }, /* 12 */
|
||||
{ 3, "subjectPublicKey", ASN1_BIT_STRING, ASN1_NONE }, /* 13 */
|
||||
{ 4, "RSAPublicKey", ASN1_SEQUENCE, ASN1_RAW }, /* 14 */
|
||||
{ 2, "issuerUniqueID", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 15 */
|
||||
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 16 */
|
||||
{ 2, "subjectUniqueID", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 17 */
|
||||
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 18 */
|
||||
{ 2, "optional extensions", ASN1_CONTEXT_C_3, ASN1_OPT }, /* 19 */
|
||||
{ 3, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */
|
||||
{ 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */
|
||||
{ 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */
|
||||
{ 5, "critical", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 23 */
|
||||
{ 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */
|
||||
{ 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
|
||||
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
|
||||
{ 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */
|
||||
{ 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 28 */
|
||||
};
|
||||
#define X509_OBJ_CERTIFICATE 0
|
||||
#define X509_OBJ_TBS_CERTIFICATE 1
|
||||
#define X509_OBJ_VERSION 3
|
||||
#define X509_OBJ_SERIAL_NUMBER 4
|
||||
#define X509_OBJ_SIG_ALG 5
|
||||
#define X509_OBJ_ISSUER 6
|
||||
#define X509_OBJ_NOT_BEFORE 8
|
||||
#define X509_OBJ_NOT_AFTER 9
|
||||
#define X509_OBJ_SUBJECT 10
|
||||
#define X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM 12
|
||||
#define X509_OBJ_SUBJECT_PUBLIC_KEY 13
|
||||
#define X509_OBJ_RSA_PUBLIC_KEY 14
|
||||
#define X509_OBJ_EXTN_ID 22
|
||||
#define X509_OBJ_CRITICAL 23
|
||||
#define X509_OBJ_EXTN_VALUE 24
|
||||
#define X509_OBJ_ALGORITHM 27
|
||||
#define X509_OBJ_SIGNATURE 28
|
||||
#define X509_OBJ_ROOF 29
|
||||
|
||||
|
||||
static u_char ASN1_subjectAltName_oid_str[] = {
|
||||
0x06, 0x03, 0x55, 0x1D, 0x11
|
||||
};
|
||||
|
||||
static const chunk_t ASN1_subjectAltName_oid = chunk_from_buf(ASN1_subjectAltName_oid_str);
|
||||
|
||||
|
||||
/**
|
||||
* compare two X.509 x509s by comparing their signatures
|
||||
*/
|
||||
static bool equals(private_x509_t *this, private_x509_t *other)
|
||||
{
|
||||
return chunk_equals(this->signature, other->signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* encode a linked list of subjectAltNames
|
||||
*/
|
||||
chunk_t build_subjectAltNames(generalName_t *subjectAltNames)
|
||||
{
|
||||
u_char *pos;
|
||||
chunk_t names;
|
||||
size_t len = 0;
|
||||
generalName_t *gn = subjectAltNames;
|
||||
|
||||
/* compute the total size of the ASN.1 attributes object */
|
||||
while (gn != NULL)
|
||||
{
|
||||
len += gn->name.len;
|
||||
gn = gn->next;
|
||||
}
|
||||
|
||||
pos = build_asn1_object(&names, ASN1_SEQUENCE, len);
|
||||
|
||||
gn = subjectAltNames;
|
||||
while (gn != NULL)
|
||||
{
|
||||
memcpy(pos, gn->name.ptr, gn->name.len);
|
||||
pos += gn->name.len;
|
||||
gn = gn->next;
|
||||
}
|
||||
|
||||
return asn1_wrap(ASN1_SEQUENCE, "cm",
|
||||
ASN1_subjectAltName_oid,
|
||||
asn1_wrap(ASN1_OCTET_STRING, "m", names)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* free the dynamic memory used to store generalNames
|
||||
*/
|
||||
void free_generalNames(generalName_t* gn, bool free_name)
|
||||
{
|
||||
while (gn != NULL)
|
||||
{
|
||||
generalName_t *gn_top = gn;
|
||||
if (free_name)
|
||||
{
|
||||
free(gn->name.ptr);
|
||||
}
|
||||
gn = gn->next;
|
||||
free(gn_top);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts the basicConstraints extension
|
||||
*/
|
||||
static bool parse_basicConstraints(chunk_t blob, int level0)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
bool isCA = FALSE;
|
||||
|
||||
asn1_init(&ctx, blob, level0, FALSE);
|
||||
|
||||
while (objectID < BASIC_CONSTRAINTS_ROOF) {
|
||||
|
||||
if (!extract_object(basicConstraintsObjects, &objectID, &object,&level, &ctx))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (objectID == BASIC_CONSTRAINTS_CA)
|
||||
{
|
||||
isCA = object.len && *object.ptr;
|
||||
logger->log(logger, RAW|LEVEL1, " %s", isCA ? "TRUE" : "FALSE");
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
return isCA;
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts one or several GNs and puts them into a chained list
|
||||
*/
|
||||
static void parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
|
||||
asn1_init(&ctx, blob, level0, implicit);
|
||||
|
||||
while (objectID < GENERAL_NAMES_ROOF)
|
||||
{
|
||||
if (!extract_object(generalNamesObjects, &objectID, &object, &level, &ctx))
|
||||
return;
|
||||
|
||||
if (objectID == GENERAL_NAMES_GN)
|
||||
{
|
||||
list->insert_last(list, identification_create_from_encoding(ID_DER_ASN1_GN, object));
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts and converts a UTCTIME or GENERALIZEDTIME object
|
||||
*/
|
||||
time_t parse_time(chunk_t blob, int level0)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
|
||||
asn1_init(&ctx, blob, level0, FALSE);
|
||||
|
||||
while (objectID < TIME_ROOF)
|
||||
{
|
||||
if (!extract_object(timeObjects, &objectID, &object, &level, &ctx))
|
||||
return 0;
|
||||
|
||||
if (objectID == TIME_UTC || objectID == TIME_GENERALIZED)
|
||||
{
|
||||
return asn1totime(&object, (objectID == TIME_UTC)
|
||||
? ASN1_UTCTIME : ASN1_GENERALIZEDTIME);
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts a keyIdentifier
|
||||
*/
|
||||
static chunk_t parse_keyIdentifier(chunk_t blob, int level0, bool implicit)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
|
||||
asn1_init(&ctx, blob, level0, implicit);
|
||||
|
||||
extract_object(keyIdentifierObjects, &objectID, &object, &level, &ctx);
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts an authoritykeyIdentifier
|
||||
*/
|
||||
void parse_authorityKeyIdentifier(chunk_t blob, int level0 , chunk_t *authKeyID, chunk_t *authKeySerialNumber)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
|
||||
asn1_init(&ctx, blob, level0, FALSE);
|
||||
while (objectID < AUTH_KEY_ID_ROOF)
|
||||
{
|
||||
if (!extract_object(authorityKeyIdentifierObjects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (objectID)
|
||||
{
|
||||
case AUTH_KEY_ID_KEY_ID:
|
||||
*authKeyID = parse_keyIdentifier(object, level+1, TRUE);
|
||||
break;
|
||||
case AUTH_KEY_ID_CERT_ISSUER:
|
||||
{
|
||||
/* TODO: parse_generalNames(object, level+1, TRUE); */
|
||||
break;
|
||||
}
|
||||
case AUTH_KEY_ID_CERT_SERIAL:
|
||||
*authKeySerialNumber = object;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts an authorityInfoAcess location
|
||||
*/
|
||||
static void parse_authorityInfoAccess(chunk_t blob, int level0, chunk_t *accessLocation)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
|
||||
u_int accessMethod = OID_UNKNOWN;
|
||||
|
||||
asn1_init(&ctx, blob, level0, FALSE);
|
||||
while (objectID < AUTH_INFO_ACCESS_ROOF)
|
||||
{
|
||||
if (!extract_object(authorityInfoAccessObjects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (objectID)
|
||||
{
|
||||
case AUTH_INFO_ACCESS_METHOD:
|
||||
accessMethod = known_oid(object);
|
||||
break;
|
||||
case AUTH_INFO_ACCESS_LOCATION:
|
||||
{
|
||||
switch (accessMethod)
|
||||
{
|
||||
case OID_OCSP:
|
||||
if (*object.ptr == ASN1_CONTEXT_S_6)
|
||||
{
|
||||
if (asn1_length(&object) == ASN1_INVALID_LENGTH)
|
||||
{
|
||||
return;
|
||||
}
|
||||
logger->log(logger, RAW|LEVEL1, " '%.*s'",(int)object.len, object.ptr);
|
||||
/* only HTTP(S) URIs accepted */
|
||||
if (strncasecmp(object.ptr, "http", 4) == 0)
|
||||
{
|
||||
*accessLocation = object;
|
||||
return;
|
||||
}
|
||||
}
|
||||
logger->log(logger, ERROR|LEVEL2, "ignoring OCSP InfoAccessLocation with unkown protocol");
|
||||
break;
|
||||
default:
|
||||
/* unkown accessMethod, ignoring */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts extendedKeyUsage OIDs
|
||||
*/
|
||||
static bool parse_extendedKeyUsage(chunk_t blob, int level0)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
|
||||
asn1_init(&ctx, blob, level0, FALSE);
|
||||
while (objectID < EXT_KEY_USAGE_ROOF)
|
||||
{
|
||||
if (!extract_object(extendedKeyUsageObjects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (objectID == EXT_KEY_USAGE_PURPOSE_ID &&
|
||||
known_oid(object) == OID_OCSP_SIGNING)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts one or several crlDistributionPoints and puts them into
|
||||
* a chained list
|
||||
*/
|
||||
static void parse_crlDistributionPoints(chunk_t blob, int level0, linked_list_t *list)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
|
||||
asn1_init(&ctx, blob, level0, FALSE);
|
||||
while (objectID < CRL_DIST_POINTS_ROOF)
|
||||
{
|
||||
if (!extract_object(crlDistributionPointsObjects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (objectID == CRL_DIST_POINTS_FULLNAME)
|
||||
{
|
||||
/* append extracted generalNames to existing chained list */
|
||||
parse_generalNames(object, level+1, TRUE, list);
|
||||
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses an X.509v3 x509
|
||||
*/
|
||||
bool parse_x509cert(chunk_t blob, u_int level0, private_x509_t *cert)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
bool critical;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
u_int extn_oid = OID_UNKNOWN;
|
||||
int objectID = 0;
|
||||
|
||||
asn1_init(&ctx, blob, level0, FALSE);
|
||||
while (objectID < X509_OBJ_ROOF)
|
||||
{
|
||||
if (!extract_object(certObjects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
/* those objects which will parsed further need the next higher level */
|
||||
level++;
|
||||
switch (objectID) {
|
||||
case X509_OBJ_CERTIFICATE:
|
||||
cert->x509 = object;
|
||||
break;
|
||||
case X509_OBJ_TBS_CERTIFICATE:
|
||||
cert->tbsCertificate = object;
|
||||
break;
|
||||
case X509_OBJ_VERSION:
|
||||
cert->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
|
||||
logger->log(logger, RAW|LEVEL1, " v%d", cert->version);
|
||||
break;
|
||||
case X509_OBJ_SERIAL_NUMBER:
|
||||
cert->serialNumber = object;
|
||||
break;
|
||||
case X509_OBJ_SIG_ALG:
|
||||
cert->sigAlg = parse_algorithmIdentifier(object, level, NULL);
|
||||
break;
|
||||
case X509_OBJ_ISSUER:
|
||||
cert->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
|
||||
break;
|
||||
case X509_OBJ_NOT_BEFORE:
|
||||
cert->notBefore = parse_time(object, level);
|
||||
break;
|
||||
case X509_OBJ_NOT_AFTER:
|
||||
cert->notAfter = parse_time(object, level);
|
||||
break;
|
||||
case X509_OBJ_SUBJECT:
|
||||
cert->subject = identification_create_from_encoding(ID_DER_ASN1_DN, object);
|
||||
break;
|
||||
case X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM:
|
||||
if (parse_algorithmIdentifier(object, level, NULL) == OID_RSA_ENCRYPTION)
|
||||
{
|
||||
cert->subjectPublicKeyAlgorithm = RSA_DIGITAL_SIGNATURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, " unsupported public key algorithm");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case X509_OBJ_SUBJECT_PUBLIC_KEY:
|
||||
if (ctx.blobs[4].len > 0 && *ctx.blobs[4].ptr == 0x00)
|
||||
{
|
||||
/* skip initial bit string octet defining 0 unused bits */
|
||||
ctx.blobs[4].ptr++; ctx.blobs[4].len--;
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->log(logger, ERROR|LEVEL1, " invalid RSA public key format");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case X509_OBJ_RSA_PUBLIC_KEY:
|
||||
cert->subjectPublicKey = object;
|
||||
break;
|
||||
case X509_OBJ_EXTN_ID:
|
||||
extn_oid = known_oid(object);
|
||||
break;
|
||||
case X509_OBJ_CRITICAL:
|
||||
critical = object.len && *object.ptr;
|
||||
logger->log(logger, ERROR|LEVEL1, " %s", critical ? "TRUE" : "FALSE");
|
||||
break;
|
||||
case X509_OBJ_EXTN_VALUE:
|
||||
{
|
||||
switch (extn_oid) {
|
||||
case OID_SUBJECT_KEY_ID:
|
||||
cert->subjectKeyID = parse_keyIdentifier(object, level, FALSE);
|
||||
break;
|
||||
case OID_SUBJECT_ALT_NAME:
|
||||
parse_generalNames(object, level, FALSE, cert->subjectAltNames);
|
||||
break;
|
||||
case OID_BASIC_CONSTRAINTS:
|
||||
cert->isCA = parse_basicConstraints(object, level);
|
||||
break;
|
||||
case OID_CRL_DISTRIBUTION_POINTS:
|
||||
parse_crlDistributionPoints(object, level, cert->crlDistributionPoints);
|
||||
break;
|
||||
case OID_AUTHORITY_KEY_ID:
|
||||
parse_authorityKeyIdentifier(object, level , &cert->authKeyID, &cert->authKeySerialNumber);
|
||||
break;
|
||||
case OID_AUTHORITY_INFO_ACCESS:
|
||||
parse_authorityInfoAccess(object, level, &cert->accessLocation);
|
||||
break;
|
||||
case OID_EXTENDED_KEY_USAGE:
|
||||
cert->isOcspSigner = parse_extendedKeyUsage(object, level);
|
||||
break;
|
||||
case OID_NS_REVOCATION_URL:
|
||||
case OID_NS_CA_REVOCATION_URL:
|
||||
case OID_NS_CA_POLICY_URL:
|
||||
case OID_NS_COMMENT:
|
||||
if (!parse_asn1_simple_object(&object, ASN1_IA5STRING , level, oid_names[extn_oid].name))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case X509_OBJ_ALGORITHM:
|
||||
cert->algorithm = parse_algorithmIdentifier(object, level, NULL);
|
||||
break;
|
||||
case X509_OBJ_SIGNATURE:
|
||||
cert->signature = object;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
time(&cert->installed);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* verify the validity of a x509 by
|
||||
* checking the notBefore and notAfter dates
|
||||
*/
|
||||
err_t check_validity(const private_x509_t *cert, time_t *until)
|
||||
{
|
||||
time_t current_time;
|
||||
|
||||
time(¤t_time);
|
||||
|
||||
if (cert->notAfter < *until)
|
||||
{
|
||||
*until = cert->notAfter;
|
||||
}
|
||||
if (current_time < cert->notBefore)
|
||||
{
|
||||
return "x509 is not valid yet";
|
||||
}
|
||||
if (current_time > cert->notAfter)
|
||||
{
|
||||
return "x509 has expired";
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements x509_t.get_public_key
|
||||
*/
|
||||
static rsa_public_key_t *get_public_key(private_x509_t *this)
|
||||
{
|
||||
return this->public_key->clone(this->public_key);;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements x509_t.get_subject
|
||||
*/
|
||||
static identification_t *get_subject(private_x509_t *this)
|
||||
{
|
||||
return this->subject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements x509_t.get_issuer
|
||||
*/
|
||||
static identification_t *get_issuer(private_x509_t *this)
|
||||
{
|
||||
return this->issuer;
|
||||
}
|
||||
|
||||
/**
|
||||
* destroy
|
||||
*/
|
||||
static void destroy(private_x509_t *this)
|
||||
{
|
||||
identification_t *id;
|
||||
while (this->subjectAltNames->remove_last(this->subjectAltNames, (void**)&id) == SUCCESS)
|
||||
{
|
||||
id->destroy(id);
|
||||
}
|
||||
this->subjectAltNames->destroy(this->subjectAltNames);
|
||||
while (this->issuerAltNames->remove_last(this->issuerAltNames, (void**)&id) == SUCCESS)
|
||||
{
|
||||
id->destroy(id);
|
||||
}
|
||||
this->issuerAltNames->destroy(this->issuerAltNames);
|
||||
while (this->crlDistributionPoints->remove_last(this->crlDistributionPoints, (void**)&id) == SUCCESS)
|
||||
{
|
||||
id->destroy(id);
|
||||
}
|
||||
this->crlDistributionPoints->destroy(this->crlDistributionPoints);
|
||||
if (this->issuer)
|
||||
{
|
||||
this->issuer->destroy(this->issuer);
|
||||
}
|
||||
if (this->subject)
|
||||
{
|
||||
this->subject->destroy(this->subject);
|
||||
}
|
||||
if (this->public_key)
|
||||
{
|
||||
this->public_key->destroy(this->public_key);
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
x509_t *x509_create_from_chunk(chunk_t chunk)
|
||||
{
|
||||
private_x509_t *this = malloc_thing(private_x509_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.equals = (bool (*) (x509_t*,x509_t*))equals;
|
||||
this->public.destroy = (void (*) (x509_t*))destroy;
|
||||
this->public.get_public_key = (rsa_public_key_t* (*) (x509_t*))get_public_key;
|
||||
this->public.get_subject = (identification_t* (*) (x509_t*))get_subject;
|
||||
this->public.get_issuer = (identification_t* (*) (x509_t*))get_issuer;
|
||||
|
||||
/* initialize */
|
||||
this->subjectPublicKey = CHUNK_INITIALIZER;
|
||||
this->public_key = NULL;
|
||||
this->subject = NULL;
|
||||
this->issuer = NULL;
|
||||
this->subjectAltNames = linked_list_create();
|
||||
this->issuerAltNames = linked_list_create();
|
||||
this->crlDistributionPoints = linked_list_create();
|
||||
|
||||
/* we do not use a per-instance logger right now, since its not always accessible */
|
||||
logger = logger_manager->get_logger(logger_manager, ASN1);
|
||||
|
||||
if (!is_asn1(chunk) ||
|
||||
!parse_x509cert(chunk, 0, this))
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this->public_key = rsa_public_key_create_from_chunk(this->subjectPublicKey);
|
||||
if (this->public_key == NULL)
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
x509_t *x509_create_from_file(char *filename)
|
||||
{
|
||||
bool pgp = FALSE;
|
||||
chunk_t chunk = CHUNK_INITIALIZER;
|
||||
x509_t *cert = NULL;
|
||||
|
||||
if (!pem_asn1_load_file(filename, "", "certificate", &chunk, &pgp))
|
||||
return NULL;
|
||||
|
||||
cert = x509_create_from_chunk(chunk);
|
||||
free(chunk.ptr);
|
||||
return cert;
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/**
|
||||
* @file x509.h
|
||||
*
|
||||
* @brief Interface of x509_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 X509_H_
|
||||
#define X509_H_
|
||||
|
||||
#include <types.h>
|
||||
#include <definitions.h>
|
||||
#include <crypto/rsa/rsa_public_key.h>
|
||||
#include <utils/identification.h>
|
||||
#include <utils/iterator.h>
|
||||
|
||||
|
||||
typedef struct x509_t x509_t;
|
||||
|
||||
/**
|
||||
* @brief X509 certificate.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - x509_create_from_chunk()
|
||||
* - x509_create_from_file()
|
||||
*
|
||||
* @todo more code cleanup needed!
|
||||
* @todo fix unimplemented functions...
|
||||
* @todo handle memory management
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
struct x509_t {
|
||||
|
||||
/**
|
||||
* @brief Get the RSA public key from the certificate.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return public_key
|
||||
*/
|
||||
rsa_public_key_t *(*get_public_key) (x509_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the certificate issuers ID.
|
||||
*
|
||||
* The resulting ID is always a identification_t
|
||||
* of type ID_DER_ASN1_DN.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return issuers ID
|
||||
*/
|
||||
identification_t *(*get_issuer) (x509_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the subjects ID.
|
||||
*
|
||||
* The resulting ID is always a identification_t
|
||||
* of type ID_DER_ASN1_DN.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return subjects ID
|
||||
*/
|
||||
identification_t *(*get_subject) (x509_t *this);
|
||||
|
||||
/**
|
||||
* @brief Check if a certificate is valid.
|
||||
*
|
||||
* This function uses the issuers public key to verify
|
||||
* the validity of a certificate.
|
||||
*
|
||||
* @todo implement!
|
||||
*/
|
||||
bool (*verify) (x509_t *this, rsa_public_key_t *signer);
|
||||
|
||||
/**
|
||||
* @brief Get the key identifier of the public key.
|
||||
*
|
||||
* @todo implement!
|
||||
*/
|
||||
chunk_t (*get_subject_key_identifier) (x509_t *this);
|
||||
|
||||
/**
|
||||
* @brief Compare two certificates.
|
||||
*
|
||||
* Comparison is done via the certificates signature.
|
||||
*
|
||||
* @param this first cert for compare
|
||||
* @param other second cert for compare
|
||||
* @return TRUE if signature is equal
|
||||
*/
|
||||
bool (*equals) (x509_t *this, x509_t *other);
|
||||
|
||||
/**
|
||||
* @brief Destroys the certificate.
|
||||
*
|
||||
* @param this certificate to destroy
|
||||
*/
|
||||
void (*destroy) (x509_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Read a x509 certificate from a DER encoded blob.
|
||||
*
|
||||
* @param chunk chunk containing DER encoded data
|
||||
* @return created x509_t certificate, or NULL if invalid.
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
x509_t *x509_create_from_chunk(chunk_t chunk);
|
||||
|
||||
/**
|
||||
* @brief Read a x509 certificate from a DER encoded file.
|
||||
*
|
||||
* @param filename file containing DER encoded data
|
||||
* @return created x509_t certificate, or NULL if invalid.
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
x509_t *x509_create_from_file(char *filename);
|
||||
|
||||
#endif /* X509_H_ */
|
||||
@@ -1,40 +0,0 @@
|
||||
/**
|
||||
* @file definitions.c
|
||||
*
|
||||
* @brief General purpose definitions and macros.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "definitions.h"
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
char *mapping_find(mapping_t * maps, int value)
|
||||
{
|
||||
int i = 0;
|
||||
while (maps[i].value != MAPPING_END)
|
||||
{
|
||||
if (maps[i].value == value)
|
||||
{
|
||||
return maps[i].string;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return "INVALID MAPPING";
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/**
|
||||
* @file definitions.h
|
||||
*
|
||||
* @brief General purpose definitions and macros.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Jan Hutter, Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
* Copyright (C) 1998, 1999 D. Hugh Redelmeier. (Endian stuff)
|
||||
*
|
||||
* 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 DEFINITIONS_H_
|
||||
#define DEFINITIONS_H_
|
||||
|
||||
|
||||
|
||||
/* stolen from strongswan */
|
||||
#if linux
|
||||
# if defined(i386) && !defined(__i386__)
|
||||
# define __i386__ 1
|
||||
# define MYHACKFORTHIS 1
|
||||
# endif
|
||||
# include <endian.h>
|
||||
# ifdef MYHACKFORTHIS
|
||||
# undef __i386__
|
||||
# undef MYHACKFORTHIS
|
||||
# endif
|
||||
#elif !(defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN) && defined(BYTE_ORDER))
|
||||
/* we don't know how to do this, so we require the macros to be defined
|
||||
* with compiler flags:
|
||||
* -DBIG_ENDIAN=4321 -DLITTLE_ENDIAN=1234 -DBYTE_ORDER=BIG_ENDIAN
|
||||
* or -DBIG_ENDIAN=4321 -DLITTLE_ENDIAN=1234 -DBYTE_ORDER=LITTLE_ENDIAN
|
||||
* Thse match the GNU definitions
|
||||
*/
|
||||
# include <sys/endian.h>
|
||||
#endif
|
||||
|
||||
#ifndef BIG_ENDIAN
|
||||
#error "BIG_ENDIAN must be defined"
|
||||
#endif
|
||||
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#error "LITTLE_ENDIAN must be defined"
|
||||
#endif
|
||||
|
||||
#ifndef BYTE_ORDER
|
||||
#error "BYTE_ORDER must be defined"
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Macro gives back larger of two values.
|
||||
*/
|
||||
#define max(x,y) (x > y ? x : y)
|
||||
|
||||
/**
|
||||
* Macro gives back smaller of two values.
|
||||
*/
|
||||
#define min(x,y) (x < y ? x : y)
|
||||
|
||||
/**
|
||||
* Debug macro to follow control flow
|
||||
*/
|
||||
#define POS printf("%s, line %d\n", __FILE__, __LINE__)
|
||||
|
||||
/**
|
||||
* Macro to allocate a sized type.
|
||||
*
|
||||
* @param thing object on which a sizeof is performed
|
||||
* @return poiner to allocated memory
|
||||
*/
|
||||
#define malloc_thing(thing) ((thing*)malloc(sizeof(thing)))
|
||||
|
||||
|
||||
/**
|
||||
* Mapping entry which defines the end of a mapping_t array.
|
||||
*/
|
||||
#define MAPPING_END (-1)
|
||||
|
||||
typedef struct mapping_t mapping_t;
|
||||
|
||||
/**
|
||||
* @brief Mapping entry, where enum-to-string mappings are stored.
|
||||
*/
|
||||
struct mapping_t
|
||||
{
|
||||
/**
|
||||
* Enumeration value.
|
||||
*/
|
||||
int value;
|
||||
|
||||
/**
|
||||
* Mapped string.
|
||||
*/
|
||||
char *string;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Find a mapping_string in the mapping[].
|
||||
*
|
||||
* @param mappings mappings array
|
||||
* @param value enum-value to get the string from
|
||||
*
|
||||
*/
|
||||
char *mapping_find(mapping_t *mappings, int value);
|
||||
|
||||
#endif /*DEFINITIONS_H_*/
|
||||
@@ -1,42 +0,0 @@
|
||||
/**
|
||||
* @file library.c
|
||||
*
|
||||
* @brief Library (de-)initialization.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <utils/logger_manager.h>
|
||||
#include <utils/leak_detective.h>
|
||||
|
||||
/**
|
||||
* Called whenever the library is linked from a process
|
||||
*/
|
||||
void __attribute__ ((constructor)) library_init(void)
|
||||
{
|
||||
logger_manager_init();
|
||||
leak_detective_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the library is unlinked from a process
|
||||
*/
|
||||
void __attribute__ ((destructor)) library_cleanup(void)
|
||||
{
|
||||
leak_detective_cleanup();
|
||||
logger_manager_cleanup();
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/**
|
||||
* @file library.h
|
||||
*
|
||||
* @brief Global library header.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 LIBRARY_H_
|
||||
#define LIBRARY_H_
|
||||
|
||||
/**
|
||||
* @defgroup lib lib
|
||||
*
|
||||
* libstrongswan: library with various crypto related things.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup asn1 asn1
|
||||
*
|
||||
* ASN1 definitions, parser and generator functions.
|
||||
*
|
||||
* @ingroup lib
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup crypto crypto
|
||||
*
|
||||
* Crypto algorithms of different kind.
|
||||
*
|
||||
* @ingroup lib
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup crypters crypters
|
||||
*
|
||||
* Symmetric encryption algorithms, used for
|
||||
* encryption and decryption.
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup hashers hashers
|
||||
*
|
||||
* Hashing algorithms, such as MD5 or SHA1
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup prfs prfs
|
||||
*
|
||||
* Pseudo random functions, used to generate
|
||||
* pseude random byte sequences.
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup rsa rsa
|
||||
*
|
||||
* RSA private/public key algorithm.
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup signers signers
|
||||
*
|
||||
* Symmetric signing algorithms,
|
||||
* used to ensure message integrity.
|
||||
*
|
||||
* @ingroup crypto
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup utils utils
|
||||
*
|
||||
* Generic helper classes.
|
||||
*
|
||||
* @ingroup lib
|
||||
*/
|
||||
|
||||
|
||||
#endif /* LIBRARY_H_ */
|
||||
@@ -1,115 +0,0 @@
|
||||
/**
|
||||
* @file types.c
|
||||
*
|
||||
* @brief Generic types.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
/**
|
||||
* String mappings for type status_t.
|
||||
*/
|
||||
mapping_t status_m[] = {
|
||||
{SUCCESS, "SUCCESS"},
|
||||
{FAILED, "FAILED"},
|
||||
{OUT_OF_RES, "OUT_OF_RES"},
|
||||
{ALREADY_DONE, "ALREADY_DONE"},
|
||||
{NOT_SUPPORTED, "NOT_SUPPORTED"},
|
||||
{INVALID_ARG, "INVALID_ARG"},
|
||||
{NOT_FOUND, "NOT_FOUND"},
|
||||
{PARSE_ERROR, "PARSE_ERROR"},
|
||||
{VERIFY_ERROR, "VERIFY_ERROR"},
|
||||
{INVALID_STATE, "INVALID_STATE"},
|
||||
{DELETE_ME, "DELETE_ME"},
|
||||
{CREATED, "CREATED"},
|
||||
{MAPPING_END, NULL}
|
||||
};
|
||||
|
||||
/**
|
||||
* Empty chunk.
|
||||
*/
|
||||
chunk_t CHUNK_INITIALIZER = {NULL,0};
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
chunk_t chunk_clone(chunk_t chunk)
|
||||
{
|
||||
chunk_t clone = CHUNK_INITIALIZER;
|
||||
|
||||
if (chunk.ptr && chunk.len > 0)
|
||||
{
|
||||
clone.ptr = malloc(chunk.len);
|
||||
clone.len = chunk.len;
|
||||
memcpy(clone.ptr, chunk.ptr, chunk.len);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
void chunk_free(chunk_t *chunk)
|
||||
{
|
||||
free(chunk->ptr);
|
||||
chunk->ptr = NULL;
|
||||
chunk->len = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
chunk_t chunk_alloc(size_t bytes)
|
||||
{
|
||||
chunk_t new_chunk;
|
||||
new_chunk.ptr = malloc(bytes);
|
||||
new_chunk.len = bytes;
|
||||
return new_chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
bool chunk_equals(chunk_t a, chunk_t b)
|
||||
{
|
||||
if (a.ptr == NULL || b.ptr == NULL ||
|
||||
a.len != b.len ||
|
||||
memcmp(a.ptr, b.ptr, a.len) != 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
void *clalloc(void * pointer, size_t size)
|
||||
{
|
||||
void *data;
|
||||
data = malloc(size);
|
||||
|
||||
memcpy(data, pointer,size);
|
||||
|
||||
return (data);
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
/**
|
||||
* @file types.h
|
||||
*
|
||||
* @brief Generic types.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TYPES_H_
|
||||
#define TYPES_H_
|
||||
|
||||
#include <gmp.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <definitions.h>
|
||||
|
||||
/**
|
||||
* General purpose boolean type.
|
||||
*/
|
||||
typedef int bool;
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
/**
|
||||
* error message, or NULL for success
|
||||
*/
|
||||
typedef const char *err_t;
|
||||
|
||||
typedef enum status_t status_t;
|
||||
|
||||
/**
|
||||
* Return values of function calls.
|
||||
*/
|
||||
enum status_t {
|
||||
/**
|
||||
* Call succeeded.
|
||||
*/
|
||||
SUCCESS,
|
||||
|
||||
/**
|
||||
* Call failed.
|
||||
*/
|
||||
FAILED,
|
||||
|
||||
/**
|
||||
* Out of ressources.
|
||||
*/
|
||||
|
||||
OUT_OF_RES,
|
||||
/**
|
||||
* Already done.
|
||||
*/
|
||||
ALREADY_DONE,
|
||||
|
||||
/**
|
||||
* Not supported.
|
||||
*/
|
||||
NOT_SUPPORTED,
|
||||
|
||||
/**
|
||||
* One of the arguments is invalid.
|
||||
*/
|
||||
INVALID_ARG,
|
||||
|
||||
/**
|
||||
* Something could not be found.
|
||||
*/
|
||||
NOT_FOUND,
|
||||
|
||||
/**
|
||||
* Error while parsing.
|
||||
*/
|
||||
PARSE_ERROR,
|
||||
|
||||
/**
|
||||
* Error while verifying.
|
||||
*/
|
||||
VERIFY_ERROR,
|
||||
|
||||
/**
|
||||
* Object in invalid state.
|
||||
*/
|
||||
INVALID_STATE,
|
||||
|
||||
/**
|
||||
* Delete object which function belongs to.
|
||||
*/
|
||||
DELETE_ME,
|
||||
|
||||
/**
|
||||
* An object got created.
|
||||
*/
|
||||
CREATED,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* String mappings for type status_t.
|
||||
*/
|
||||
extern mapping_t status_m[];
|
||||
|
||||
/**
|
||||
* Handle struct timeval like an own type.
|
||||
*/
|
||||
typedef struct timeval timeval_t;
|
||||
|
||||
/**
|
||||
* Handle struct timespec like an own type.
|
||||
*/
|
||||
typedef struct timespec timespec_t;
|
||||
|
||||
/**
|
||||
* Handle struct chunk_t like an own type.
|
||||
*/
|
||||
typedef struct sockaddr sockaddr_t;
|
||||
|
||||
/**
|
||||
* Use struct chunk_t as chunk_t.
|
||||
*/
|
||||
typedef struct chunk_t chunk_t;
|
||||
|
||||
/**
|
||||
* General purpose pointer/length abstraction.
|
||||
*/
|
||||
struct chunk_t {
|
||||
/**
|
||||
* Pointer to start of data
|
||||
*/
|
||||
u_char *ptr;
|
||||
|
||||
/**
|
||||
* Length of data in bytes
|
||||
*/
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/**
|
||||
* {NULL, 0}-chunk, handy for initialization
|
||||
* of chunks.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
chunk_t chunk_clone(chunk_t chunk);
|
||||
|
||||
/**
|
||||
* Free contents of a chunk
|
||||
*/
|
||||
void chunk_free(chunk_t *chunk);
|
||||
|
||||
/**
|
||||
* Allocate a chunk
|
||||
*/
|
||||
chunk_t chunk_alloc(size_t bytes);
|
||||
|
||||
/**
|
||||
* Compare two chunks for equality,
|
||||
* NULL chunks are never equal.
|
||||
*/
|
||||
bool chunk_equals(chunk_t a, chunk_t b);
|
||||
|
||||
/**
|
||||
* Clone a data to a newly allocated buffer
|
||||
*/
|
||||
void *clalloc(void *pointer, size_t size);
|
||||
|
||||
|
||||
#endif /*TYPES_H_*/
|
||||
@@ -1,51 +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 <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.
|
||||
#
|
||||
|
||||
UTILS_DIR= $(LIB_DIR)utils/
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)leak_detective.o
|
||||
$(BUILD_DIR)leak_detective.o : $(UTILS_DIR)leak_detective.c $(UTILS_DIR)leak_detective.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)lexparser.o
|
||||
$(BUILD_DIR)lexparser.o : $(UTILS_DIR)lexparser.c $(UTILS_DIR)lexparser.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)linked_list.o
|
||||
$(BUILD_DIR)linked_list.o : $(UTILS_DIR)linked_list.c $(UTILS_DIR)linked_list.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)logger.o
|
||||
$(BUILD_DIR)logger.o : $(UTILS_DIR)logger.c $(UTILS_DIR)logger.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)logger_manager.o
|
||||
$(BUILD_DIR)logger_manager.o : $(UTILS_DIR)logger_manager.c $(UTILS_DIR)logger_manager.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)randomizer.o
|
||||
$(BUILD_DIR)randomizer.o : $(UTILS_DIR)randomizer.c $(UTILS_DIR)randomizer.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)tester.o
|
||||
$(BUILD_DIR)tester.o : $(UTILS_DIR)tester.c $(UTILS_DIR)tester.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)identification.o
|
||||
$(BUILD_DIR)identification.o : $(UTILS_DIR)identification.c $(UTILS_DIR)identification.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
LIB_OBJS+= $(BUILD_DIR)host.o
|
||||
$(BUILD_DIR)host.o : $(UTILS_DIR)host.c $(UTILS_DIR)host.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
@@ -1,365 +0,0 @@
|
||||
/**
|
||||
* @file host.c
|
||||
*
|
||||
* @brief Implementation of host_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "host.h"
|
||||
|
||||
|
||||
typedef struct private_host_t private_host_t;
|
||||
|
||||
/**
|
||||
* @brief Private Data of a host object.
|
||||
*/
|
||||
struct private_host_t {
|
||||
/**
|
||||
* Public data
|
||||
*/
|
||||
host_t public;
|
||||
|
||||
/**
|
||||
* Address family to use, such as AF_INET or AF_INET6
|
||||
*/
|
||||
int family;
|
||||
|
||||
/**
|
||||
* string representation of host
|
||||
*/
|
||||
char *string;
|
||||
|
||||
/**
|
||||
* low-lewel structure, wich stores the address
|
||||
*/
|
||||
union {
|
||||
struct sockaddr address;
|
||||
struct sockaddr_in address4;
|
||||
};
|
||||
/**
|
||||
* length of address structure
|
||||
*/
|
||||
socklen_t socklen;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* implements host_t.get_sockaddr
|
||||
*/
|
||||
static sockaddr_t *get_sockaddr(private_host_t *this)
|
||||
{
|
||||
return &(this->address);
|
||||
}
|
||||
|
||||
/**
|
||||
* implements host_t.get_sockaddr_len
|
||||
*/
|
||||
static socklen_t *get_sockaddr_len(private_host_t *this)
|
||||
{
|
||||
return &(this->socklen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of host_t.is_default_route.
|
||||
*/
|
||||
static bool is_default_route (private_host_t *this)
|
||||
{
|
||||
switch (this->family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
static u_int8_t default_route[4] = {0x00,0x00,0x00,0x00};
|
||||
|
||||
if (memcmp(default_route,&(this->address4.sin_addr.s_addr),4) == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* empty chunk is returned */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* implements host_t.get_address
|
||||
*/
|
||||
static char *get_address(private_host_t *this)
|
||||
{
|
||||
switch (this->family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
char *string;
|
||||
/* we need to clone it, since inet_ntoa overwrites
|
||||
* internal buffer on subsequent calls
|
||||
*/
|
||||
free(this->string);
|
||||
string = inet_ntoa(this->address4.sin_addr);
|
||||
this->string = malloc(strlen(string)+1);
|
||||
strcpy(this->string, string);
|
||||
return this->string;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return "(family not supported)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of host_t.get_address_as_chunk.
|
||||
*/
|
||||
static chunk_t get_address_as_chunk(private_host_t *this)
|
||||
{
|
||||
chunk_t address = CHUNK_INITIALIZER;
|
||||
|
||||
switch (this->family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
/* allocate 4 bytes for IPV4 address*/
|
||||
address.ptr = malloc(4);
|
||||
address.len = 4;
|
||||
memcpy(address.ptr,&(this->address4.sin_addr.s_addr),4);
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* empty chunk is returned */
|
||||
return address;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static xfrm_address_t get_xfrm_addr(private_host_t *this)
|
||||
{
|
||||
switch (this->family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
return (xfrm_address_t)(this->address4.sin_addr.s_addr);
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* todo */
|
||||
return (xfrm_address_t)(this->address4.sin_addr.s_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int get_family(private_host_t *this)
|
||||
{
|
||||
return this->family;
|
||||
}
|
||||
|
||||
/**
|
||||
* implements host_t.get_port
|
||||
*/
|
||||
static u_int16_t get_port(private_host_t *this)
|
||||
{
|
||||
switch (this->family)
|
||||
{
|
||||
case AF_INET:
|
||||
{
|
||||
return ntohs(this->address4.sin_port);
|
||||
}
|
||||
default:
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implements host_t.clone.
|
||||
*/
|
||||
static private_host_t *clone(private_host_t *this)
|
||||
{
|
||||
private_host_t *new = malloc_thing(private_host_t);
|
||||
|
||||
|
||||
memcpy(new, this, sizeof(private_host_t));
|
||||
if (this->string)
|
||||
{
|
||||
new->string = malloc(strlen(this->string)+1);
|
||||
strcpy(new->string, this->string);
|
||||
}
|
||||
return new;
|
||||
}
|
||||
|
||||
/**
|
||||
* Impelements host_t.ip_equals
|
||||
*/
|
||||
static bool ip_equals(private_host_t *this, private_host_t *other)
|
||||
{
|
||||
switch (this->family)
|
||||
{
|
||||
/* IPv4 */
|
||||
case AF_INET:
|
||||
{
|
||||
if ((this->address4.sin_family == other->address4.sin_family) &&
|
||||
(this->address4.sin_addr.s_addr == other->address4.sin_addr.s_addr))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Impelements host_t.equals
|
||||
*/
|
||||
static bool equals(private_host_t *this, private_host_t *other)
|
||||
{
|
||||
switch (this->family)
|
||||
{
|
||||
/* IPv4 */
|
||||
case AF_INET:
|
||||
{
|
||||
if ((this->address4.sin_family == other->address4.sin_family) &&
|
||||
(this->address4.sin_addr.s_addr == other->address4.sin_addr.s_addr) &&
|
||||
(this->address4.sin_port == other->address4.sin_port))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements host_t.destroy
|
||||
*/
|
||||
static void destroy(private_host_t *this)
|
||||
{
|
||||
free(this->string);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty host_t object
|
||||
*/
|
||||
static private_host_t *host_create_empty(void)
|
||||
{
|
||||
private_host_t *this = malloc_thing(private_host_t);
|
||||
|
||||
this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
|
||||
this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
|
||||
this->public.clone = (host_t* (*) (host_t*))clone;
|
||||
this->public.get_family = (int (*) (host_t*))get_family;
|
||||
this->public.get_xfrm_addr = (xfrm_address_t (*) (host_t *))get_xfrm_addr;
|
||||
this->public.get_address = (char* (*) (host_t *))get_address;
|
||||
this->public.get_address_as_chunk = (chunk_t (*) (host_t *)) get_address_as_chunk;
|
||||
this->public.get_port = (u_int16_t (*) (host_t *))get_port;
|
||||
this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals;
|
||||
this->public.equals = (bool (*) (host_t *,host_t *)) equals;
|
||||
this->public.is_default_route = (bool (*) (host_t *)) is_default_route;
|
||||
this->public.destroy = (void (*) (host_t*))destroy;
|
||||
|
||||
this->string = NULL;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
host_t *host_create(int family, char *address, u_int16_t port)
|
||||
{
|
||||
private_host_t *this = host_create_empty();
|
||||
|
||||
this->family = family;
|
||||
|
||||
switch (family)
|
||||
{
|
||||
/* IPv4 */
|
||||
case AF_INET:
|
||||
{
|
||||
this->address4.sin_family = AF_INET;
|
||||
this->address4.sin_addr.s_addr = inet_addr(address);
|
||||
this->address4.sin_port = htons(port);
|
||||
this->socklen = sizeof(struct sockaddr_in);
|
||||
return &(this->public);
|
||||
}
|
||||
default:
|
||||
{
|
||||
free(this);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
|
||||
{
|
||||
private_host_t *this = host_create_empty();
|
||||
|
||||
this->family = family;
|
||||
switch (family)
|
||||
{
|
||||
/* IPv4 */
|
||||
case AF_INET:
|
||||
{
|
||||
if (address.len != 4)
|
||||
{
|
||||
break;
|
||||
}
|
||||
this->address4.sin_family = AF_INET;
|
||||
memcpy(&(this->address4.sin_addr.s_addr),address.ptr,4);
|
||||
this->address4.sin_port = htons(port);
|
||||
this->socklen = sizeof(struct sockaddr_in);
|
||||
return &(this->public);
|
||||
}
|
||||
}
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
|
||||
{
|
||||
chunk_t address;
|
||||
|
||||
switch (sockaddr->sa_family)
|
||||
{
|
||||
/* IPv4 */
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)sockaddr;
|
||||
address.ptr = (void*)&(sin->sin_addr.s_addr);
|
||||
address.len = 4;
|
||||
return host_create_from_chunk(AF_INET, address, ntohs(sin->sin_port));
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
/**
|
||||
* @file host.h
|
||||
*
|
||||
* @brief Interface of host_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HOST_H_
|
||||
#define HOST_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/xfrm.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
|
||||
typedef struct host_t host_t;
|
||||
|
||||
/**
|
||||
* @brief Representates a Host
|
||||
*
|
||||
* Host object, identifies a address:port pair and defines some
|
||||
* useful functions on it.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - host_create()
|
||||
* - host_create_from_chunk()
|
||||
* - host_create_from_sockaddr()
|
||||
*
|
||||
* @todo Add IPv6 support
|
||||
*
|
||||
* @ingroup network
|
||||
*/
|
||||
struct host_t {
|
||||
|
||||
/**
|
||||
* @brief Build a clone of this host object.
|
||||
*
|
||||
* @param this object to clone
|
||||
* @return cloned host
|
||||
*/
|
||||
host_t *(*clone) (host_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the internal sockaddr struct.
|
||||
*
|
||||
* This is used for sending and receiving via sockets.
|
||||
*
|
||||
* @param this object to clone
|
||||
* @return pointer to the internal sockaddr structure
|
||||
*/
|
||||
sockaddr_t *(*get_sockaddr) (host_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the length of the sockaddr struct.
|
||||
*
|
||||
* Sepending on the family, the length of the sockaddr struct
|
||||
* is different. Use this function to get the length of the sockaddr
|
||||
* struct returned by get_sock_addr.
|
||||
*
|
||||
* This is used for sending and receiving via sockets.
|
||||
*
|
||||
* @param this object to clone
|
||||
* @return length of the sockaddr struct
|
||||
*/
|
||||
socklen_t *(*get_sockaddr_len) (host_t *this);
|
||||
|
||||
/**
|
||||
* @brief Gets the address as xfrm_address_t.
|
||||
*
|
||||
* This function allows the conversion to an
|
||||
* xfrm_address_t, used for netlink communication
|
||||
* with the kernel.
|
||||
*
|
||||
* @see kernel_interface_t.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return address in xfrm_address_t format
|
||||
*/
|
||||
xfrm_address_t (*get_xfrm_addr) (host_t *this);
|
||||
|
||||
/**
|
||||
* @brief Gets the family of the address
|
||||
*
|
||||
* @param this calling object
|
||||
* @return family
|
||||
*/
|
||||
int (*get_family) (host_t *this);
|
||||
|
||||
/**
|
||||
* @brief get the address of this host
|
||||
*
|
||||
* Mostly used for debugging purposes.
|
||||
* @warning string must NOT be freed
|
||||
*
|
||||
* @param this object
|
||||
* @return address string,
|
||||
*/
|
||||
char* (*get_address) (host_t *this);
|
||||
|
||||
/**
|
||||
* @brief Checks if the ip address of host is set to default route.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return
|
||||
* - TRUE if host has IP 0.0.0.0 for default route
|
||||
* - FALSE otherwise
|
||||
*/
|
||||
bool (*is_default_route) (host_t *this);
|
||||
|
||||
/**
|
||||
* @brief get the address of this host as chunk_t
|
||||
*
|
||||
* @warning returned chunk has to get destroyed by caller.
|
||||
*
|
||||
* @param this object
|
||||
* @return address string,
|
||||
*/
|
||||
chunk_t (*get_address_as_chunk) (host_t *this);
|
||||
|
||||
/**
|
||||
* @brief get the port of this host
|
||||
*
|
||||
* Mostly used for debugging purposes.
|
||||
*
|
||||
* @param this object to clone
|
||||
* @return port number
|
||||
*/
|
||||
u_int16_t (*get_port) (host_t *this);
|
||||
|
||||
/**
|
||||
* @brief Compare the ips of two hosts hosts.
|
||||
*
|
||||
* @param this object to compare
|
||||
* @param other the other to compare
|
||||
* @return TRUE if addresses are equal.
|
||||
*/
|
||||
bool (*ip_equals) (host_t *this, host_t *other);
|
||||
|
||||
/**
|
||||
* @brief Compare two hosts, with port.
|
||||
*
|
||||
* @param this object to compare
|
||||
* @param other the other to compare
|
||||
* @return TRUE if addresses and ports are equal.
|
||||
*/
|
||||
bool (*equals) (host_t *this, host_t *other);
|
||||
|
||||
/**
|
||||
* @brief Destroy this host object
|
||||
*
|
||||
* @param this calling
|
||||
* @return SUCCESS in any case
|
||||
*/
|
||||
void (*destroy) (host_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor to create a host_t object from an address string
|
||||
*
|
||||
* Currently supports only IPv4!
|
||||
*
|
||||
* @param family Address family to use for this object, such as AF_INET or AF_INET6
|
||||
* @param address string of an address, such as "152.96.193.130"
|
||||
* @param port port number
|
||||
* @return
|
||||
* - host_t object
|
||||
* - NULL, if family not supported.
|
||||
*
|
||||
* @ingroup network
|
||||
*/
|
||||
host_t *host_create(int family, char *address, u_int16_t port);
|
||||
|
||||
/**
|
||||
* @brief Constructor to create a host_t object from an address chunk
|
||||
*
|
||||
* Currently supports only IPv4!
|
||||
*
|
||||
* @param family Address family to use for this object, such as AF_INET or AF_INET6
|
||||
* @param address address as 4 byte chunk_t in networ order
|
||||
* @param port port number
|
||||
* @return
|
||||
* - host_t object
|
||||
* - NULL, if family not supported or chunk_t length not 4 bytes.
|
||||
*
|
||||
* @ingroup network
|
||||
*/
|
||||
host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port);
|
||||
|
||||
/**
|
||||
* @brief Constructor to create a host_t object from a sockaddr struct
|
||||
*
|
||||
* Currently supports only IPv4!
|
||||
*
|
||||
* @param sockaddr sockaddr struct which contains family, address and port
|
||||
* @return
|
||||
* - host_t object
|
||||
* - NULL, if family not supported.
|
||||
*
|
||||
* @ingroup network
|
||||
*/
|
||||
host_t *host_create_from_sockaddr(sockaddr_t *sockaddr);
|
||||
|
||||
|
||||
#endif /*HOST_H_*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,245 +0,0 @@
|
||||
/**
|
||||
* @file identification.h
|
||||
*
|
||||
* @brief Interface of identification_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef IDENTIFICATION_H_
|
||||
#define IDENTIFICATION_H_
|
||||
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef enum id_type_t id_type_t;
|
||||
|
||||
/**
|
||||
* @brief ID Types in a ID payload.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
enum id_type_t {
|
||||
|
||||
/**
|
||||
* ID data is a single four (4) octet IPv4 address.
|
||||
*/
|
||||
ID_IPV4_ADDR = 1,
|
||||
|
||||
/**
|
||||
* ID data is a fully-qualified domain name string.
|
||||
* An example of a ID_FQDN is, "example.com".
|
||||
* The string MUST not contain any terminators (e.g., NULL, CR, etc.).
|
||||
*/
|
||||
ID_FQDN = 2,
|
||||
|
||||
/**
|
||||
* ID data is a fully-qualified RFC822 email address string, An example of
|
||||
* a ID_RFC822_ADDR is, "[email protected]". The string MUST
|
||||
* not contain any terminators.
|
||||
*/
|
||||
ID_RFC822_ADDR = 3,
|
||||
|
||||
/**
|
||||
* ID data is a single sixteen (16) octet IPv6 address.
|
||||
*/
|
||||
ID_IPV6_ADDR = 5,
|
||||
|
||||
/**
|
||||
* ID data is the binary DER encoding of an ASN.1 X.500 Distinguished Name
|
||||
* [X.501].
|
||||
*/
|
||||
ID_DER_ASN1_DN = 9,
|
||||
|
||||
/**
|
||||
* ID data is the binary DER encoding of an ASN.1 X.500 GeneralName
|
||||
* [X.509].
|
||||
*/
|
||||
ID_DER_ASN1_GN = 10,
|
||||
|
||||
/**
|
||||
* ID data is an opaque octet stream which may be used to pass vendor-
|
||||
* specific information necessary to do certain proprietary
|
||||
* types of identification.
|
||||
*/
|
||||
ID_KEY_ID = 11,
|
||||
|
||||
/**
|
||||
* Special type of PRIVATE USE which matches to any other id.
|
||||
*/
|
||||
ID_ANY = 201,
|
||||
};
|
||||
|
||||
/**
|
||||
* String mappings for id_type_t.
|
||||
*/
|
||||
extern mapping_t id_type_m[];
|
||||
|
||||
typedef struct identification_t identification_t;
|
||||
|
||||
/**
|
||||
* @brief Generic identification, such as used in ID payload.
|
||||
*
|
||||
* The following types are possible:
|
||||
* - ID_IPV4_ADDR
|
||||
* - ID_FQDN
|
||||
* - ID_RFC822_ADDR
|
||||
* - ID_IPV6_ADDR
|
||||
* - ID_DER_ASN1_DN
|
||||
* - ID_DER_ASN1_GN
|
||||
* - ID_KEY_ID
|
||||
*
|
||||
* @b Constructors:
|
||||
* - identification_create_from_string()
|
||||
* - identification_create_from_encoding()
|
||||
*
|
||||
* @todo Support for ID_DER_ASN1_GN is minimal right now. Comparison
|
||||
* between them and ID_IPV4_ADDR/RFC822_ADDR would be nice.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct identification_t {
|
||||
|
||||
/**
|
||||
* @brief Get the encoding of this id, to send over
|
||||
* the network.
|
||||
*
|
||||
* @warning Result points to internal data, do NOT free!
|
||||
*
|
||||
* @param this the identification_t object
|
||||
* @return a chunk containing the encoded bytes
|
||||
*/
|
||||
chunk_t (*get_encoding) (identification_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get the type of this identification.
|
||||
*
|
||||
* @param this the identification_t object
|
||||
* @return id_type_t
|
||||
*/
|
||||
id_type_t (*get_type) (identification_t *this);
|
||||
|
||||
/**
|
||||
* @brief Get a string representation of this id.
|
||||
*
|
||||
* @warning Result points to internal data, do NOT free!
|
||||
*
|
||||
* @param this the identification_t object
|
||||
* @return string
|
||||
*/
|
||||
char *(*get_string) (identification_t *this);
|
||||
|
||||
/**
|
||||
* @brief Check if two identification_t objects are equal.
|
||||
*
|
||||
* @param this the identification_t object
|
||||
* @param other other identification_t object
|
||||
* @return TRUE if the IDs are equal
|
||||
*/
|
||||
bool (*equals) (identification_t *this,identification_t *other);
|
||||
|
||||
/**
|
||||
* @brief Check if an ID belongs to a wildcard ID.
|
||||
*
|
||||
* An identification_t may contain wildcards, such as
|
||||
* *@strongswan.org. This call checks if a given ID
|
||||
* (e.g. [email protected]) belongs to a such wildcard
|
||||
* ID. Returns TRUE if
|
||||
* - IDs are identical
|
||||
* - other is of type ID_ANY
|
||||
* - other contains a wildcard and matches this
|
||||
*
|
||||
* @param this the ID without wildcard
|
||||
* @param other the ID containing a wildcard
|
||||
* @return TRUE if other belongs to this
|
||||
*/
|
||||
bool (*belongs_to) (identification_t *this, identification_t *other);
|
||||
|
||||
/**
|
||||
* @brief Check if an ID is a wildcard ID.
|
||||
*
|
||||
* If the ID represents multiple IDs (with wildcards, or
|
||||
* as the type ID_ANY), TRUE is returned. If it is unique,
|
||||
* FALSE is returned.
|
||||
*
|
||||
* @param this identification_t object
|
||||
* @return TRUE if ID contains wildcards
|
||||
*/
|
||||
bool (*contains_wildcards) (identification_t *this);
|
||||
|
||||
/**
|
||||
* @brief Clone a identification_t instance.
|
||||
*
|
||||
* @param this the identification_t object to clone
|
||||
* @return clone of this
|
||||
*/
|
||||
identification_t *(*clone) (identification_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys a identification_t object.
|
||||
*
|
||||
* @param this identification_t object
|
||||
*/
|
||||
void (*destroy) (identification_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates an identification_t object from a string.
|
||||
*
|
||||
* @param string input string, which will be converted
|
||||
* @return
|
||||
* - created identification_t object, or
|
||||
* - NULL if unsupported string supplied.
|
||||
*
|
||||
* The input string may be e.g. one of the following:
|
||||
* - ID_IPV4_ADDR: 192.168.0.1
|
||||
* - ID_IPV6_ADDR: 2001:0db8:85a3:08d3:1319:8a2e:0370:7345
|
||||
* - ID_FQDN: @www.strongswan.org (@indicates FQDN)
|
||||
* - ID_RFC822_ADDR: [email protected]
|
||||
* - ID_DER_ASN1_DN: C=CH, O=Linux strongSwan, CN=bob
|
||||
*
|
||||
* In favour of pluto, domainnames are prepended with an @, since
|
||||
* pluto resolves domainnames without an @ to IPv4 addresses. Since
|
||||
* we use a seperate host_t class for addresses, this doesn't
|
||||
* make sense for us.
|
||||
*
|
||||
* A distinguished name may contain one or more of the following RDNs:
|
||||
* ND, UID, DC, CN, S, SN, serialNumber, C, L, ST, O, OU, T, D,
|
||||
* N, G, I, ID, EN, EmployeeNumber, E, Email, emailAddress, UN,
|
||||
* unstructuredName, TCGID.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
identification_t * identification_create_from_string(char *string);
|
||||
|
||||
/**
|
||||
* @brief Creates an identification_t object from an encoded chunk.
|
||||
*
|
||||
* @param type type of this id, such as ID_IPV4_ADDR
|
||||
* @param encoded encoded bytes, such as from identification_t.get_encoding
|
||||
* @return identification_t object
|
||||
*
|
||||
* In contrast to identification_create_from_string(), this constructor never
|
||||
* returns NULL, even when the conversion to a sring representation fails.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
identification_t * identification_create_from_encoding(id_type_t type, chunk_t encoded);
|
||||
|
||||
|
||||
#endif /* IDENTIFICATION_H_ */
|
||||
@@ -1,153 +0,0 @@
|
||||
/**
|
||||
* @file iterator.h
|
||||
*
|
||||
* @brief Interface iterator_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ITERATOR_H_
|
||||
#define ITERATOR_H_
|
||||
|
||||
typedef struct iterator_t iterator_t;
|
||||
|
||||
/**
|
||||
* @brief Iterator interface, allows iteration over collections.
|
||||
*
|
||||
* iterator_t defines an interface for iterating over collections.
|
||||
* It allows searching, deleting, updating and inserting.
|
||||
*
|
||||
* Thanks to JMP for iterator lessons :-)
|
||||
*
|
||||
* @b Constructors:
|
||||
* - via linked_list_t.create_iterator, or
|
||||
* - any other class which supports the iterator_t interface
|
||||
*
|
||||
* @see linked_list_t
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct iterator_t {
|
||||
|
||||
/**
|
||||
* @brief Iterate over all items.
|
||||
*
|
||||
* The easy way to iterate over items.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param[out] value item
|
||||
* @return
|
||||
* - TRUE, if more elements are avaiable,
|
||||
* - FALSE otherwise
|
||||
*/
|
||||
bool (*iterate) (iterator_t *this, void** value);
|
||||
|
||||
/**
|
||||
* @brief Moves to the next element, if available.
|
||||
*
|
||||
* A newly created iterator_t object doesn't point to any item.
|
||||
* Call iterator_t.has_next first to point it to the first item.
|
||||
*
|
||||
* @param this calling object
|
||||
* @return
|
||||
* - TRUE, if more elements are avaiable,
|
||||
* - FALSE otherwise
|
||||
*/
|
||||
bool (*has_next) (iterator_t *this);
|
||||
|
||||
/**
|
||||
* @brief Returns the current value at the iterator position.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param[out] value value is set to the current value at iterator position
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - FAILED if iterator on an invalid position
|
||||
*/
|
||||
status_t (*current) (iterator_t *this, void **value);
|
||||
|
||||
/**
|
||||
* @brief Inserts a new item before the given iterator position.
|
||||
*
|
||||
* The iterator position is not changed after inserting
|
||||
*
|
||||
* @param this calling iterator
|
||||
* @param[in] item value to insert in list
|
||||
*/
|
||||
void (*insert_before) (iterator_t *this, void *item);
|
||||
|
||||
/**
|
||||
* @brief Inserts a new item after the given iterator position.
|
||||
*
|
||||
* The iterator position is not changed after inserting.
|
||||
*
|
||||
* @param this calling iterator
|
||||
* @param[in] item value to insert in list
|
||||
*/
|
||||
void (*insert_after) (iterator_t *this, void *item);
|
||||
|
||||
/**
|
||||
* @brief Replace the current item at current iterator position.
|
||||
*
|
||||
* The iterator position is not changed after replacing.
|
||||
*
|
||||
* @param this calling iterator
|
||||
* @param[out] old_item old value will be written here(can be NULL)
|
||||
* @param[in] new_item new value
|
||||
*
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - FAILED if iterator is on an invalid position
|
||||
*/
|
||||
status_t (*replace) (iterator_t *this, void **old_item, void *new_item);
|
||||
|
||||
/**
|
||||
* @brief Removes an element from list at the given iterator position.
|
||||
*
|
||||
* The position of the iterator is set in the following order:
|
||||
* - to the item before, if available
|
||||
* - otherwise to the item after, if available
|
||||
* - otherwise it gets reseted
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - FAILED if iterator is on an invalid position
|
||||
*/
|
||||
status_t (*remove) (iterator_t *iterator);
|
||||
|
||||
/**
|
||||
* @brief Resets the iterator position.
|
||||
*
|
||||
* After reset, the iterator_t objects doesn't point to an element.
|
||||
* A call to iterator_t.has_next is necessary to do any other operations
|
||||
* with the resetted iterator.
|
||||
*
|
||||
* @param this calling object
|
||||
*/
|
||||
void (*reset) (iterator_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys an iterator.
|
||||
*
|
||||
* @param this iterator to destroy
|
||||
*
|
||||
*/
|
||||
void (*destroy) (iterator_t *this);
|
||||
};
|
||||
|
||||
#endif /*ITERATOR_H_*/
|
||||
@@ -1,540 +0,0 @@
|
||||
/**
|
||||
* @file leak_detective.c
|
||||
*
|
||||
* @brief Allocation hooks to find memory leaks.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <execinfo.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "leak_detective.h"
|
||||
|
||||
#include <types.h>
|
||||
#include <utils/logger_manager.h>
|
||||
|
||||
#ifdef LEAK_DETECTIVE
|
||||
|
||||
/**
|
||||
* Magic value which helps to detect memory corruption
|
||||
*/
|
||||
#define MEMORY_HEADER_MAGIC 0xF1367ADF
|
||||
|
||||
static void install_hooks(void);
|
||||
static void uninstall_hooks(void);
|
||||
static void *malloc_hook(size_t, const void *);
|
||||
static void *realloc_hook(void *, size_t, const void *);
|
||||
static void free_hook(void*, const void *);
|
||||
static void load_excluded_functions();
|
||||
|
||||
typedef struct memory_header_t memory_header_t;
|
||||
|
||||
/**
|
||||
* Header which is prepended to each allocated memory block
|
||||
*/
|
||||
struct memory_header_t {
|
||||
/**
|
||||
* Magci byte which must(!) hold MEMORY_HEADER_MAGIC
|
||||
*/
|
||||
u_int32_t magic;
|
||||
|
||||
/**
|
||||
* Number of bytes following after the header
|
||||
*/
|
||||
size_t bytes;
|
||||
|
||||
/**
|
||||
* Stack frames at the time of allocation
|
||||
*/
|
||||
void *stack_frames[STACK_FRAMES_COUNT];
|
||||
|
||||
/**
|
||||
* Number of stacks frames obtained in stack_frames
|
||||
*/
|
||||
int stack_frame_count;
|
||||
|
||||
/**
|
||||
* Pointer to previous entry in linked list
|
||||
*/
|
||||
memory_header_t *previous;
|
||||
|
||||
/**
|
||||
* Pointer to next entry in linked list
|
||||
*/
|
||||
memory_header_t *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* first mem header is just a dummy to chain
|
||||
* the others on it...
|
||||
*/
|
||||
static memory_header_t first_header = {
|
||||
magic: MEMORY_HEADER_MAGIC,
|
||||
bytes: 0,
|
||||
stack_frame_count: 0,
|
||||
previous: NULL,
|
||||
next: NULL
|
||||
};
|
||||
|
||||
/**
|
||||
* logger for the leak detective
|
||||
*/
|
||||
static logger_t *logger;
|
||||
|
||||
/**
|
||||
* standard hooks, used to temparily remove hooking
|
||||
*/
|
||||
static void *old_malloc_hook, *old_realloc_hook, *old_free_hook;
|
||||
|
||||
/**
|
||||
* are the hooks currently installed?
|
||||
*/
|
||||
static bool installed = FALSE;
|
||||
|
||||
/**
|
||||
* Mutex to exclusivly uninstall hooks, access heap list
|
||||
*/
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
/**
|
||||
* log stack frames queried by backtrace()
|
||||
* TODO: Dump symbols of static functions!!!
|
||||
*/
|
||||
static void log_stack_frames(void **stack_frames, int stack_frame_count)
|
||||
{
|
||||
char **strings;
|
||||
size_t i;
|
||||
|
||||
strings = backtrace_symbols (stack_frames, stack_frame_count);
|
||||
|
||||
logger->log(logger, ERROR, " dumping %d stack frame addresses.", stack_frame_count);
|
||||
|
||||
for (i = 0; i < stack_frame_count; i++)
|
||||
{
|
||||
logger->log(logger, ERROR, " %s", strings[i]);
|
||||
}
|
||||
free (strings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report leaks at library destruction
|
||||
*/
|
||||
void report_leaks()
|
||||
{
|
||||
memory_header_t *hdr;
|
||||
int leaks = 0;
|
||||
|
||||
/* reaquire a logger is necessary, this will force ((destructor))
|
||||
* order to work correctly */
|
||||
logger = logger_manager->get_logger(logger_manager, LEAK_DETECT);
|
||||
for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
|
||||
{
|
||||
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:
|
||||
logger->log(logger, CONTROL, "No leaks detected");
|
||||
break;
|
||||
case 1:
|
||||
logger->log(logger, ERROR, "One leak detected");
|
||||
break;
|
||||
default:
|
||||
logger->log(logger, ERROR, "%d leaks detected", leaks);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs the malloc hooks, enables leak detection
|
||||
*/
|
||||
static void install_hooks()
|
||||
{
|
||||
if (!installed)
|
||||
{
|
||||
old_malloc_hook = __malloc_hook;
|
||||
old_realloc_hook = __realloc_hook;
|
||||
old_free_hook = __free_hook;
|
||||
__malloc_hook = malloc_hook;
|
||||
__realloc_hook = realloc_hook;
|
||||
__free_hook = free_hook;
|
||||
installed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstalls the malloc hooks, disables leak detection
|
||||
*/
|
||||
static void uninstall_hooks()
|
||||
{
|
||||
if (installed)
|
||||
{
|
||||
__malloc_hook = old_malloc_hook;
|
||||
__free_hook = old_free_hook;
|
||||
__realloc_hook = old_realloc_hook;
|
||||
installed = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook function for malloc()
|
||||
*/
|
||||
void *malloc_hook(size_t bytes, const void *caller)
|
||||
{
|
||||
memory_header_t *hdr;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
hdr = malloc(bytes + sizeof(memory_header_t));
|
||||
|
||||
hdr->magic = MEMORY_HEADER_MAGIC;
|
||||
hdr->bytes = bytes;
|
||||
hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT);
|
||||
|
||||
/* insert at the beginning of the list */
|
||||
hdr->next = first_header.next;
|
||||
if (hdr->next)
|
||||
{
|
||||
hdr->next->previous = hdr;
|
||||
}
|
||||
hdr->previous = &first_header;
|
||||
first_header.next = hdr;
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return hdr + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook function for free()
|
||||
*/
|
||||
void free_hook(void *ptr, const void *caller)
|
||||
{
|
||||
void *stack_frames[STACK_FRAMES_COUNT];
|
||||
int stack_frame_count;
|
||||
memory_header_t *hdr = ptr - sizeof(memory_header_t);
|
||||
|
||||
/* allow freeing of NULL */
|
||||
if (ptr == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
if (hdr->magic != MEMORY_HEADER_MAGIC)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
/* TODO: since pthread_join cannot be excluded cleanly, we are not whining about bad frees */
|
||||
return;
|
||||
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);
|
||||
return;
|
||||
}
|
||||
/* remove magic from hdr */
|
||||
hdr->magic = 0;
|
||||
|
||||
/* remove item from list */
|
||||
if (hdr->next)
|
||||
{
|
||||
hdr->next->previous = hdr->previous;
|
||||
}
|
||||
hdr->previous->next = hdr->next;
|
||||
|
||||
uninstall_hooks();
|
||||
free(hdr);
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook function for realloc()
|
||||
*/
|
||||
void *realloc_hook(void *old, size_t bytes, const void *caller)
|
||||
{
|
||||
void *new;
|
||||
memory_header_t *hdr = old - sizeof(memory_header_t);
|
||||
void *stack_frames[STACK_FRAMES_COUNT];
|
||||
int stack_frame_count;
|
||||
|
||||
/* allow reallocation of NULL */
|
||||
if (old == NULL)
|
||||
{
|
||||
return malloc_hook(bytes, caller);
|
||||
}
|
||||
if (hdr->magic != MEMORY_HEADER_MAGIC)
|
||||
{
|
||||
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(getpid(), SIGKILL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* malloc and free is done with hooks */
|
||||
new = malloc_hook(bytes, caller);
|
||||
memcpy(new, old, min(bytes, hdr->bytes));
|
||||
free_hook(old, caller);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup leak detective
|
||||
*/
|
||||
void leak_detective_init()
|
||||
{
|
||||
logger = logger_manager->get_logger(logger_manager, LEAK_DETECT);
|
||||
load_excluded_functions();
|
||||
install_hooks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up leak detective
|
||||
*/
|
||||
void leak_detective_cleanup()
|
||||
{
|
||||
uninstall_hooks();
|
||||
report_leaks();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The following glibc functions are excluded from leak detection, since
|
||||
* they use static allocated buffers or other ugly allocation hacks.
|
||||
* For this to work, the linker must link libstrongswan preferred to
|
||||
* the other (overriden) libs.
|
||||
*/
|
||||
struct excluded_function {
|
||||
char *lib_name;
|
||||
char *function_name;
|
||||
void *handle;
|
||||
void *lib_function;
|
||||
} excluded_functions[] = {
|
||||
{"libc.so.6", "inet_ntoa", NULL, NULL},
|
||||
{"libpthread.so.0", "pthread_create", NULL, NULL},
|
||||
{"libpthread.so.0", "pthread_cancel", NULL, NULL},
|
||||
{"libpthread.so.0", "pthread_join", NULL, NULL},
|
||||
{"libpthread.so.0", "_pthread_cleanup_push",NULL, NULL},
|
||||
{"libpthread.so.0", "_pthread_cleanup_pop", NULL, NULL},
|
||||
{"libc.so.6", "mktime", NULL, NULL},
|
||||
{"libc.so.6", "vsyslog", NULL, NULL},
|
||||
{"libc.so.6", "strerror", NULL, NULL},
|
||||
};
|
||||
#define INET_NTOA 0
|
||||
#define PTHREAD_CREATE 1
|
||||
#define PTHREAD_CANCEL 2
|
||||
#define PTHREAD_JOIN 3
|
||||
#define PTHREAD_CLEANUP_PUSH 4
|
||||
#define PTHREAD_CLEANUP_POP 5
|
||||
#define MKTIME 6
|
||||
#define VSYSLOG 7
|
||||
#define STRERROR 8
|
||||
|
||||
|
||||
/**
|
||||
* Load libraries and function pointers for excluded functions
|
||||
*/
|
||||
static void load_excluded_functions()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(excluded_functions)/sizeof(struct excluded_function); i++)
|
||||
{
|
||||
void *handle, *function;
|
||||
handle = dlopen(excluded_functions[i].lib_name, RTLD_LAZY);
|
||||
if (handle == NULL)
|
||||
{
|
||||
kill(getpid(), SIGSEGV);
|
||||
}
|
||||
|
||||
function = dlsym(handle, excluded_functions[i].function_name);
|
||||
|
||||
if (function == NULL)
|
||||
{
|
||||
dlclose(handle);
|
||||
kill(getpid(), SIGSEGV);
|
||||
}
|
||||
excluded_functions[i].handle = handle;
|
||||
excluded_functions[i].lib_function = function;
|
||||
}
|
||||
}
|
||||
|
||||
char *inet_ntoa(struct in_addr in)
|
||||
{
|
||||
char *(*_inet_ntoa)(struct in_addr) = excluded_functions[INET_NTOA].lib_function;
|
||||
char *result;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
|
||||
result = _inet_ntoa(in);
|
||||
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_create(pthread_t *__restrict __threadp, __const pthread_attr_t *__restrict __attr,
|
||||
void *(*__start_routine) (void *), void *__restrict __arg)
|
||||
{
|
||||
int (*_pthread_create) (pthread_t *__restrict __threadp,
|
||||
__const pthread_attr_t *__restrict __attr,
|
||||
void *(*__start_routine) (void *),
|
||||
void *__restrict __arg) = excluded_functions[PTHREAD_CREATE].lib_function;
|
||||
int result;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
|
||||
result = _pthread_create(__threadp, __attr, __start_routine, __arg);
|
||||
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int pthread_cancel(pthread_t __th)
|
||||
{
|
||||
int (*_pthread_cancel) (pthread_t) = excluded_functions[PTHREAD_CANCEL].lib_function;
|
||||
int result;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
|
||||
result = _pthread_cancel(__th);
|
||||
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
// /* TODO: join has probs, since it dellocates memory
|
||||
// * allocated (somewhere) with leak_detective :-(.
|
||||
// * We should exclude all pthread_ functions to fix it !? */
|
||||
// int pthread_join(pthread_t __th, void **__thread_return)
|
||||
// {
|
||||
// int (*_pthread_join) (pthread_t, void **) = excluded_functions[PTHREAD_JOIN].lib_function;
|
||||
// int result;
|
||||
//
|
||||
// pthread_mutex_lock(&mutex);
|
||||
// uninstall_hooks();
|
||||
//
|
||||
// result = _pthread_join(__th, __thread_return);
|
||||
//
|
||||
// install_hooks();
|
||||
// pthread_mutex_unlock(&mutex);
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
|
||||
// void (*__routine) (void *),
|
||||
// void *__arg)
|
||||
// {
|
||||
// int (*__pthread_cleanup_push) (struct _pthread_cleanup_buffer *__buffer,
|
||||
// void (*__routine) (void *),
|
||||
// void *__arg) =
|
||||
// excluded_functions[PTHREAD_CLEANUP_PUSH].lib_function;
|
||||
//
|
||||
// pthread_mutex_lock(&mutex);
|
||||
// uninstall_hooks();
|
||||
//
|
||||
// __pthread_cleanup_push(__buffer, __routine, __arg);
|
||||
//
|
||||
// install_hooks();
|
||||
// pthread_mutex_unlock(&mutex);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer, int __execute)
|
||||
// {
|
||||
// int (*__pthread_cleanup_pop) (struct _pthread_cleanup_buffer *__buffer, int __execute) =
|
||||
// excluded_functions[PTHREAD_CLEANUP_POP].lib_function;
|
||||
//
|
||||
// pthread_mutex_lock(&mutex);
|
||||
// uninstall_hooks();
|
||||
//
|
||||
// __pthread_cleanup_pop(__buffer, __execute);
|
||||
//
|
||||
// install_hooks();
|
||||
// pthread_mutex_unlock(&mutex);
|
||||
// return;
|
||||
// }
|
||||
|
||||
time_t mktime(struct tm *tm)
|
||||
{
|
||||
time_t (*_mktime)(struct tm *tm) = excluded_functions[MKTIME].lib_function;
|
||||
time_t result;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
|
||||
result = _mktime(tm);
|
||||
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
void vsyslog (int __pri, __const char *__fmt, __gnuc_va_list __ap)
|
||||
{
|
||||
void (*_vsyslog) (int __pri, __const char *__fmt, __gnuc_va_list __ap) = excluded_functions[VSYSLOG].lib_function;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
|
||||
_vsyslog(__pri, __fmt, __ap);
|
||||
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *strerror(int errnum)
|
||||
{
|
||||
char* (*_strerror) (int) = excluded_functions[STRERROR].lib_function;
|
||||
char *result;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uninstall_hooks();
|
||||
|
||||
result = _strerror(errnum);
|
||||
|
||||
install_hooks();
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* LEAK_DETECTION */
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* @file leak_detective.h
|
||||
*
|
||||
* @brief malloc/free hooks to detect leaks.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 LEAK_DETECTIVE_H_
|
||||
#define LEAK_DETECTIVE_H_
|
||||
|
||||
|
||||
#ifdef LEAK_DETECTIVE
|
||||
|
||||
/**
|
||||
* Max number of stack frames to include in a backtrace.
|
||||
*/
|
||||
#define STACK_FRAMES_COUNT 30
|
||||
|
||||
/**
|
||||
* Initialize leak detective, activates it
|
||||
*/
|
||||
void leak_detective_init();
|
||||
|
||||
/**
|
||||
* Cleanup leak detective, deactivates it
|
||||
*/
|
||||
void leak_detective_cleanup();
|
||||
|
||||
#else /* !LEAK_DETECTIVE */
|
||||
|
||||
#define leak_detective_init() {}
|
||||
#define leak_detective_cleanup() {}
|
||||
|
||||
#endif /* LEAK_DETECTIVE */
|
||||
|
||||
#endif /* LEAK_DETECTIVE_H_ */
|
||||
@@ -1,135 +0,0 @@
|
||||
/**
|
||||
* @file lexparser.c
|
||||
*
|
||||
* @brief lexical parser for text-based configuration files
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001-2006 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "lexparser.h"
|
||||
|
||||
|
||||
/**
|
||||
* eat whitespace
|
||||
*/
|
||||
bool eat_whitespace(chunk_t *src)
|
||||
{
|
||||
while (src->len > 0 && (*src->ptr == ' ' || *src->ptr == '\t'))
|
||||
{
|
||||
src->ptr++; src->len--;
|
||||
}
|
||||
return src->len > 0 && *src->ptr != '#';
|
||||
}
|
||||
|
||||
/**
|
||||
* compare string with chunk
|
||||
*/
|
||||
bool match(const char *pattern, const chunk_t *ch)
|
||||
{
|
||||
return ch->len == strlen(pattern) && strncmp(pattern, ch->ptr, ch->len) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts a token ending with a given termination symbol
|
||||
*/
|
||||
bool extract_token(chunk_t *token, const 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches a new line terminated by \n or \r\n
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
err_t extract_value(chunk_t *value, chunk_t *line)
|
||||
{
|
||||
char delimiter = ' ';
|
||||
|
||||
if (!eat_whitespace(line))
|
||||
{
|
||||
return "missing value";
|
||||
}
|
||||
if (*line->ptr == '\'' || *line->ptr == '"')
|
||||
{
|
||||
delimiter = *line->ptr;
|
||||
line->ptr++; line->len--;
|
||||
}
|
||||
if (!extract_token(value, delimiter, line))
|
||||
{
|
||||
if (delimiter == ' ')
|
||||
{
|
||||
*value = *line;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "missing second delimiter";
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts a parameter: value pair
|
||||
*/
|
||||
err_t extract_parameter_value(chunk_t *name, chunk_t *value, chunk_t *line)
|
||||
{
|
||||
/* extract name */
|
||||
if (!extract_token(name,':', line))
|
||||
{
|
||||
return "missing ':'";
|
||||
}
|
||||
|
||||
/* extract value */
|
||||
return extract_value(value, line);
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* @file lexparser.h
|
||||
*
|
||||
* @brief lexical parser for text-based configuration files
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001-2006 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.
|
||||
*/
|
||||
|
||||
#include <types.h>
|
||||
|
||||
/**
|
||||
* @brief Eats whitespace
|
||||
*/
|
||||
bool eat_whitespace(chunk_t *src);
|
||||
|
||||
/**
|
||||
* @brief Compare null-terminated pattern with chunk
|
||||
*/
|
||||
bool match(const char *pattern, const chunk_t *ch);
|
||||
|
||||
/**
|
||||
* @brief Extracts a token ending with a given termination symbol
|
||||
*/
|
||||
bool extract_token(chunk_t *token, const char termination, chunk_t *src);
|
||||
|
||||
/**
|
||||
* @brief Fetches a new text line terminated by \n or \r\n
|
||||
*/
|
||||
bool fetchline(chunk_t *src, chunk_t *line);
|
||||
|
||||
/**
|
||||
* @brief Extracts a value that might be single or double quoted
|
||||
*/
|
||||
err_t extract_value(chunk_t *value, chunk_t *line);
|
||||
|
||||
/**
|
||||
* @brief extracts a name: value pair from a text line
|
||||
*/
|
||||
err_t extract_name_value(chunk_t *name, chunk_t *value, chunk_t *line);
|
||||
|
||||
/**
|
||||
* @brief extracts a parameter: value from a text line
|
||||
*/
|
||||
err_t extract_parameter_value(chunk_t *name, chunk_t *value, chunk_t *line);
|
||||
@@ -1,727 +0,0 @@
|
||||
/**
|
||||
* @file linked_list.c
|
||||
*
|
||||
* @brief Implementation of linked_list_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
|
||||
#include "linked_list.h"
|
||||
|
||||
|
||||
|
||||
typedef struct linked_list_element_t linked_list_element_t;
|
||||
|
||||
/**
|
||||
* @brief Element in a linked list.
|
||||
*
|
||||
* This element holds a pointer to the value it represents.
|
||||
*/
|
||||
struct linked_list_element_t {
|
||||
|
||||
/**
|
||||
* Value of a list item.
|
||||
*/
|
||||
void *value;
|
||||
|
||||
/**
|
||||
* Previous list element.
|
||||
*
|
||||
* NULL if first element in list.
|
||||
*/
|
||||
linked_list_element_t *previous;
|
||||
|
||||
/**
|
||||
* Next list element.
|
||||
*
|
||||
* NULL if last element in list.
|
||||
*/
|
||||
linked_list_element_t *next;
|
||||
|
||||
/**
|
||||
* Destroys a linked_list_element object.
|
||||
*
|
||||
* @param linked_list_element_t calling object
|
||||
*/
|
||||
void (*destroy) (linked_list_element_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_element_t.destroy.
|
||||
*/
|
||||
static void linked_list_element_destroy(linked_list_element_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates an empty linked list object.
|
||||
*
|
||||
* @warning Only the pointer to the value is stored.
|
||||
*
|
||||
* @param[in] value value of item to be set
|
||||
* @return linked_list_element_t object
|
||||
*/
|
||||
|
||||
linked_list_element_t *linked_list_element_create(void *value)
|
||||
{
|
||||
linked_list_element_t *this = malloc_thing(linked_list_element_t);
|
||||
|
||||
this->destroy = linked_list_element_destroy;
|
||||
|
||||
this->previous=NULL;
|
||||
this->next=NULL;
|
||||
this->value = value;
|
||||
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
typedef struct private_linked_list_t private_linked_list_t;
|
||||
|
||||
/**
|
||||
* Private data of a linked_list_t object.
|
||||
*
|
||||
*/
|
||||
struct private_linked_list_t {
|
||||
/**
|
||||
* Public part of linked list.
|
||||
*/
|
||||
linked_list_t public;
|
||||
|
||||
/**
|
||||
* Number of items in the list.
|
||||
*/
|
||||
int count;
|
||||
|
||||
/**
|
||||
* First element in list.
|
||||
* NULL if no elements in list.
|
||||
*/
|
||||
linked_list_element_t *first;
|
||||
|
||||
/**
|
||||
* Last element in list.
|
||||
* NULL if no elements in list.
|
||||
*/
|
||||
linked_list_element_t *last;
|
||||
};
|
||||
|
||||
|
||||
typedef struct private_iterator_t private_iterator_t;
|
||||
|
||||
/**
|
||||
* Private variables and functions of linked list iterator.
|
||||
*/
|
||||
struct private_iterator_t {
|
||||
/**
|
||||
* Public part of linked list iterator.
|
||||
*/
|
||||
iterator_t public;
|
||||
|
||||
/**
|
||||
* Associated linked list.
|
||||
*/
|
||||
private_linked_list_t * list;
|
||||
|
||||
/**
|
||||
* Current element of the iterator.
|
||||
*/
|
||||
linked_list_element_t *current;
|
||||
|
||||
/**
|
||||
* Direction of iterator.
|
||||
*/
|
||||
bool forward;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of iterator_t.has_next.
|
||||
*/
|
||||
static bool iterate(private_iterator_t *this, void** value)
|
||||
{
|
||||
if (this->list->count == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (this->current == NULL)
|
||||
{
|
||||
this->current = (this->forward) ? this->list->first : this->list->last;
|
||||
*value = this->current->value;
|
||||
return TRUE;
|
||||
}
|
||||
if (this->forward)
|
||||
{
|
||||
if (this->current->next == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
this->current = this->current->next;
|
||||
*value = this->current->value;
|
||||
return TRUE;
|
||||
}
|
||||
/* backward */
|
||||
if (this->current->previous == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
this->current = this->current->previous;
|
||||
*value = this->current->value;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of iterator_t.has_next.
|
||||
*/
|
||||
static bool iterator_has_next(private_iterator_t *this)
|
||||
{
|
||||
if (this->list->count == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if (this->current == NULL)
|
||||
{
|
||||
this->current = (this->forward) ? this->list->first : this->list->last;
|
||||
return TRUE;
|
||||
}
|
||||
if (this->forward)
|
||||
{
|
||||
if (this->current->next == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
this->current = this->current->next;
|
||||
return TRUE;
|
||||
}
|
||||
/* backward */
|
||||
if (this->current->previous == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
this->current = this->current->previous;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of iterator_t.current.
|
||||
*/
|
||||
static status_t iterator_current(private_iterator_t *this, void **value)
|
||||
{
|
||||
if (this->current == NULL)
|
||||
{
|
||||
return NOT_FOUND;
|
||||
}
|
||||
*value = this->current->value;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of iterator_t.reset.
|
||||
*/
|
||||
static void iterator_reset(private_iterator_t *this)
|
||||
{
|
||||
this->current = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of iterator_t.remove.
|
||||
*/
|
||||
static status_t remove(private_iterator_t *this)
|
||||
{
|
||||
linked_list_element_t *new_current;
|
||||
|
||||
if (this->current == NULL)
|
||||
{
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
if (this->list->count == 0)
|
||||
{
|
||||
return NOT_FOUND;
|
||||
}
|
||||
/* find out the new iterator position */
|
||||
if (this->current->previous != NULL)
|
||||
{
|
||||
new_current = this->current->previous;
|
||||
}
|
||||
else if (this->current->next != NULL)
|
||||
{
|
||||
new_current = this->current->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_current = NULL;
|
||||
}
|
||||
|
||||
/* now delete the entry :-) */
|
||||
if (this->current->previous == NULL)
|
||||
{
|
||||
if (this->current->next == NULL)
|
||||
{
|
||||
this->list->first = NULL;
|
||||
this->list->last = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current->next->previous = NULL;
|
||||
this->list->first = this->current->next;
|
||||
}
|
||||
}
|
||||
else if (this->current->next == NULL)
|
||||
{
|
||||
this->current->previous->next = NULL;
|
||||
this->list->last = this->current->previous;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->current->previous->next = this->current->next;
|
||||
this->current->next->previous = this->current->previous;
|
||||
}
|
||||
|
||||
this->list->count--;
|
||||
this->current->destroy(this->current);
|
||||
/* set the new iterator position */
|
||||
this->current = new_current;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of iterator_t.insert_before.
|
||||
*/
|
||||
static void insert_before(private_iterator_t * iterator, void *item)
|
||||
{
|
||||
if (iterator->current == NULL)
|
||||
{
|
||||
iterator->list->public.insert_first(&(iterator->list->public), item);
|
||||
}
|
||||
|
||||
linked_list_element_t *element =(linked_list_element_t *) linked_list_element_create(item);
|
||||
|
||||
if (iterator->current->previous == NULL)
|
||||
{
|
||||
iterator->current->previous = element;
|
||||
element->next = iterator->current;
|
||||
iterator->list->first = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
iterator->current->previous->next = element;
|
||||
element->previous = iterator->current->previous;
|
||||
iterator->current->previous = element;
|
||||
element->next = iterator->current;
|
||||
}
|
||||
|
||||
iterator->list->count++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of iterator_t.replace.
|
||||
*/
|
||||
static status_t replace (private_iterator_t *this, void **old_item, void *new_item)
|
||||
{
|
||||
if (this->current == NULL)
|
||||
{
|
||||
return NOT_FOUND;
|
||||
}
|
||||
if (old_item != NULL)
|
||||
{
|
||||
*old_item = this->current->value;
|
||||
}
|
||||
this->current->value = new_item;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of iterator_t.insert_after.
|
||||
*/
|
||||
static void insert_after(private_iterator_t * iterator, void *item)
|
||||
{
|
||||
if (iterator->current == NULL)
|
||||
{
|
||||
iterator->list->public.insert_first(&(iterator->list->public),item);
|
||||
return;
|
||||
}
|
||||
|
||||
linked_list_element_t *element =(linked_list_element_t *) linked_list_element_create(item);
|
||||
|
||||
if (iterator->current->next == NULL)
|
||||
{
|
||||
iterator->current->next = element;
|
||||
element->previous = iterator->current;
|
||||
iterator->list->last = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
iterator->current->next->previous = element;
|
||||
element->next = iterator->current->next;
|
||||
iterator->current->next = element;
|
||||
element->previous = iterator->current;
|
||||
}
|
||||
iterator->list->count++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of iterator_t.destroy.
|
||||
*/
|
||||
static void iterator_destroy(private_iterator_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.get_count.
|
||||
*/
|
||||
static int get_count(private_linked_list_t *this)
|
||||
{
|
||||
return this->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.call_on_items.
|
||||
*/
|
||||
static void call_on_items(private_linked_list_t *this, void(*func)(void*))
|
||||
{
|
||||
iterator_t *iterator;
|
||||
void *item;
|
||||
|
||||
iterator = this->public.create_iterator(&(this->public),TRUE);
|
||||
|
||||
while (iterator->has_next(iterator))
|
||||
{
|
||||
iterator->current(iterator, &item);
|
||||
(*func)(item);
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.insert_first.
|
||||
*/
|
||||
static void insert_first(private_linked_list_t *this, void *item)
|
||||
{
|
||||
linked_list_element_t *element;
|
||||
|
||||
element =(linked_list_element_t *) linked_list_element_create(item);
|
||||
|
||||
if (this->count == 0)
|
||||
{
|
||||
/* first entry in list */
|
||||
this->first = element;
|
||||
this->last = element;
|
||||
element->previous = NULL;
|
||||
element->next = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
linked_list_element_t *old_first_element = this->first;
|
||||
element->next = old_first_element;
|
||||
element->previous = NULL;
|
||||
old_first_element->previous = element;
|
||||
this->first = element;
|
||||
}
|
||||
|
||||
this->count++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.remove_first.
|
||||
*/
|
||||
static status_t remove_first(private_linked_list_t *this, void **item)
|
||||
{
|
||||
if (this->count == 0)
|
||||
{
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
linked_list_element_t *element = this->first;
|
||||
|
||||
if (element->next != NULL)
|
||||
{
|
||||
element->next->previous = NULL;
|
||||
}
|
||||
this->first = element->next;
|
||||
|
||||
if (item != NULL)
|
||||
{
|
||||
*item = element->value;
|
||||
}
|
||||
|
||||
this->count--;
|
||||
|
||||
element->destroy(element);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.get_first.
|
||||
*/
|
||||
static status_t get_first(private_linked_list_t *this, void **item)
|
||||
{
|
||||
if (this->count == 0)
|
||||
{
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
*item = this->first->value;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.insert_last.
|
||||
*/
|
||||
static void insert_last(private_linked_list_t *this, void *item)
|
||||
{
|
||||
linked_list_element_t *element = (linked_list_element_t *) linked_list_element_create(item);
|
||||
|
||||
if (this->count == 0)
|
||||
{
|
||||
/* first entry in list */
|
||||
this->first = element;
|
||||
this->last = element;
|
||||
element->previous = NULL;
|
||||
element->next = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
linked_list_element_t *old_last_element = this->last;
|
||||
element->previous = old_last_element;
|
||||
element->next = NULL;
|
||||
old_last_element->next = element;
|
||||
this->last = element;
|
||||
}
|
||||
|
||||
this->count++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.remove_last.
|
||||
*/
|
||||
static status_t remove_last(private_linked_list_t *this, void **item)
|
||||
{
|
||||
if (this->count == 0)
|
||||
{
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
linked_list_element_t *element = this->last;
|
||||
|
||||
if (element->previous != NULL)
|
||||
{
|
||||
element->previous->next = NULL;
|
||||
}
|
||||
this->last = element->previous;
|
||||
|
||||
if (item != NULL)
|
||||
{
|
||||
*item = element->value;
|
||||
}
|
||||
|
||||
this->count--;
|
||||
|
||||
element->destroy(element);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.insert_at_position.
|
||||
*/
|
||||
static status_t insert_at_position (private_linked_list_t *this,size_t position, void *item)
|
||||
{
|
||||
linked_list_element_t *current_element;
|
||||
int i;
|
||||
|
||||
if (this->count <= position)
|
||||
{
|
||||
return INVALID_ARG;
|
||||
}
|
||||
|
||||
current_element = this->first;
|
||||
|
||||
for (i = 0; i < position;i++)
|
||||
{
|
||||
current_element = current_element->next;
|
||||
}
|
||||
|
||||
if (current_element == NULL)
|
||||
{
|
||||
this->public.insert_last(&(this->public),item);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
linked_list_element_t *element =(linked_list_element_t *) linked_list_element_create(item);
|
||||
|
||||
|
||||
if (current_element->previous == NULL)
|
||||
{
|
||||
current_element->previous = element;
|
||||
element->next = current_element;
|
||||
this->first = element;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_element->previous->next = element;
|
||||
element->previous = current_element->previous;
|
||||
current_element->previous = element;
|
||||
element->next = current_element;
|
||||
}
|
||||
|
||||
|
||||
this->count++;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.remove_at_position.
|
||||
*/
|
||||
static status_t remove_at_position (private_linked_list_t *this,size_t position, void **item)
|
||||
{
|
||||
iterator_t *iterator;
|
||||
int i;
|
||||
|
||||
if (this->count <= position)
|
||||
{
|
||||
return INVALID_ARG;
|
||||
}
|
||||
|
||||
iterator = this->public.create_iterator(&(this->public),TRUE);
|
||||
|
||||
iterator->has_next(iterator);
|
||||
for (i = 0; i < position;i++)
|
||||
{
|
||||
iterator->has_next(iterator);
|
||||
}
|
||||
iterator->current(iterator,item);
|
||||
iterator->remove(iterator);
|
||||
iterator->destroy(iterator);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.get_at_position.
|
||||
*/
|
||||
static status_t get_at_position (private_linked_list_t *this,size_t position, void **item)
|
||||
{
|
||||
int i;
|
||||
iterator_t *iterator;
|
||||
status_t status;
|
||||
if (this->count <= position)
|
||||
{
|
||||
return INVALID_ARG;
|
||||
}
|
||||
|
||||
iterator = this->public.create_iterator(&(this->public),TRUE);
|
||||
|
||||
iterator->has_next(iterator);
|
||||
for (i = 0; i < position;i++)
|
||||
{
|
||||
iterator->has_next(iterator);
|
||||
}
|
||||
status = iterator->current(iterator,item);
|
||||
iterator->destroy(iterator);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.get_last.
|
||||
*/
|
||||
static status_t get_last(private_linked_list_t *this, void **item)
|
||||
{
|
||||
if (this->count == 0)
|
||||
{
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
*item = this->last->value;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.create_iterator.
|
||||
*/
|
||||
static iterator_t *create_iterator (private_linked_list_t *linked_list,bool forward)
|
||||
{
|
||||
private_iterator_t *this = malloc_thing(private_iterator_t);
|
||||
|
||||
this->public.iterate = (bool (*) (iterator_t *this, void **value)) iterate;
|
||||
this->public.has_next = (bool (*) (iterator_t *this)) iterator_has_next;
|
||||
this->public.current = (status_t (*) (iterator_t *this, void **value)) iterator_current;
|
||||
this->public.insert_before = (void (*) (iterator_t *this, void *item)) insert_before;
|
||||
this->public.insert_after = (void (*) (iterator_t *this, void *item)) insert_after;
|
||||
this->public.replace = (status_t (*) (iterator_t *, void **, void *)) replace;
|
||||
this->public.remove = (status_t (*) (iterator_t *this)) remove;
|
||||
this->public.reset = (void (*) (iterator_t *this)) iterator_reset;
|
||||
this->public.destroy = (void (*) (iterator_t *this)) iterator_destroy;
|
||||
|
||||
this->forward = forward;
|
||||
this->current = NULL;
|
||||
this->list = linked_list;
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of linked_list_t.destroy.
|
||||
*/
|
||||
static void linked_list_destroy(private_linked_list_t *this)
|
||||
{
|
||||
void * value;
|
||||
/* Remove all list items before destroying list */
|
||||
while (this->public.remove_first(&(this->public),&value) != NOT_FOUND)
|
||||
{
|
||||
/* values are not destroyed so memory leaks are possible
|
||||
* if list is not empty when deleting */
|
||||
}
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
linked_list_t *linked_list_create()
|
||||
{
|
||||
private_linked_list_t *this = malloc_thing(private_linked_list_t);
|
||||
|
||||
this->public.get_count = (int (*) (linked_list_t *)) get_count;
|
||||
this->public.create_iterator = (iterator_t * (*) (linked_list_t *,bool )) create_iterator;
|
||||
this->public.call_on_items = (void (*) (linked_list_t *, void(*func)(void*)))call_on_items;
|
||||
this->public.get_first = (status_t (*) (linked_list_t *, void **item)) get_first;
|
||||
this->public.get_last = (status_t (*) (linked_list_t *, void **item)) get_last;
|
||||
this->public.insert_first = (void (*) (linked_list_t *, void *item)) insert_first;
|
||||
this->public.insert_last = (void (*) (linked_list_t *, void *item)) insert_last;
|
||||
this->public.remove_first = (status_t (*) (linked_list_t *, void **item)) remove_first;
|
||||
this->public.remove_last = (status_t (*) (linked_list_t *, void **item)) remove_last;
|
||||
this->public.insert_at_position =(status_t (*) (linked_list_t *,size_t, void *)) insert_at_position;
|
||||
this->public.remove_at_position =(status_t (*) (linked_list_t *,size_t, void **)) remove_at_position;
|
||||
this->public.get_at_position =(status_t (*) (linked_list_t *,size_t, void **)) get_at_position;
|
||||
|
||||
this->public.destroy = (void (*) (linked_list_t *)) linked_list_destroy;
|
||||
|
||||
this->count = 0;
|
||||
this->first = NULL;
|
||||
this->last = NULL;
|
||||
|
||||
return (&(this->public));
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
/**
|
||||
* @file linked_list.h
|
||||
*
|
||||
* @brief Interface of linked_list_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LINKED_LIST_H_
|
||||
#define LINKED_LIST_H_
|
||||
|
||||
#include <types.h>
|
||||
#include <utils/iterator.h>
|
||||
|
||||
|
||||
typedef struct linked_list_t linked_list_t;
|
||||
|
||||
/**
|
||||
* @brief Class implementing a double linked list (named only as linked list).
|
||||
*
|
||||
* @warning Access to an object of this type is not thread-save.
|
||||
*
|
||||
* @b Costructors:
|
||||
* - linked_list_create()
|
||||
*
|
||||
* @see
|
||||
* - job_queue_t
|
||||
* - event_queue_t
|
||||
* - send_queue_t
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct linked_list_t {
|
||||
|
||||
/**
|
||||
* @brief Gets the count of items in the list.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @return number of items in list
|
||||
*/
|
||||
int (*get_count) (linked_list_t *linked_list);
|
||||
|
||||
/**
|
||||
* @brief Creates a iterator for the given list.
|
||||
*
|
||||
* @warning Created iterator_t object has to get destroyed by the caller.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param forward iterator direction (TRUE: front to end)
|
||||
* @return new iterator_t object
|
||||
*/
|
||||
iterator_t * (*create_iterator) (linked_list_t *linked_list, bool forward);
|
||||
|
||||
/**
|
||||
* @brief Call a function with list element as argument.
|
||||
*
|
||||
* This method accepts a function, which will be called for
|
||||
* each list element once. The function must accept the list
|
||||
* element as the first argument. Handy for destruction of
|
||||
* list elements.
|
||||
*
|
||||
* @todo Additional vararg which are passed to the
|
||||
* function would be nice...
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param func function to call
|
||||
*/
|
||||
void (*call_on_items) (linked_list_t *linked_list, void(*func)(void*));
|
||||
|
||||
/**
|
||||
* @brief Inserts a new item at the beginning of the list.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param[in] item item value to insert in list
|
||||
*/
|
||||
void (*insert_first) (linked_list_t *linked_list, void *item);
|
||||
|
||||
/**
|
||||
* @brief Removes the first item in the list and returns its value.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param[out] item returned value of first item, or NULL
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - NOT_FOUND, if list is empty
|
||||
*/
|
||||
status_t (*remove_first) (linked_list_t *linked_list, void **item);
|
||||
|
||||
/**
|
||||
* @brief Returns the value of the first list item without removing it.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param[out] item item returned value of first item
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - NOT_FOUND, if list is empty
|
||||
*/
|
||||
status_t (*get_first) (linked_list_t *linked_list, void **item);
|
||||
|
||||
/**
|
||||
* @brief Inserts a new item at the end of the list.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param[in] item item value to insert into list
|
||||
*/
|
||||
void (*insert_last) (linked_list_t *linked_list, void *item);
|
||||
|
||||
/**
|
||||
* @brief Inserts a new item at a given position in the list.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param position position starting at 0 to insert new entry
|
||||
* @param[in] item item value to insert into list
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - INVALID_ARG if position not existing
|
||||
*/
|
||||
status_t (*insert_at_position) (linked_list_t *linked_list,size_t position, void *item);
|
||||
|
||||
/**
|
||||
* @brief Removes an item from a given position in the list.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param position position starting at 0 to remove entry from
|
||||
* @param[out] item removed item will be stored at this location
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - INVALID_ARG if position not existing
|
||||
*/
|
||||
status_t (*remove_at_position) (linked_list_t *linked_list,size_t position, void **item);
|
||||
|
||||
/**
|
||||
* @brief Get an item from a given position in the list.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param position position starting at 0 to get entry from
|
||||
* @param[out] item item will be stored at this location
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - INVALID_ARG if position not existing
|
||||
*/
|
||||
status_t (*get_at_position) (linked_list_t *linked_list,size_t position, void **item);
|
||||
|
||||
/**
|
||||
* @brief Removes the last item in the list and returns its value.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param[out] item returned value of last item, or NULL
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - NOT_FOUND if list is empty
|
||||
*/
|
||||
status_t (*remove_last) (linked_list_t *linked_list, void **item);
|
||||
|
||||
/**
|
||||
* @brief Returns the value of the last list item without removing it.
|
||||
*
|
||||
* @param linked_list calling object
|
||||
* @param[out] item returned value of last item
|
||||
* @return
|
||||
* - SUCCESS
|
||||
* - NOT_FOUND if list is empty
|
||||
*/
|
||||
status_t (*get_last) (linked_list_t *linked_list, void **item);
|
||||
|
||||
/**
|
||||
* @brief Destroys a linked_list object.
|
||||
*
|
||||
* @warning All items are removed before deleting the list. The
|
||||
* associated values are NOT destroyed.
|
||||
* Destroying an list which is not empty may cause
|
||||
* memory leaks!
|
||||
*
|
||||
* @param linked_list calling object
|
||||
*/
|
||||
void (*destroy) (linked_list_t *linked_list);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates an empty linked list object.
|
||||
*
|
||||
* @return linked_list_t object.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
linked_list_t *linked_list_create(void);
|
||||
|
||||
|
||||
#endif /*LINKED_LIST_H_*/
|
||||
@@ -1,346 +0,0 @@
|
||||
/**
|
||||
* @file logger.c
|
||||
*
|
||||
* @brief Implementation of logger_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <syslog.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
|
||||
/**
|
||||
* Maximum length of a log entry (only used for logger_s.log).
|
||||
*/
|
||||
#define MAX_LOG 8192
|
||||
|
||||
/**
|
||||
* Maximum number of logged bytes per line
|
||||
*/
|
||||
#define MAX_BYTES 16
|
||||
|
||||
typedef struct private_logger_t private_logger_t;
|
||||
|
||||
/**
|
||||
* @brief Private data of a logger_t object.
|
||||
*/
|
||||
struct private_logger_t {
|
||||
/**
|
||||
* Public data.
|
||||
*/
|
||||
logger_t public;
|
||||
/**
|
||||
* Detail-level of logger.
|
||||
*/
|
||||
log_level_t level;
|
||||
/**
|
||||
* Name of logger.
|
||||
*/
|
||||
char *name;
|
||||
/**
|
||||
* File to write log output to.
|
||||
* NULL for syslog.
|
||||
*/
|
||||
FILE *output;
|
||||
|
||||
/**
|
||||
* Should a thread_id be included in the log?
|
||||
*/
|
||||
bool log_thread_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* prepend the logging prefix to string and store it in buffer
|
||||
*/
|
||||
static void prepend_prefix(private_logger_t *this, log_level_t loglevel, const char *string, char *buffer)
|
||||
{
|
||||
char log_type, log_details;
|
||||
char thread_id[10] = "";
|
||||
|
||||
if (loglevel & CONTROL)
|
||||
{
|
||||
log_type = 'C';
|
||||
}
|
||||
else if (loglevel & ERROR)
|
||||
{
|
||||
log_type = 'E';
|
||||
}
|
||||
else if (loglevel & RAW)
|
||||
{
|
||||
log_type = 'R';
|
||||
}
|
||||
else if (loglevel & PRIVATE)
|
||||
{
|
||||
log_type = 'P';
|
||||
}
|
||||
else if (loglevel & AUDIT)
|
||||
{
|
||||
log_type = 'A';
|
||||
}
|
||||
else
|
||||
{
|
||||
log_type = '-';
|
||||
}
|
||||
|
||||
if (loglevel & (LEVEL3 - LEVEL2))
|
||||
{
|
||||
log_details = '3';
|
||||
}
|
||||
else if (loglevel & (LEVEL2 - LEVEL1))
|
||||
{
|
||||
log_details = '2';
|
||||
}
|
||||
else if (loglevel & LEVEL1)
|
||||
{
|
||||
log_details = '1';
|
||||
}
|
||||
else
|
||||
{
|
||||
log_details = '0';
|
||||
}
|
||||
|
||||
if (this->log_thread_id)
|
||||
{
|
||||
snprintf(thread_id, sizeof(thread_id), " @%d", (int)pthread_self());
|
||||
}
|
||||
snprintf(buffer, MAX_LOG, "[%c%c:%s]%s %s", log_type, log_details, this->name, thread_id, string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a charon-loglevel to a syslog priority
|
||||
*/
|
||||
static int get_priority(log_level_t loglevel)
|
||||
{
|
||||
if (loglevel & ERROR)
|
||||
{
|
||||
return LOG_AUTHPRIV|LOG_ERR;
|
||||
}
|
||||
if (loglevel & AUDIT)
|
||||
{
|
||||
return LOG_AUTHPRIV|LOG_INFO;
|
||||
}
|
||||
return LOG_AUTHPRIV|LOG_DEBUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.log.
|
||||
*
|
||||
* Yes, logg is written wrong :-).
|
||||
*/
|
||||
static void logg(private_logger_t *this, log_level_t loglevel, const char *format, ...)
|
||||
{
|
||||
if ((this->level & loglevel) == loglevel)
|
||||
{
|
||||
char buffer[MAX_LOG];
|
||||
va_list args;
|
||||
|
||||
|
||||
if (this->output == NULL)
|
||||
{
|
||||
/* syslog */
|
||||
prepend_prefix(this, loglevel, format, buffer);
|
||||
va_start(args, format);
|
||||
vsyslog(get_priority(loglevel), buffer, args);
|
||||
va_end(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* File output */
|
||||
prepend_prefix(this, loglevel, format, buffer);
|
||||
va_start(args, format);
|
||||
vfprintf(this->output, buffer, args);
|
||||
va_end(args);
|
||||
fprintf(this->output, "\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.log_bytes.
|
||||
*/
|
||||
static void log_bytes(private_logger_t *this, log_level_t loglevel, const char *label, const char *bytes, size_t len)
|
||||
{
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
if ((this->level & loglevel) == loglevel)
|
||||
{
|
||||
char thread_id[10] = "";
|
||||
char buffer[MAX_LOG];
|
||||
char ascii_buffer[MAX_BYTES+1];
|
||||
|
||||
char *buffer_pos = buffer;
|
||||
const char format[] = "%s %d bytes @ %p";
|
||||
const char *bytes_pos = bytes;
|
||||
const char *bytes_roof = bytes + len;
|
||||
|
||||
int line_start = 0;
|
||||
int i = 0;
|
||||
|
||||
if (this->log_thread_id)
|
||||
{
|
||||
snprintf(thread_id, sizeof(thread_id), " @%d", (int)pthread_self());
|
||||
}
|
||||
|
||||
/* since me can't do multi-line output to syslog,
|
||||
* we must do multiple syslogs. To avoid
|
||||
* problems in output order, lock this by a mutex.
|
||||
*/
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
prepend_prefix(this, loglevel, format, buffer);
|
||||
|
||||
if (this->output == NULL)
|
||||
{
|
||||
syslog(get_priority(loglevel), buffer, label, len, bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(this->output, buffer, label, len, bytes);
|
||||
fprintf(this->output, "\n");
|
||||
}
|
||||
|
||||
while (bytes_pos < bytes_roof)
|
||||
{
|
||||
static char hexdig[] = "0123456789ABCDEF";
|
||||
|
||||
*buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
|
||||
*buffer_pos++ = hexdig[ *bytes_pos & 0xF];
|
||||
|
||||
ascii_buffer[i++] = (*bytes_pos > 31 && *bytes_pos < 127)
|
||||
? *bytes_pos : '.';
|
||||
|
||||
if (++bytes_pos == bytes_roof || i == MAX_BYTES)
|
||||
{
|
||||
int padding = 3 * (MAX_BYTES - i);
|
||||
|
||||
while (padding--)
|
||||
{
|
||||
*buffer_pos++ = ' ';
|
||||
}
|
||||
*buffer_pos++ = '\0';
|
||||
ascii_buffer[i] = '\0';
|
||||
|
||||
if (this->output == NULL)
|
||||
{
|
||||
syslog(get_priority(loglevel), "[ :%5d]%s %s %s", line_start, thread_id, buffer, ascii_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(this->output, "[ :%5d]%s %s %s\n", line_start, thread_id, buffer, ascii_buffer);
|
||||
}
|
||||
buffer_pos = buffer;
|
||||
line_start += MAX_BYTES;
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*buffer_pos++ = ' ';
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.log_chunk.
|
||||
*/
|
||||
static void log_chunk(logger_t *this, log_level_t loglevel, const char *label, chunk_t chunk)
|
||||
{
|
||||
this->log_bytes(this, loglevel, label, chunk.ptr, chunk.len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.enable_level.
|
||||
*/
|
||||
static void enable_level(private_logger_t *this, log_level_t log_level)
|
||||
{
|
||||
this->level |= log_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.disable_level.
|
||||
*/
|
||||
static void disable_level(private_logger_t *this, log_level_t log_level)
|
||||
{
|
||||
this->level &= ~log_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.set_output.
|
||||
*/
|
||||
static void set_output(private_logger_t *this, FILE * output)
|
||||
{
|
||||
this->output = output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.get_level.
|
||||
*/
|
||||
static log_level_t get_level(private_logger_t *this)
|
||||
{
|
||||
return this->level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_t.destroy.
|
||||
*/
|
||||
static void destroy(private_logger_t *this)
|
||||
{
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
logger_t *logger_create(char *logger_name, log_level_t log_level, bool log_thread_id, FILE * output)
|
||||
{
|
||||
private_logger_t *this = malloc_thing(private_logger_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.log = (void(*)(logger_t*,log_level_t,const char*,...))logg;
|
||||
this->public.log_bytes = (void(*)(logger_t*, log_level_t, const char*, const char*,size_t))log_bytes;
|
||||
this->public.log_chunk = log_chunk;
|
||||
this->public.enable_level = (void(*)(logger_t*,log_level_t))enable_level;
|
||||
this->public.disable_level = (void(*)(logger_t*,log_level_t))disable_level;
|
||||
this->public.get_level = (log_level_t(*)(logger_t*))get_level;
|
||||
this->public.set_output = (void(*)(logger_t*,FILE*))set_output;
|
||||
this->public.destroy = (void(*)(logger_t*))destroy;
|
||||
|
||||
if (logger_name == NULL)
|
||||
{
|
||||
logger_name = "";
|
||||
}
|
||||
|
||||
/* private variables */
|
||||
this->level = log_level;
|
||||
this->log_thread_id = log_thread_id;
|
||||
this->name = malloc(strlen(logger_name) + 1);
|
||||
|
||||
strcpy(this->name,logger_name);
|
||||
this->output = output;
|
||||
|
||||
return (logger_t*)this;
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
/**
|
||||
* @file logger.h
|
||||
*
|
||||
* @brief Interface of logger_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LOGGER_H_
|
||||
#define LOGGER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
typedef enum log_level_t log_level_t;
|
||||
|
||||
/**
|
||||
* @brief Log Levels supported by the logger object.
|
||||
*
|
||||
* Logleves are devided in two different kinds:
|
||||
* - levels to specify the type of the log
|
||||
* - levels to specify the detail-level of the log
|
||||
*
|
||||
* Use combinations of these to build detailed loglevels, such
|
||||
* as CONTROL|LEVEL2 fore a detailed cotrol level, or
|
||||
* use RAW to see all raw data dumps (except private).
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
enum log_level_t {
|
||||
/**
|
||||
* Control flow.
|
||||
*/
|
||||
CONTROL = 1,
|
||||
/**
|
||||
* Error reporting.
|
||||
*/
|
||||
ERROR = 2,
|
||||
/**
|
||||
* Logs important for the sysadmin.
|
||||
*/
|
||||
AUDIT = 4,
|
||||
/**
|
||||
* Raw data dumps.
|
||||
*/
|
||||
RAW = 8,
|
||||
/**
|
||||
* Private data dumps.
|
||||
*/
|
||||
PRIVATE = 16,
|
||||
|
||||
/**
|
||||
* Log most important output, can be omitted.
|
||||
*/
|
||||
LEVEL0 = 0,
|
||||
/**
|
||||
* Log more detailed output.
|
||||
*/
|
||||
LEVEL1 = 32,
|
||||
/**
|
||||
* Log even more detailed output.
|
||||
*/
|
||||
LEVEL2 = LEVEL1 + 64,
|
||||
/**
|
||||
* Use maximum detailed output.
|
||||
*/
|
||||
LEVEL3 = LEVEL2 + 128,
|
||||
|
||||
/**
|
||||
* Summary for all types with all detail-levels.
|
||||
*/
|
||||
FULL = LEVEL3 + CONTROL + ERROR + RAW + PRIVATE + AUDIT
|
||||
};
|
||||
|
||||
typedef struct logger_t logger_t;
|
||||
|
||||
/**
|
||||
* @brief Class to simplify logging.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - logger_create()
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct logger_t {
|
||||
|
||||
/**
|
||||
* @brief Log an entry, using printf()-like params.
|
||||
*
|
||||
* All specified loglevels must be activated that
|
||||
* the log is done.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param loglevel or'ed set of log_level_t's
|
||||
* @param format printf like format string
|
||||
* @param ... printf like parameters
|
||||
*/
|
||||
void (*log) (logger_t *this, log_level_t log_level, const char *format, ...);
|
||||
|
||||
/**
|
||||
* @brief Log some bytes, useful for debugging.
|
||||
*
|
||||
* All specified loglevels must be activated that
|
||||
* the log is done.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param loglevel or'ed set of log_level_t's
|
||||
* @param label a labeling name, logged with the bytes
|
||||
* @param bytes pointer to the bytes to dump
|
||||
* @param len number of bytes to dump
|
||||
*/
|
||||
void (*log_bytes) (logger_t *this, log_level_t loglevel, const char *label, const char *bytes, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Log a chunk, useful for debugging.
|
||||
*
|
||||
* All specified loglevels must be activated that
|
||||
* the log is done.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param loglevel or'ed set of log_level_t's
|
||||
* @param label a labeling name, logged with the bytes
|
||||
* @param chunk chunk to log
|
||||
*/
|
||||
void (*log_chunk) (logger_t *this, log_level_t loglevel, const char *label, chunk_t chunk);
|
||||
|
||||
/**
|
||||
* @brief Enables a loglevel for the current logger_t object.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param log_level loglevel to enable
|
||||
*/
|
||||
void (*enable_level) (logger_t *this, log_level_t log_level);
|
||||
|
||||
/**
|
||||
* @brief Disables a loglevel for the current logger_t object.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param log_level loglevel to enable
|
||||
*/
|
||||
void (*disable_level) (logger_t *this, log_level_t log_level);
|
||||
|
||||
/**
|
||||
* @brief Set the output of the logger.
|
||||
*
|
||||
* Use NULL for syslog.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @param output file, where log output should be written
|
||||
*/
|
||||
void (*set_output) (logger_t *this, FILE *output);
|
||||
|
||||
/**
|
||||
* @brief Get the currently used loglevel.
|
||||
*
|
||||
* @param this logger_t object
|
||||
* @return currently used loglevel
|
||||
*/
|
||||
log_level_t (*get_level) (logger_t *this);
|
||||
|
||||
/**
|
||||
* @brief Destroys a logger_t object.
|
||||
*
|
||||
* @param this logger_t object
|
||||
*/
|
||||
void (*destroy) (logger_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructor to create a logger_t object.
|
||||
*
|
||||
* @param logger_name name for the logger_t object
|
||||
* @param log_level or'ed set of log_levels to assign to the new logger_t object
|
||||
* @param log_thread_id TRUE if thread id should also be logged
|
||||
* @param output FILE * if log has to go on a file output, NULL for syslog
|
||||
* @return logger_t object
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
logger_t *logger_create(char *logger_name, log_level_t log_level, bool log_thread_id, FILE * output);
|
||||
|
||||
|
||||
#endif /*LOGGER_H_*/
|
||||
@@ -1,220 +0,0 @@
|
||||
/**
|
||||
* @file logger_manager.c
|
||||
*
|
||||
* @brief Implementation of logger_manager_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "logger_manager.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <definitions.h>
|
||||
#include <utils/linked_list.h>
|
||||
|
||||
/**
|
||||
* String mappings for logger_context_t
|
||||
*/
|
||||
mapping_t logger_context_t_mappings[] = {
|
||||
{PARSER, "PARSER"},
|
||||
{GENERATOR, "GENERATOR"},
|
||||
{IKE_SA, "IKE_SA"},
|
||||
{IKE_SA_MANAGER, "IKE_SA_MANAGER"},
|
||||
{CHILD_SA, "CHILD_SA"},
|
||||
{MESSAGE, "MESSAGE"},
|
||||
{THREAD_POOL, "THREAD_POOL"},
|
||||
{WORKER, "WORKER"},
|
||||
{SCHEDULER, "SCHEDULER"},
|
||||
{SENDER, "SENDER"},
|
||||
{RECEIVER, "RECEIVER"},
|
||||
{SOCKET, "SOCKET"},
|
||||
{TESTER, "TESTER"},
|
||||
{DAEMON, "DAEMON"},
|
||||
{CONFIG, "CONFIG"},
|
||||
{ENCRYPTION_PAYLOAD, "ENCRYPTION_PAYLOAD"},
|
||||
{PAYLOAD, "PAYLOAD"},
|
||||
{DER_DECODER, "DER_DECODER"},
|
||||
{DER_ENCODER, "DER_ENCODER"},
|
||||
{ASN1, "ASN1"},
|
||||
{XFRM, "XFRM"},
|
||||
{LEAK_DETECT, "LEAK_DETECT"},
|
||||
{MAPPING_END, NULL},
|
||||
};
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
log_level_t level;
|
||||
bool log_thread_ids;
|
||||
} logger_defaults[] = {
|
||||
{ "PARSR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* PARSER */
|
||||
{ "GNRAT", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* GENERATOR */
|
||||
{ "IKESA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* IKE_SA */
|
||||
{ "SAMGR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* IKE_SA_MANAGER */
|
||||
{ "CHDSA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* CHILD_SA */
|
||||
{ "MESSG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* MESSAGE */
|
||||
{ "TPOOL", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* THREAD_POOL */
|
||||
{ "WORKR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* WORKER */
|
||||
{ "SCHED", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* SCHEDULER */
|
||||
{ "SENDR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* SENDER */
|
||||
{ "RECVR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* RECEIVER */
|
||||
{ "SOCKT", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* SOCKET */
|
||||
{ "TESTR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* TESTER */
|
||||
{ "DAEMN", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* DAEMON */
|
||||
{ "CONFG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* CONFIG */
|
||||
{ "ENCPL", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* ENCRYPTION_PAYLOAD */
|
||||
{ "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|LEVEL0, TRUE }, /* ASN1 */
|
||||
{ "XFRM ", ERROR|CONTROL|AUDIT|LEVEL0, TRUE }, /* XFRM */
|
||||
{ "LEAKD", ERROR|CONTROL|AUDIT|LEVEL0, FALSE}, /* LEAK_DETECT */
|
||||
};
|
||||
|
||||
|
||||
typedef struct private_logger_manager_t private_logger_manager_t;
|
||||
|
||||
/**
|
||||
* Private data of logger_manager_t object.
|
||||
*/
|
||||
struct private_logger_manager_t {
|
||||
/**
|
||||
* Public data.
|
||||
*/
|
||||
logger_manager_t public;
|
||||
|
||||
/**
|
||||
* Array of loggers, one for each context
|
||||
*/
|
||||
logger_t *loggers[LOGGER_CONTEXT_ROOF];
|
||||
};
|
||||
|
||||
/**
|
||||
* The one and only instance of the logger manager
|
||||
*/
|
||||
static private_logger_manager_t private_logger_manager;
|
||||
|
||||
/**
|
||||
* Exported pointer for the logger manager
|
||||
*/
|
||||
logger_manager_t *logger_manager = (logger_manager_t *)&private_logger_manager;
|
||||
|
||||
/**
|
||||
* Implementation of logger_manager_t.get_logger.
|
||||
*/
|
||||
static logger_t *get_logger(private_logger_manager_t *this, logger_context_t context)
|
||||
{
|
||||
return this->loggers[context];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of logger_manager_t.get_log_level.
|
||||
*/
|
||||
static log_level_t get_log_level (private_logger_manager_t *this, logger_context_t context)
|
||||
{
|
||||
return this->loggers[context]->get_level(this->loggers[context]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_logger_manager_t.enable_log_level.
|
||||
*/
|
||||
static void enable_log_level(private_logger_manager_t *this, logger_context_t context, log_level_t level)
|
||||
{
|
||||
if (context == ALL_LOGGERS)
|
||||
{
|
||||
for (context = 0; context < LOGGER_CONTEXT_ROOF; context++)
|
||||
{
|
||||
this->loggers[context]->enable_level(this->loggers[context], level);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->loggers[context]->enable_level(this->loggers[context], level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_logger_manager_t.disable_log_level.
|
||||
*/
|
||||
static void disable_log_level(private_logger_manager_t *this, logger_context_t context, log_level_t level)
|
||||
{
|
||||
if (context == ALL_LOGGERS)
|
||||
{
|
||||
for (context = 0; context < LOGGER_CONTEXT_ROOF; context++)
|
||||
{
|
||||
this->loggers[context]->disable_level(this->loggers[context], level);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->loggers[context]->disable_level(this->loggers[context], level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_logger_manager_t.set_output.
|
||||
*/
|
||||
static void set_output(private_logger_manager_t *this, logger_context_t context, FILE *output)
|
||||
{
|
||||
if (context == ALL_LOGGERS)
|
||||
{
|
||||
for (context = 0; context < LOGGER_CONTEXT_ROOF; context++)
|
||||
{
|
||||
this->loggers[context]->set_output(this->loggers[context], output);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->loggers[context]->set_output(this->loggers[context], output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the instance of the logger manager at library startup
|
||||
*/
|
||||
void logger_manager_init()
|
||||
{
|
||||
int i;
|
||||
|
||||
logger_manager->get_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context))get_logger;
|
||||
logger_manager->get_log_level = (log_level_t (*)(logger_manager_t *, logger_context_t)) get_log_level;
|
||||
logger_manager->enable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) enable_log_level;
|
||||
logger_manager->disable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) disable_log_level;
|
||||
logger_manager->set_output = (void (*)(logger_manager_t *, logger_context_t, FILE*)) set_output;
|
||||
|
||||
for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
|
||||
{
|
||||
private_logger_manager.loggers[i] = logger_create(logger_defaults[i].name,
|
||||
logger_defaults[i].level,
|
||||
logger_defaults[i].log_thread_ids,
|
||||
INITIAL_LOG_OUTPUT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the logger manager at library exit
|
||||
*/
|
||||
void logger_manager_cleanup()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
|
||||
{
|
||||
private_logger_manager.loggers[i]->destroy(private_logger_manager.loggers[i]);
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
/**
|
||||
* @file logger_manager.h
|
||||
*
|
||||
* @brief Interface of logger_manager_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef LOGGER_MANAGER_H_
|
||||
#define LOGGER_MANAGER_H_
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <utils/logger.h>
|
||||
|
||||
#define INITIAL_LOG_OUTPUT stdout
|
||||
|
||||
typedef enum logger_context_t logger_context_t;
|
||||
|
||||
/**
|
||||
* @brief Context of a specific logger.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
enum logger_context_t {
|
||||
ALL_LOGGERS = -1,
|
||||
PARSER = 0,
|
||||
GENERATOR,
|
||||
IKE_SA,
|
||||
IKE_SA_MANAGER,
|
||||
CHILD_SA,
|
||||
MESSAGE,
|
||||
THREAD_POOL,
|
||||
WORKER,
|
||||
SCHEDULER,
|
||||
SENDER,
|
||||
RECEIVER,
|
||||
SOCKET,
|
||||
TESTER,
|
||||
DAEMON,
|
||||
CONFIG,
|
||||
ENCRYPTION_PAYLOAD,
|
||||
PAYLOAD,
|
||||
DER_DECODER,
|
||||
DER_ENCODER,
|
||||
ASN1,
|
||||
XFRM,
|
||||
LEAK_DETECT,
|
||||
LOGGER_CONTEXT_ROOF,
|
||||
};
|
||||
|
||||
|
||||
typedef struct logger_manager_t logger_manager_t;
|
||||
|
||||
/**
|
||||
* @brief Class to manage logger_t objects.
|
||||
*
|
||||
* The logger manager manages all logger_t object in a list and
|
||||
* allows their manipulation. Via a logger_context_t, the loglevel
|
||||
* of a specific logging type can be adjusted at runtime.
|
||||
* This class differs from others, as it has no constructor or destroy
|
||||
* function. The one and only instance "logger_manager" is created at
|
||||
* library start and destroyed at exit.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - none, logger_manager is the single instance
|
||||
* use logger_manager_init/logger_manager_cleanup
|
||||
*
|
||||
* @see logger_t
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct logger_manager_t {
|
||||
|
||||
/**
|
||||
* @brief Gets a logger_t object for a specific logger context.
|
||||
*
|
||||
* @param this logger_manager_t object
|
||||
* @param context logger_context to use the logger for
|
||||
* @param name name for the new logger. Context name is already included
|
||||
* and has not to be specified (so NULL is allowed)
|
||||
* @return logger_t object
|
||||
*/
|
||||
logger_t *(*get_logger) (logger_manager_t *this, logger_context_t context);
|
||||
|
||||
/**
|
||||
* @brief Returns the set log_level of a specific context.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param context context to check level
|
||||
* @return log_level for the given logger_context
|
||||
*/
|
||||
log_level_t (*get_log_level) (logger_manager_t *this, logger_context_t context);
|
||||
|
||||
/**
|
||||
* @brief Enables a logger level of a specific context.
|
||||
*
|
||||
* Use context ALL_LOGGERS to manipulate all loggers.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param context context to set level
|
||||
* @param log_level logger level to eanble
|
||||
*/
|
||||
void (*enable_log_level) (logger_manager_t *this, logger_context_t context,log_level_t log_level);
|
||||
|
||||
/**
|
||||
* @brief Disables a logger level of a specific context.
|
||||
*
|
||||
* Use context ALL_LOGGERS to manipulate all loggers.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param context context to set level
|
||||
* @param log_level logger level to disable
|
||||
*/
|
||||
void (*disable_log_level) (logger_manager_t *this, logger_context_t context,log_level_t log_level);
|
||||
|
||||
/**
|
||||
* @brief Sets the output of a logger.
|
||||
*
|
||||
* Use context ALL_LOGGERS to redirect all loggers.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param context context to set output
|
||||
* @param log_level logger level to disable
|
||||
*/
|
||||
void (*set_output) (logger_manager_t *this, logger_context_t context, FILE *output);
|
||||
};
|
||||
|
||||
/**
|
||||
* The single and global instance of the logger_manager
|
||||
*/
|
||||
extern logger_manager_t *logger_manager;
|
||||
|
||||
/**
|
||||
* Initialize the logger manager with all its logger.
|
||||
* Has to be called before logger_manager is accessed.
|
||||
*/
|
||||
void logger_manager_init(void);
|
||||
|
||||
/**
|
||||
* Free any resources hold by the logger manager. Do
|
||||
* not access logger_manager after this call.
|
||||
*/
|
||||
void logger_manager_cleanup(void);
|
||||
|
||||
#endif /*LOGGER_MANAGER_H_*/
|
||||
@@ -1,164 +0,0 @@
|
||||
/**
|
||||
* @file randomizer.c
|
||||
*
|
||||
* @brief Implementation of randomizer_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "randomizer.h"
|
||||
|
||||
|
||||
typedef struct private_randomizer_t private_randomizer_t;
|
||||
|
||||
/**
|
||||
* Private data of an randomizer_t object.
|
||||
*/
|
||||
struct private_randomizer_t {
|
||||
|
||||
/**
|
||||
* Public randomizer_t interface.
|
||||
*/
|
||||
randomizer_t public;
|
||||
|
||||
/**
|
||||
* @brief Reads a specific number of bytes from random or pseudo random device.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param pseudo_random TRUE, if from pseudo random bytes should be read,
|
||||
* FALSE for true random bytes
|
||||
* @param bytes number of bytes to read
|
||||
* @param[out] buffer pointer to buffer where to write the data in.
|
||||
* Size of buffer has to be at least bytes.
|
||||
*/
|
||||
status_t (*get_bytes_from_device) (private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of private_randomizer_t.get_bytes_from_device.
|
||||
*/
|
||||
static status_t get_bytes_from_device(private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer)
|
||||
{
|
||||
size_t ndone;
|
||||
int device;
|
||||
size_t got;
|
||||
char * device_name;
|
||||
|
||||
device_name = pseudo_random ? PSEUDO_RANDOM_DEVICE : RANDOM_DEVICE;
|
||||
|
||||
device = open(device_name, 0);
|
||||
if (device < 0) {
|
||||
return FAILED;
|
||||
}
|
||||
ndone = 0;
|
||||
|
||||
/* read until nbytes are read */
|
||||
while (ndone < bytes)
|
||||
{
|
||||
got = read(device, buffer + ndone, bytes - ndone);
|
||||
if (got <= 0) {
|
||||
close(device);
|
||||
return FAILED;
|
||||
}
|
||||
ndone += got;
|
||||
}
|
||||
close(device);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of randomizer_t.get_random_bytes.
|
||||
*/
|
||||
static status_t get_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer)
|
||||
{
|
||||
return this->get_bytes_from_device(this, FALSE, bytes, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of randomizer_t.allocate_random_bytes.
|
||||
*/
|
||||
static status_t allocate_random_bytes(private_randomizer_t *this, size_t bytes, chunk_t *chunk)
|
||||
{
|
||||
status_t status;
|
||||
chunk->len = bytes;
|
||||
chunk->ptr = malloc(bytes);
|
||||
status = this->get_bytes_from_device(this, FALSE, bytes, chunk->ptr);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
free(chunk->ptr);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of randomizer_t.get_pseudo_random_bytes.
|
||||
*/
|
||||
static status_t get_pseudo_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer)
|
||||
{
|
||||
return (this->get_bytes_from_device(this, TRUE, bytes, buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of randomizer_t.allocate_pseudo_random_bytes.
|
||||
*/
|
||||
static status_t allocate_pseudo_random_bytes(private_randomizer_t *this, size_t bytes, chunk_t *chunk)
|
||||
{
|
||||
status_t status;
|
||||
chunk->len = bytes;
|
||||
chunk->ptr = malloc(bytes);
|
||||
status = this->get_bytes_from_device(this, TRUE, bytes, chunk->ptr);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
free(chunk->ptr);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of randomizer_t.destroy.
|
||||
*/
|
||||
static void destroy(private_randomizer_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
randomizer_t *randomizer_create(void)
|
||||
{
|
||||
private_randomizer_t *this = malloc_thing(private_randomizer_t);
|
||||
|
||||
/* public functions */
|
||||
this->public.get_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_random_bytes;
|
||||
this->public.allocate_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_random_bytes;
|
||||
this->public.get_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_pseudo_random_bytes;
|
||||
this->public.allocate_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_pseudo_random_bytes;
|
||||
this->public.destroy = (void (*) (randomizer_t *))destroy;
|
||||
|
||||
/* private functions */
|
||||
this->get_bytes_from_device = get_bytes_from_device;
|
||||
|
||||
return &(this->public);
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
/**
|
||||
* @file randomizer.h
|
||||
*
|
||||
* @brief Interface of randomizer_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RANDOMIZER_H_
|
||||
#define RANDOMIZER_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
|
||||
/**
|
||||
* Device to read real random bytes
|
||||
*/
|
||||
#define RANDOM_DEVICE "/dev/random"
|
||||
|
||||
/**
|
||||
* Device to read pseudo random bytes
|
||||
*/
|
||||
#define PSEUDO_RANDOM_DEVICE "/dev/urandom"
|
||||
|
||||
typedef struct randomizer_t randomizer_t;
|
||||
|
||||
/**
|
||||
* @brief Class used to get random and pseudo random values.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - randomizer_create()
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct randomizer_t {
|
||||
|
||||
/**
|
||||
* @brief Reads a specific number of bytes from random device.
|
||||
*
|
||||
* @param this calling randomizer_t object
|
||||
* @param bytes number of bytes to read
|
||||
* @param[out] buffer pointer to buffer where to write the data in.
|
||||
* Size of buffer has to be at least bytes.
|
||||
* @return SUCCESS, or FAILED
|
||||
*/
|
||||
status_t (*get_random_bytes) (randomizer_t *this, size_t bytes, u_int8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief Allocates space and writes in random bytes.
|
||||
*
|
||||
* @param this calling randomizer_t object
|
||||
* @param bytes number of bytes to allocate
|
||||
* @param[out] chunk chunk which will hold the allocated random bytes
|
||||
* @return SUCCESS, or FAILED
|
||||
*/
|
||||
status_t (*allocate_random_bytes) (randomizer_t *this, size_t bytes, chunk_t *chunk);
|
||||
|
||||
/**
|
||||
* @brief Reads a specific number of bytes from pseudo random device.
|
||||
*
|
||||
* @param this calling randomizer_t object
|
||||
* @param bytes number of bytes to read
|
||||
* @param[out] buffer pointer to buffer where to write the data in.
|
||||
* size of buffer has to be at least bytes.
|
||||
* @return SUCCESS, or FAILED
|
||||
*/
|
||||
status_t (*get_pseudo_random_bytes) (randomizer_t *this,size_t bytes, u_int8_t *buffer);
|
||||
|
||||
/**
|
||||
* @brief Allocates space and writes in pseudo random bytes.
|
||||
*
|
||||
* @param this calling randomizer_t object
|
||||
* @param bytes number of bytes to allocate
|
||||
* @param[out] chunk chunk which will hold the allocated random bytes
|
||||
* @return SUCCESS, or FAILED
|
||||
*/
|
||||
status_t (*allocate_pseudo_random_bytes) (randomizer_t *this, size_t bytes, chunk_t *chunk);
|
||||
|
||||
/**
|
||||
* @brief Destroys a randomizer_t object.
|
||||
*
|
||||
* @param this randomizer_t object to destroy
|
||||
*/
|
||||
void (*destroy) (randomizer_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates a randomizer_t object.
|
||||
*
|
||||
* @return created randomizer_t, or
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
randomizer_t *randomizer_create(void);
|
||||
|
||||
#endif /*RANDOMIZER_H_*/
|
||||
@@ -1,256 +0,0 @@
|
||||
/**
|
||||
* @file tester.c
|
||||
*
|
||||
* @brief Implementation of tester_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "tester.h"
|
||||
|
||||
#include <utils/linked_list.h>
|
||||
#include <queues/job_queue.h>
|
||||
|
||||
|
||||
typedef struct private_tester_t private_tester_t;
|
||||
|
||||
/**
|
||||
* @brief Private Data of tester_t class.
|
||||
*
|
||||
*/
|
||||
struct private_tester_t {
|
||||
|
||||
/**
|
||||
* Protected interface of tester_t.
|
||||
*/
|
||||
protected_tester_t protected;
|
||||
|
||||
/**
|
||||
* Runs a specific test.
|
||||
*
|
||||
* @param tester associated tester object
|
||||
* @param test_function test function to perform
|
||||
* @param test_name name for the given test
|
||||
*/
|
||||
void (*run_test) (private_tester_t *tester, void (*test_function) (protected_tester_t * tester), char * test_name);
|
||||
|
||||
/**
|
||||
* Returns the difference of to timeval structs in microseconds.
|
||||
*
|
||||
* @warning this function is also defined in the event queue
|
||||
* in later improvements, this function can be added to a general
|
||||
* class type!
|
||||
*
|
||||
* @param end_time end time
|
||||
* @param start_time start time
|
||||
*
|
||||
* @TODO make object function or move to utils!
|
||||
*
|
||||
* @return difference in microseconds
|
||||
*/
|
||||
long (*time_difference) (private_tester_t *tester,struct timeval *end_time, struct timeval *start_time);
|
||||
|
||||
/**
|
||||
* Output is written into this file.
|
||||
*/
|
||||
FILE* output;
|
||||
|
||||
/**
|
||||
* Number of already performed tests.
|
||||
*/
|
||||
int tests_count;
|
||||
|
||||
/**
|
||||
* Number of failed tests.
|
||||
*/
|
||||
int failed_tests_count;
|
||||
|
||||
/**
|
||||
* Number of failed asserts in current test.
|
||||
*/
|
||||
int failed_asserts_count;
|
||||
|
||||
/**
|
||||
* TRUE if also succeeded asserts should be written to output.
|
||||
*/
|
||||
bool display_succeeded_asserts;
|
||||
|
||||
/**
|
||||
* Mutex to make this class thread-save.
|
||||
*/
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of tester_t.perform_tests.
|
||||
*/
|
||||
static void perform_tests(private_tester_t *this,test_t **tests)
|
||||
{
|
||||
int current_test = 0;
|
||||
fprintf(this->output,"\nStart testing...\n\n");
|
||||
fprintf(this->output,"_____________________________________________________________________\n");
|
||||
fprintf(this->output,"Testname | running time\n");
|
||||
fprintf(this->output,"_______________________________________________________|_____________\n");
|
||||
|
||||
while (tests[current_test] != NULL)
|
||||
{
|
||||
this->run_test(this,tests[current_test]->test_function,tests[current_test]->test_name);
|
||||
current_test++;
|
||||
}
|
||||
fprintf(this->output,"=====================================================================\n");
|
||||
fprintf(this->output,"End testing. %d of %d tests succeeded\n",this->tests_count - this->failed_tests_count,this->tests_count);
|
||||
fprintf(this->output,"=====================================================================\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of tester_t.perform_test.
|
||||
*/
|
||||
static void perform_test(private_tester_t *this, test_t *test)
|
||||
{
|
||||
test_t *tests[] = {test, NULL};
|
||||
return (perform_tests(this,tests));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference of to timeval structs in microseconds.
|
||||
*
|
||||
* @warning this function is also defined in the event queue
|
||||
* in later improvements, this function can be added to a general
|
||||
* class type!
|
||||
*
|
||||
* @param end_time end time
|
||||
* @param start_time start time
|
||||
*
|
||||
* @TODO make object function or move to utils!
|
||||
*
|
||||
* @return difference in microseconds
|
||||
*/
|
||||
static long time_difference(private_tester_t *this,struct timeval *end_time, struct timeval *start_time)
|
||||
{
|
||||
long seconds, microseconds;
|
||||
|
||||
seconds = (end_time->tv_sec - start_time->tv_sec);
|
||||
microseconds = (end_time->tv_usec - start_time->tv_usec);
|
||||
return ((seconds * 1000000) + microseconds);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of private_tester_t.run_test.
|
||||
*/
|
||||
static void run_test(private_tester_t *this, void (*test_function) (protected_tester_t * tester), char * test_name)
|
||||
{
|
||||
struct timeval start_time, end_time;
|
||||
long timediff;
|
||||
this->tests_count++;
|
||||
this->failed_asserts_count = 0;
|
||||
fprintf(this->output,"%-55s\n", test_name);
|
||||
gettimeofday(&start_time,NULL);
|
||||
test_function(&(this->protected));
|
||||
gettimeofday(&end_time,NULL);
|
||||
timediff = this->time_difference(this,&end_time, &start_time);
|
||||
|
||||
if (this->failed_asserts_count > 0)
|
||||
{
|
||||
fprintf(this->output," => Test failed: %-37s|%10ld us\n",test_name,timediff);
|
||||
}else
|
||||
{
|
||||
fprintf(this->output,"\033[1A\033[55C|%10ld us\033[1B\033[80D",timediff);
|
||||
}
|
||||
if (this->failed_asserts_count > 0)
|
||||
{
|
||||
this->failed_tests_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of tester_t.assert_true.
|
||||
*/
|
||||
static void assert_true(private_tester_t *this, bool to_be_true,char * assert_name)
|
||||
{
|
||||
if (assert_name == NULL)
|
||||
{
|
||||
assert_name = "unknown";
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&(this->mutex));
|
||||
if (!to_be_true)
|
||||
{
|
||||
this->failed_asserts_count++;
|
||||
fprintf(this->output," check '%s' failed!\n", assert_name);
|
||||
}else
|
||||
{
|
||||
if (this->display_succeeded_asserts)
|
||||
{
|
||||
fprintf(this->output," check '%s' succeeded\n", assert_name);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&(this->mutex));
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of tester_t.assert_false.
|
||||
*/
|
||||
static void assert_false(private_tester_t *this, bool to_be_false,char * assert_name)
|
||||
{
|
||||
this->protected.assert_true(&(this->protected),(!to_be_false),assert_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of tester_t.destroy.
|
||||
*/
|
||||
static void destroy(private_tester_t *tester)
|
||||
{
|
||||
private_tester_t *this = (private_tester_t*) tester;
|
||||
pthread_mutex_destroy(&(this->mutex));
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
tester_t *tester_create(FILE *output, bool display_succeeded_asserts)
|
||||
{
|
||||
private_tester_t *this = malloc_thing(private_tester_t);
|
||||
|
||||
/* public functions */
|
||||
this->protected.public.destroy = (void (*) (tester_t *))destroy;
|
||||
this->protected.public.perform_tests = (void (*) (tester_t *, test_t**)) perform_tests;
|
||||
this->protected.public.perform_test = (void (*) (tester_t *, test_t*))perform_test;
|
||||
this->protected.assert_true = (void (*) (protected_tester_t *, bool, char*)) assert_true;
|
||||
this->protected.assert_false = (void (*) (protected_tester_t *, bool, char*)) assert_false;
|
||||
|
||||
/* private functions */
|
||||
this->run_test = run_test;
|
||||
this->time_difference = time_difference;
|
||||
|
||||
/* private data */
|
||||
this->display_succeeded_asserts = display_succeeded_asserts;
|
||||
this->failed_tests_count = 0;
|
||||
this->tests_count = 0;
|
||||
this->output = output;
|
||||
pthread_mutex_init(&(this->mutex),NULL);
|
||||
|
||||
return &(this->protected.public);
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/**
|
||||
* @file tester.h
|
||||
*
|
||||
* @brief Interface of tester_t.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TESTER_H_
|
||||
#define TESTER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <types.h>
|
||||
|
||||
|
||||
/* must be defined here cause it is used in test_t */
|
||||
typedef struct protected_tester_t protected_tester_t;
|
||||
|
||||
typedef struct test_t test_t;
|
||||
|
||||
/**
|
||||
* @brief Representing a specified test.
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct test_t {
|
||||
/**
|
||||
* Testfunction called for this test.
|
||||
*
|
||||
* @param tester associated tester_t object
|
||||
*/
|
||||
void (*test_function) (protected_tester_t * tester);
|
||||
|
||||
/**
|
||||
* Name of the test.
|
||||
*/
|
||||
char * test_name;
|
||||
};
|
||||
|
||||
|
||||
typedef struct tester_t tester_t;
|
||||
|
||||
/**
|
||||
* @brief A class to perform tests.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - tester_create()
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct tester_t {
|
||||
/**
|
||||
* @brief Test all testcases in array tests with specific tester_t object.
|
||||
*
|
||||
* @param tester tester_t object
|
||||
* @param tests pointer to an array of test_t-pointers.
|
||||
* The last item has to be NULL to mark end of array.
|
||||
*/
|
||||
void (*perform_tests) (tester_t *tester,test_t **tests);
|
||||
|
||||
/**
|
||||
* @brief Run a specific test case.
|
||||
*
|
||||
* @param this tester_t object
|
||||
* @param test pointer to a test_t object which will be performed
|
||||
*/
|
||||
void (*perform_test) (tester_t *tester, test_t *test);
|
||||
|
||||
/**
|
||||
* @brief Destroys a tester_t object.
|
||||
*
|
||||
* @param tester tester_t object
|
||||
*/
|
||||
void (*destroy) (tester_t *tester);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief A class used in a specific testcase.
|
||||
*
|
||||
* For each testcase an object of this type is passed to the testfunction. The testfunction uses this
|
||||
* object to check specific asserts with protected_tester_t.assert_true and protected_tester_t.assert_false.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - tester_create()
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
struct protected_tester_t {
|
||||
|
||||
/**
|
||||
* Public functions of a tester_t object
|
||||
*/
|
||||
tester_t public;
|
||||
|
||||
/**
|
||||
* @brief Is called in a testcase to check a specific situation for TRUE.
|
||||
*
|
||||
* Log-Values to the tester output are protected from multiple access.
|
||||
*
|
||||
* @param this tester_t object
|
||||
* @param to_be_true assert which has to be TRUE
|
||||
* @param assert_name name of the assertion
|
||||
*/
|
||||
void (*assert_true) (protected_tester_t *tester, bool to_be_true, char *assert_name);
|
||||
|
||||
/**
|
||||
* @brief Is called in a testcase to check a specific situation for FALSE.
|
||||
*
|
||||
* Log-Values to the tester output are protected from multiple access.
|
||||
*
|
||||
* @param this tester_t object
|
||||
* @param to_be_false assert which has to be FALSE
|
||||
* @param assert_name name of the assertion
|
||||
*/
|
||||
void (*assert_false) (protected_tester_t *tester, bool to_be_false, char *assert_name);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates a tester_t object used to perform tests with.
|
||||
*
|
||||
* @param output test output is written to this output.
|
||||
* @param display_succeeded_asserts has to be TRUE, if all asserts should be displayed,
|
||||
* FALSE otherwise
|
||||
*
|
||||
* @return tester_t object
|
||||
*
|
||||
* @ingroup utils
|
||||
*/
|
||||
tester_t *tester_create(FILE *output, bool display_succeeded_asserts);
|
||||
|
||||
#endif /*TESTER_H_*/
|
||||
Reference in New Issue
Block a user