- rewrote a lot of RSA stuff
- done major work for ASN1/decoder - allow loading of ASN1 der encoded private keys, public keys and certificates - extracting public key from certificates - passing certificates from stroke to charon => basic authentication with RSA certificates works!
This commit is contained in:
@@ -78,7 +78,7 @@ $(BINNAMESTROKE) : stroke.c
|
||||
TEST_OBJS = $(OBJS)
|
||||
include $(MAIN_DIR)testcases/Makefile.testcases
|
||||
|
||||
$(BUILD_DIR)run_tests : $(TEST_OBJS)
|
||||
$(BUILD_DIR)run_tests : build_dir $(TEST_OBJS)
|
||||
$(CC) $(LDFLAGS) $(TEST_OBJS) -o $@
|
||||
|
||||
install : $(BINNAMECHARON)
|
||||
|
||||
+24
-10
@@ -1,21 +1,33 @@
|
||||
/**
|
||||
* @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_BIT_STRING, "ASN1_BIT_STRING"},
|
||||
{ASN1_OCTET_STRING, "ASN1_OCTET_STRING"},
|
||||
{ASN1_BITSTRING, "ASN1_BITSTRING"},
|
||||
{ASN1_OCTETSTRING, "ASN1_OCTETSTRING"},
|
||||
{ASN1_NULL, "ASN1_NULL"},
|
||||
{ASN1_OID, "ASN1_OID"},
|
||||
{ASN1_ENUMERATED, "ASN1_ENUMERATED"},
|
||||
@@ -43,6 +55,7 @@ mapping_t asn1_type_m[] = {
|
||||
{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"},
|
||||
@@ -50,6 +63,7 @@ mapping_t asn1_type_m[] = {
|
||||
{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[] = {
|
||||
|
||||
+71
-15
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file asn1.h
|
||||
*
|
||||
* @brief Definition of asn1_type_t and asn1_rule_t.
|
||||
* @brief Definition of asn1_rule_t and other ASN1 stuff.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -27,12 +27,20 @@
|
||||
|
||||
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_BIT_STRING = 0x03,
|
||||
ASN1_OCTET_STRING = 0x04,
|
||||
ASN1_BITSTRING = 0x03,
|
||||
ASN1_OCTETSTRING = 0x04,
|
||||
ASN1_NULL = 0x05,
|
||||
ASN1_OID = 0x06,
|
||||
ASN1_ENUMERATED = 0x0A,
|
||||
@@ -52,6 +60,9 @@ enum asn1_type_t {
|
||||
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,
|
||||
@@ -60,6 +71,10 @@ enum asn1_type_t {
|
||||
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,
|
||||
@@ -67,24 +82,70 @@ enum asn1_type_t {
|
||||
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
|
||||
@@ -98,18 +159,13 @@ struct asn1_rule_t {
|
||||
* offset of data in structure
|
||||
*/
|
||||
u_int data_offset;
|
||||
// union {
|
||||
/**
|
||||
* offset to a boolean, which says if optional
|
||||
* data is available at data_offset. Used if
|
||||
* flags & ASN1_OPTIONAL.
|
||||
*/
|
||||
// u_int available_offset;
|
||||
/**
|
||||
* default value, used if flags & ASN1_DEFAULT
|
||||
*/
|
||||
u_int default_value;
|
||||
// };
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2005 Jan Hutter, Martin Willi
|
||||
* 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
|
||||
@@ -39,56 +42,269 @@ struct private_der_decoder_t {
|
||||
*/
|
||||
der_decoder_t public;
|
||||
|
||||
/**
|
||||
* Rule which was just processed
|
||||
*/
|
||||
asn1_rule_t *rule;
|
||||
|
||||
/**
|
||||
* First rule of the hole 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)
|
||||
{
|
||||
while (this->rule->type != ASN1_END)
|
||||
status_t status;
|
||||
asn1_rule_t *next_rule;
|
||||
|
||||
while(TRUE)
|
||||
{
|
||||
read_hdr(this, &data);
|
||||
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);
|
||||
u_int *integ = (u_int*)((u_int8_t*)this->output + this->rule->data_offset);
|
||||
|
||||
*integ = 0;
|
||||
while (data.len-- > 0)
|
||||
if (this->rule->flags & ASN1_MPZ)
|
||||
{
|
||||
*integ = 256 * (*integ) + *data.ptr++;
|
||||
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;
|
||||
}
|
||||
|
||||
status_t read_mpz(private_der_decoder_t *this, chunk_t data)
|
||||
/**
|
||||
* Read boolean value
|
||||
*/
|
||||
status_t read_bool(private_der_decoder_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);
|
||||
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;
|
||||
|
||||
mpz_import(*mpz, data.len, 1, 1, 1, 0, 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;
|
||||
|
||||
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;
|
||||
|
||||
/* read first octet of length field */
|
||||
n = *data->ptr++;
|
||||
n = *data->ptr;
|
||||
data->ptr++; data->len--;
|
||||
|
||||
if ((n & 0x80) == 0)
|
||||
{
|
||||
@@ -114,81 +330,138 @@ u_int32_t read_length(chunk_t *data)
|
||||
len = 0;
|
||||
while (n-- > 0)
|
||||
{
|
||||
len = 256 * len + *data->ptr++;
|
||||
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++;
|
||||
|
||||
if (this->rule->type == ASN1_END)
|
||||
{
|
||||
return SUCCESS;
|
||||
}
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "reading rule %d %s",
|
||||
this->rule - this->first_rule,
|
||||
mapping_find(asn1_type_m, this->rule->type));
|
||||
|
||||
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);
|
||||
case ASN1_END:
|
||||
/* ignore, handled outside */
|
||||
return SUCCESS;
|
||||
case ASN1_CHOICE:
|
||||
/* CHOICE has no type/length */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,15 +29,29 @@
|
||||
typedef struct der_decoder_t der_decoder_t;
|
||||
|
||||
/**
|
||||
* @brief Decode der_encoded bytes to usable structures.
|
||||
* @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);
|
||||
|
||||
/**
|
||||
@@ -52,7 +66,11 @@ struct der_decoder_t {
|
||||
/**
|
||||
* @brief Create a der_decoder instance.
|
||||
*
|
||||
* @return der_decoder_t object
|
||||
* 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
|
||||
*/
|
||||
|
||||
@@ -166,6 +166,13 @@
|
||||
*
|
||||
* @ingroup transforms
|
||||
*/
|
||||
/**
|
||||
* @defgroup asn1 asn1
|
||||
*
|
||||
* ASN1 structure definition, en-/decoder of for DER
|
||||
*
|
||||
* @todo Implement a der_encoder_t class.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup utils utils
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
IKEv1 and IKEv2 is handled in different keying daemons. The ole IKEv1 stuff is
|
||||
completely handled in pluto, as it was all the times. IKEv2 is handled in the
|
||||
new keying daemon, which is called charon.
|
||||
Daemon control is done over unix sockets. Pluto uses whack, as it did all the
|
||||
times. Charon uses another socket interface, called stroke. Stroke uses another
|
||||
Daemon control is done over unix sockets. Pluto uses whack, as it did for years.
|
||||
Charon uses another socket interface, called stroke. Stroke uses another
|
||||
format as whack and therefore is not compatible to whack. The starter utility,
|
||||
wich does fast configuration parsing, speaks both the protocols, whack and
|
||||
stroke. It also handles daemon startup and termination.
|
||||
|
||||
@@ -205,6 +205,8 @@ static status_t verify_auth_data (private_authenticator_t *this,
|
||||
&preshared_secret);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "No shared secret found for %s",
|
||||
other_id->get_string(other_id));
|
||||
other_id->destroy(other_id);
|
||||
return status;
|
||||
}
|
||||
@@ -252,6 +254,8 @@ static status_t verify_auth_data (private_authenticator_t *this,
|
||||
&public_key);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "No RSA public key found for %s",
|
||||
other_id->get_string(other_id));
|
||||
other_id->destroy(other_id);
|
||||
return status;
|
||||
}
|
||||
@@ -307,11 +311,14 @@ static status_t compute_auth_data (private_authenticator_t *this,
|
||||
my_id,
|
||||
&preshared_secret);
|
||||
|
||||
my_id->destroy(my_id);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "No shared secret found for %s",
|
||||
my_id->get_string(my_id));
|
||||
my_id->destroy(my_id);
|
||||
return status;
|
||||
}
|
||||
my_id->destroy(my_id);
|
||||
|
||||
auth_data = this->build_preshared_secret_signature(this, last_sent_packet, other_nonce,
|
||||
my_id_payload, initiator, preshared_secret);
|
||||
@@ -331,11 +338,14 @@ static status_t compute_auth_data (private_authenticator_t *this,
|
||||
chunk_t octets, auth_data;
|
||||
|
||||
status = charon->credentials->get_rsa_private_key(charon->credentials, my_id, &private_key);
|
||||
my_id->destroy(my_id);
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR|LEVEL1, "No RSA private key found for %s",
|
||||
my_id->get_string(my_id));
|
||||
my_id->destroy(my_id);
|
||||
return status;
|
||||
}
|
||||
my_id->destroy(my_id);
|
||||
|
||||
octets = this->allocate_octets(this,last_sent_packet,other_nonce,my_id_payload,initiator);
|
||||
|
||||
|
||||
@@ -135,4 +135,8 @@ $(BUILD_DIR)child_sa_test.o : $(TESTCASES_DIR)child_sa_test.c $(TESTCASES_DIR)c
|
||||
TEST_OBJS+= $(BUILD_DIR)der_decoder_test.o
|
||||
$(BUILD_DIR)der_decoder_test.o : $(TESTCASES_DIR)der_decoder_test.c $(TESTCASES_DIR)der_decoder_test.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
TEST_OBJS+= $(BUILD_DIR)certificate_test.o
|
||||
$(BUILD_DIR)certificate_test.o : $(TESTCASES_DIR)certificate_test.c $(TESTCASES_DIR)certificate_test.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @file certificate_test.c
|
||||
*
|
||||
* @brief Tests for the certificate_t class.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 "certificate_test.h"
|
||||
|
||||
#include <daemon.h>
|
||||
#include <transforms/certificate.h>
|
||||
#include <utils/allocator.h>
|
||||
#include <utils/logger.h>
|
||||
|
||||
|
||||
|
||||
static char certificate_buffer[] = {
|
||||
0x30,0x82,0x02,0xf9,0x30,0x82,0x01,0xe1,0xa0,0x03,0x02,0x01,0x02,0x02,0x11,0x00,
|
||||
0xfe,0xae,0xe3,0xcf,0x00,0x27,0x8d,0xa0,0xe1,0xfa,0xb2,0x07,0xd4,0x15,0x40,0x93,
|
||||
0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,
|
||||
0x38,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x19,
|
||||
0x30,0x17,0x06,0x03,0x55,0x04,0x0a,0x13,0x10,0x4c,0x69,0x6e,0x75,0x78,0x20,0x73,
|
||||
0x74,0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,
|
||||
0x04,0x03,0x13,0x05,0x6d,0x61,0x65,0x6e,0x6f,0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,
|
||||
0x33,0x32,0x37,0x30,0x36,0x35,0x32,0x33,0x38,0x5a,0x17,0x0d,0x31,0x31,0x30,0x33,
|
||||
0x32,0x36,0x30,0x36,0x35,0x32,0x33,0x38,0x5a,0x30,0x38,0x31,0x0b,0x30,0x09,0x06,
|
||||
0x03,0x55,0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x19,0x30,0x17,0x06,0x03,0x55,0x04,
|
||||
0x0a,0x13,0x10,0x4c,0x69,0x6e,0x75,0x78,0x20,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,
|
||||
0x77,0x61,0x6e,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x6d,0x61,
|
||||
0x65,0x6e,0x6f,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
|
||||
0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,
|
||||
0x82,0x01,0x01,0x00,0xe3,0x75,0x56,0xb9,0x68,0x46,0xa6,0x3e,0x6c,0x19,0x36,0xfb,
|
||||
0x9a,0xb4,0xbc,0xc1,0x22,0x47,0xc0,0x00,0x8a,0x44,0x1c,0xa7,0x44,0x2e,0x73,0x50,
|
||||
0xfc,0xd2,0x91,0x9c,0xaa,0xc3,0xa3,0x88,0x8c,0x4b,0x33,0xef,0x9a,0x52,0x89,0x9c,
|
||||
0x8e,0x01,0x62,0x21,0x7a,0x75,0x5e,0xa3,0x3b,0xc0,0xb0,0x58,0xc0,0xc0,0xce,0x77,
|
||||
0xe0,0x84,0x9a,0x9e,0xc1,0x51,0x71,0xc7,0xc4,0xa0,0x1e,0xf0,0x8e,0xb3,0x90,0x3e,
|
||||
0xcd,0xe3,0x7d,0x8e,0x11,0x7b,0x92,0x5d,0x4a,0x37,0x3b,0x4b,0xb3,0x3d,0x58,0x9a,
|
||||
0x8b,0x51,0x39,0x15,0xcd,0x27,0xd4,0x5b,0xad,0x5e,0xa5,0x07,0x94,0x29,0x0f,0x02,
|
||||
0x0c,0x61,0x85,0x97,0x3b,0xc4,0xcf,0x5d,0x17,0x86,0x4d,0x96,0x5e,0x42,0xe9,0xf2,
|
||||
0x72,0x2f,0xd4,0x58,0x4d,0x02,0xf8,0x0f,0xbd,0xe7,0x37,0xc8,0xa9,0x87,0xfe,0xab,
|
||||
0x26,0x37,0x13,0x90,0x65,0x2d,0x51,0x41,0x18,0x18,0xdf,0x48,0x21,0x87,0x70,0x61,
|
||||
0xcb,0x1b,0x62,0xad,0xaf,0x65,0xd2,0x29,0x27,0x93,0x58,0x7b,0xea,0x89,0xdd,0x58,
|
||||
0x01,0x6d,0xeb,0x60,0xd8,0xc3,0x82,0x07,0x2c,0x67,0x39,0xc3,0x68,0xfc,0xcd,0xeb,
|
||||
0xe9,0x7c,0x67,0xe3,0x1b,0x7a,0x50,0xf9,0x36,0x68,0xea,0xe2,0x15,0x01,0xee,0x99,
|
||||
0xf2,0x52,0xe0,0x0a,0x8e,0x5f,0x63,0xb1,0x61,0x7a,0x38,0x88,0x07,0xae,0xb0,0x8d,
|
||||
0x44,0x26,0xe8,0xce,0x1b,0x6f,0xcd,0x05,0x4b,0x94,0x9d,0xee,0xb5,0xeb,0x28,0xc4,
|
||||
0x93,0x47,0xfd,0x47,0x40,0x45,0x58,0xc0,0x3e,0x44,0x74,0x7b,0x78,0x8d,0xc8,0x25,
|
||||
0xc1,0xe1,0x0a,0x43,0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
|
||||
0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x77,0xfd,0xd2,
|
||||
0x68,0x7e,0xb9,0xc2,0x40,0xb4,0xa3,0xea,0xe8,0x15,0x55,0x18,0xfe,0xe3,0x80,0xe0,
|
||||
0x73,0xf9,0xe1,0xe5,0xe2,0x91,0xf5,0xa7,0xcb,0xdf,0xfb,0xc1,0x36,0xa6,0x55,0x6a,
|
||||
0xd9,0x27,0xcd,0xef,0x64,0x30,0x70,0xd8,0x4b,0x72,0x7c,0xd1,0x9c,0x32,0xf8,0xb4,
|
||||
0x15,0x7f,0xd7,0x79,0x0c,0x9f,0x24,0xf8,0x50,0xea,0xc7,0xd9,0xef,0x1f,0xf1,0x76,
|
||||
0x3c,0x19,0xdb,0x61,0xb7,0x35,0x97,0xf9,0x03,0x87,0x42,0x77,0x23,0xd8,0xfe,0xd1,
|
||||
0x74,0xf2,0x1e,0x95,0x87,0x5f,0x42,0x80,0x8e,0xee,0x6c,0x19,0x7b,0x2c,0x25,0xe6,
|
||||
0xf9,0xdb,0x24,0x35,0x94,0x65,0x44,0xa0,0x56,0x6f,0x7f,0x57,0x2e,0x1a,0xcd,0xa6,
|
||||
0xed,0x7f,0x42,0xf2,0x64,0xd4,0xf9,0x3f,0xc1,0x46,0xf6,0xc8,0xb1,0xb2,0x80,0x75,
|
||||
0x3e,0xd1,0xa8,0x5e,0x07,0xd0,0x3b,0x35,0x81,0x49,0x93,0x77,0xd2,0xcf,0xf7,0xb6,
|
||||
0xd0,0xeb,0xe5,0xf3,0x2c,0x03,0x52,0xc7,0x6d,0x02,0x26,0xa6,0xdc,0x39,0xcd,0x4d,
|
||||
0x9e,0xca,0x99,0x01,0x01,0x73,0xd6,0x55,0x89,0x93,0x12,0xa0,0xc5,0xe6,0xa7,0x9a,
|
||||
0xdc,0x5f,0x9f,0x5c,0x2c,0x2b,0xdb,0x23,0xa5,0xee,0x69,0x15,0x1f,0x3a,0xf1,0x76,
|
||||
0x36,0xb5,0x77,0x18,0x57,0xff,0xff,0xf7,0x45,0x59,0xce,0x1b,0x0b,0x56,0xcb,0x09,
|
||||
0x00,0x12,0x17,0xb8,0xa2,0x81,0x86,0x70,0x29,0x63,0x99,0x76,0xff,0x18,0x80,0x2b,
|
||||
0x9b,0x5e,0x04,0xb1,0xcc,0xe4,0x15,0x90,0x29,0xa6,0x40,0xdd,0x85,0x38,0xd7,0xfe,
|
||||
0x10,0xb5,0x97,0x6e,0x62,0x60,0xb9,0x02,0x67,0xef,0xf1,0xab,0xb3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
void test_certificate(protected_tester_t *tester)
|
||||
{
|
||||
//chunk_t certificate = {certificate_buffer, sizeof(certificate_buffer)};
|
||||
|
||||
//certificate_t *cert = certificate_create_from_chunk(certificate);
|
||||
|
||||
certificate_t *cert = certificate_create_from_file("myCert.der");
|
||||
|
||||
cert->destroy(cert);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file certificate_test.h
|
||||
*
|
||||
* @brief Tests for the certificate_t class.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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_TEST_H_
|
||||
#define CERTIFICATE_TEST_H_
|
||||
|
||||
#include <utils/tester.h>
|
||||
|
||||
/**
|
||||
* @brief Test function used to test the certificate_t functionality.
|
||||
*
|
||||
* @param tester associated protected_tester_t object
|
||||
*
|
||||
* @ingroup testcases
|
||||
*/
|
||||
void test_certificate(protected_tester_t *tester);
|
||||
|
||||
#endif /* CERTIFICATE_TEST_H_ */
|
||||
|
||||
|
||||
|
||||
|
||||
+149
-115
@@ -27,103 +27,108 @@
|
||||
#include <daemon.h>
|
||||
#include <utils/allocator.h>
|
||||
#include <utils/logger.h>
|
||||
#include <transforms/certificate.h>
|
||||
|
||||
char private_key_buffer[] = {
|
||||
0x30,0x82,0x04,0xa2,0x02,0x00,0x02,0x82,0x01,0x01,0x00,0x9b,0x28,0x10,0x02,0xd2,
|
||||
0x43,0x5b,0x2b,0x7c,0x81,0xce,0x2b,0x77,0xb4,0xbf,0x5f,0x2a,0x9a,0x96,0xc9,0xa4,
|
||||
0xd7,0xbb,0xb3,0xfb,0xc1,0x8a,0xad,0xbe,0x21,0x4e,0xd7,0x15,0xc4,0x8c,0x0a,0x88,
|
||||
0x5b,0x02,0xa9,0xcd,0x2e,0xee,0xd3,0x5e,0xb9,0xfd,0x27,0x0b,0xdb,0xf6,0xe7,0xb7,
|
||||
0x39,0xc1,0xfa,0x34,0x3f,0xa7,0xe4,0x04,0xaf,0xa8,0xc2,0x36,0x4e,0xf5,0x0c,0xf1,
|
||||
0x9b,0x92,0x26,0x32,0x20,0xdb,0x04,0xf5,0xb8,0x2e,0xf5,0xfc,0x47,0xd3,0x2a,0xa1,
|
||||
0x2d,0x5b,0x68,0x2c,0x5e,0xc6,0xc9,0x35,0x57,0x7b,0x65,0x17,0xd7,0x5d,0x10,0x5c,
|
||||
0x51,0xfb,0xcb,0x95,0xd1,0x17,0x42,0xa9,0xfd,0xd1,0xc4,0x32,0x1f,0x13,0xf2,0xeb,
|
||||
0x6b,0x91,0x01,0xe9,0x89,0x19,0x3a,0x2b,0x6d,0xae,0x91,0x27,0xe2,0x5e,0x06,0x5b,
|
||||
0x99,0xfb,0x20,0x3c,0xc4,0x92,0x20,0xc4,0x68,0x24,0x6b,0x74,0xdc,0x6d,0xf7,0xa8,
|
||||
0x10,0x1b,0xdf,0x20,0xed,0x4e,0x90,0x0e,0x3d,0xf6,0xef,0x3a,0x94,0x8b,0x12,0x61,
|
||||
0xac,0xed,0x95,0xbc,0xe2,0xed,0xb9,0x22,0xc2,0xdd,0xc7,0x19,0x68,0x09,0x14,0x71,
|
||||
0xb0,0x37,0xf7,0xbd,0x65,0x11,0x31,0x9d,0x89,0x6e,0x21,0xcf,0x60,0xc1,0x8d,0xbe,
|
||||
0x31,0x96,0xd2,0xdd,0x0e,0x20,0x38,0x07,0xd5,0xea,0xda,0xc8,0x9a,0x47,0x5b,0x05,
|
||||
0xce,0x7d,0xf7,0x4e,0xcd,0xbb,0x89,0xdd,0x46,0x16,0x8f,0x39,0x9d,0x32,0x19,0xaf,
|
||||
0x6e,0xc4,0xb3,0x6c,0x79,0x5a,0x70,0x11,0x8f,0xe2,0x75,0x33,0x09,0xc8,0xf6,0xd7,
|
||||
0x40,0x25,0xe7,0xa3,0xf0,0x6f,0x9a,0xdb,0x35,0x74,0xc1,0x02,0x03,0x01,0x00,0x01,
|
||||
0x02,0x82,0x01,0x00,0x12,0x42,0x38,0x58,0x21,0xfc,0x51,0x34,0xa0,0x8b,0x4f,0x58,
|
||||
0x28,0x2c,0x7a,0x14,0xd8,0x98,0xfb,0xee,0x5b,0x85,0x69,0x0e,0x63,0x83,0x16,0xd9,
|
||||
0xc9,0x5f,0xcc,0x12,0x5d,0xa5,0x15,0x41,0xd6,0xb8,0x0c,0x6b,0xda,0x67,0x3a,0x83,
|
||||
0x09,0xf3,0xb8,0x89,0xd4,0x1d,0xc7,0x99,0x8f,0x23,0x59,0xe3,0x78,0x2b,0x41,0x8b,
|
||||
0xab,0x78,0x2c,0x7e,0x3b,0xbb,0xe0,0xf4,0x96,0xa8,0xd3,0x1d,0xc6,0xea,0x67,0x91,
|
||||
0x2c,0x30,0x1c,0xe9,0x4f,0xb8,0xa2,0xc3,0x5d,0x2c,0xf9,0x99,0x1c,0x6c,0xee,0xd7,
|
||||
0x16,0x28,0x3c,0x5a,0x32,0x35,0xb8,0x3a,0xf3,0xa7,0xa6,0x35,0x02,0xba,0xbf,0x67,
|
||||
0xab,0x44,0xe1,0x09,0x9b,0x48,0x5d,0xa5,0x9e,0xf4,0xb7,0xf4,0xd1,0xfc,0x68,0x9e,
|
||||
0x98,0x26,0x69,0x28,0xcc,0x19,0x75,0xf2,0x61,0x0e,0x23,0xeb,0xf9,0x6d,0x2c,0x2b,
|
||||
0x01,0x3f,0x4d,0x18,0x41,0xc5,0x31,0x9d,0x1c,0x20,0x81,0x4e,0x38,0x92,0xd5,0xbb,
|
||||
0xd7,0xe7,0x49,0x0c,0x3a,0xf3,0x8f,0x9e,0xf0,0xb3,0x32,0x1e,0xa7,0x77,0xe8,0x9c,
|
||||
0xf3,0xce,0x88,0x66,0xcc,0xe8,0x16,0xbb,0xfd,0xbc,0x62,0xc7,0xc3,0xeb,0x0a,0xf5,
|
||||
0xd8,0x53,0x02,0x6c,0x45,0xcb,0x1d,0xa3,0x96,0xfb,0xa5,0x26,0x18,0x7f,0x04,0x9f,
|
||||
0x80,0x4a,0xdb,0x3b,0x74,0xcf,0x0d,0x45,0xf4,0xd5,0x49,0xe9,0x27,0x54,0x9c,0x57,
|
||||
0x92,0x48,0x78,0x52,0xb6,0x40,0x89,0x3f,0xf3,0x95,0x06,0x3d,0x90,0xab,0xa0,0x8a,
|
||||
0xc7,0x54,0xf1,0x63,0xcf,0xa6,0xd2,0x83,0x1e,0x69,0x54,0xe0,0x77,0x2c,0x9e,0x3a,
|
||||
0x4f,0xdd,0x14,0x6d,0x02,0x81,0x81,0x00,0xd9,0x40,0x76,0x90,0x7c,0xe7,0x3b,0xa3,
|
||||
0x59,0x23,0x14,0x6b,0xf3,0x5f,0x6e,0x6b,0x82,0x34,0xf6,0xbd,0x3e,0xfb,0x65,0xac,
|
||||
0x2f,0x46,0xd5,0x6e,0x9b,0xb8,0x62,0x80,0xc3,0x0c,0xa9,0xa6,0x00,0xd6,0xb8,0x1c,
|
||||
0x12,0x8d,0x4d,0xd0,0x64,0x29,0x4c,0xac,0x38,0xe8,0x6c,0xe4,0x82,0x02,0x4e,0x10,
|
||||
0xd5,0x39,0x19,0x29,0x0c,0x58,0x3f,0x68,0xa0,0x11,0x0e,0x11,0x74,0x22,0x2b,0x7e,
|
||||
0xc2,0xa7,0x88,0xe3,0x33,0xe8,0xb4,0x50,0x6e,0x0c,0x54,0xc5,0x3f,0xb7,0x16,0xcb,
|
||||
0x39,0xed,0x23,0xd0,0x66,0x26,0x57,0xf9,0xcb,0xc9,0xac,0xe2,0xa4,0xb8,0xba,0xd8,
|
||||
0xd2,0x1f,0x4a,0xed,0x73,0x89,0xda,0x42,0x27,0x5a,0x26,0x30,0x33,0xc8,0x42,0x2a,
|
||||
0x3d,0xc5,0xf3,0xc2,0x29,0x3d,0x58,0x67,0x02,0x81,0x81,0x00,0xb6,0xd4,0x61,0x05,
|
||||
0x49,0xcb,0xf4,0x29,0x8a,0x22,0xd3,0xa3,0x7c,0x9c,0xd2,0x07,0xa4,0x66,0xe4,0x36,
|
||||
0xfa,0x5e,0xf6,0x64,0xb7,0x59,0x74,0x2f,0x36,0x6d,0x12,0xd0,0xc9,0x4d,0xf8,0xd1,
|
||||
0xba,0xd1,0xee,0xd2,0x78,0xcd,0x51,0x69,0x33,0x6a,0x03,0xff,0xc2,0x35,0x1d,0x0d,
|
||||
0x9c,0x0a,0x87,0x5e,0x09,0xa3,0x23,0x4c,0xab,0xc3,0x4c,0x4a,0x1c,0xa4,0xc5,0xe2,
|
||||
0x70,0x42,0x1c,0xcf,0xea,0x79,0xfb,0xb9,0x87,0x67,0x4d,0xc3,0xfc,0xcc,0x86,0x9d,
|
||||
0xfa,0xea,0x99,0xa5,0x1b,0xc1,0x96,0xf4,0x79,0x4d,0x66,0x12,0x8f,0x90,0x98,0xb4,
|
||||
0xa1,0x3b,0xd6,0x2f,0x64,0xb4,0x5f,0x8f,0x47,0x7f,0x43,0xa5,0x6d,0xeb,0x06,0x58,
|
||||
0xfb,0x04,0x9e,0xef,0xaf,0x88,0x35,0x88,0xa1,0x15,0x30,0x97,0x02,0x81,0x80,0x59,
|
||||
0xbe,0xe0,0x7b,0xc5,0xad,0x3c,0x1c,0xb9,0x98,0xdd,0x39,0xce,0xfa,0xd0,0x41,0x87,
|
||||
0x33,0x5b,0xee,0x47,0x93,0x50,0xa7,0xf5,0x8b,0xbc,0x65,0x89,0xdc,0x7c,0x8c,0x96,
|
||||
0x86,0xa7,0x9a,0x54,0xe4,0x5e,0x7f,0xf2,0x45,0xff,0x2c,0x24,0x04,0x4f,0x91,0x21,
|
||||
0x9d,0x1a,0x46,0xb7,0x52,0x3e,0x6f,0x83,0xb5,0xa7,0xa8,0x26,0x5a,0x5a,0x2f,0x5d,
|
||||
0x58,0x4e,0x48,0x75,0x82,0x1c,0x17,0xac,0x4f,0xcb,0x23,0x98,0x70,0xfb,0xf3,0xf1,
|
||||
0xd2,0x14,0x3e,0xbb,0x98,0x65,0xc9,0x24,0x2f,0xcb,0x48,0xae,0xba,0x0e,0x43,0xb9,
|
||||
0xa4,0xa1,0x4f,0xab,0x1e,0x48,0xc9,0x82,0xdb,0xbc,0x77,0x24,0xf0,0x80,0x82,0x2d,
|
||||
0x81,0x77,0x1f,0x18,0x75,0x14,0xa8,0x20,0x86,0xa2,0xb0,0xc5,0x9a,0x7a,0xe7,0x02,
|
||||
0x81,0x80,0x1b,0x6d,0xb1,0x40,0x81,0xd9,0xbf,0x3f,0x9c,0x21,0xad,0x6e,0x91,0x7b,
|
||||
0x55,0x67,0x20,0x1a,0xef,0x91,0xef,0xed,0xdf,0x39,0x2c,0xe8,0x96,0xad,0x9e,0x94,
|
||||
0xae,0x85,0xf4,0x2d,0x66,0x6e,0xd0,0x80,0x3e,0x3c,0x05,0x33,0x88,0x4b,0x28,0x13,
|
||||
0x77,0x96,0x1f,0x24,0xa8,0xbf,0x29,0xf1,0xca,0x6d,0x29,0x34,0xf8,0x4e,0xc0,0x56,
|
||||
0x04,0x53,0xfa,0x08,0x1e,0x47,0xe2,0x5f,0x88,0xc3,0x08,0x82,0x54,0x69,0x79,0x0e,
|
||||
0xde,0x73,0xd0,0xb1,0x3e,0x60,0xe5,0x0b,0xdd,0x11,0x10,0x20,0xf2,0xec,0xaa,0x66,
|
||||
0x1a,0x32,0x1e,0xa7,0xaa,0xc1,0x2e,0x8f,0x33,0x8a,0xd8,0xa8,0xd6,0xcd,0x40,0x04,
|
||||
0xaf,0xb9,0x59,0xcc,0x30,0x9f,0x98,0xc9,0x10,0xaf,0x14,0xbe,0x72,0x89,0x94,0xe1,
|
||||
0x00,0xf1,0x02,0x81,0x81,0x00,0xd6,0xac,0x26,0xd2,0x42,0x5b,0x16,0xa9,0x39,0x02,
|
||||
0x63,0x76,0xa4,0xf5,0x40,0x3a,0xde,0xfa,0xea,0xd8,0xd3,0x12,0xee,0x44,0x00,0xfe,
|
||||
0xcb,0xa1,0x78,0x18,0xaa,0xa7,0x08,0xea,0x5e,0x36,0x52,0x28,0x0d,0x02,0x5a,0x9e,
|
||||
0x2d,0xc1,0x22,0x29,0x08,0x4f,0xed,0xff,0xa9,0xa6,0x08,0x8d,0x77,0xa4,0x5c,0xae,
|
||||
0xa7,0x8a,0x19,0x90,0xc2,0x12,0xc8,0x0f,0xb8,0x24,0xb5,0xba,0x45,0x2f,0xa6,0xc2,
|
||||
0x10,0x4c,0x0d,0x7e,0xf2,0xfd,0x11,0x26,0x16,0x34,0xbe,0x08,0x25,0x41,0x8b,0xcc,
|
||||
0x60,0xe7,0x02,0x3e,0x6a,0x54,0x05,0x80,0x66,0x2d,0x55,0x06,0xe6,0xbe,0x9b,0x15,
|
||||
0x9d,0xd3,0x5d,0xc4,0x6b,0x3f,0x74,0xa6,0x24,0xbc,0x7f,0x13,0xdf,0xe3,0x51,0x86,
|
||||
0x64,0x0f,0x1d,0x1f,0xf2,0x1e,
|
||||
0x30,0x82,0x04,0xa2,0x02,0x00,0x02,0x82,0x01,0x00,0x6f,0x25,0x74,0x63,0x2a,0x2f,
|
||||
0x5d,0xd4,0x54,0x03,0xbe,0xd5,0x34,0x71,0xe0,0x30,0x37,0xe5,0x2e,0x39,0xda,0xe7,
|
||||
0x04,0xd4,0xe2,0x5b,0x43,0xc3,0x6a,0x50,0x61,0xe8,0x4b,0x5d,0x58,0x30,0xa4,0xcc,
|
||||
0x6d,0xab,0xdf,0x8b,0x75,0x8c,0x22,0x43,0xd4,0xd0,0x18,0x5e,0x32,0x24,0xba,0x38,
|
||||
0x6f,0xab,0x64,0x86,0x8f,0x54,0x40,0x77,0xcb,0x3a,0xb5,0x30,0xde,0xb4,0xcd,0x98,
|
||||
0xbb,0xb1,0xdb,0x7a,0xd4,0xc7,0x0e,0xc7,0x99,0xc4,0x05,0xd5,0xa4,0x96,0x2a,0x3c,
|
||||
0x71,0x0f,0x31,0xa4,0xcd,0xc2,0x15,0x28,0xec,0x16,0x02,0x28,0x61,0x5e,0x8e,0xcf,
|
||||
0xb6,0x0b,0x8c,0x81,0x79,0x58,0xfc,0x9b,0x5b,0x32,0x26,0xcb,0xbc,0xf2,0xc9,0x8a,
|
||||
0x76,0x26,0x4e,0x87,0xaa,0x1b,0xd4,0xa7,0xb3,0xcf,0x96,0x99,0x86,0xcc,0xcb,0x5e,
|
||||
0xb2,0x66,0xc9,0xe0,0x10,0xbe,0xf7,0xd9,0x99,0xa3,0x49,0x5c,0x41,0x1f,0xa4,0xd0,
|
||||
0xd0,0x48,0x77,0xad,0x0f,0xbc,0x2c,0x2a,0x29,0x34,0x3f,0x20,0xb5,0x15,0xa1,0xa7,
|
||||
0x22,0xda,0x15,0xf3,0xf1,0x51,0x83,0x1f,0x3d,0x49,0x26,0x81,0x6d,0x65,0xa6,0x9c,
|
||||
0x09,0x01,0xfa,0x10,0x26,0x76,0xec,0x46,0x77,0xa6,0xc1,0xf5,0xc7,0xa3,0x2d,0xf9,
|
||||
0x60,0xa1,0x8f,0x94,0x17,0x58,0x0d,0xc9,0x55,0x50,0x2a,0xeb,0x44,0x5e,0xea,0x69,
|
||||
0xc9,0x76,0x67,0x9c,0x8e,0xd1,0x9c,0x4f,0x9d,0x9e,0x0a,0xec,0x44,0x6b,0x7e,0x01,
|
||||
0x2d,0x53,0xf2,0xd6,0x7c,0x27,0x30,0x3d,0x40,0x6c,0x3c,0xef,0x82,0xd1,0x7f,0xe2,
|
||||
0xd2,0x9b,0xb6,0x96,0x08,0xd2,0xe0,0x8a,0x28,0xeb,0x02,0x03,0x01,0x00,0x01,0x02,
|
||||
0x82,0x01,0x00,0x0b,0x89,0xcc,0x5c,0xd5,0x0e,0xc8,0xc3,0x57,0x9b,0x71,0xee,0xa9,
|
||||
0x3c,0x9f,0x24,0xf2,0x50,0x88,0xed,0x79,0xa3,0x9c,0xf5,0x4a,0xb0,0x65,0xc6,0xfe,
|
||||
0x1c,0xed,0x25,0x13,0xd9,0xd3,0x63,0x6d,0x60,0x49,0x8c,0x5b,0xaf,0x1b,0x1b,0x5a,
|
||||
0x9d,0x47,0x14,0xf9,0x4a,0xa2,0x12,0xfd,0x00,0x09,0xdb,0xb5,0x9a,0x60,0x7b,0xc3,
|
||||
0x1b,0x8c,0x8e,0x02,0x2c,0x5a,0x1a,0x53,0xf3,0xa4,0x9c,0x90,0xa7,0xde,0x39,0xf1,
|
||||
0xf7,0x57,0xa7,0xa9,0x61,0x65,0xee,0x2e,0xe1,0x4a,0x6d,0x64,0xde,0x72,0x7b,0xd0,
|
||||
0xfd,0x88,0x10,0xba,0xd5,0x9d,0x52,0x17,0x2a,0x4a,0x00,0x45,0xec,0x55,0x00,0x1f,
|
||||
0x6d,0x33,0x58,0xef,0xfd,0x1b,0x96,0xea,0xc4,0x44,0x82,0xb2,0x89,0x53,0xe8,0x02,
|
||||
0xba,0x0c,0x28,0xff,0xd1,0xda,0xdc,0xea,0xae,0x80,0xbe,0x33,0x86,0xbc,0x38,0xe9,
|
||||
0x1c,0xa9,0x39,0xc5,0x28,0x14,0x53,0x5a,0x52,0x3e,0xff,0xb8,0xc6,0x77,0x7c,0xe2,
|
||||
0xf9,0x50,0x9a,0x58,0x46,0x4e,0xdf,0x11,0x0f,0x4d,0x70,0xf3,0xe7,0xe7,0x9a,0x8a,
|
||||
0x9f,0x58,0x05,0x54,0xda,0x60,0x52,0xec,0xa8,0x10,0x60,0x9c,0x83,0xf0,0xd7,0x15,
|
||||
0xaf,0xf9,0x44,0xe8,0x3e,0x68,0xb2,0x06,0xa5,0x6d,0x6d,0xc1,0x8d,0x55,0xa3,0x6e,
|
||||
0x7e,0xe4,0x86,0x2a,0x6e,0x23,0xe0,0xf5,0xe6,0x08,0x05,0xb5,0x1a,0x6d,0x9c,0xf4,
|
||||
0xbd,0x18,0x20,0x58,0x43,0x67,0x72,0xde,0x47,0x56,0xee,0x94,0xc6,0x70,0xc1,0xda,
|
||||
0x15,0x2a,0xb9,0xb7,0x6a,0x10,0xc4,0x02,0x6e,0xae,0x93,0xe8,0x5e,0x8f,0x55,0x80,
|
||||
0x4e,0x9a,0x75,0x02,0x81,0x81,0x00,0xc4,0x25,0x05,0xab,0x8d,0x6b,0xa0,0xac,0x82,
|
||||
0x44,0xe2,0x13,0x06,0x2e,0x1c,0x7b,0x6b,0x37,0x69,0x93,0x9e,0x33,0x41,0xb1,0xf0,
|
||||
0x54,0x6e,0xe1,0x52,0x98,0x83,0x36,0x2b,0xe4,0x86,0x85,0x19,0x53,0x1f,0xd7,0x2f,
|
||||
0xbb,0x76,0xef,0x8d,0xb1,0x42,0xd3,0xfc,0xba,0xc7,0xb6,0xe4,0x73,0x42,0x83,0x1d,
|
||||
0x08,0xf9,0x17,0x83,0xd3,0xb7,0xe7,0xb4,0x26,0x74,0x59,0xb6,0x07,0xe1,0x1f,0x97,
|
||||
0x1e,0x66,0x77,0xe2,0x7a,0x3e,0xb2,0x43,0x2a,0x60,0x34,0xa6,0x2e,0x4a,0x13,0xb9,
|
||||
0x4f,0xc3,0x64,0xc5,0xee,0x04,0x40,0xf4,0xa5,0x01,0x45,0xba,0x9e,0x09,0x22,0xd9,
|
||||
0x99,0x0c,0x0e,0x23,0xd9,0x43,0x8b,0x01,0x1a,0x3f,0xd4,0xa8,0x8d,0x9a,0xfc,0x9c,
|
||||
0x05,0x1d,0x6d,0x7b,0x18,0xe0,0x95,0x02,0x81,0x81,0x00,0x91,0x10,0x4b,0x84,0xdc,
|
||||
0x10,0x67,0x22,0x84,0x60,0x96,0x2e,0x11,0x1a,0xe9,0x1c,0xb7,0x2f,0xa4,0x4c,0xf4,
|
||||
0xd0,0x57,0xa2,0x4b,0xbc,0xa2,0x02,0x0f,0x33,0x1b,0x1f,0x19,0x19,0x68,0x8d,0xb6,
|
||||
0x8a,0x36,0xe3,0xeb,0x2c,0x8c,0xba,0x69,0xb4,0x17,0x97,0xfe,0x0b,0x76,0x2a,0x97,
|
||||
0x87,0x0c,0xdf,0x1e,0x7a,0xbc,0xc0,0x86,0x27,0x31,0xb9,0x9d,0xc2,0xf2,0xb7,0xcc,
|
||||
0x83,0x6a,0x5a,0xa1,0xab,0x05,0x60,0xa0,0x04,0x90,0xe2,0xc4,0x03,0xb4,0xd8,0x30,
|
||||
0xaa,0x93,0xd8,0x90,0x4e,0x3c,0x33,0x1f,0x43,0xa2,0x3a,0x2c,0x34,0xb9,0x01,0x89,
|
||||
0xbb,0xdc,0x0b,0x2e,0x4f,0x89,0x1b,0xf8,0x77,0x4c,0x4c,0x25,0xc5,0xca,0x38,0x00,
|
||||
0xd4,0x3a,0xaa,0x7c,0xf6,0xb6,0xad,0x69,0x0d,0x03,0x7f,0x02,0x81,0x81,0x00,0xa3,
|
||||
0xcc,0xef,0x21,0x46,0xe6,0xdc,0xb5,0x73,0xcc,0xa6,0xa7,0x90,0x7f,0xad,0x95,0x7c,
|
||||
0x02,0x38,0x8e,0xe8,0x8c,0x91,0x8e,0x51,0xcf,0x91,0x11,0x66,0x72,0xab,0x10,0xf0,
|
||||
0x32,0xd6,0x0c,0x0d,0x0c,0x18,0x09,0x12,0x79,0x91,0x67,0x98,0x82,0xb1,0xf6,0x6a,
|
||||
0x96,0x68,0xf6,0x59,0x6d,0xcf,0xdb,0xc2,0xc1,0x9d,0x93,0x7f,0xa9,0xad,0x69,0x38,
|
||||
0x4e,0xec,0xd7,0x86,0x66,0xaa,0x20,0x41,0x89,0x47,0xb5,0x52,0x53,0x18,0x4c,0xb2,
|
||||
0x3e,0x8f,0x3d,0x28,0x92,0x7b,0x96,0x61,0x29,0x35,0x59,0xd0,0xd9,0x66,0x80,0x00,
|
||||
0x4e,0x53,0xf3,0xb1,0x57,0x0c,0xf6,0x27,0x95,0xe2,0x35,0x64,0xc6,0xa9,0xdb,0x49,
|
||||
0xbe,0x6c,0x13,0xe1,0xf6,0xef,0xb9,0x89,0x69,0xd4,0x1b,0x7b,0xb3,0x58,0xc9,0x02,
|
||||
0x81,0x80,0x40,0x28,0x3d,0xce,0x37,0xea,0x05,0x43,0x2d,0xda,0xed,0xf0,0xd7,0xdd,
|
||||
0xd8,0x05,0xbc,0x3b,0x14,0xe6,0x78,0x4c,0x00,0xc6,0x25,0xca,0xfa,0xb8,0x00,0x72,
|
||||
0xf0,0xe6,0xd3,0x19,0xfa,0xb4,0xda,0x6b,0xcc,0x95,0x06,0xf9,0x00,0x10,0x9e,0x19,
|
||||
0x69,0x69,0xee,0x90,0xb1,0x25,0x6b,0x38,0xee,0x87,0x6b,0x9a,0x8b,0x0a,0x77,0x0a,
|
||||
0xb4,0xa2,0x4c,0x54,0xe1,0x36,0x4a,0xfc,0x40,0x38,0x6f,0x52,0x0d,0x21,0xcc,0x03,
|
||||
0xd8,0xf4,0x82,0x0e,0xc5,0x97,0xec,0x06,0x35,0x37,0x4d,0xb3,0x5c,0x4a,0x9b,0xe4,
|
||||
0x34,0xc6,0x97,0xb0,0x85,0xb6,0x59,0x6d,0x3d,0x87,0xb0,0x66,0xba,0xd4,0x25,0x12,
|
||||
0xd6,0x2a,0xc3,0x75,0xf3,0xd6,0xca,0xff,0x12,0x27,0x3e,0xf7,0x7a,0x99,0xbd,0x61,
|
||||
0x65,0x0f,0x02,0x81,0x81,0x00,0xb2,0xcb,0x21,0xf9,0x77,0x44,0x20,0xee,0xe9,0x60,
|
||||
0xf2,0x32,0x7e,0xd0,0xb2,0x8b,0xa7,0x96,0x20,0x20,0xf2,0x88,0xbd,0xbe,0x1f,0x92,
|
||||
0x59,0x26,0x7c,0x26,0x64,0x13,0xfc,0x9a,0x1c,0xd6,0x48,0xbf,0xe3,0xad,0x2d,0x89,
|
||||
0xd4,0x11,0x9b,0xed,0x38,0x99,0x3e,0xf4,0xe3,0x54,0xa3,0x0c,0x2a,0x91,0xdc,0xf9,
|
||||
0x38,0x94,0xbe,0xd7,0x90,0xc2,0x8d,0xcc,0x5a,0x28,0xbd,0x46,0x4e,0xd7,0x86,0x52,
|
||||
0x95,0xb1,0x39,0xb9,0x30,0x33,0x1f,0xe8,0xe7,0x37,0xfe,0x37,0xa5,0x20,0x82,0x1a,
|
||||
0xfd,0xc3,0x30,0xd0,0xdc,0x8d,0x71,0x66,0x30,0xb4,0x9a,0xb2,0xd6,0x03,0xfe,0xc5,
|
||||
0x4b,0xfd,0xd2,0x1b,0x3e,0x4e,0xc6,0xb0,0xe8,0x6c,0x83,0x44,0x6b,0xaa,0x05,0x51,
|
||||
0xd3,0xb2,0x04,0xca,0xf6,0xf3,
|
||||
};
|
||||
|
||||
char public_key_buffer[] = {
|
||||
0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0x9b,0x28,0x10,0x02,0xd2,0x43,0x5b,
|
||||
0x2b,0x7c,0x81,0xce,0x2b,0x77,0xb4,0xbf,0x5f,0x2a,0x9a,0x96,0xc9,0xa4,0xd7,0xbb,
|
||||
0xb3,0xfb,0xc1,0x8a,0xad,0xbe,0x21,0x4e,0xd7,0x15,0xc4,0x8c,0x0a,0x88,0x5b,0x02,
|
||||
0xa9,0xcd,0x2e,0xee,0xd3,0x5e,0xb9,0xfd,0x27,0x0b,0xdb,0xf6,0xe7,0xb7,0x39,0xc1,
|
||||
0xfa,0x34,0x3f,0xa7,0xe4,0x04,0xaf,0xa8,0xc2,0x36,0x4e,0xf5,0x0c,0xf1,0x9b,0x92,
|
||||
0x26,0x32,0x20,0xdb,0x04,0xf5,0xb8,0x2e,0xf5,0xfc,0x47,0xd3,0x2a,0xa1,0x2d,0x5b,
|
||||
0x68,0x2c,0x5e,0xc6,0xc9,0x35,0x57,0x7b,0x65,0x17,0xd7,0x5d,0x10,0x5c,0x51,0xfb,
|
||||
0xcb,0x95,0xd1,0x17,0x42,0xa9,0xfd,0xd1,0xc4,0x32,0x1f,0x13,0xf2,0xeb,0x6b,0x91,
|
||||
0x01,0xe9,0x89,0x19,0x3a,0x2b,0x6d,0xae,0x91,0x27,0xe2,0x5e,0x06,0x5b,0x99,0xfb,
|
||||
0x20,0x3c,0xc4,0x92,0x20,0xc4,0x68,0x24,0x6b,0x74,0xdc,0x6d,0xf7,0xa8,0x10,0x1b,
|
||||
0xdf,0x20,0xed,0x4e,0x90,0x0e,0x3d,0xf6,0xef,0x3a,0x94,0x8b,0x12,0x61,0xac,0xed,
|
||||
0x95,0xbc,0xe2,0xed,0xb9,0x22,0xc2,0xdd,0xc7,0x19,0x68,0x09,0x14,0x71,0xb0,0x37,
|
||||
0xf7,0xbd,0x65,0x11,0x31,0x9d,0x89,0x6e,0x21,0xcf,0x60,0xc1,0x8d,0xbe,0x31,0x96,
|
||||
0xd2,0xdd,0x0e,0x20,0x38,0x07,0xd5,0xea,0xda,0xc8,0x9a,0x47,0x5b,0x05,0xce,0x7d,
|
||||
0xf7,0x4e,0xcd,0xbb,0x89,0xdd,0x46,0x16,0x8f,0x39,0x9d,0x32,0x19,0xaf,0x6e,0xc4,
|
||||
0xb3,0x6c,0x79,0x5a,0x70,0x11,0x8f,0xe2,0x75,0x33,0x09,0xc8,0xf6,0xd7,0x40,0x25,
|
||||
0xe7,0xa3,0xf0,0x6f,0x9a,0xdb,0x35,0x74,0xc1,0x02,0x03,0x01,0x00,0x01,
|
||||
// 0x30,0x82,0x01,0x21,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
|
||||
// 0x01,0x05,0x00,0x03,0x82,0x01,0x0e,0x00,
|
||||
0x30,0x82,0x01,0x09,0x02,0x82,0x01,0x00,
|
||||
0x6f,0x25,0x74,0x63,0x2a,0x2f,0x5d,0xd4,0x54,0x03,0xbe,0xd5,0x34,0x71,0xe0,0x30,
|
||||
0x37,0xe5,0x2e,0x39,0xda,0xe7,0x04,0xd4,0xe2,0x5b,0x43,0xc3,0x6a,0x50,0x61,0xe8,
|
||||
0x4b,0x5d,0x58,0x30,0xa4,0xcc,0x6d,0xab,0xdf,0x8b,0x75,0x8c,0x22,0x43,0xd4,0xd0,
|
||||
0x18,0x5e,0x32,0x24,0xba,0x38,0x6f,0xab,0x64,0x86,0x8f,0x54,0x40,0x77,0xcb,0x3a,
|
||||
0xb5,0x30,0xde,0xb4,0xcd,0x98,0xbb,0xb1,0xdb,0x7a,0xd4,0xc7,0x0e,0xc7,0x99,0xc4,
|
||||
0x05,0xd5,0xa4,0x96,0x2a,0x3c,0x71,0x0f,0x31,0xa4,0xcd,0xc2,0x15,0x28,0xec,0x16,
|
||||
0x02,0x28,0x61,0x5e,0x8e,0xcf,0xb6,0x0b,0x8c,0x81,0x79,0x58,0xfc,0x9b,0x5b,0x32,
|
||||
0x26,0xcb,0xbc,0xf2,0xc9,0x8a,0x76,0x26,0x4e,0x87,0xaa,0x1b,0xd4,0xa7,0xb3,0xcf,
|
||||
0x96,0x99,0x86,0xcc,0xcb,0x5e,0xb2,0x66,0xc9,0xe0,0x10,0xbe,0xf7,0xd9,0x99,0xa3,
|
||||
0x49,0x5c,0x41,0x1f,0xa4,0xd0,0xd0,0x48,0x77,0xad,0x0f,0xbc,0x2c,0x2a,0x29,0x34,
|
||||
0x3f,0x20,0xb5,0x15,0xa1,0xa7,0x22,0xda,0x15,0xf3,0xf1,0x51,0x83,0x1f,0x3d,0x49,
|
||||
0x26,0x81,0x6d,0x65,0xa6,0x9c,0x09,0x01,0xfa,0x10,0x26,0x76,0xec,0x46,0x77,0xa6,
|
||||
0xc1,0xf5,0xc7,0xa3,0x2d,0xf9,0x60,0xa1,0x8f,0x94,0x17,0x58,0x0d,0xc9,0x55,0x50,
|
||||
0x2a,0xeb,0x44,0x5e,0xea,0x69,0xc9,0x76,0x67,0x9c,0x8e,0xd1,0x9c,0x4f,0x9d,0x9e,
|
||||
0x0a,0xec,0x44,0x6b,0x7e,0x01,0x2d,0x53,0xf2,0xd6,0x7c,0x27,0x30,0x3d,0x40,0x6c,
|
||||
0x3c,0xef,0x82,0xd1,0x7f,0xe2,0xd2,0x9b,0xb6,0x96,0x08,0xd2,0xe0,0x8a,0x28,0xeb,
|
||||
0x02,0x03,0x01,0x00,0x01
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -133,23 +138,23 @@ void test_rsa(protected_tester_t *tester)
|
||||
{
|
||||
rsa_private_key_t *private_key;
|
||||
rsa_public_key_t *public_key;
|
||||
certificate_t *certificate;
|
||||
chunk_t data, signature;
|
||||
chunk_t der_private_key = {private_key_buffer, sizeof(private_key_buffer)};
|
||||
chunk_t der_public_key = {public_key_buffer, sizeof(public_key_buffer)};
|
||||
logger_t *logger;
|
||||
status_t status;
|
||||
|
||||
/* key generation and signing */
|
||||
u_int8_t test_data[] = {
|
||||
0x01,0x02,0x03,0x04,
|
||||
0x01,0x02,0x03,0x04,
|
||||
0x01,0x02,0x03,0x04,
|
||||
0x01,0x02,0x03,0x04,
|
||||
0x01,0x02,0x03,0x04,
|
||||
0x01,0x02,0x03,0x04,
|
||||
0x01,0x02,0x03,0x04,
|
||||
0x01,0x02,0x03,0x04,
|
||||
0x01,0x02,0x03,0x04,
|
||||
0x11,0x12,0x13,0x14,
|
||||
0x21,0x22,0x23,0x24,
|
||||
0x31,0x32,0x33,0x34,
|
||||
0x41,0x42,0x43,0x44,
|
||||
0x51,0x52,0x53,0x54,
|
||||
0x61,0x62,0x63,0x64,
|
||||
0x71,0x72,0x73,0x74,
|
||||
0x81,0x82,0x83,0x84,
|
||||
};
|
||||
data.ptr = test_data;
|
||||
data.len = sizeof(test_data);
|
||||
@@ -157,37 +162,66 @@ void test_rsa(protected_tester_t *tester)
|
||||
logger = charon->logger_manager->get_logger(charon->logger_manager, TESTER);
|
||||
logger->disable_level(logger, FULL);
|
||||
|
||||
private_key = rsa_private_key_create();
|
||||
/* key generation and signing */
|
||||
// private_key = rsa_private_key_create(512);
|
||||
// tester->assert_true(tester, private_key != NULL, "generating private key");
|
||||
//
|
||||
// status = private_key->build_emsa_pkcs1_signature(private_key, HASH_MD5, data, &signature);
|
||||
// tester->assert_true(tester, status == SUCCESS, "build emsa_pkcs1_signature (genkey)");
|
||||
//
|
||||
// public_key = private_key->get_public_key(private_key);
|
||||
// tester->assert_true(tester, public_key != NULL, "extracting public key");
|
||||
//
|
||||
// status = public_key->verify_emsa_pkcs1_signature(public_key, data, signature);
|
||||
// tester->assert_true(tester, status == SUCCESS, "verify emsa_pkcs1_signature (genkey)");
|
||||
//
|
||||
// allocator_free(signature.ptr);
|
||||
//
|
||||
// private_key->destroy(private_key);
|
||||
// public_key->destroy(public_key);
|
||||
|
||||
private_key->generate_key(private_key, 512);
|
||||
/* key setting */
|
||||
private_key = rsa_private_key_create_from_chunk(der_private_key);
|
||||
tester->assert_true(tester, private_key != NULL, "loading private key from chunk");
|
||||
public_key = rsa_public_key_create_from_chunk(der_public_key);
|
||||
tester->assert_true(tester, public_key != NULL, "loading public key from chunk");
|
||||
|
||||
status = private_key->build_emsa_pkcs1_signature(private_key, HASH_MD5, data, &signature);
|
||||
tester->assert_true(tester, status == SUCCESS, "build emsa_pkcs1_signature (genkey)");
|
||||
|
||||
public_key = private_key->get_public_key(private_key);
|
||||
|
||||
tester->assert_true(tester, status == SUCCESS, "build emsa_pkcs1_signature (setkey)");
|
||||
status = public_key->verify_emsa_pkcs1_signature(public_key, data, signature);
|
||||
tester->assert_true(tester, status == SUCCESS, "verify emsa_pkcs1_signature (genkey)");
|
||||
tester->assert_true(tester, status == SUCCESS, "verify emsa_pkcs1_signature (setkey)");
|
||||
|
||||
allocator_free(signature.ptr);
|
||||
|
||||
/* key comparison */
|
||||
tester->assert_true(tester, private_key->belongs_to(private_key, public_key), "key belongs to");
|
||||
|
||||
private_key->destroy(private_key);
|
||||
private_key = rsa_private_key_create(512);
|
||||
tester->assert_false(tester, private_key->belongs_to(private_key, public_key), "key belongs not to");
|
||||
|
||||
public_key->destroy(public_key);
|
||||
private_key->destroy(private_key);
|
||||
|
||||
/* key loading */
|
||||
private_key = rsa_private_key_create();
|
||||
private_key->set_key(private_key, der_private_key);
|
||||
private_key = rsa_private_key_create_from_file("alice.der", NULL);
|
||||
tester->assert_true(tester, private_key != NULL, "loading private key from file");
|
||||
certificate = certificate_create_from_file("alice-cert.der");
|
||||
tester->assert_true(tester, public_key != NULL, "loading certificate from file");
|
||||
public_key = certificate->get_public_key(certificate);
|
||||
tester->assert_true(tester, public_key != NULL, "loading public key from certificate");
|
||||
|
||||
public_key = rsa_public_key_create();
|
||||
public_key->set_key(public_key, der_public_key);
|
||||
tester->assert_true(tester, private_key->belongs_to(private_key, public_key), "key belongs to");
|
||||
|
||||
status = private_key->build_emsa_pkcs1_signature(private_key, HASH_MD5, data, &signature);
|
||||
tester->assert_true(tester, status == SUCCESS, "build emsa_pkcs1_signature (setkey)");
|
||||
status = private_key->build_emsa_pkcs1_signature(private_key, HASH_SHA1, data, &signature);
|
||||
tester->assert_true(tester, status == SUCCESS, "build emsa_pkcs1_signature (loadkey)");
|
||||
status = public_key->verify_emsa_pkcs1_signature(public_key, data, signature);
|
||||
tester->assert_true(tester, status == SUCCESS, "verify emsa_pkcs1_signature (setkey)");
|
||||
tester->assert_true(tester, status == SUCCESS, "verify emsa_pkcs1_signature (loadkey)");
|
||||
|
||||
allocator_free(signature.ptr);
|
||||
|
||||
certificate->destroy(certificate);
|
||||
public_key->destroy(public_key);
|
||||
private_key->destroy(private_key);
|
||||
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#include <testcases/kernel_interface_test.h>
|
||||
#include <testcases/child_sa_test.h>
|
||||
#include <testcases/der_decoder_test.h>
|
||||
#include <testcases/certificate_test.h>
|
||||
|
||||
/* output for test messages */
|
||||
extern FILE * stderr;
|
||||
@@ -130,6 +131,7 @@ test_t rsa_test = {test_rsa, "RSA private/public key test"};
|
||||
test_t kernel_interface_test = {test_kernel_interface, "Kernel Interface"};
|
||||
test_t child_sa_test = {test_child_sa, "Child SA"};
|
||||
test_t der_decoder_test = {test_der_decoder, "DER decoder"};
|
||||
test_t certificate_test = {test_certificate, "X509 Certificate"};
|
||||
|
||||
|
||||
daemon_t* charon;
|
||||
@@ -251,12 +253,11 @@ int main()
|
||||
|
||||
daemon_create();
|
||||
|
||||
charon->logger_manager->disable_log_level(charon->logger_manager,TESTER,FULL);
|
||||
charon->logger_manager->enable_log_level(charon->logger_manager,DER_DECODER,FULL);
|
||||
//charon->logger_manager->enable_log_level(charon->logger_manager, ALL_LOGGERS, FULL);
|
||||
charon->logger_manager->set_output(charon->logger_manager, ALL_LOGGERS, stdout);
|
||||
|
||||
tester_t *tester = tester_create(test_output, FALSE);
|
||||
|
||||
|
||||
//tester->perform_tests(tester,all_tests);
|
||||
tester->perform_test(tester,&rsa_test);
|
||||
|
||||
|
||||
+190
-28
@@ -27,6 +27,7 @@
|
||||
#include <sys/un.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
@@ -34,6 +35,7 @@
|
||||
|
||||
#include <types.h>
|
||||
#include <daemon.h>
|
||||
#include <transforms/certificate.h>
|
||||
#include <utils/allocator.h>
|
||||
#include <queues/jobs/initiate_ike_sa_job.h>
|
||||
|
||||
@@ -53,7 +55,7 @@ struct configuration_entry_t {
|
||||
|
||||
/**
|
||||
* Configuration name.
|
||||
*
|
||||
*
|
||||
*/
|
||||
char *name;
|
||||
|
||||
@@ -67,6 +69,16 @@ struct configuration_entry_t {
|
||||
*/
|
||||
policy_t *policy;
|
||||
|
||||
/**
|
||||
* Public key of other peer
|
||||
*/
|
||||
rsa_public_key_t *public_key;
|
||||
|
||||
/**
|
||||
* Own private key
|
||||
*/
|
||||
rsa_private_key_t *private_key;
|
||||
|
||||
/**
|
||||
* Destroys a configuration_entry_t
|
||||
*/
|
||||
@@ -80,6 +92,10 @@ static void configuration_entry_destroy (configuration_entry_t *this)
|
||||
{
|
||||
this->connection->destroy(this->connection);
|
||||
this->policy->destroy(this->policy);
|
||||
if (this->public_key)
|
||||
{
|
||||
this->public_key->destroy(this->public_key);
|
||||
}
|
||||
allocator_free(this->name);
|
||||
allocator_free(this);
|
||||
}
|
||||
@@ -87,7 +103,8 @@ static void configuration_entry_destroy (configuration_entry_t *this)
|
||||
/**
|
||||
* Creates a configuration_entry_t object.
|
||||
*/
|
||||
static configuration_entry_t * configuration_entry_create(char *name, connection_t* connection, policy_t *policy)
|
||||
static configuration_entry_t * configuration_entry_create(char *name, connection_t* connection, policy_t *policy,
|
||||
rsa_private_key_t *private_key, rsa_public_key_t *public_key)
|
||||
{
|
||||
configuration_entry_t *entry = allocator_alloc_thing(configuration_entry_t);
|
||||
|
||||
@@ -97,6 +114,8 @@ static configuration_entry_t * configuration_entry_create(char *name, connection
|
||||
/* private data */
|
||||
entry->connection = connection;
|
||||
entry->policy = policy;
|
||||
entry->public_key = public_key;
|
||||
entry->private_key = private_key;
|
||||
entry->name = allocator_alloc(strlen(name) + 1);
|
||||
strcpy(entry->name, name);
|
||||
|
||||
@@ -123,12 +142,7 @@ struct private_stroke_t {
|
||||
/**
|
||||
* The list of RSA private keys accessible through crendial_store_t interface
|
||||
*/
|
||||
linked_list_t *rsa_private_keys;
|
||||
|
||||
/**
|
||||
* The list of RSA public keys accessible through crendial_store_t interface
|
||||
*/
|
||||
linked_list_t *rsa_public_keys;
|
||||
linked_list_t *private_keys;
|
||||
|
||||
/**
|
||||
* Assigned logger_t object.
|
||||
@@ -158,8 +172,8 @@ struct private_stroke_t {
|
||||
|
||||
/**
|
||||
* Helper function which corrects the string pointers
|
||||
* in a stroke_msg_t. Strings in a stroke_msg sent over wire
|
||||
* contain RELATIVE addresses (relative to the beginning of the
|
||||
* in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
|
||||
* contains RELATIVE addresses (relative to the beginning of the
|
||||
* stroke_msg). They must be corrected if they reach our address
|
||||
* space...
|
||||
*/
|
||||
@@ -183,6 +197,69 @@ static void pop_string(stroke_msg_t *msg, char **string)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the private key for a public key
|
||||
*/
|
||||
static rsa_private_key_t *find_private_key(private_stroke_t *this, rsa_public_key_t *public_key)
|
||||
{
|
||||
rsa_private_key_t *private_key = NULL;
|
||||
iterator_t *iterator;
|
||||
|
||||
iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
|
||||
while (iterator->has_next(iterator))
|
||||
{
|
||||
iterator->current(iterator, (void**)&private_key);
|
||||
if (private_key->belongs_to(private_key, public_key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return private_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all private keys form "/etc/ipsec.d/private/"
|
||||
*/
|
||||
static void load_private_keys(private_stroke_t *this)
|
||||
{
|
||||
struct dirent* entry;
|
||||
struct stat stb;
|
||||
DIR* dir;
|
||||
rsa_private_key_t *key;
|
||||
|
||||
/* currently only unencrypted binary DER files are loaded */
|
||||
dir = opendir(PRIVATE_KEY_DIR);
|
||||
if (dir == NULL || chdir(PRIVATE_KEY_DIR) == -1) {
|
||||
this->logger->log(this->logger, ERROR, "error opening private key directory \"%s\"", PRIVATE_KEY_DIR);
|
||||
return;
|
||||
}
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if (stat(entry->d_name, &stb) == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* try to parse all regular files */
|
||||
if (stb.st_mode & S_IFREG)
|
||||
{
|
||||
key = rsa_private_key_create_from_file(entry->d_name, NULL);
|
||||
if (key)
|
||||
{
|
||||
this->private_keys->insert_last(this->private_keys, (void*)key);
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1, "loaded private key \"%s%s\"",
|
||||
PRIVATE_KEY_DIR, entry->d_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1, "private key \"%s%s\" invalid, skipped",
|
||||
PRIVATE_KEY_DIR, entry->d_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_stroke_t.stroke_receive.
|
||||
*/
|
||||
@@ -232,6 +309,7 @@ static void stroke_receive(private_stroke_t *this)
|
||||
{
|
||||
initiate_ike_sa_job_t *job;
|
||||
connection_t *connection;
|
||||
|
||||
pop_string(msg, &(msg->initiate.name));
|
||||
this->logger->log(this->logger, CONTROL, "received stroke: initiate \"%s\"", msg->initiate.name);
|
||||
connection = this->get_connection_by_name(this, msg->initiate.name);
|
||||
@@ -260,12 +338,17 @@ static void stroke_receive(private_stroke_t *this)
|
||||
host_t *my_host, *other_host, *my_subnet, *other_subnet;
|
||||
proposal_t *proposal;
|
||||
traffic_selector_t *my_ts, *other_ts;
|
||||
certificate_t *my_cert, *other_cert;
|
||||
rsa_private_key_t *private_key = NULL;
|
||||
rsa_public_key_t *public_key = NULL;
|
||||
|
||||
pop_string(msg, &msg->add_conn.name);
|
||||
pop_string(msg, &msg->add_conn.me.address);
|
||||
pop_string(msg, &msg->add_conn.other.address);
|
||||
pop_string(msg, &msg->add_conn.me.id);
|
||||
pop_string(msg, &msg->add_conn.other.id);
|
||||
pop_string(msg, &msg->add_conn.me.cert);
|
||||
pop_string(msg, &msg->add_conn.other.cert);
|
||||
pop_string(msg, &msg->add_conn.me.subnet);
|
||||
pop_string(msg, &msg->add_conn.other.subnet);
|
||||
|
||||
@@ -339,6 +422,7 @@ static void stroke_receive(private_stroke_t *this)
|
||||
host_t *tmp_host = my_host;
|
||||
identification_t *tmp_id = my_id;
|
||||
traffic_selector_t *tmp_ts = my_ts;
|
||||
char *tmp_cert = msg->add_conn.me.cert;
|
||||
|
||||
my_host = other_host;
|
||||
other_host = tmp_host;
|
||||
@@ -346,6 +430,8 @@ static void stroke_receive(private_stroke_t *this)
|
||||
other_id = tmp_id;
|
||||
my_ts = other_ts;
|
||||
other_ts = tmp_ts;
|
||||
msg->add_conn.me.cert = msg->add_conn.other.cert;
|
||||
msg->add_conn.other.cert = tmp_cert;
|
||||
}
|
||||
else if (charon->socket->is_listening_on(charon->socket, my_host))
|
||||
{
|
||||
@@ -364,7 +450,8 @@ static void stroke_receive(private_stroke_t *this)
|
||||
break;
|
||||
}
|
||||
|
||||
connection = connection_create(my_host, other_host, my_id->clone(my_id), other_id->clone(other_id), SHARED_KEY_MESSAGE_INTEGRITY_CODE);
|
||||
connection = connection_create(my_host, other_host, my_id->clone(my_id), other_id->clone(other_id),
|
||||
RSA_DIGITAL_SIGNATURE);
|
||||
proposal = proposal_create(1);
|
||||
proposal->add_algorithm(proposal, PROTO_IKE, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
|
||||
proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
|
||||
@@ -387,8 +474,44 @@ static void stroke_receive(private_stroke_t *this)
|
||||
policy->add_my_traffic_selector(policy, my_ts);
|
||||
policy->add_other_traffic_selector(policy, other_ts);
|
||||
|
||||
|
||||
chdir(CERTIFICATE_DIR);
|
||||
my_cert = certificate_create_from_file(msg->add_conn.me.cert);
|
||||
if (my_cert == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "loading own certificate \"%s%s\" failed",
|
||||
CERTIFICATE_DIR, msg->add_conn.me.cert);
|
||||
}
|
||||
else
|
||||
{
|
||||
private_key = find_private_key(this, my_cert->get_public_key(my_cert));
|
||||
if (private_key)
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1, "found private key for certificate \"%s%s\"",
|
||||
CERTIFICATE_DIR, msg->add_conn.me.cert);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "no private key for certificate \"%s%s\" found",
|
||||
CERTIFICATE_DIR, msg->add_conn.me.cert);
|
||||
}
|
||||
}
|
||||
other_cert = certificate_create_from_file(msg->add_conn.other.cert);
|
||||
if (other_cert == NULL)
|
||||
{
|
||||
this->logger->log(this->logger, ERROR, "loading peers certificate \"%s%s\" failed",
|
||||
CERTIFICATE_DIR, msg->add_conn.other.cert);
|
||||
}
|
||||
else
|
||||
{
|
||||
public_key = other_cert->get_public_key(other_cert);
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1, "loaded certificate \"%s%s\" (%p)",
|
||||
CERTIFICATE_DIR, msg->add_conn.other.cert, public_key);
|
||||
|
||||
}
|
||||
|
||||
this->configurations->insert_last(this->configurations,
|
||||
configuration_entry_create(msg->add_conn.name, connection, policy));
|
||||
configuration_entry_create(msg->add_conn.name, connection, policy, private_key, public_key));
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL1, "connection \"%s\" added (%d in store)",
|
||||
msg->add_conn.name,
|
||||
@@ -405,7 +528,6 @@ static void stroke_receive(private_stroke_t *this)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of connection_store_t.get_connection_by_hosts.
|
||||
*/
|
||||
@@ -608,17 +730,63 @@ static status_t get_shared_secret(credential_store_t *this, identification_t *id
|
||||
/**
|
||||
* Implementation of credential_store_t.get_rsa_public_key.
|
||||
*/
|
||||
static status_t get_rsa_public_key(credential_store_t *this, identification_t *identification, rsa_public_key_t **public_key)
|
||||
static status_t get_rsa_public_key(credential_store_t *store, identification_t *identification, rsa_public_key_t **public_key)
|
||||
{
|
||||
return FAILED;
|
||||
private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, credentials));
|
||||
iterator_t *iterator;
|
||||
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "Looking for public key for %s",
|
||||
identification->get_string(identification));
|
||||
iterator = this->configurations->create_iterator(this->configurations, TRUE);
|
||||
while (iterator->has_next(iterator))
|
||||
{
|
||||
configuration_entry_t *config;
|
||||
iterator->current(iterator, (void**)&config);
|
||||
identification_t *stored = config->policy->get_other_id(config->policy);
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "there is one for %s",
|
||||
stored->get_string(stored));
|
||||
if (identification->equals(identification, stored))
|
||||
{
|
||||
this->logger->log(this->logger, CONTROL|LEVEL2, "found a match: %p",
|
||||
config->public_key);
|
||||
if (config->public_key)
|
||||
{
|
||||
iterator->destroy(iterator);
|
||||
*public_key = config->public_key;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of credential_store_t.get_rsa_private_key.
|
||||
*/
|
||||
static status_t get_rsa_private_key(credential_store_t *this, identification_t *identification, rsa_private_key_t **private_key)
|
||||
static status_t get_rsa_private_key(credential_store_t *store, identification_t *identification, rsa_private_key_t **private_key)
|
||||
{
|
||||
return FAILED;
|
||||
private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, credentials));
|
||||
iterator_t *iterator;
|
||||
|
||||
iterator = this->configurations->create_iterator(this->configurations, TRUE);
|
||||
while (iterator->has_next(iterator))
|
||||
{
|
||||
configuration_entry_t *config;
|
||||
iterator->current(iterator, (void**)&config);
|
||||
identification_t *stored = config->policy->get_my_id(config->policy);
|
||||
if (identification->equals(identification, stored))
|
||||
{
|
||||
if (config->private_key)
|
||||
{
|
||||
iterator->destroy(iterator);
|
||||
*private_key = config->private_key;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
iterator->destroy(iterator);
|
||||
return NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -627,7 +795,6 @@ static status_t get_rsa_private_key(credential_store_t *this, identification_t *
|
||||
static void destroy(private_stroke_t *this)
|
||||
{
|
||||
configuration_entry_t *entry;
|
||||
rsa_public_key_t *pub_key;
|
||||
rsa_private_key_t *priv_key;
|
||||
|
||||
while (this->configurations->remove_first(this->configurations, (void **)&entry) == SUCCESS)
|
||||
@@ -636,17 +803,11 @@ static void destroy(private_stroke_t *this)
|
||||
}
|
||||
this->configurations->destroy(this->configurations);
|
||||
|
||||
while (this->rsa_private_keys->remove_first(this->rsa_private_keys, (void **)&priv_key) == SUCCESS)
|
||||
while (this->private_keys->remove_first(this->private_keys, (void **)&priv_key) == SUCCESS)
|
||||
{
|
||||
priv_key->destroy(priv_key);
|
||||
}
|
||||
this->rsa_private_keys->destroy(this->rsa_private_keys);
|
||||
|
||||
while (this->rsa_public_keys->remove_first(this->rsa_public_keys, (void **)&pub_key) == SUCCESS)
|
||||
{
|
||||
pub_key->destroy(pub_key);
|
||||
}
|
||||
this->rsa_public_keys->destroy(this->rsa_public_keys);
|
||||
this->private_keys->destroy(this->private_keys);
|
||||
|
||||
close(this->socket);
|
||||
unlink(socket_addr.sun_path);
|
||||
@@ -729,8 +890,9 @@ stroke_t *stroke_create()
|
||||
|
||||
/* private variables */
|
||||
this->configurations = linked_list_create();
|
||||
this->rsa_private_keys = linked_list_create();
|
||||
this->rsa_public_keys = linked_list_create();
|
||||
this->private_keys = linked_list_create();
|
||||
|
||||
load_private_keys(this);
|
||||
|
||||
return (&this->public);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
|
||||
|
||||
#define STROKE_SOCKET "/var/run/charon.ctl"
|
||||
#define IPSEC_DIR "/etc/ipsec.d/"
|
||||
#define PRIVATE_KEY_DIR IPSEC_DIR "private/"
|
||||
#define CERTIFICATE_DIR IPSEC_DIR "certs/"
|
||||
|
||||
/**
|
||||
* @brief A stroke message sent over the unix socket.
|
||||
@@ -61,6 +64,7 @@ struct stroke_msg_t {
|
||||
char *name;
|
||||
struct {
|
||||
char *id;
|
||||
char *cert;
|
||||
char *address;
|
||||
char *subnet;
|
||||
u_int8_t subnet_mask;
|
||||
|
||||
@@ -31,3 +31,7 @@ $(BUILD_DIR)hmac.o : $(TRANSFORMS_DIR)hmac.c $(TRANSFORMS_DIR)hmac.h
|
||||
OBJS+= $(BUILD_DIR)prf_plus.o
|
||||
$(BUILD_DIR)prf_plus.o : $(TRANSFORMS_DIR)prf_plus.c $(TRANSFORMS_DIR)prf_plus.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
OBJS+= $(BUILD_DIR)certificate.o
|
||||
$(BUILD_DIR)certificate.o : $(TRANSFORMS_DIR)certificate.c $(TRANSFORMS_DIR)certificate.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
|
||||
#include <gmp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "certificate.h"
|
||||
|
||||
@@ -39,430 +41,108 @@ 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_certiciate_t, x)
|
||||
#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, 0, 0, 0 }, /* tbsCertificate */
|
||||
{ ASN1_TAG_E_0, ASN1_DEFAULT, OSET(version), 0 }, /* EXPLICIT version DEFAULT v1(0) */
|
||||
{ ASN1_INTEGER, 0, OSET(version), 0 },
|
||||
{ ASN1_INTEGER, 0, OSET(serial), 0 }, /* serialNumber */
|
||||
{ ASN1_SEQUENCE, 0, 0, 0 }, /* signature */
|
||||
{ ASN1_OID, 0, OSET(sign_alg), 0 }, /* algorithm */
|
||||
{ ASN1_END, 0, 0, 0 }, /* signature */
|
||||
{ ASN1_CHOICE, 0, 0, 0 }, /* issuer */
|
||||
{ ASN1_SEQUENCE, ASN1_OF, 0, 0 },
|
||||
/* name */
|
||||
{ ASN1_END, 0, 0, 0 },
|
||||
{ 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_CHOICE, 0, 0, 0 }, /* subject */
|
||||
{ ASN1_SEQUENCE, ASN1_OF, 0, 0 },
|
||||
/* name */
|
||||
{ ASN1_END, 0, 0, 0 },
|
||||
{ ASN1_END, 0, 0, 0 }, /* subject */
|
||||
{ ASN1_SEQUENCE, 0, 0, 0 }, /* subjectPublicKeyInfo */
|
||||
{ ASN1_OID, 0, OSET(pubkey_alg), 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 issuerUniqueID OPTIONAL */
|
||||
{ ASN1_BITSTRING, 0, OSET(issuer_uid), 0 },
|
||||
{ ASN1_TAG_I_2, ASN1_OPTIONAL, 0, OSET(has_subject_uid)},/* IMPLICIT subjectUniqueID OPTIONAL */
|
||||
{ ASN1_BITSTRING, 0, OSET(subject_uid), 0 },
|
||||
{ ASN1_TAG_E_3, ASN1_OPTIONAL, 0, 0 }, /* EXPLICIT extensions OPTIONAL*/
|
||||
{ ASN1_SEQUENCE, ASN1_OF, 0, 0 },
|
||||
/* extension */
|
||||
{ ASN1_END 0, 0, 0, }, /* extensions */
|
||||
{ ASN1_END, 0, 0, 0 }, /* certificate */
|
||||
{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 private_certificate_t.compute_prime.
|
||||
*/
|
||||
static void compute_prime(private_certificate_t *this, size_t prime_size, mpz_t *prime)
|
||||
{
|
||||
randomizer_t *randomizer;
|
||||
chunk_t random_bytes;
|
||||
|
||||
randomizer = randomizer_create();
|
||||
mpz_init(*prime);
|
||||
|
||||
do
|
||||
{
|
||||
randomizer->allocate_random_bytes(randomizer, prime_size, &random_bytes);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of private_certificate_t.rsadp and private_certificate_t.rsasp1.
|
||||
*/
|
||||
static chunk_t rsadp(private_certificate_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 certificate.build_emsa_signature.
|
||||
*/
|
||||
static status_t build_emsa_pkcs1_signature(private_certificate_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 certificate.set_key.
|
||||
*/
|
||||
static status_t set_key(private_certificate_t *this, chunk_t key)
|
||||
{
|
||||
der_decoder_t *dd;
|
||||
status_t status;
|
||||
|
||||
dd = der_decoder_create(certificate_rules);
|
||||
|
||||
status = dd->decode(dd, key, this);
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
this->is_key_set = TRUE;
|
||||
this->k = mpz_sizeinbase(this->n, 2) / 8;
|
||||
}
|
||||
dd->destroy(dd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of certificate.get_key.
|
||||
*/
|
||||
static status_t get_key(private_certificate_t *this, chunk_t *key)
|
||||
{
|
||||
if (!this->is_key_set)
|
||||
{
|
||||
return INVALID_STATE;
|
||||
}
|
||||
|
||||
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 certificate.load_key.
|
||||
*/
|
||||
static status_t load_key(private_certificate_t *this, char *file)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of certificate.save_key.
|
||||
*/
|
||||
static status_t save_key(private_certificate_t *this, char *file)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of certificate.generate_key.
|
||||
*/
|
||||
static status_t generate_key(private_certificate_t *this, size_t key_size)
|
||||
{
|
||||
mpz_t p, q, n, e, d, exp1, exp2, coeff;
|
||||
mpz_t m, q1, t;
|
||||
|
||||
if (key_size < 0)
|
||||
{
|
||||
return INVALID_ARG;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
key_size = key_size / 8;
|
||||
|
||||
mpz_init(t);
|
||||
mpz_init(n);
|
||||
mpz_init(d);
|
||||
mpz_init(exp1);
|
||||
mpz_init(exp2);
|
||||
mpz_init(coeff);
|
||||
|
||||
/* Get values of primes p and q */
|
||||
this->compute_prime(this, key_size/2, &p);
|
||||
this->compute_prime(this, key_size/2, &q);
|
||||
|
||||
/* 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->is_key_set = TRUE;
|
||||
this->k = key_size;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of certificate.get_public_key.
|
||||
*/
|
||||
rsa_public_key_t *get_public_key(private_certificate_t *this)
|
||||
static rsa_public_key_t *get_public_key(private_certificate_t *this)
|
||||
{
|
||||
rsa_public_key_t *public_key;
|
||||
//chunk_t key;
|
||||
|
||||
public_key = rsa_public_key_create();
|
||||
|
||||
if (this->is_key_set)
|
||||
{
|
||||
|
||||
chunk_t n, e, key;
|
||||
|
||||
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);
|
||||
|
||||
public_key->set_key(public_key, key);
|
||||
allocator_free(key.ptr);
|
||||
|
||||
}
|
||||
|
||||
return public_key;
|
||||
return this->public_key->clone(this->public_key);
|
||||
}
|
||||
|
||||
|
||||
@@ -471,48 +151,81 @@ rsa_public_key_t *get_public_key(private_certificate_t *this)
|
||||
*/
|
||||
static void destroy(private_certificate_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);
|
||||
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(hash_algorithm_t hash_algoritm)
|
||||
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.build_emsa_pkcs1_signature = (status_t (*) (certificate_t*,hash_algorithm_t,chunk_t,chunk_t*))build_emsa_pkcs1_signature;
|
||||
this->public.set_key = (status_t (*) (certificate_t*,chunk_t))set_key;
|
||||
this->public.get_key = (status_t (*) (certificate_t*,chunk_t*))get_key;
|
||||
this->public.load_key = (status_t (*) (certificate_t*,char*))load_key;
|
||||
this->public.save_key = (status_t (*) (certificate_t*,char*))save_key;
|
||||
this->public.generate_key = (status_t (*) (certificate_t*,size_t))generate_key;
|
||||
this->public.get_public_key = (rsa_public_key_t *(*) (certificate_t*))get_public_key;
|
||||
this->public.destroy = (void (*) (certificate_t*))destroy;
|
||||
|
||||
/* private functions */
|
||||
this->rsadp = rsadp;
|
||||
this->rsasp1 = rsadp; /* same algorithm */
|
||||
this->compute_prime = compute_prime;
|
||||
/* initialize */
|
||||
this->pubkey = CHUNK_INITIALIZER;
|
||||
this->signature = CHUNK_INITIALIZER;
|
||||
this->tbs_cert = CHUNK_INITIALIZER;
|
||||
|
||||
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);
|
||||
this->is_key_set = FALSE;
|
||||
dd = der_decoder_create(certificate_rules);
|
||||
|
||||
return &(this->public);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <types.h>
|
||||
#include <definitions.h>
|
||||
#include <transforms/rsa/rsa_public_key.h>
|
||||
#include <transforms/hashers/hasher.h>
|
||||
|
||||
|
||||
typedef struct certificate_t certificate_t;
|
||||
@@ -34,12 +33,10 @@ typedef struct certificate_t certificate_t;
|
||||
/**
|
||||
* @brief X509 certificate.
|
||||
*
|
||||
* Currently only supports signing using EMSA encoding.
|
||||
*
|
||||
* @b Constructors:
|
||||
* - certificate_create()
|
||||
* - certificate_create_from_chunk()
|
||||
*
|
||||
* @ingroup rsa
|
||||
* @ingroup transforms
|
||||
*/
|
||||
struct certificate_t {
|
||||
|
||||
@@ -60,13 +57,14 @@ struct certificate_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a new certificate without
|
||||
* any key inside.
|
||||
* @brief Read a certificate from a blob.
|
||||
*
|
||||
* @return created certificate_t.
|
||||
*
|
||||
* @ingroup rsa
|
||||
* @ingroup transforms
|
||||
*/
|
||||
certificate_t *certificate_create();
|
||||
certificate_t *certificate_create_from_chunk(chunk_t chunk);
|
||||
|
||||
certificate_t *certificate_create_from_file(char *filename);
|
||||
|
||||
#endif /* CERTIFICATE_H_ */
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
|
||||
#include <gmp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "rsa_private_key.h"
|
||||
|
||||
@@ -63,11 +65,6 @@ struct private_rsa_private_key_t {
|
||||
*/
|
||||
u_int version;
|
||||
|
||||
/**
|
||||
* Is the key already set ?
|
||||
*/
|
||||
bool is_key_set;
|
||||
|
||||
/**
|
||||
* Public modulus.
|
||||
*/
|
||||
@@ -317,37 +314,11 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this, hash
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.set_key.
|
||||
*/
|
||||
static status_t set_key(private_rsa_private_key_t *this, chunk_t key)
|
||||
{
|
||||
der_decoder_t *dd;
|
||||
status_t status;
|
||||
|
||||
dd = der_decoder_create(rsa_private_key_rules);
|
||||
|
||||
status = dd->decode(dd, key, this);
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
this->is_key_set = TRUE;
|
||||
this->k = mpz_sizeinbase(this->n, 2) / 8;
|
||||
}
|
||||
dd->destroy(dd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.get_key.
|
||||
*/
|
||||
static status_t get_key(private_rsa_private_key_t *this, chunk_t *key)
|
||||
{
|
||||
if (!this->is_key_set)
|
||||
{
|
||||
return INVALID_STATE;
|
||||
}
|
||||
|
||||
{
|
||||
chunk_t n, e, p, q, d, exp1, exp2, coeff;
|
||||
|
||||
n.len = this->k;
|
||||
@@ -389,14 +360,6 @@ static status_t get_key(private_rsa_private_key_t *this, chunk_t *key)
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.load_key.
|
||||
*/
|
||||
static status_t load_key(private_rsa_private_key_t *this, char *file)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.save_key.
|
||||
@@ -407,18 +370,31 @@ static status_t save_key(private_rsa_private_key_t *this, char *file)
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.generate_key.
|
||||
* Implementation of rsa_private_key.get_public_key.
|
||||
*/
|
||||
static status_t generate_key(private_rsa_private_key_t *this, size_t key_size)
|
||||
rsa_public_key_t *get_public_key(private_rsa_private_key_t *this)
|
||||
{
|
||||
mpz_t p, q, n, e, d, exp1, exp2, coeff;
|
||||
mpz_t m, q1, t;
|
||||
|
||||
if (key_size < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.belongs_to.
|
||||
*/
|
||||
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 INVALID_ARG;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
@@ -427,6 +403,42 @@ static status_t generate_key(private_rsa_private_key_t *this, size_t key_size)
|
||||
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.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;
|
||||
|
||||
@@ -491,86 +503,21 @@ static status_t generate_key(private_rsa_private_key_t *this, size_t key_size)
|
||||
*(this->coeff) = *coeff;
|
||||
|
||||
/* set key size in bytes */
|
||||
|
||||
this->is_key_set = TRUE;
|
||||
this->k = key_size;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_private_key.get_public_key.
|
||||
*/
|
||||
rsa_public_key_t *get_public_key(private_rsa_private_key_t *this)
|
||||
{
|
||||
rsa_public_key_t *public_key;
|
||||
//chunk_t key;
|
||||
|
||||
public_key = rsa_public_key_create();
|
||||
|
||||
if (this->is_key_set)
|
||||
{
|
||||
|
||||
chunk_t n, e, key;
|
||||
|
||||
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);
|
||||
|
||||
public_key->set_key(public_key, key);
|
||||
allocator_free(key.ptr);
|
||||
|
||||
}
|
||||
|
||||
return public_key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
* see header
|
||||
*/
|
||||
rsa_private_key_t *rsa_private_key_create(hash_algorithm_t hash_algoritm)
|
||||
rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk)
|
||||
{
|
||||
private_rsa_private_key_t *this = allocator_alloc_thing(private_rsa_private_key_t);
|
||||
private_rsa_private_key_t *this;
|
||||
der_decoder_t *dd;
|
||||
status_t status;
|
||||
|
||||
/* 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.set_key = (status_t (*) (rsa_private_key_t*,chunk_t))set_key;
|
||||
this->public.get_key = (status_t (*) (rsa_private_key_t*,chunk_t*))get_key;
|
||||
this->public.load_key = (status_t (*) (rsa_private_key_t*,char*))load_key;
|
||||
this->public.save_key = (status_t (*) (rsa_private_key_t*,char*))save_key;
|
||||
this->public.generate_key = (status_t (*) (rsa_private_key_t*,size_t))generate_key;
|
||||
this->public.get_public_key = (rsa_public_key_t *(*) (rsa_private_key_t*))get_public_key;
|
||||
this->public.destroy = (void (*) (rsa_private_key_t*))destroy;
|
||||
|
||||
/* private functions */
|
||||
this->rsadp = rsadp;
|
||||
this->rsasp1 = rsadp; /* same algorithm */
|
||||
this->compute_prime = compute_prime;
|
||||
this = rsa_private_key_create_empty();
|
||||
|
||||
mpz_init(this->n);
|
||||
mpz_init(this->e);
|
||||
@@ -580,7 +527,49 @@ rsa_private_key_t *rsa_private_key_create(hash_algorithm_t hash_algoritm)
|
||||
mpz_init(this->exp1);
|
||||
mpz_init(this->exp2);
|
||||
mpz_init(this->coeff);
|
||||
this->is_key_set = FALSE;
|
||||
|
||||
return &(this->public);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -38,10 +38,12 @@ typedef struct rsa_private_key_t rsa_private_key_t;
|
||||
*
|
||||
* @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 proper key set/get load/save methods using ASN1.
|
||||
* @todo Implement get_key(), save_key(), get_public_key()
|
||||
*
|
||||
* @ingroup rsa
|
||||
*/
|
||||
@@ -65,27 +67,10 @@ struct rsa_private_key_t {
|
||||
*/
|
||||
status_t (*build_emsa_pkcs1_signature) (rsa_private_key_t *this, hash_algorithm_t hash_algorithm, chunk_t data, chunk_t *signature);
|
||||
|
||||
/**
|
||||
* @brief Set 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 currently SUCCESS in any case
|
||||
*/
|
||||
status_t (*set_key) (rsa_private_key_t *this, chunk_t key);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* UNIMPLEMENTED!
|
||||
*
|
||||
* @param this calling object
|
||||
* @param key key (in a propriarity format)
|
||||
@@ -95,17 +80,6 @@ struct rsa_private_key_t {
|
||||
*/
|
||||
status_t (*get_key) (rsa_private_key_t *this, chunk_t *key);
|
||||
|
||||
/**
|
||||
* @brief Loads a key from a file.
|
||||
*
|
||||
* Not implemented!
|
||||
*
|
||||
* @param this calling object
|
||||
* @param file file from which key should be read
|
||||
* @return NOT_SUPPORTED
|
||||
*/
|
||||
status_t (*load_key) (rsa_private_key_t *this, char *file);
|
||||
|
||||
/**
|
||||
* @brief Saves a key to a file.
|
||||
*
|
||||
@@ -139,6 +113,18 @@ struct rsa_private_key_t {
|
||||
*/
|
||||
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 Destroys the private key.
|
||||
*
|
||||
@@ -148,13 +134,44 @@ struct rsa_private_key_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a new rsa_private_key without
|
||||
* any key inside.
|
||||
* @brief Generate a new RSA key with specified key lenght.
|
||||
*
|
||||
* @return created rsa_private_key_t.
|
||||
* @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();
|
||||
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_*/
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
|
||||
#include <gmp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "rsa_public_key.h"
|
||||
|
||||
@@ -84,11 +86,6 @@ struct private_rsa_public_key_t {
|
||||
*/
|
||||
rsa_public_key_t public;
|
||||
|
||||
/**
|
||||
* Is the key already set ?
|
||||
*/
|
||||
bool is_key_set;
|
||||
|
||||
/**
|
||||
* Public modulus.
|
||||
*/
|
||||
@@ -123,6 +120,24 @@ struct private_rsa_public_key_t {
|
||||
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
|
||||
*/
|
||||
@@ -133,6 +148,21 @@ static asn1_rule_t rsa_public_key_rules[] = {
|
||||
{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
|
||||
*/
|
||||
@@ -167,11 +197,6 @@ static status_t verify_emsa_pkcs1_signature(private_rsa_public_key_t *this, chun
|
||||
chunk_t em;
|
||||
u_int8_t *pos;
|
||||
|
||||
if(!this->is_key_set)
|
||||
{
|
||||
return INVALID_STATE;
|
||||
}
|
||||
|
||||
if (signature.len > this->k)
|
||||
{
|
||||
return INVALID_ARG;
|
||||
@@ -285,37 +310,11 @@ static status_t verify_emsa_pkcs1_signature(private_rsa_public_key_t *this, chun
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_public_key.set_key.
|
||||
*/
|
||||
static status_t set_key(private_rsa_public_key_t *this, chunk_t key)
|
||||
{
|
||||
der_decoder_t *dd;
|
||||
status_t status;
|
||||
|
||||
dd = der_decoder_create(rsa_public_key_rules);
|
||||
|
||||
status = dd->decode(dd, key, this);
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
this->is_key_set = TRUE;
|
||||
this->k = mpz_sizeinbase(this->n, 2) / 8;
|
||||
}
|
||||
dd->destroy(dd);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of rsa_public_key.get_key.
|
||||
*/
|
||||
static status_t get_key(private_rsa_public_key_t *this, chunk_t *key)
|
||||
{
|
||||
if (!this->is_key_set)
|
||||
{
|
||||
return INVALID_STATE;
|
||||
}
|
||||
|
||||
{
|
||||
chunk_t n, e;
|
||||
|
||||
n.len = this->k;
|
||||
@@ -332,14 +331,6 @@ static status_t get_key(private_rsa_public_key_t *this, chunk_t *key)
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_public_key.load_key.
|
||||
*/
|
||||
static status_t load_key(private_rsa_public_key_t *this, char *file)
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of rsa_public_key.save_key.
|
||||
@@ -349,6 +340,28 @@ 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.
|
||||
*/
|
||||
@@ -359,28 +372,97 @@ static void destroy(private_rsa_public_key_t *this)
|
||||
allocator_free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
/**
|
||||
* Generic private constructor
|
||||
*/
|
||||
rsa_public_key_t *rsa_public_key_create()
|
||||
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.set_key = (status_t (*) (rsa_public_key_t*,chunk_t))set_key;
|
||||
this->public.get_key = (status_t (*) (rsa_public_key_t*,chunk_t*))get_key;
|
||||
this->public.load_key = (status_t (*) (rsa_public_key_t*,char*))load_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);
|
||||
this->is_key_set = FALSE;
|
||||
|
||||
return &(this->public);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -38,11 +38,13 @@ typedef struct rsa_public_key_t rsa_public_key_t;
|
||||
* the EMSA encoding (see PKCS1)
|
||||
*
|
||||
* @b Constructors:
|
||||
* - rsa_public_key_create()
|
||||
* - 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 proper key set/get load/save methods using ASN1.
|
||||
* @todo Implement getkey() and savekey()
|
||||
*
|
||||
* @ingroup rsa
|
||||
*/
|
||||
@@ -55,7 +57,7 @@ struct rsa_public_key_t {
|
||||
* selects the hash algorithm form the resultign ASN1-OID and
|
||||
* verifies the hash against the supplied data.
|
||||
*
|
||||
* @param this rsa_private_key to use
|
||||
* @param this rsa_public_key to use
|
||||
* @param data data to sign
|
||||
* @param signature signature to verify
|
||||
* @return
|
||||
@@ -67,20 +69,6 @@ struct rsa_public_key_t {
|
||||
*/
|
||||
status_t (*verify_emsa_pkcs1_signature) (rsa_public_key_t *this, chunk_t data, chunk_t signature);
|
||||
|
||||
/**
|
||||
* @brief Set 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 currently SUCCESS in any case
|
||||
*/
|
||||
status_t (*set_key) (rsa_public_key_t *this, chunk_t key);
|
||||
|
||||
/**
|
||||
* @brief Gets the key.
|
||||
*
|
||||
@@ -97,17 +85,6 @@ struct rsa_public_key_t {
|
||||
*/
|
||||
status_t (*get_key) (rsa_public_key_t *this, chunk_t *key);
|
||||
|
||||
/**
|
||||
* @brief Loads a key from a file.
|
||||
*
|
||||
* Not implemented!
|
||||
*
|
||||
* @param this calling object
|
||||
* @param file file from which key should be read
|
||||
* @return NOT_SUPPORTED
|
||||
*/
|
||||
status_t (*load_key) (rsa_public_key_t *this, char *file);
|
||||
|
||||
/**
|
||||
* @brief Saves a key to a file.
|
||||
*
|
||||
@@ -119,6 +96,22 @@ struct rsa_public_key_t {
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@@ -128,12 +121,33 @@ struct rsa_public_key_t {
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a public key without any key inside.
|
||||
* @brief Load an RSA public key from a chunk.
|
||||
*
|
||||
* @return created rsa_public_key_t.
|
||||
* 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();
|
||||
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_*/
|
||||
|
||||
@@ -192,7 +192,7 @@ static void log_bytes(private_logger_t *this, log_level_t loglevel, char *label,
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
|
||||
format = "%s (%d bytes)";
|
||||
format = "%s (%d bytes @%p)";
|
||||
this->prepend_prefix(this, loglevel, format, buffer);
|
||||
|
||||
if (this->output == NULL)
|
||||
@@ -201,7 +201,7 @@ static void log_bytes(private_logger_t *this, log_level_t loglevel, char *label,
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(this->output, buffer, label, len);
|
||||
fprintf(this->output, buffer, label, len, bytes);
|
||||
fprintf(this->output, "\n");
|
||||
}
|
||||
|
||||
@@ -293,6 +293,14 @@ 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.
|
||||
*/
|
||||
@@ -324,6 +332,7 @@ logger_t *logger_create(char *logger_name, log_level_t log_level, bool log_threa
|
||||
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 */
|
||||
|
||||
@@ -156,6 +156,16 @@ struct logger_t {
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
||||
@@ -77,8 +77,8 @@ struct {
|
||||
{ "CONFG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, NULL}, /* CONFIG */
|
||||
{ "ENCPL", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, NULL}, /* ENCRYPTION_PAYLOAD */
|
||||
{ "PAYLD", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, NULL}, /* PAYLOAD */
|
||||
{ "DERDC", ERROR|CONTROL|AUDIT|RAW|PRIVATE|LEVEL3, TRUE, NULL}, /* DER_DECODER */
|
||||
{ "DEREC", ERROR|CONTROL|AUDIT|RAW|PRIVATE|LEVEL3, TRUE, NULL}, /* DER_ENCODER */
|
||||
{ "DERDC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, NULL}, /* DER_DECODER */
|
||||
{ "DEREC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, NULL}, /* DER_ENCODER */
|
||||
};
|
||||
|
||||
|
||||
@@ -120,16 +120,54 @@ static log_level_t get_log_level (private_logger_manager_t *this, logger_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)
|
||||
{
|
||||
this->loggers[context]->enable_level(this->loggers[context], 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)
|
||||
{
|
||||
this->loggers[context]->disable_level(this->loggers[context], level);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -158,6 +196,7 @@ logger_manager_t *logger_manager_create(log_level_t default_log_level)
|
||||
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++)
|
||||
|
||||
@@ -36,6 +36,7 @@ typedef enum logger_context_t logger_context_t;
|
||||
* @ingroup utils
|
||||
*/
|
||||
enum logger_context_t {
|
||||
ALL_LOGGERS = -1,
|
||||
PARSER = 0,
|
||||
GENERATOR,
|
||||
IKE_SA,
|
||||
@@ -89,7 +90,7 @@ struct logger_manager_t {
|
||||
logger_t *(*get_logger) (logger_manager_t *this, logger_context_t context);
|
||||
|
||||
/**
|
||||
* Returns the set log_level of a specific context or 0.
|
||||
* @brief Returns the set log_level of a specific context.
|
||||
*
|
||||
* @param this calling object
|
||||
* @param context context to check level
|
||||
@@ -98,29 +99,42 @@ struct logger_manager_t {
|
||||
log_level_t (*get_log_level) (logger_manager_t *this, logger_context_t context);
|
||||
|
||||
/**
|
||||
* Enables a logger level of a specific 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);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disables a logger level of a specific context.
|
||||
* @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
|
||||
* @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 remaining managed logger_t objects are also destroyed.
|
||||
* All managed logger_t objects are also destroyed.
|
||||
*
|
||||
* @param this logger_manager_t object
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user