../svn-commit.tmp

This commit is contained in:
Martin Willi
2006-04-05 12:10:50 +00:00
parent 3dbbbf3e16
commit 6862128151
171 changed files with 674 additions and 1355 deletions
+27
View File
@@ -0,0 +1,27 @@
# 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/
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 $@ $<
include $(MAIN_DIR)lib/crypto/Makefile.transforms
include $(MAIN_DIR)lib/utils/Makefile.utils
include $(MAIN_DIR)lib/asn1/Makefile.asn1
+24
View File
@@ -0,0 +1,24 @@
# 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.
#
ASN1_DIR= $(LIB_DIR)asn1/
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)der_decoder.o
$(BUILD_DIR)der_decoder.o : $(ASN1_DIR)der_decoder.c $(ASN1_DIR)der_decoder.h
$(CC) $(CFLAGS) -c -o $@ $<
+74
View File
@@ -0,0 +1,74 @@
/**
* @file asn1.c
*
* @brief String mappings for asn1.h
*
*/
/*
* 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 "asn1.h"
mapping_t asn1_type_m[] = {
{ASN1_END, "ASN1_END"},
{ASN1_BOOLEAN, "ASN1_BOOLEAN"},
{ASN1_INTEGER, "ASN1_INTEGER"},
{ASN1_BITSTRING, "ASN1_BITSTRING"},
{ASN1_OCTETSTRING, "ASN1_OCTETSTRING"},
{ASN1_NULL, "ASN1_NULL"},
{ASN1_OID, "ASN1_OID"},
{ASN1_ENUMERATED, "ASN1_ENUMERATED"},
{ASN1_UTF8STRING, "ASN1_UTF8STRING"},
{ASN1_NUMERICSTRING, "ASN1_NUMERICSTRING"},
{ASN1_PRINTABLESTRING, "ASN1_PRINTABLESTRING"},
{ASN1_T61STRING, "ASN1_T61STRING"},
{ASN1_VIDEOTEXSTRING, "ASN1_VIDEOTEXSTRING"},
{ASN1_IA5STRING, "ASN1_IA5STRING"},
{ASN1_UTCTIME, "ASN1_UTCTIME"},
{ASN1_GENERALIZEDTIME, "ASN1_GENERALIZEDTIME"},
{ASN1_GRAPHICSTRING, "ASN1_GRAPHICSTRING"},
{ASN1_VISIBLESTRING, "ASN1_VISIBLESTRING"},
{ASN1_GENERALSTRING, "ASN1_GENERALSTRING"},
{ASN1_UNIVERSALSTRING, "ASN1_UNIVERSALSTRING"},
{ASN1_BMPSTRING, "ASN1_BMPSTRING"},
{ASN1_CONSTRUCTED, "ASN1_CONSTRUCTED"},
{ASN1_SEQUENCE, "ASN1_SEQUENCE"},
{ASN1_SET, "ASN1_SET"},
{ASN1_TAG_E_0, "ASN1_TAG_E_0"},
{ASN1_TAG_E_1, "ASN1_TAG_E_1"},
{ASN1_TAG_E_2, "ASN1_TAG_E_2"},
{ASN1_TAG_E_3, "ASN1_TAG_E_3"},
{ASN1_TAG_E_4, "ASN1_TAG_E_4"},
{ASN1_TAG_E_5, "ASN1_TAG_E_5"},
{ASN1_TAG_E_6, "ASN1_TAG_E_6"},
{ASN1_TAG_E_7, "ASN1_TAG_E_7"},
{ASN1_TAG_I_0, "ASN1_TAG_I_0"},
{ASN1_TAG_I_1, "ASN1_TAG_I_1"},
{ASN1_TAG_I_2, "ASN1_TAG_I_2"},
{ASN1_TAG_I_3, "ASN1_TAG_I_3"},
{ASN1_TAG_I_4, "ASN1_TAG_I_4"},
{ASN1_TAG_I_5, "ASN1_TAG_I_5"},
{ASN1_TAG_I_6, "ASN1_TAG_I_6"},
{ASN1_TAG_I_7, "ASN1_TAG_I_7"},
{ASN1_CHOICE, "ASN1_CHOICE"},
};
mapping_t asn1_flag_m[] = {
{ASN1_OPTIONAL, "ASN1_OPTIONAL"},
{ASN1_DEFAULT, "ASN1_DEFAULT"},
{ASN1_MPZ, "ASN1_MPZ"},
{ASN1_OF, "ASN1_OF"},
};
+172
View File
@@ -0,0 +1,172 @@
/**
* @file asn1.h
*
* @brief Definition of asn1_rule_t and other ASN1 stuff.
*
*/
/*
* 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 ASN1_H_
#define ASN1_H_
#include <types.h>
typedef enum asn1_type_t asn1_type_t;
/**
* @brief Real and some special ASN1 types.
*
* @ingroup asn1
*/
enum asn1_type_t {
/**
* End of a sequence, set, choice
*/
ASN1_END = 0x00,
ASN1_BOOLEAN = 0x01,
ASN1_INTEGER = 0x02,
ASN1_BITSTRING = 0x03,
ASN1_OCTETSTRING = 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,
/**
* EXCPLICIT tags
*/
ASN1_TAG_E_0 = 0xA0,
ASN1_TAG_E_1 = 0xA1,
ASN1_TAG_E_2 = 0xA2,
ASN1_TAG_E_3 = 0xA3,
ASN1_TAG_E_4 = 0xA4,
ASN1_TAG_E_5 = 0xA5,
ASN1_TAG_E_6 = 0xA6,
ASN1_TAG_E_7 = 0xA7,
/**
* IMPLICIT tags
*/
ASN1_TAG_I_0 = 0x80,
ASN1_TAG_I_1 = 0x81,
ASN1_TAG_I_2 = 0x82,
ASN1_TAG_I_3 = 0x83,
ASN1_TAG_I_4 = 0x84,
ASN1_TAG_I_5 = 0x85,
ASN1_TAG_I_6 = 0x86,
ASN1_TAG_I_7 = 0x87,
/**
* Begin of a choice
*/
ASN1_CHOICE = 0xFE,
/**
* ANY type
*/
ASN1_ANY = 0xFF,
};
/**
* String mappings for asn1_type_t
*/
extern mapping_t asn1_type_m[];
typedef enum asn1_flag_t asn1_flag_t;
/**
* @brief Flags used to build ASN1 rules.
*
* @ingroup asn1
*/
enum asn1_flag_t {
/**
* Field is optional
*/
ASN1_OPTIONAL = 0x01,
/**
* Field has a default value and is therefore optional
*/
ASN1_DEFAULT = 0x02,
/**
* Convert this INTEGER to an mpz_t
*/
ASN1_MPZ = 0x04,
/**
* SEQUENCE or SET OF
*/
ASN1_OF = 0x08,
/**
* Parse this Sequence in a RAW chunk too.
* Used for crypto calculations...
*/
ASN1_RAW = 0x10,
};
/**
* String mappings for asn1_flag_t
*/
extern mapping_t asn1_flag_m[];
typedef struct asn1_rule_t asn1_rule_t;
/**
* @brief Single rule of a complet ruleset.
*
* This rule containing a type, flags and additional
* data allow modellation of complex ASN1 structures and
* allow their en- and decoding...
*
* @ingroup asn1
*/
struct asn1_rule_t {
/**
* ASN1 type
*/
asn1_type_t type;
/**
* implicit or explicit tag, if any
*/
asn1_flag_t flags;
/**
* offset of data in structure
*/
u_int data_offset;
/**
* offset to a boolean, which says if optional
* data is available at data_offset. Used if
* flags & ASN1_OPTIONAL.
* default value, used if flags & ASN1_DEFAULT
*/
u_int additional;
};
#endif /* ASN1_H_ */
+502
View File
@@ -0,0 +1,502 @@
/**
* @file der_decoder.c
*
* @brief Implementation of der_decoder_t.
*/
/*
* Copyright (C) 2000-2004 Andreas Steffen
* Copyright (C) 2006 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* Some parts taken over from pluto/asn1.c
*
* 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 "der_decoder.h"
#include <utils/allocator.h>
#include <daemon.h>
typedef struct private_der_decoder_t private_der_decoder_t;
/**
* Private data of a der_decoder_t object.
*/
struct private_der_decoder_t {
/**
* Public interface for this signer.
*/
der_decoder_t public;
/**
* Rule which was just processed
*/
asn1_rule_t *rule;
/**
* First rule of the whole ruleset
*/
asn1_rule_t *first_rule;
/**
* Output data struct
*/
void *output;
/**
* Complex things like this need a logger ;-)
*/
logger_t *logger;
};
status_t read_hdr(private_der_decoder_t *this, chunk_t *data);
/**
* Read a sequence from data, parse its contents recursivly
*/
status_t read_sequence(private_der_decoder_t *this, chunk_t data)
{
status_t status;
asn1_rule_t *next_rule;
while(TRUE)
{
next_rule = this->rule + 1;
if (next_rule->type == ASN1_END)
{
this->rule++;
break;
}
status = read_hdr(this, &data);
if (status != SUCCESS)
{
return status;
}
}
this->logger->log(this->logger, CONTROL|LEVEL2, "Sequence end");
return SUCCESS;
}
/**
* Read choice of data, parse if one of the choosable types arise
*/
status_t read_choice(private_der_decoder_t *this, chunk_t *data)
{
status_t status = PARSE_ERROR;
asn1_rule_t *next_rule;
bool found = FALSE;
this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "Choice data", *data);
while(TRUE)
{
next_rule = this->rule + 1;
if (next_rule->type == ASN1_END)
{
this->rule++;
return status;
}
if (!found && *(data->ptr) == next_rule->type)
{
found = TRUE;
status = read_hdr(this, data);
}
else
{
this->rule++;
}
}
this->logger->log(this->logger, CONTROL|LEVEL2, "Choice end");
return status;
}
/**
* Read a utc or generalized time
*/
status_t read_time(private_der_decoder_t *this, chunk_t data)
{
struct tm t;
time_t tz_offset;
u_char *eot = NULL;
const char* format;
time_t *result = (time_t*)((u_int8_t*)this->output + this->rule->data_offset);
/* TODO: Test it */
this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "TIME", data);
if ((eot = memchr(data.ptr, 'Z', data.len)) != NULL)
{
/* Zulu time with a zero time zone offset */
tz_offset = 0;
}
else if ((eot = memchr(data.ptr, '+', data.len)) != NULL)
{
int tz_hour, tz_min;
sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min);
/* positive time zone offset */
tz_offset = 3600*tz_hour + 60*tz_min;
}
else if ((eot = memchr(data.ptr, '-', data.len)) != NULL)
{
int tz_hour, tz_min;
sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min);
/* negative time zone offset */
tz_offset = -3600*tz_hour - 60*tz_min;
}
else
{
/* error in time format */
return PARSE_ERROR;
}
if (this->rule->type == ASN1_UTCTIME)
{
format = "%2d%2d%2d%2d%2d";
}
else
{
format = "%4d%2d%2d%2d%2d";
}
sscanf(data.ptr, format, &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min);
/* is there a seconds field? */
if ((eot - data.ptr) == ((this->rule->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 PARSE_ERROR;
}
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 */
*result = mktime(&t) - timezone - tz_offset;
return SUCCESS;
}
/**
* Read an integer as u_int or as mpz_t
*/
status_t read_int(private_der_decoder_t *this, chunk_t data)
{
this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "ASN1_INTEGER", data);
if (this->rule->flags & ASN1_MPZ)
{
mpz_t *mpz = (mpz_t*)((u_int8_t*)this->output + this->rule->data_offset);
mpz_import(*mpz, data.len, 1, 1, 1, 0, data.ptr);
}
else
{
u_int *integ = (u_int*)((u_int8_t*)this->output + this->rule->data_offset);
*integ = 0;
while (data.len-- > 0)
{
*integ = 256 * (*integ) + *data.ptr++;
}
}
return SUCCESS;
}
/**
* Read boolean value
*/
status_t read_bool(private_der_decoder_t *this, chunk_t data)
{
this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "ASN1_BOOLEAN", data);
bool *boolean = (u_int*)((u_int8_t*)this->output + this->rule->data_offset);
*boolean = *data.ptr;
return SUCCESS;
}
/**
* Read an OID
*/
status_t read_oid(private_der_decoder_t *this, chunk_t data)
{
this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "ASN1_OID", data);
/* TODO: OID parsing stuff */
return SUCCESS;
}
/**
* Read a bitstring
*/
status_t read_bitstring(private_der_decoder_t *this, chunk_t data)
{
/* TODO: cleanly determine amount of unused bits */
/* skip "unused-bits-in-following-byte"-byte */
data.ptr += 1;
data.len -= 1;
if (data.len < 1)
{
return FAILED;
}
chunk_t *chunk = (chunk_t*)((u_int8_t*)this->output + this->rule->data_offset);
*chunk = allocator_clone_chunk(data);
this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "ASN1_BITSTRING", data);
return SUCCESS;
}
/**
* Read any type which appears in a chunk
*/
status_t read_any(private_der_decoder_t *this, chunk_t data)
{
chunk_t *chunk = (chunk_t*)((u_int8_t*)this->output + this->rule->data_offset);
*chunk = allocator_clone_chunk(data);
this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "ASN1_ANY", data);
return SUCCESS;
}
/**
* Read the length field of a type
*/
u_int32_t read_length(chunk_t *data)
{
u_int8_t n;
size_t len;
if (data->len < 1)
{
return -1;
}
/* read first octet of length field */
n = *data->ptr;
data->ptr++; data->len--;
if ((n & 0x80) == 0)
{
/* single length octet */
return n;
}
/* composite length, determine number of length octets */
n &= 0x7f;
if (n > data->len)
{
/* length longer than available bytes */
return -1;
}
if (n > sizeof(len))
{
/* larger than size_t can hold */
return -1;
}
len = 0;
while (n-- > 0)
{
len = 256 * len + *data->ptr;
data->ptr++; data->len--;
}
return len;
}
/**
* Read the next field
*/
status_t read_hdr(private_der_decoder_t *this, chunk_t *data)
{
chunk_t inner;
/* TODO: Redo this that an average mid-european can understand it */
beginning:
/* advance to the next rule */
this->rule++;
this->logger->log(this->logger, CONTROL|LEVEL2, "reading rule %d %s",
this->rule - this->first_rule,
mapping_find(asn1_type_m, this->rule->type));
switch (this->rule->type)
{
case ASN1_END:
/* ignore, handled outside */
return SUCCESS;
case ASN1_CHOICE:
/* CHOICE has no type/length */
break;
default:
/* anything else has type/length */
if (data->len == 0)
{
goto beginning;
}
this->logger->log_chunk(this->logger, CONTROL|LEVEL3, "reading from:", *data);
/* read type, advance in data */
if (this->rule->type != ASN1_ANY && *(data->ptr) != this->rule->type)
{
if (this->rule->flags & ASN1_OPTIONAL)
{
goto beginning;
}
if (this->rule->flags & ASN1_DEFAULT)
{
goto beginning;
}
this->logger->log(this->logger, CONTROL|LEVEL2, "Bad byte found: %x, %x expected",
*data->ptr, this->rule->type);
return PARSE_ERROR;
}
data->ptr++;
data->len--;
/* read length, advance in data */
inner.len = read_length(data);
if (inner.len == -1)
{
this->logger->log(this->logger, CONTROL|LEVEL2, "Error reading length");
return PARSE_ERROR;
}
this->logger->log(this->logger, CONTROL|LEVEL2, "Length is %d", inner.len);
inner.ptr = data->ptr;
/* advance in data, at the size of the inner */
data->ptr += inner.len;
data->len -= inner.len;
}
/* process inner */
while (TRUE)
{
switch (this->rule->type)
{
case ASN1_INTEGER:
return read_int(this, inner);
case ASN1_BOOLEAN:
return read_bool(this, inner);
case ASN1_SEQUENCE:
case ASN1_SET:
return read_sequence(this, inner);
case ASN1_TAG_E_0:
case ASN1_TAG_E_1:
case ASN1_TAG_E_2:
case ASN1_TAG_E_3:
case ASN1_TAG_E_4:
case ASN1_TAG_E_5:
case ASN1_TAG_E_6:
case ASN1_TAG_E_7:
return read_hdr(this, &inner);
case ASN1_TAG_I_0:
case ASN1_TAG_I_1:
case ASN1_TAG_I_2:
case ASN1_TAG_I_3:
case ASN1_TAG_I_4:
case ASN1_TAG_I_5:
case ASN1_TAG_I_6:
case ASN1_TAG_I_7:
this->rule++;
continue;
case ASN1_OID:
return read_oid(this, inner);
case ASN1_CHOICE:
return read_choice(this, data);
case ASN1_NULL:
return SUCCESS;
case ASN1_ANY:
return read_any(this, inner);
case ASN1_UTCTIME:
return read_time(this, inner);
case ASN1_GENERALIZEDTIME:
return read_time(this, inner);
case ASN1_BITSTRING:
return read_bitstring(this, inner);
case ASN1_OCTETSTRING:
return read_any(this, inner);
default:
return NOT_SUPPORTED;
}
}
}
/**
* Implements der_decoder_t.decode
*/
status_t decode(private_der_decoder_t *this, chunk_t input, void *output)
{
this->rule = this->first_rule - 1;
this->output = output;
/* start parsing recursivly */
return read_hdr(this, &input);
}
/**
* Implementation of der_decoder.destroy.
*/
static void destroy(private_der_decoder_t *this)
{
this->logger->destroy(this->logger);
allocator_free(this);
}
/*
* Described in header.
*/
der_decoder_t *der_decoder_create(asn1_rule_t *rules)
{
private_der_decoder_t *this = allocator_alloc_thing(private_der_decoder_t);
/* public functions */
this->public.decode = (status_t (*) (der_decoder_t*,chunk_t,void*))decode;
this->public.destroy = (void (*) (der_decoder_t*))destroy;
this->first_rule = rules;
this->logger = logger_create("[DERDC]", CONTROL, FALSE, NULL);
return &(this->public);
}
+79
View File
@@ -0,0 +1,79 @@
/**
* @file der_decoder.h
*
* @brief Interface of der_decoder_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 DER_DECODER_H_
#define DER_DECODER_H_
#include <types.h>
#include <asn1/asn1.h>
typedef struct der_decoder_t der_decoder_t;
/**
* @brief Decode ASN1 DER encoded chunks.
*
* @b Constructors:
* - der_decoder_create()
*
* @todo A lot.
*
* @ingroup asn1
*/
struct der_decoder_t {
/**
* @brief Decode a chunk of bytes to a data structure
*
* @param der_decoder calling object
* @param input chunk of data to decode
* @param output data structure where decoded data is written
* @return
* - PARSE_ERROR
* - FAILED
* - NOT_SUPPORTED
* - or SUCCESS sometimes
*/
status_t (*decode) (der_decoder_t *this, chunk_t input, void *output);
/**
* @brief Destroys a der_decoder object.
*
* @param der_decoder calling object
*/
void (*destroy) (der_decoder_t *this);
};
/**
* @brief Create a der_decoder instance.
*
* The instance needs ASN1 rules to know how to decode
* data...
*
* @param rules set of ASN1 coding rules
* @return der_decoder_t object
*
* @ingroup ans1
*/
der_decoder_t * der_decoder_create(asn1_rule_t* rules);
#endif /* DER_DECODER_H_ */
+218
View File
@@ -0,0 +1,218 @@
/**
* @file der_encoder.c
*
* @brief Implementation of der_encoder_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 "der_encoder.h"
#include <utils/allocator.h>
#include <daemon.h>
typedef struct private_der_encoder_t private_der_encoder_t;
/**
* Private data of a der_encoder_t object.
*/
struct private_der_encoder_t {
/**
* Public interface for this signer.
*/
der_encoder_t public;
asn1_rule_t *rule;
asn1_rule_t *first_rule;
void *output;
logger_t *logger;
};
static status_t read_hdr(private_der_encoder_t *this, chunk_t *data);
static status_t read_sequence(private_der_encoder_t *this, chunk_t data)
{
while (this->rule->type != ASN1_END)
{
read_hdr(this, &data);
}
return SUCCESS;
}
static status_t read_int(private_der_encoder_t *this, chunk_t data)
{
this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "ASN1_INTEGER", data);
u_int *integ = (u_int*)((u_int8_t*)this->output + this->rule->data_offset);
*integ = 0;
while (data.len-- > 0)
{
*integ = 256 * (*integ) + *data.ptr++;
}
return SUCCESS;
}
static status_t read_mpz(private_der_encoder_t *this, chunk_t data)
{
this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "ASN1_INTEGER as mpz", data);
mpz_t *mpz = (mpz_t*)((u_int8_t*)this->output + this->rule->data_offset);
mpz_import(*mpz, data.len, 1, 1, 1, 0, data.ptr);
return SUCCESS;
}
static u_int32_t read_length(chunk_t *data)
{
u_int8_t n;
size_t len;
/* read first octet of length field */
n = *data->ptr++;
if ((n & 0x80) == 0)
{
/* single length octet */
return n;
}
/* composite length, determine number of length octets */
n &= 0x7f;
if (n > data->len)
{
/* length longer than available bytes */
return -1;
}
if (n > sizeof(len))
{
/* larger than size_t can hold */
return -1;
}
len = 0;
while (n-- > 0)
{
len = 256 * len + *data->ptr++;
}
return len;
}
static status_t read_hdr(private_der_encoder_t *this, chunk_t *data)
{
chunk_t inner;
/* advance to the next rule */
this->rule++;
if (this->rule->type == ASN1_END)
{
return SUCCESS;
}
this->logger->log(this->logger, CONTROL|LEVEL2, "reading header of rule %s",
mapping_find(asn1_type_m, this->rule->type));
this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "reading from:", *data);
/* read type, advance in data */
if (*(data->ptr) != this->rule->type)
{
this->logger->log(this->logger, CONTROL|LEVEL2, "Bad byte found (%x)", *data->ptr);
return PARSE_ERROR;
}
data->ptr++;
data->len--;
/* read length, advance in data */
inner.len = read_length(data);
if (inner.len == -1)
{
this->logger->log(this->logger, CONTROL|LEVEL2, "Error reading length");
return PARSE_ERROR;
}
this->logger->log(this->logger, CONTROL|LEVEL2, "Length is %d",
inner.len);
inner.ptr = data->ptr;
/* advance in data */
data->ptr += inner.len;
data->len -= inner.len;
/* process inner */
switch (this->rule->type)
{
case ASN1_INTEGER:
if (this->rule->flags & ASN1_MPZ)
{
read_mpz(this, inner);
}
else
{
read_int(this, inner);
}
break;
case ASN1_SEQUENCE:
read_sequence(this, inner);
break;
default:
break;
}
return SUCCESS;
}
static status_t decode(private_der_encoder_t *this, chunk_t input, void *output)
{
this->rule = this->first_rule - 1;
this->output = output;
return read_hdr(this, &input);
}
/**
* Implementation of der_encoder.destroy.
*/
static void destroy(private_der_encoder_t *this)
{
allocator_free(this);
}
/*
* Described in header.
*/
der_encoder_t *der_encoder_create(asn1_rule_t *rules)
{
private_der_encoder_t *this = allocator_alloc_thing(private_der_encoder_t);
/* public functions */
this->public.decode = (status_t (*) (der_encoder_t*,chunk_t,void*))decode;
this->public.destroy = (void (*) (der_encoder_t*))destroy;
this->first_rule = rules;
this->logger = charon->logger_manager->get_logger(charon->logger_manager, DER_DECODER);
return &(this->public);
}
+60
View File
@@ -0,0 +1,60 @@
/**
* @file der_encoder.h
*
* @brief Interface of der_encoder_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 DER_ENCODER_H_
#define DER_ENCODER_H_
#include <types.h>
typedef struct der_encoder_t der_encoder_t;
/**
* @brief Decode der_encoded bytes to usable structures.
*
* @b Constructors:
* - der_encoder_create()
*
* @ingroup asn1
*/
struct der_encoder_t {
status_t encode(der_encoder_t *this, void *input, chunk_t output);
/**
* @brief Destroys a der_encoder object.
*
* @param der_encoder calling object
*/
void (*destroy) (der_encoder_t *this);
};
/**
* @brief Create a der_encoder instance.
*
* @return der_encoder_t object
*
* @ingroup ans1
*/
der_encoder_t * der_encoder_create(asn1_rule_t *rules);
#endif /* DER_ENCODER_H_ */
+37
View File
@@ -0,0 +1,37 @@
# 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)certificate.o
$(BUILD_DIR)certificate.o : $(CRYPTO_DIR)certificate.c $(CRYPTO_DIR)certificate.h
$(CC) $(CFLAGS) -c -o $@ $<
+230
View File
@@ -0,0 +1,230 @@
/**
* @file certificate.c
*
* @brief Implementation of certificate_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 "certificate.h"
#include <daemon.h>
#include <utils/allocator.h>
#include <asn1/der_decoder.h>
typedef struct private_certificate_t private_certificate_t;
/**
* Private data of a certificate_t object.
*/
struct private_certificate_t {
/**
* Public interface for this signer.
*/
certificate_t public;
u_int version;
u_int serial;
chunk_t sign_alg;
time_t not_before;
time_t not_after;
chunk_t pubkey;
chunk_t pubkey_alg;
bool has_issuer_uid;
chunk_t issuer_uid;
bool has_subject_uid;
chunk_t subject_uid;
chunk_t tbs_cert;
chunk_t signature;
rsa_public_key_t *public_key;
};
#define OSET(x) offsetof(private_certificate_t, x)
/**
* Rules for de-/encoding of a certificate from/in ASN1
*/
static asn1_rule_t certificate_rules[] = {
{ASN1_SEQUENCE, 0, 0, 0 }, /* certificate */
{ ASN1_SEQUENCE, ASN1_RAW, OSET(tbs_cert), 0 }, /* tbsCertificate */
{ ASN1_TAG_E_0, ASN1_DEFAULT, OSET(version), 0 }, /* EXPLICIT */
{ ASN1_INTEGER, ASN1_DEFAULT, OSET(version), 0 }, /* version DEFAULT v1(0) */
{ ASN1_INTEGER, 0, OSET(serial), 0 }, /* serialNumber */
{ ASN1_SEQUENCE, 0, 0, 0 }, /* signature */
{ ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm-oid */
{ ASN1_NULL, 0, 0, 0 }, /* parameters */
{ ASN1_END, 0, 0, 0 }, /* signature */
{ ASN1_SEQUENCE, ASN1_OF, 0, 0 }, /* issuer */
// { ASN1_SET, ASN1_OF, 0, 0, }, /* RelativeDistinguishedName */
// { ASN1_SEQUENCE, 0, 0, 0, }, /* AttributeTypeAndValue */
// { ASN1_OID, 0, 0, 0 }, /* AttributeType */
// { ASN1_ANY, 0, 0, 0 }, /* AttributeValue */
// { ASN1_END, 0, 0, 0 }, /* AttributeTypeAndValue */
// { ASN1_END, 0, 0, 0 }, /* RelativeDistinguishedName */
{ ASN1_END, 0, 0, 0 }, /* issuer */
{ ASN1_SEQUENCE, 0, 0, 0 }, /* validity */
{ ASN1_CHOICE, 0, 0, 0 }, /* notBefore */
{ ASN1_UTCTIME, 0, OSET(not_before), 0 }, /* utcTime */
{ ASN1_GENERALIZEDTIME, 0, OSET(not_before), 0 }, /* generalTime */
{ ASN1_END, 0, 0, 0 }, /* notBefore */
{ ASN1_CHOICE, 0, 0, 0 }, /* notAfter */
{ ASN1_UTCTIME, 0, OSET(not_after), 0 }, /* utcTime */
{ ASN1_GENERALIZEDTIME, 0, OSET(not_after), 0 }, /* generalTime */
{ ASN1_END, 0, 0, 0 }, /* notAfter */
{ ASN1_END, 0, 0, 0 }, /* validity */
{ ASN1_SEQUENCE, ASN1_OF, 0, 0 }, /* subject */
// { ASN1_SET, ASN1_OF, 0, 0, }, /* RelativeDistinguishedName */
// { ASN1_SEQUENCE, 0, 0, 0, }, /* AttributeTypeAndValue */
// { ASN1_OID, 0, 0, 0 }, /* AttributeType */
// { ASN1_ANY, 0, 0, 0 }, /* AttributeValue */
// { ASN1_END, 0, 0, 0 }, /* AttributeTypeAndValue */
// { ASN1_END, 0, 0, 0 }, /* RelativeDistinguishedName */
{ ASN1_END, 0, 0, 0 }, /* subject */
{ ASN1_SEQUENCE, 0, 0, 0 }, /* subjectPublicKeyInfo */
{ ASN1_SEQUENCE, 0, 0, 0 }, /* algorithm */
{ ASN1_OID, 0, OSET(pubkey_alg), 0 }, /* algorithm-oid */
{ ASN1_NULL, 0, 0, 0 }, /* parameters */
{ ASN1_END, 0, 0, 0 }, /* algorithm */
{ ASN1_BITSTRING, 0, OSET(pubkey), 0 }, /* subjectPublicKey */
{ ASN1_END, 0, 0, 0 }, /* subjectPublicKeyInfo */
{ ASN1_TAG_I_1, ASN1_OPTIONAL, 0, OSET(has_issuer_uid)}, /* IMPLICIT */
{ ASN1_BITSTRING, ASN1_OPTIONAL, OSET(issuer_uid), 0 }, /* issuerUniqueID OPTIONAL */
{ ASN1_TAG_I_2, ASN1_OPTIONAL, 0, OSET(has_subject_uid)},/* IMPLICIT */
{ ASN1_BITSTRING, ASN1_OPTIONAL, OSET(subject_uid), 0 }, /* subjectUniqueID OPTIONAL */
{ ASN1_TAG_E_3, ASN1_OPTIONAL, 0, 0 }, /* EXPLICIT */
{ ASN1_SEQUENCE, ASN1_OF|ASN1_OPTIONAL, 0, 0 }, /* extensions OPTIONAL */
// { ASN1_SEQUENCE, 0, 0, 0, }, /* extension */
// { ASN1_OID, 0, 0, 0 }, /* extnID */
// { ASN1_BOOLEAN, ASN1_DEFAULT, 0, FALSE }, /* critical */
// { ASN1_OCTETSTRING, 0, 0, 0, }, /* extnValue */
// { ASN1_END, 0, 0, 0, }, /* extension */
{ ASN1_END, 0, 0, 0, }, /* extensions */
{ ASN1_END, 0, 0, 0 }, /* tbsCertificate */
{ ASN1_SEQUENCE, 0, 0, 0 }, /* signatureAlgorithm */
{ ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm-oid */
{ ASN1_NULL, 0, 0, 0 }, /* parameters */
{ ASN1_END, 0, 0, 0 }, /* signatureAlgorithm */
{ ASN1_BITSTRING, 0, OSET(signature), 0 }, /* signatureValue */
{ASN1_END, 0, 0, 0 }, /* certificate */
};
/**
* Implementation of certificate.get_public_key.
*/
static rsa_public_key_t *get_public_key(private_certificate_t *this)
{
return this->public_key->clone(this->public_key);
}
/**
* Implementation of certificate.destroy.
*/
static void destroy(private_certificate_t *this)
{
this->public_key->destroy(this->public_key);
allocator_free(this->pubkey.ptr);
allocator_free(this->signature.ptr);
allocator_free(this->tbs_cert.ptr);
allocator_free(this);
}
/*
* Described in header.
*/
certificate_t *certificate_create_from_chunk(chunk_t chunk)
{
private_certificate_t *this = allocator_alloc_thing(private_certificate_t);
der_decoder_t *dd;
/* public functions */
this->public.get_public_key = (rsa_public_key_t *(*) (certificate_t*))get_public_key;
this->public.destroy = (void (*) (certificate_t*))destroy;
/* initialize */
this->pubkey = CHUNK_INITIALIZER;
this->signature = CHUNK_INITIALIZER;
this->tbs_cert = CHUNK_INITIALIZER;
dd = der_decoder_create(certificate_rules);
if (dd->decode(dd, chunk, this) != SUCCESS)
{
allocator_free(this);
dd->destroy(dd);
return NULL;
}
dd->destroy(dd);
this->public_key = rsa_public_key_create_from_chunk(this->pubkey);
if (this->public_key == NULL)
{
allocator_free(this->pubkey.ptr);
allocator_free(this);
return NULL;
}
return &this->public;
}
/*
* Described in header.
*/
certificate_t *certificate_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 certificate_create_from_chunk(chunk);
}
+70
View File
@@ -0,0 +1,70 @@
/**
* @file certificate.h
*
* @brief Interface of certificate_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 CERTIFICATE_H_
#define CERTIFICATE_H_
#include <types.h>
#include <definitions.h>
#include <crypto/rsa/rsa_public_key.h>
typedef struct certificate_t certificate_t;
/**
* @brief X509 certificate.
*
* @b Constructors:
* - certificate_create_from_chunk()
*
* @ingroup transforms
*/
struct certificate_t {
/**
* @brief Get the RSA public key from the certificate.
*
* @param this calling object
* @return public_key
*/
rsa_public_key_t *(*get_public_key) (certificate_t *this);
/**
* @brief Destroys the private key.
*
* @param this private key to destroy
*/
void (*destroy) (certificate_t *this);
};
/**
* @brief Read a certificate from a blob.
*
* @return created certificate_t.
*
* @ingroup transforms
*/
certificate_t *certificate_create_from_chunk(chunk_t chunk);
certificate_t *certificate_create_from_file(char *filename);
#endif /* CERTIFICATE_H_ */
@@ -0,0 +1,23 @@
# 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
@@ -0,0 +1,61 @@
/**
* @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_ */
+63
View File
@@ -0,0 +1,63 @@
/**
* @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;
}
}
+153
View File
@@ -0,0 +1,153 @@
/**
* @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_*/
+616
View File
@@ -0,0 +1,616 @@
/**
* @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/allocator.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);
}
allocator_free(this);
}
/*
* Described in header.
*/
diffie_hellman_t *diffie_hellman_create(diffie_hellman_group_t dh_group_number)
{
private_diffie_hellman_t *this = allocator_alloc_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)
{
allocator_free(this);
return NULL;
}
randomizer = randomizer_create();
if (randomizer == NULL)
{
allocator_free(this);
return NULL;
}
if (randomizer->allocate_pseudo_random_bytes(randomizer, this->modulus_length, &random_bytes) != SUCCESS)
{
randomizer->destroy(randomizer);
allocator_free(this);
return NULL;
}
mpz_import(this->my_private_value, random_bytes.len, 1, 1, 1, 0, random_bytes.ptr);
allocator_free_chunk(&random_bytes);
randomizer->destroy(randomizer);
this->compute_public_value(this);
this->shared_secret_is_computed = FALSE;
return &(this->public);
}
+149
View File
@@ -0,0 +1,149 @@
/**
* @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_*/
@@ -0,0 +1,27 @@
# 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 $@ $<
+60
View File
@@ -0,0 +1,60 @@
/**
* @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;
}
}
+147
View File
@@ -0,0 +1,147 @@
/**
* @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 block size of this hashing function.
*
* @param this calling object
* @return block size in bytes
*/
size_t (*get_block_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_*/
+393
View File
@@ -0,0 +1,393 @@
/**
* @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 "md5_hasher.h"
#include <definitions.h>
#include <utils/allocator.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 = allocator_alloc(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_block_size.
*/
static size_t get_block_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)
{
allocator_free(this);
}
/*
* Described in header.
*/
md5_hasher_t *md5_hasher_create()
{
private_md5_hasher_t *this = allocator_alloc_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_block_size = (size_t (*) (hasher_t*))get_block_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);
}
+60
View File
@@ -0,0 +1,60 @@
/**
* @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();
#endif /*MD5_HASHER_H_*/
+268
View File
@@ -0,0 +1,268 @@
/**
* @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 "sha1_hasher.h"
#include <definitions.h>
#include <utils/allocator.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 = allocator_alloc(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_block_size.
*/
static size_t get_block_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)
{
allocator_free(this);
}
/*
* Described in header.
*/
sha1_hasher_t *sha1_hasher_create()
{
private_sha1_hasher_t *this = allocator_alloc_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_block_size = (size_t (*) (hasher_t*))get_block_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);
}
+60
View File
@@ -0,0 +1,60 @@
/**
* @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();
#endif /*SHA1_HASHER_H_*/
+210
View File
@@ -0,0 +1,210 @@
/**
* @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 "hmac.h"
#include <utils/allocator.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_block_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_block_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_block_size(this->h);
out->ptr = allocator_alloc(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_block_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);
allocator_free(this->opaded_key.ptr);
allocator_free(this->ipaded_key.ptr);
allocator_free(this);
}
/*
* Described in header
*/
hmac_t *hmac_create(hash_algorithm_t hash_algorithm)
{
private_hmac_t *this;
this = allocator_alloc_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:
allocator_free(this);
return NULL;
}
/* build the hasher */
this->h = hasher_create(hash_algorithm);
/* build ipad and opad */
this->opaded_key.ptr = allocator_alloc(this->b);
this->opaded_key.len = this->b;
this->ipaded_key.ptr = allocator_alloc(this->b);
this->ipaded_key.len = this->b;
return &(this->hmac);
}
+118
View File
@@ -0,0 +1,118 @@
/**
* @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_*/
+157
View File
@@ -0,0 +1,157 @@
/**
* @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 "prf_plus.h"
#include <utils/allocator.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 = allocator_alloc(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)
{
allocator_free(this->buffer.ptr);
allocator_free(this->seed.ptr);
allocator_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 = allocator_alloc_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 = allocator_alloc(this->buffer.len);
this->appending_octet = 0x01;
/* clone seed */
this->seed.ptr = allocator_clone_bytes(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);
}
+93
View File
@@ -0,0 +1,93 @@
/**
* @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_*/
+23
View File
@@ -0,0 +1,23 @@
# 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 $@ $<
+118
View File
@@ -0,0 +1,118 @@
/**
* @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 <utils/allocator.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)
{
allocator_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 = allocator_alloc_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)
{
allocator_free(this);
return NULL;
}
return &(this->public);
}
+64
View File
@@ -0,0 +1,64 @@
/**
* @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_*/
+67
View File
@@ -0,0 +1,67 @@
/**
* @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;
}
}
+136
View File
@@ -0,0 +1,136 @@
/**
* @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_*/
+23
View File
@@ -0,0 +1,23 @@
# 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 $@ $<
+615
View File
@@ -0,0 +1,615 @@
/**
* @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 "rsa_private_key.h"
#include <daemon.h>
#include <utils/allocator.h>
#include <asn1/der_decoder.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);
};
/**
* Rules for de-/encoding of a private key from/in ASN1
*/
static asn1_rule_t rsa_private_key_rules[] = {
{ASN1_SEQUENCE, 0, 0, 0},
{ ASN1_INTEGER, 0, offsetof(private_rsa_private_key_t, version), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, n), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, e), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, d), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, p), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, q), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, exp1), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, exp2), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_private_key_t, coeff), 0},
{ASN1_END, 0, 0, 0},
};
static private_rsa_private_key_t *rsa_private_key_create_empty();
/**
* 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);
allocator_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 = allocator_alloc(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);
allocator_free(hash.ptr);
allocator_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 = allocator_alloc(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);
allocator_free(n.ptr);
allocator_free(e.ptr);
allocator_free(p.ptr);
allocator_free(q.ptr);
allocator_free(d.ptr);
allocator_free(exp1.ptr);
allocator_free(exp2.ptr);
allocator_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;
}
/**
* 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);
allocator_free(this);
}
/**
* Internal generic constructor
*/
static private_rsa_private_key_t *rsa_private_key_create_empty()
{
private_rsa_private_key_t *this = allocator_alloc_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)
{
allocator_free(this);
return NULL;
}
if (this->compute_prime(this, key_size/2, &q) != SUCCESS)
{
mpz_clear(p);
allocator_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 chunk)
{
private_rsa_private_key_t *this;
der_decoder_t *dd;
status_t status;
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);
dd = der_decoder_create(rsa_private_key_rules);
status = dd->decode(dd, chunk, this);
dd->destroy(dd);
if (status != SUCCESS)
{
destroy(this);
return NULL;
}
this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
return &this->public;
}
/*
* see header
*/
rsa_private_key_t *rsa_private_key_create_from_file(char *filename, char *passphrase)
{
chunk_t chunk;
struct stat stb;
FILE *file;
char *buffer;
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_private_key_create_from_chunk(chunk);
}
+185
View File
@@ -0,0 +1,185 @@
/**
* @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_*/
+468
View File
@@ -0,0 +1,468 @@
/**
* @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 "rsa_public_key.h"
#include <daemon.h>
#include <utils/allocator.h>
#include <crypto/hashers/hasher.h>
#include <asn1/der_decoder.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.
*/
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
};
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;
};
/**
* Rules for de-/encoding of a public key from/in ASN1
*/
static asn1_rule_t rsa_public_key_rules[] = {
{ASN1_SEQUENCE, 0, 0, 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_public_key_t, n), 0},
{ ASN1_INTEGER, ASN1_MPZ, offsetof(private_rsa_public_key_t, e), 0},
{ASN1_END, 0, 0, 0},
};
/**
* Rules for de-/encoding of a PublicKeyInfo from/in ASN1
*/
static asn1_rule_t rsa_public_key_info_rules[] = {
{ASN1_SEQUENCE, 0, 0, 0},
{ ASN1_SEQUENCE, 0, 0, 0},
{ ASN1_OID, 0, offsetof(rsa_public_key_info_t, algorithm_oid), 0},
{ ASN1_NULL, 0, 0, 0},
{ ASN1_END, 0, 0, 0},
{ ASN1_BITSTRING, 0, offsetof(rsa_public_key_info_t, public_key), 0},
{ASN1_END, 0, 0, 0},
};
private_rsa_public_key_t *rsa_public_key_create_empty();
/**
* 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))
{
allocator_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 ?!*/
allocator_free(em.ptr);
return FAILED;
}
pos++;
}
if (pos + 20 > em.ptr + em.len)
{
/* not enought room for oid compare */
allocator_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 */
allocator_free(em.ptr);
return NOT_SUPPORTED;
}
if (pos + hasher->get_block_size(hasher) != em.ptr + em.len)
{
/* bad length */
allocator_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 */
allocator_free(hash.ptr);
allocator_free(em.ptr);
return FAILED;
}
/* seems good */
allocator_free(hash.ptr);
allocator_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 = allocator_alloc(key->len);
memcpy(key->ptr, n.ptr, n.len);
memcpy(key->ptr + n.len, e.ptr, e.len);
allocator_free(n.ptr);
allocator_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);
allocator_free(this);
}
/**
* Generic private constructor
*/
private_rsa_public_key_t *rsa_public_key_create_empty()
{
private_rsa_public_key_t *this = allocator_alloc_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 chunk)
{
der_decoder_t *dd;
status_t status;
private_rsa_public_key_t *this;
this = rsa_public_key_create_empty();
mpz_init(this->n);
mpz_init(this->e);
dd = der_decoder_create(rsa_public_key_rules);
status = dd->decode(dd, chunk, this);
dd->destroy(dd);
if (status != SUCCESS)
{
destroy(this);
return NULL;
}
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;
rsa_public_key_info_t key_info = {CHUNK_INITIALIZER, CHUNK_INITIALIZER};
der_decoder_t *dd;
status_t status;
rsa_public_key_t *public_key = NULL;
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;
/* parse public key info first */
dd = der_decoder_create(rsa_public_key_info_rules);
status = dd->decode(dd, chunk, &key_info);
dd->destroy(dd);
allocator_free_chunk(&key_info.algorithm_oid);
if (status == SUCCESS)
{
public_key = rsa_public_key_create_from_chunk(chunk);
}
allocator_free_chunk(&key_info.public_key);
return public_key;
}
+153
View File
@@ -0,0 +1,153 @@
/**
* @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_*/
@@ -0,0 +1,23 @@
# 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 $@ $<
+168
View File
@@ -0,0 +1,168 @@
/**
* @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 "hmac_signer.h"
#include <utils/allocator.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 = allocator_alloc(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);
allocator_free(this);
return SUCCESS;
}
/*
* Described in header
*/
hmac_signer_t *hmac_signer_create(hash_algorithm_t hash_algoritm)
{
private_hmac_signer_t *this = allocator_alloc_thing(private_hmac_signer_t);
this->hmac_prf = (prf_t *) hmac_prf_create(hash_algoritm);
if (this->hmac_prf == NULL)
{
/* algorithm not supported */
allocator_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);
}
+58
View File
@@ -0,0 +1,58 @@
/**
* @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_*/
+59
View File
@@ -0,0 +1,59 @@
/**
* @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;
}
}
+147
View File
@@ -0,0 +1,147 @@
/**
* @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_*/
+40
View File
@@ -0,0 +1,40 @@
/**
* @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";
}
+239
View File
@@ -0,0 +1,239 @@
/**
* @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
/**
* @defgroup config config
*
* Classes implementing configuration related things.
*/
/**
* @defgroup encoding encoding
*
* Classes used to encode and decode IKEv2 messages.
*/
/**
* @defgroup network network
*
* Classes for network relevant stuff.
*/
/**
* @defgroup payloads payloads
*
* Classes representing specific IKEv2 payloads.
*
* @ingroup encoding
*/
/**
* @defgroup sa sa
*
* Security association and helper classes.
*/
/**
* @defgroup states states
*
* Varius states in which an IKE SA can be.
*
* @ingroup sa
*/
/**
* @defgroup queues queues
*
* Different kind of queues.
*/
/**
* @defgroup jobs jobs
*
* Jobs used in job queue and event queue.
*
* @ingroup queues
*/
/**
* @defgroup testcases testcases
*
* Testcases used to test the different classes in seperate module tests.
*/
/**
* @defgroup transforms transforms
*
* Transform algorithms of different kind.
*/
/**
* @defgroup rsa rsa
*
* RSA public key algorithm.
*
* @ingroup transforms
*/
/**
* @defgroup prfs prfs
*
* Pseudo random functions.
*
* @ingroup transforms
*/
/**
* @defgroup signers signers
*
* Symmetric signing algorithms, used to ensure message integrity.
*
* @ingroup transforms
*/
/**
* @defgroup crypters crypters
*
* Symmetric encryption algorithms, used to encrypt and decrypt.
*
* @ingroup transforms
*/
/**
* @defgroup hashers hashers
*
* Hashing algorithms.
*
* @ingroup transforms
*/
/**
* @defgroup asn1 asn1
*
* ASN1 structure definition, en-/decoder of for DER
*
* @todo Implement a der_encoder_t class.
*/
/**
* @defgroup utils utils
*
* Generic helper classes.
*/
/**
* @defgroup threads threads
*
* Threaded classes, which will do their job alone.
*/
/**
* 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__)
/**
* Papping 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_*/
+48
View File
@@ -0,0 +1,48 @@
/**
* @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 "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};
+155
View File
@@ -0,0 +1,155 @@
/**
* @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>
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;
/**
* General purpose boolean type.
*/
typedef int bool;
#define FALSE 0
#define TRUE 1
#endif /*TYPES_H_*/
+48
View File
@@ -0,0 +1,48 @@
# 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)allocator.o
$(BUILD_DIR)allocator.o : $(UTILS_DIR)allocator.c $(UTILS_DIR)allocator.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 $@ $<
+445
View File
@@ -0,0 +1,445 @@
/**
* @file allocator.c
*
* @brief Implementation of allocator_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 <stddef.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <gmp.h>
#include "allocator.h"
#ifdef LEAK_DETECTIVE
typedef union memory_hdr_t memory_hdr_t;
/**
* @brief Header of each allocated memory area.
*
* Ideas stolen from pluto's defs.c.
*
* Used to detect memory leaks.
*/
union memory_hdr_t {
/**
* Informations.
*/
struct {
/**
* Filename withing memory was allocated.
*/
const char *filename;
/**
* Line number in given file.
*/
size_t line;
/**
* Allocated memory size. Needed for reallocation.
*/
size_t size_of_memory;
/**
* Link to the previous and next memory area.
*/
memory_hdr_t *older, *newer;
} info;
/**
* Force maximal alignment ?
*
*/
unsigned long junk;
};
typedef struct private_allocator_t private_allocator_t;
/**
* @brief Private allocator_t object.
*
* Contains private variables of allocator_t object.
*/
struct private_allocator_t
{
/**
* Public part of an allocator_t object.
*/
allocator_t public;
/**
* Global list of allocations.
*
* Thread-save through mutex.
*/
memory_hdr_t *allocations;
/**
* Mutex used to make sure, all functions are thread-save.
*/
pthread_mutex_t mutex;
/**
* Number of allocations done
*/
u_int32_t allocs;
/**
* Number of frees done
*/
u_int32_t frees;
/**
* Allocates memory with LEAK_DETECTION and
* returns an empty data area filled with zeros.
*
* @param this private_allocator_t object
* @param bytes number of bytes to allocate
* @param file filename from which the memory is allocated
* @param line line number in specific file
* @param use_mutex if FALSE no mutex is used for allocation
* @return pointer to allocated memory area
*/
void * (*allocate_special) (private_allocator_t *this,size_t bytes, char * file,int line, bool use_mutex);
};
/**
* Implementation of private_allocator_t.allocate_special.
*/
static void *allocate_special(private_allocator_t *this,size_t bytes, char * file,int line, bool use_mutex)
{
memory_hdr_t *allocated_memory = malloc(sizeof(memory_hdr_t) + bytes);
this->allocs++;
if (allocated_memory == NULL)
{
/* TODO LOG this case */
exit(-1);
}
if (use_mutex)
{
pthread_mutex_lock( &(this->mutex));
}
allocated_memory->info.line = line;
allocated_memory->info.filename = file;
allocated_memory->info.size_of_memory = bytes;
allocated_memory->info.older = this->allocations;
if (this->allocations != NULL)
{
this->allocations->info.newer = allocated_memory;
}
this->allocations = allocated_memory;
allocated_memory->info.newer = NULL;
/* fill memory with zero's */
memset(allocated_memory+1, '\0', bytes);
if (use_mutex)
{
pthread_mutex_unlock(&(this->mutex));
}
/* real memory starts after header */
return (allocated_memory+1);
}
/**
* Implementation of allocator_t.allocate.
*/
static void * allocate(allocator_t *allocator,size_t bytes, char * file,int line)
{
private_allocator_t *this = (private_allocator_t *) allocator;
return (this->allocate_special(this,bytes, file,line,TRUE));
}
/**
* Implementation of allocator_t.allocate_as_chunk.
*/
static chunk_t allocate_as_chunk(allocator_t *allocator,size_t bytes, char * file,int line)
{
private_allocator_t *this = (private_allocator_t *) allocator;
chunk_t new_chunk;
new_chunk.ptr = this->allocate_special(this,bytes, file,line,TRUE);
new_chunk.len = (new_chunk.ptr == NULL) ? 0 : bytes;
return new_chunk;
}
/**
* Implementation of allocator_t.free_pointer.
*/
static void free_pointer(allocator_t *allocator, void * pointer)
{
private_allocator_t *this = (private_allocator_t *) allocator;
memory_hdr_t *allocated_memory;
if (pointer == NULL)
{
return;
}
this->frees++;
pthread_mutex_lock( &(this->mutex));
allocated_memory = ((memory_hdr_t *)pointer) - 1;
if (allocated_memory->info.older != NULL)
{
assert(allocated_memory->info.older->info.newer == allocated_memory);
allocated_memory->info.older->info.newer = allocated_memory->info.newer;
}
if (allocated_memory->info.newer == NULL)
{
assert(allocated_memory == this->allocations);
this->allocations = allocated_memory->info.older;
}
else
{
assert(allocated_memory->info.newer->info.older == allocated_memory);
allocated_memory->info.newer->info.older = allocated_memory->info.older;
}
pthread_mutex_unlock(&(this->mutex));
free(allocated_memory);
}
/**
* Implementation of allocator_t.reallocate.
*/
static void * reallocate(allocator_t *allocator, void * old, size_t bytes, char * file,int line)
{
private_allocator_t *this = (private_allocator_t *) allocator;
memory_hdr_t *allocated_memory;
pthread_mutex_lock( &(this->mutex));
allocated_memory = ((memory_hdr_t *)old) - 1;
void *new_space = this->allocate_special(this,bytes,file,line,FALSE);
if (old != NULL)
{
/* the smaller size is copied to avoid overflows */
memcpy(new_space,old,(allocated_memory->info.size_of_memory < bytes) ? allocated_memory->info.size_of_memory : bytes);
}
pthread_mutex_unlock(&(this->mutex));
this->public.free_pointer(&(this->public),old);
return new_space;
}
/**
* Implementation of allocator_t.clone_bytes.
*/
static void * clone_bytes(allocator_t *allocator,void * to_clone, size_t bytes, char * file, int line)
{
private_allocator_t *this = (private_allocator_t *) allocator;
if (to_clone == NULL)
{
return NULL;
}
void *new_space = this->allocate_special(this,bytes,file,line,TRUE);
if (new_space == NULL)
{
return NULL;
}
memcpy(new_space,to_clone,bytes);
return new_space;
}
/**
* Implementation of allocator_t.clone_chunk.
*/
static chunk_t clone_chunk(allocator_t *allocator, chunk_t chunk, char * file, int line)
{
private_allocator_t *this = (private_allocator_t *) allocator;
chunk_t clone = CHUNK_INITIALIZER;
if (chunk.ptr && chunk.len > 0)
{
clone.ptr = this->allocate_special(this,chunk.len,file,line,TRUE);
clone.len = chunk.len;
memcpy(clone.ptr, chunk.ptr, chunk.len);
}
return clone;
}
/**
* Implementation of allocator_t.allocator_report_memory_leaks.
*/
static void allocator_report_memory_leaks(allocator_t *allocator)
{
private_allocator_t *this = (private_allocator_t *) allocator;
memory_hdr_t *p = this->allocations;
memory_hdr_t *pprev = NULL;
unsigned long n = 0;
pthread_mutex_lock(&(this->mutex));
while (p != NULL)
{
assert(pprev == p->info.newer);
pprev = p;
p = p->info.older;
n++;
if (p == NULL || pprev->info.filename != p->info.filename)
{
if (n != 1)
fprintf(stderr,"LEAK: \"%lu * %s, line %d\"\n", n, pprev->info.filename,pprev->info.line);
else
fprintf(stderr,"LEAK: \"%s, line %d\"\n", pprev->info.filename,pprev->info.line);
n = 0;
}
}
pthread_mutex_unlock( &(this->mutex));
fprintf(stderr, "Allocator statistics: %d allocs, %d frees\n", this->allocs, this->frees);
}
/**
* Only Initiation of allocator object.
*
* All allocation macros use this object.
*/
static private_allocator_t allocator = {
public: {allocate: allocate,
allocate_as_chunk: allocate_as_chunk,
free_pointer: free_pointer,
reallocate: reallocate,
clone_bytes : clone_bytes,
clone_chunk : clone_chunk,
report_memory_leaks: allocator_report_memory_leaks},
allocations: NULL,
allocate_special : allocate_special,
mutex: PTHREAD_MUTEX_INITIALIZER,
allocs: 0,
frees: 0
};
allocator_t *global_allocator = &(allocator.public);
/*
* Alloc function for gmp.
*/
void *gmp_alloc(size_t bytes)
{
return allocator.allocate_special(&allocator, bytes, "[ gmp internal ]", 0 , TRUE);
}
/*
* Realloc function for gmp.
*/
void *gmp_realloc(void *old, size_t old_bytes, size_t new_bytes)
{
return global_allocator->reallocate(global_allocator, old, new_bytes, "[ gmp internal ]", 0);
}
/*
* Free function for gmp.
*/
void gmp_free(void *ptr, size_t bytes)
{
free_pointer(global_allocator, ptr);
}
/*
* Described in header
*/
void allocator_init()
{
mp_set_memory_functions (gmp_alloc, gmp_realloc, gmp_free);
}
#else /* !LEAK_DETECTION */
/*
* Described in header.
*/
chunk_t allocator_alloc_as_chunk(size_t bytes)
{
chunk_t new_chunk;
new_chunk.ptr = malloc(bytes);
if (new_chunk.ptr == NULL)
{
exit(-1);
}
new_chunk.len = bytes;
return new_chunk;
}
/*
* Described in header.
*/
void * allocator_realloc(void * old, size_t newsize)
{
void *data = realloc(old,newsize);
return data;
}
/*
* Described in header.
*/
void * allocator_clone_bytes(void * pointer, size_t size)
{
void *data;
data = malloc(size);
if (data == NULL){exit(-1);}
memmove(data,pointer,size);
return (data);
}
/**
* Described in header.
*/
chunk_t allocator_clone_chunk(chunk_t chunk)
{
chunk_t clone = CHUNK_INITIALIZER;
if (chunk.ptr && chunk.len > 0)
{
clone.ptr = malloc(chunk.len);
if (clone.ptr == NULL) {exit(-1);}
clone.len = chunk.len;
memcpy(clone.ptr, chunk.ptr, chunk.len);
}
return clone;
}
/*
* Described in header.
*/
void allocator_free_chunk(chunk_t *chunk)
{
free(chunk->ptr);
chunk->ptr = NULL;
chunk->len = 0;
}
#endif /* LEAK_DETECTION */
+324
View File
@@ -0,0 +1,324 @@
/**
* @file allocator.h
*
* @brief Interface of allocator_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 ALLOCATOR_H_
#define ALLOCATOR_H_
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <types.h>
/**
* Macro to allocate a special type.
*
* @param thing object on which a sizeof is performed
* @return pointer to allocated memory
*
* @ingroup utils
*/
#define allocator_alloc_thing_as_chunk(thing) (allocator_alloc_as_chunk(sizeof(thing)))
/**
* Macro to allocate a special type as chunk_t.
*
* @param thing object on which a sizeof is performed
* @return chunk_t pointing to allocated memory
*
* @ingroup utils
*/
#define allocator_alloc_thing(thing) (allocator_alloc(sizeof(thing)))
#ifdef LEAK_DETECTIVE
typedef struct allocator_t allocator_t;
/**
*@brief Allocater object use to detect memory leaks.
*
* @ingroup utils
*/
struct allocator_t {
/**
* Allocates memory with LEAK_DETECTION and
* returns an empty data area filled with zeros.
*
* @warning Use this function not directly, only with assigned macros
* #allocator_alloc and #allocator_alloc_thing.
*
* @param this allocator_t object
* @param bytes number of bytes to allocate
* @param file filename from which the memory is allocated
* @param line line number in specific file
* @return pointer to allocated memory area
*/
void * (*allocate) (allocator_t *this,size_t bytes, char * file,int line);
/**
* Allocates memory with LEAK_DETECTION and
* returns an chunk pointing to an empy data area filled with zeros.
*
* @warning Use this function not directly, only with assigned
* macros #allocator_alloc_as_chunk and
* #allocator_alloc_thing_as_chunk.
*
* @param this allocator_t object
* @param bytes number of bytes to allocate
* @param file filename from which the memory is allocated
* @param line line number in specific file
* @return pointer to allocated memory area
*/
chunk_t (*allocate_as_chunk) (allocator_t *this,size_t bytes, char * file,int line);
/**
* Reallocates memory with LEAK_DETECTION and
* returns an empty data area filled with zeros.
*
* @warning Use this function not directly, only with assigned macro
* #allocator_realloc.
*
* @param this allocator_t object
* @param old pointer to the old data area
* @param bytes number of bytes to allocate
* @param file filename from which the memory is allocated
* @param line line number in specific file
* @return pointer to reallocated memory area
*/
void * (*reallocate) (allocator_t *this,void * old, size_t bytes, char * file, int line);
/**
* Clones memory with LEAK_DETECTION and returns a cloned data area.
*
* @warning Use this function not directly, only with assigned macro
* #allocator_clone_bytes.
*
* @param this allocator_t object
* @param old pointer to the old data area
* @param bytes number of bytes to allocate
* @param file filename from which the memory is allocated
* @param line line number in specific file
* @return pointer to reallocated memory area
*/
void * (*clone_bytes) (allocator_t *this,void * to_clone, size_t bytes, char * file, int line);
/**
* Clones a chunk with LEAK_DETECTION and returns a cloned chunk.
*
* @warning Use this function not directly, only with assigned macro
* #allocator_clone_chunk-
*
* @param this allocator_t object
* @param chunk chunk to clone
* @param file filename from which the memory is allocated
* @param line line number in specific file
* @return pointer to reallocated memory
*/
chunk_t (*clone_chunk) (allocator_t *this, chunk_t chunk, char * file, int line);
/**
* Frees memory with LEAK_DETECTION.
*
* @warning Use this function not directly, only with assigned macro
* #allocator_free.
*
* @param this allocator_t object
* @param pointer pointer to the data area to free
*/
void (*free_pointer) (allocator_t *this,void * pointer);
/**
* Report memory leaks to stderr.
*
* @warning Use this function not directly, only with assigned macro
* #report_memory_leaks
*
* @param this allocator_t object
*/
void (*report_memory_leaks) (allocator_t *this);
};
/**
* @brief Initialize the allocator.
*
* Setup the allocator (set allocation functions for libgmp)
*/
void allocator_init();
/**
* @brief Global allocater_t object.
*
* Only accessed over macros.
*/
extern allocator_t *global_allocator;
/**
* Macro to allocate some memory.
*
* See #allocator_t.allocate for description.
*
* @ingroup utils
*/
#define allocator_alloc(bytes) (global_allocator->allocate(global_allocator,bytes,__FILE__,__LINE__))
/**
* Macro to allocate some memory for a chunk_t.
*
* See #allocator_t.allocate_as_chunk for description.
*
* @ingroup utils
*/
#define allocator_alloc_as_chunk(bytes) (global_allocator->allocate_as_chunk(global_allocator,bytes,__FILE__,__LINE__))
/**
* Macro to reallocate some memory.
*
* See #allocator_t.reallocate for description.
*
* @ingroup utils
*/
#define allocator_realloc(old,bytes) (global_allocator->reallocate(global_allocator,old,bytes,__FILE__, __LINE__))
/**
* Macro to clone some memory.
*
* See #allocator_t.*clone_bytes for description.
*
* @ingroup utils
*/
#define allocator_clone_bytes(old,bytes) (global_allocator->clone_bytes(global_allocator,old,bytes,__FILE__, __LINE__))
/**
* Macro to clone a chunk and its contents
*
* See #allocator_t.clone_chunk for description.
*
* @ingroup utils
*/
#define allocator_clone_chunk(chunk) (global_allocator->clone_chunk(global_allocator,chunk,__FILE__, __LINE__))
/**
* Macro to free some memory.
*
* See #allocator_t.free_pointer for description.
*
* @ingroup utils
*/
#define allocator_free(pointer) (global_allocator->free_pointer(global_allocator,pointer))
/**
* Macro to free a chunk.
*/
#define allocator_free_chunk(chunk){ \
global_allocator->free_pointer(global_allocator,(chunk)->ptr); \
(chunk)->ptr = NULL; \
(chunk)->len = 0; \
}
/**
* Macro to report memory leaks.
*
* See #allocator_s.report_memory_leaks for description.
*
* @ingroup utils
*/
#define report_memory_leaks(void) (global_allocator->report_memory_leaks(global_allocator))
#else
/**
* Macro to allocate some memory.
*
* @ingroup utils
*/
#define allocator_alloc(bytes) (malloc(bytes))
/**
* Allocate some memory as chunk.
*
* @ingroup utils
*/
chunk_t allocator_alloc_as_chunk(size_t bytes);
/**
* Reallocate some memory.
*
* @ingroup utils
*/
void * allocator_realloc(void * old, size_t newsize);
/**
* Free allocated memory.
*
* @ingroup utils
*/
#define allocator_free(pointer) (free(pointer))
/**
* Clone bytes.
*
*
* @param pointer pointer to read data from
* @param size number of bytes to clone
*
* @ingroup utils
*/
void * allocator_clone_bytes(void * pointer, size_t size);
/**
* Clone a chunk and its contents.
*
*
* @param chunk chunk to clone
* @return cloned chunk
*
* @ingroup utils
*/
chunk_t allocator_clone_chunk(chunk_t chunk);
/**
* Frees memory used by chunk.
*
* @param chunk pointer of chunk to free
*
* @ingroup utils
*/
void allocator_free_chunk(chunk_t *chunk);
/**
* Report memory leaks.
*
* @ingroup utils
*/
#define report_memory_leaks() {}
/**
* Initialize the allocator.
*
* @ingroup utils
*/
#define allocator_init() {}
#endif
#endif /*ALLOCATOR_H_*/
+365
View File
@@ -0,0 +1,365 @@
/**
* @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 "host.h"
#include <utils/allocator.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
*/
allocator_free(this->string);
string = inet_ntoa(this->address4.sin_addr);
this->string = allocator_alloc(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 = allocator_alloc(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 = allocator_alloc_thing(private_host_t);
memcpy(new, this, sizeof(private_host_t));
if (this->string)
{
new->string = allocator_alloc(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)
{
allocator_free(this->string);
allocator_free(this);
}
/**
* Creates an empty host_t object
*/
static private_host_t *host_create_empty()
{
private_host_t *this = allocator_alloc_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:
{
allocator_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);
}
}
allocator_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;
}
}
+225
View File
@@ -0,0 +1,225 @@
/**
* @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_*/
+291
View File
@@ -0,0 +1,291 @@
/**
* @file identification.c
*
* @brief Implementation 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.
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "identification.h"
#include <utils/allocator.h>
/**
* String mappings for id_type_t.
*/
mapping_t id_type_m[] = {
{ID_IPV4_ADDR, "ID_IPV4_ADDR"},
{ID_FQDN, "ID_FQDN"},
{ID_RFC822_ADDR, "ID_RFC822_ADDR"},
{ID_IPV6_ADDR, "ID_IPV6_ADDR"},
{ID_DER_ASN1_DN, "ID_DER_ASN1_DN"},
{ID_DER_ASN1_GN, "ID_DER_ASN1_GN"},
{ID_KEY_ID, "ID_KEY_ID"},
{MAPPING_END, NULL}
};
typedef struct private_identification_t private_identification_t;
/**
* Private data of an identification_t object.
*/
struct private_identification_t {
/**
* Public interface.
*/
identification_t public;
/**
* String representation of this ID.
*/
char *string;
/**
* Encoded representation of this ID.
*/
chunk_t encoded;
/**
* Type of this ID.
*/
id_type_t type;
};
static private_identification_t *identification_create();
/**
* Implementation of identification_t.get_encoding.
*/
static chunk_t get_encoding(private_identification_t *this)
{
return this->encoded;
}
/**
* Implementation of identification_t.get_type.
*/
static id_type_t get_type(private_identification_t *this)
{
return this->type;
}
/**
* Implementation of identification_t.get_string.
*/
static char *get_string(private_identification_t *this)
{
return this->string;
}
/**
* Implementation of identification_t.equals.
*/
static bool equals (private_identification_t *this,private_identification_t *other)
{
if (this->type == other->type)
{
if (this->encoded.len != other->encoded.len)
{
return FALSE;
}
if (memcmp(this->encoded.ptr,other->encoded.ptr,this->encoded.len) == 0)
{
return TRUE;
}
}
return FALSE;
}
/**
* Implementation of identification_t.belongs_to.
*/
static bool belongs_to(private_identification_t *this, private_identification_t *other)
{
if (this->public.equals(&this->public, &other->public))
{
return TRUE;
}
if (this->type == other->type && this->type == ID_IPV4_ADDR)
{
/* is this %any (0.0.0.0)?*/
if (*((u_int32_t*)this->encoded.ptr) == 0)
{
return TRUE;
}
/* TODO: Do we need subnet support? */
}
return FALSE;
}
/**
* Implementation of identification_t.clone.
*/
static identification_t *clone(private_identification_t *this)
{
private_identification_t *clone = identification_create();
clone->type = this->type;
clone->encoded = allocator_clone_chunk(this->encoded);
clone->string = allocator_alloc(strlen(this->string) + 1);
strcpy(clone->string, this->string);
return &clone->public;
}
/**
* Implementation of identification_t.destroy.
*/
static void destroy(private_identification_t *this)
{
allocator_free(this->string);
allocator_free(this->encoded.ptr);
allocator_free(this);
}
/*
* Generic constructor used for the other constructors.
*
* @return private_identification_t object
*/
static private_identification_t *identification_create()
{
private_identification_t *this = allocator_alloc_thing(private_identification_t);
this->public.equals = (bool (*) (identification_t*,identification_t*))equals;
this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to;
this->public.get_encoding = (chunk_t (*) (identification_t*))get_encoding;
this->public.get_type = (id_type_t (*) (identification_t*))get_type;
this->public.get_string = (char* (*) (identification_t*))get_string;
this->public.clone = (identification_t* (*) (identification_t*))clone;
this->public.destroy = (void (*) (identification_t*))destroy;
this->string = NULL;
this->encoded = CHUNK_INITIALIZER;
return this;
}
/*
* Described in header.
*/
identification_t *identification_create_from_string(id_type_t type, char *string)
{
private_identification_t *this = identification_create();
this->type = type;
switch (type)
{
case ID_IPV4_ADDR:
{
/* convert string */
this->encoded.len = 4;
this->encoded.ptr = allocator_alloc(this->encoded.len);
if (inet_aton(string, ((struct in_addr*)(this->encoded.ptr))) == 0)
{
allocator_free(this->encoded.ptr);
allocator_free(this);
return NULL;
}
/* clone string */
this->string = allocator_alloc(strlen(string)+1);
strcpy(this->string, string);
return &(this->public);
}
case ID_IPV6_ADDR:
case ID_FQDN:
case ID_RFC822_ADDR:
case ID_DER_ASN1_DN:
case ID_DER_ASN1_GN:
case ID_KEY_ID:
default:
{
/* not supported */
allocator_free(this);
return NULL;
}
}
}
/*
* Described in header.
*/
identification_t *identification_create_from_encoding(id_type_t type, chunk_t encoded)
{
char *string;
private_identification_t *this = identification_create();
this->encoded = allocator_clone_chunk(encoded);
this->type = type;
switch (type)
{
case ID_IPV4_ADDR:
{
string = inet_ntoa(*((struct in_addr*)(encoded.ptr)));
break;
}
case ID_IPV6_ADDR:
{
string = "[ID_IPV6_ADDR]";
break;
}
case ID_FQDN:
{
string = "[ID_FQDN]";
break;
}
case ID_RFC822_ADDR:
{
string = "[ID_RFC822_ADDR]";
break;
}
case ID_DER_ASN1_DN:
{
string = "[ID_DER_ASN1_DN]";
break;
}
case ID_DER_ASN1_GN:
{
string = "[ID_DER_ASN1_GN]";
break;
}
case ID_KEY_ID:
{
string = "[ID_KEY_ID]";
break;
}
default:
{
string = "[unknown id_type_t]";
}
}
/* build string, must be cloned since
* inet_ntoa points to a subsequently
* overwritten buffer */
this->string = allocator_alloc(strlen(string)+1);
strcpy(this->string, string);
return &(this->public);
}
+211
View File
@@ -0,0 +1,211 @@
/**
* @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.
*
* @see
* - identification_t
* - id_payload_t
*
* @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
};
/**
* 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*
* (* = string conversion not supported)
*
* @b Constructors:
* - identification_create_from_string()
* - identification_create_from_encoding()
*
* @todo Support for other ID types then ID_IPV4_ADDR.
*
* @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.
*
* @param this the ID containing a wildcard
* @param other the ID without wildcard
* @return TRUE if other belongs to this
*/
bool (*belongs_to) (identification_t *this, identification_t *other);
/**
* @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 type type of this id, such as ID_IPV4_ADDR
* @param string input string, which will be converted
* @return
* - created identification_t object, or
* - NULL if type not supported.
*
* @ingroup utils
*/
identification_t * identification_create_from_string(id_type_t type, 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
*
* @ingroup utils
*/
identification_t * identification_create_from_encoding(id_type_t type, chunk_t encoded);
#endif /* IDENTIFICATION_H_ */
+153
View File
@@ -0,0 +1,153 @@
/**
* @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_*/
+729
View File
@@ -0,0 +1,729 @@
/**
* @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"
#include <utils/allocator.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)
{
allocator_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 = allocator_alloc_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)
{
allocator_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 = allocator_alloc_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 */
}
allocator_free(this);
}
/*
* Described in header.
*/
linked_list_t *linked_list_create()
{
private_linked_list_t *this = allocator_alloc_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));
}
+203
View File
@@ -0,0 +1,203 @@
/**
* @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();
#endif /*LINKED_LIST_H_*/
+360
View File
@@ -0,0 +1,360 @@
/**
* @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"
#include <daemon.h>
#include <utils/allocator.h>
/**
* Maximum length of a log entry (only used for logger_s.log).
*/
#define MAX_LOG 8192
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;
/**
* Applies a prefix to string and stores it in buffer.
*
* @warning: buffer must be at least have MAX_LOG size.
*/
void (*prepend_prefix) (private_logger_t *this, log_level_t loglevel, char *string, char *buffer);
};
/**
* Implementation of private_logger_t.prepend_prefix.
*/
static void prepend_prefix(private_logger_t *this, log_level_t loglevel, char *string, char *buffer)
{
char log_type, log_details;
if (loglevel & CONTROL)
{
log_type = '~';
}
else if (loglevel & ERROR)
{
log_type = '!';
}
else if (loglevel & RAW)
{
log_type = '#';
}
else if (loglevel & PRIVATE)
{
log_type = '?';
}
else if (loglevel & AUDIT)
{
log_type = '>';
}
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(buffer, MAX_LOG, "[%c%c] [%s] @%u %s", log_type, log_details, this->name, (int)pthread_self(), string);
}
else
{
snprintf(buffer, MAX_LOG, "[%c%c] [%s] %s", log_type, log_details, this->name, string);
}
}
/**
* Implementation of logger_t.log.
*
* Yes, logg is wrong written :-).
*/
static void logg(private_logger_t *this, log_level_t loglevel, char *format, ...)
{
if ((this->level & loglevel) == loglevel)
{
char buffer[MAX_LOG];
va_list args;
if (this->output == NULL)
{
/* syslog */
this->prepend_prefix(this, loglevel, format, buffer);
va_start(args, format);
vsyslog(LOG_INFO, buffer, args);
va_end(args);
}
else
{
/* File output */
this->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, char *label, char *bytes, size_t len)
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
if ((this->level & loglevel) == loglevel)
{
char buffer[MAX_LOG];
char ascii_buffer[17];
char *format;
char *buffer_pos;
char *bytes_pos, *bytes_roof;
int i;
int line_start = 0;
/* 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);
format = "%s (%d bytes @%p)";
this->prepend_prefix(this, loglevel, format, buffer);
if (this->output == NULL)
{
syslog(LOG_INFO, buffer, label, len);
}
else
{
fprintf(this->output, buffer, label, len, bytes);
fprintf(this->output, "\n");
}
bytes_pos = bytes;
bytes_roof = bytes + len;
buffer_pos = buffer;
memset(ascii_buffer, 0, 17);
for (i = 1; bytes_pos < bytes_roof; i++)
{
static char hexdig[] = "0123456789ABCDEF";
*buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
*buffer_pos++ = hexdig[ *bytes_pos & 0xF];
if ((i % 16) == 0)
{
*buffer_pos++ = '\0';
buffer_pos = buffer;
if (this->output == NULL)
{
syslog(LOG_INFO, "[=>] [%5d ] %s %s", line_start, buffer, ascii_buffer);
}
else
{
fprintf(this->output, "[=>] [%5d ] %s %s\n", line_start, buffer, ascii_buffer);
}
memset(ascii_buffer, 0, 16);
line_start += 16;
}
else if ((i % 4) == 0)
{
*buffer_pos++ = ' ';
// *buffer_pos++ = ' ';
}
else
{
*buffer_pos++ = ' ';
}
if (*bytes_pos > 31 && *bytes_pos < 127)
{
ascii_buffer[(i % 16)] = *bytes_pos;
}
else
{
ascii_buffer[(i % 16)] = '*';
}
bytes_pos++;
}
*buffer_pos++ = '\0';
if (buffer_pos > buffer + 1)
{
buffer_pos = buffer;
if (this->output == NULL)
{
syslog(LOG_INFO, "[=>] [%5d ] %s %16s", line_start, buffer, ascii_buffer);
}
else
{
fprintf(this->output, "[=>] [%5d ] %s %16s\n", line_start, buffer, ascii_buffer);
}
}
pthread_mutex_unlock(&mutex);
}
}
/**
* Implementation of logger_t.log_chunk.
*/
static void log_chunk(logger_t *this, log_level_t loglevel, 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)
{
allocator_free(this->name);
allocator_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 = allocator_alloc_thing(private_logger_t);
/* public functions */
this->public.log = (void(*)(logger_t*,log_level_t,char*,...))logg;
this->public.log_bytes = (void(*)(logger_t*, log_level_t, char*,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;
/* private functions */
this->prepend_prefix = prepend_prefix;
if (logger_name == NULL)
{
logger_name = "";
}
/* private variables */
this->level = log_level;
this->log_thread_id = log_thread_id;
this->name = allocator_alloc(strlen(logger_name) + 1);
strcpy(this->name,logger_name);
this->output = output;
if (output == NULL)
{
openlog(DAEMON_NAME, 0, LOG_DAEMON);
}
return (logger_t*)this;
}
+199
View File
@@ -0,0 +1,199 @@
/**
* @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|MORE 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, 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, char *label, 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, 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_*/
+212
View File
@@ -0,0 +1,212 @@
/**
* @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/allocator.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"},
{MAPPING_END, NULL},
};
#define DEFAULT_OUTPUT NULL
struct {
char *name;
log_level_t level;
bool log_thread_ids;
FILE *output;
} logger_defaults[] = {
{ "PARSR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* PARSER */
{ "GNRAT", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* GENERATOR */
{ "IKESA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* IKE_SA */
{ "SAMGR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* IKE_SA_MANAGER */
{ "CHDSA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* CHILD_SA */
{ "MESSG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* MESSAGE */
{ "TPOOL", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* THREAD_POOL */
{ "WORKR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* WORKER */
{ "SCHED", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* SCHEDULER */
{ "SENDR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* SENDER */
{ "RECVR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* RECEIVER */
{ "SOCKT", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* SOCKET */
{ "TESTR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* TESTER */
{ "DAEMN", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* DAEMON */
{ "CONFG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* CONFIG */
{ "ENCPL", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* ENCRYPTION_PAYLOAD */
{ "PAYLD", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* PAYLOAD */
{ "DERDC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* DER_DECODER */
{ "DEREC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* DER_ENCODER */
};
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];
};
/**
* 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);
}
}
/**
* Implementation of logger_manager_t.destroy.
*/
static void destroy(private_logger_manager_t *this)
{
int i;
for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
{
this->loggers[i]->destroy(this->loggers[i]);
}
allocator_free(this);
}
/*
* Described in header.
*/
logger_manager_t *logger_manager_create(log_level_t default_log_level)
{
private_logger_manager_t *this = allocator_alloc_thing(private_logger_manager_t);
int i;
this->public.get_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context))get_logger;
this->public.get_log_level = (log_level_t (*)(logger_manager_t *, logger_context_t)) get_log_level;
this->public.enable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) enable_log_level;
this->public.disable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) disable_log_level;
this->public.set_output = (void (*)(logger_manager_t *, logger_context_t, FILE*)) set_output;
this->public.destroy = (void(*)(logger_manager_t*))destroy;
for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
{
this->loggers[i] = logger_create(logger_defaults[i].name, logger_defaults[i].level,
logger_defaults[i].log_thread_ids, stdout);//logger_defaults[i].output);
}
return &this->public;
}
+155
View File
@@ -0,0 +1,155 @@
/**
* @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>
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,
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.
*
* @b Constructors:
* - logger_manager_create()
*
* @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);
/**
* @brief Destroys a logger_manager_t object.
*
* All managed logger_t objects are also destroyed.
*
* @param this logger_manager_t object
*/
void (*destroy) (logger_manager_t *this);
};
/**
* @brief Constructor to create a logger_manager_t object.
*
* @param default_log_level default log level for all context
* @return logger_manager_t object
*
* @ingroup utils
*/
logger_manager_t *logger_manager_create(log_level_t default_log_level);
#endif /*LOGGER_MANAGER_H_*/
+165
View File
@@ -0,0 +1,165 @@
/**
* @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"
#include <utils/allocator.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 ? RANDOM_DEVICE : PSEUDO_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 = allocator_alloc(bytes);
status = this->get_bytes_from_device(this, FALSE, bytes, chunk->ptr);
if (status != SUCCESS)
{
allocator_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 = allocator_alloc(bytes);
status = this->get_bytes_from_device(this, TRUE, bytes, chunk->ptr);
if (status != SUCCESS)
{
allocator_free(chunk->ptr);
}
return status;
}
/**
* Implementation of randomizer_t.destroy.
*/
static void destroy(private_randomizer_t *this)
{
allocator_free(this);
}
/*
* Described in header.
*/
randomizer_t *randomizer_create(void)
{
private_randomizer_t *this = allocator_alloc_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);
}
+110
View File
@@ -0,0 +1,110 @@
/**
* @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();
#endif /*RANDOMIZER_H_*/
+257
View File
@@ -0,0 +1,257 @@
/**
* @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/allocator.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));
allocator_free(this);
}
/*
* Described in header.
*/
tester_t *tester_create(FILE *output, bool display_succeeded_asserts)
{
private_tester_t *this = allocator_alloc_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);
}
+148
View File
@@ -0,0 +1,148 @@
/**
* @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_*/