../svn-commit.tmp
This commit is contained in:
@@ -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
|
||||
@@ -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 $@ $<
|
||||
@@ -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"},
|
||||
};
|
||||
@@ -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_ */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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 $@ $<
|
||||
Executable
+230
@@ -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);
|
||||
}
|
||||
Executable
+70
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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 $@ $<
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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 $@ $<
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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_*/
|
||||
@@ -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 $@ $<
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 $@ $<
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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};
|
||||
@@ -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_*/
|
||||
@@ -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 $@ $<
|
||||
@@ -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 */
|
||||
@@ -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_*/
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_*/
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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_*/
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_*/
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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_*/
|
||||
Reference in New Issue
Block a user