- rewrote a lot of RSA stuff
authorMartin Willi <martin@strongswan.org>
Thu, 30 Mar 2006 07:22:01 +0000 (07:22 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 30 Mar 2006 07:22:01 +0000 (07:22 -0000)
- 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!

26 files changed:
Source/charon/Makefile
Source/charon/asn1/asn1.c
Source/charon/asn1/asn1.h
Source/charon/asn1/der_decoder.c
Source/charon/asn1/der_decoder.h
Source/charon/definitions.h
Source/charon/doc/Architecture.txt
Source/charon/sa/authenticator.c
Source/charon/testcases/Makefile.testcases
Source/charon/testcases/certificate_test.c [new file with mode: 0644]
Source/charon/testcases/certificate_test.h [new file with mode: 0644]
Source/charon/testcases/rsa_test.c
Source/charon/testcases/testcases.c
Source/charon/threads/stroke.c
Source/charon/threads/stroke.h
Source/charon/transforms/Makefile.transforms
Source/charon/transforms/certificate.c
Source/charon/transforms/certificate.h
Source/charon/transforms/rsa/rsa_private_key.c
Source/charon/transforms/rsa/rsa_private_key.h
Source/charon/transforms/rsa/rsa_public_key.c
Source/charon/transforms/rsa/rsa_public_key.h
Source/charon/utils/logger.c
Source/charon/utils/logger.h
Source/charon/utils/logger_manager.c
Source/charon/utils/logger_manager.h

index 5154d02..f792c5b 100644 (file)
@@ -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)
index cbd030b..0195238 100644 (file)
@@ -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[] = {
index a828034..894f048 100644 (file)
@@ -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.
  *
  */
 
 
 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;
 };
 
 
index 59ea4b0..91521b9 100644 (file)
@@ -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);
        
-       mpz_import(*mpz, data.len, 1, 1, 1, 0, data.ptr);
+       *boolean = *data.ptr;
+       
+       return SUCCESS;
+}
+
+/**
+ * Read an OID
+ */
+status_t read_oid(private_der_decoder_t *this, chunk_t data)
+{
+       this->logger->log_chunk(this->logger, CONTROL|LEVEL2, "ASN1_OID", data);
+       /* TODO: OID parsing stuff */
        return SUCCESS;
 }
 
+/**
+ * Read a bitstring
+ */
+status_t read_bitstring(private_der_decoder_t *this, chunk_t data)
+{
+       /* TODO: cleanly determine amount of unused bits */
+       
+       /* skip "unused-bits-in-following-byte"-byte */
+       data.ptr += 1;
+       data.len -= 1;
+       
+       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 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;
+       this->logger->log(this->logger, CONTROL|LEVEL2, "reading rule %d %s",
+                                               this->rule - this->first_rule,
+                                               mapping_find(asn1_type_m, this->rule->type));
        
-       /* process inner */
        switch (this->rule->type)
        {
-               case ASN1_INTEGER:
-                       if (this->rule->flags & ASN1_MPZ)
+               case ASN1_END:
+                       /* ignore, handled outside */
+                       return SUCCESS;
+               case ASN1_CHOICE:
+                       /* CHOICE has no type/length */
+                       break;
+               default:
+                       /* anything else has type/length */
+                       if (data->len == 0)
                        {
-                               read_mpz(this, inner);
+                               goto beginning;
                        }
-                       else
+                       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)
                        {
-                               read_int(this, inner);
+                               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;
                        }
-                       break;
-               case ASN1_SEQUENCE:
-                       read_sequence(this, inner);
-                       break;
-               default:
-                       break;
+                       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);
 }
 
index d6ccaf4..68731b5 100644 (file)
 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
  */
index 958b313..06f0e63 100644 (file)
  * 
  * @ingroup transforms
  */
+/**
+ * @defgroup asn1 asn1
+ * 
+ * ASN1 structure definition, en-/decoder of for DER
+ * 
+ * @todo Implement a der_encoder_t class.
+ */
  
 /**
  * @defgroup utils utils
index fb7c28a..81b3e2f 100644 (file)
@@ -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. 
index 2ec1733..20667f7 100644 (file)
@@ -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);
                        
index c3fe498..b6113fa 100644 (file)
@@ -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 $@ $<
                                                                        
\ No newline at end of file
diff --git a/Source/charon/testcases/certificate_test.c b/Source/charon/testcases/certificate_test.c
new file mode 100644 (file)
index 0000000..55b9d04
--- /dev/null
@@ -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);
+}
+
+
+
diff --git a/Source/charon/testcases/certificate_test.h b/Source/charon/testcases/certificate_test.h
new file mode 100644 (file)
index 0000000..8dcbd0f
--- /dev/null
@@ -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_ */
+
+
+
+
index 847096e..fcc3008 100644 (file)
 #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);
+       
 }
index 34a3ff5..627ab6e 100644 (file)
@@ -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);
        
index 40b3cec..fac2dc6 100755 (executable)
@@ -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;
        
@@ -68,6 +70,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
         */
        void (*destroy) (configuration_entry_t *this);
@@ -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...
  */
@@ -184,6 +198,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.
  */
 static void stroke_receive(private_stroke_t *this)
@@ -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);
 }
index 267c455..113d38d 100644 (file)
@@ -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;
index bed865c..4be5d27 100644 (file)
@@ -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 $@ $<
index 6d10d9f..e8ee61b 100755 (executable)
@@ -21,6 +21,8 @@
  */
 
 #include <gmp.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "certificate.h"
 
@@ -39,480 +41,191 @@ struct private_certificate_t {
         * Public interface for this signer.
         */
        certificate_t public;
-};
-
-#define OSET(x) offsetof(private_certiciate_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 */
-};
-
-/**
- * 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);
+       u_int version;
        
-       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);
+       u_int serial;
        
-       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);
+       chunk_t sign_alg;
        
-       mpz_import(t1, data.len, 1, 1, 1, 0, data.ptr);
+       time_t not_before;
        
-       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);
+       time_t not_after;
        
-       mpz_mul(t2, t2, this->q);                               /* m = m2 + h q */
-       mpz_add(t1, t1, t2);
+       chunk_t pubkey;
        
-       decrypted.len = this->k;
-       decrypted.ptr = mpz_export(NULL, NULL, 1, decrypted.len, 1, 0, t1);
+       chunk_t pubkey_alg;
        
-       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;   
-       }
+       bool has_issuer_uid;
+       chunk_t issuer_uid;
        
-       /* build hash */
-       hasher->allocate_hash(hasher, data, &hash);
-       hasher->destroy(hasher);
+       bool has_subject_uid;
+       chunk_t subject_uid;
        
-       /* 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);
+       chunk_t tbs_cert;
+       chunk_t signature;
        
-       /* 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);
+       rsa_public_key_t *public_key;
+};
 
-       
-       /* build signature */
-       *signature = this->rsasp1(this, em);
-       
-       allocator_free(hash.ptr);
-       allocator_free(em.ptr);
-       
-       return SUCCESS; 
-}
+#define OSET(x) offsetof(private_certificate_t, x)
 
-       
 /**
- * Implementation of certificate.set_key.
+ * Rules for de-/encoding of a certificate from/in ASN1 
  */
-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;
-}
+static asn1_rule_t certificate_rules[] = {
+       {ASN1_SEQUENCE,                         0,                                              0,                                      0                                       }, /* certificate */
+       { ASN1_SEQUENCE,                        ASN1_RAW,                               OSET(tbs_cert),         0                                       }, /*  tbsCertificate */
+       {  ASN1_TAG_E_0,                        ASN1_DEFAULT,                   OSET(version),          0                                       }, /*   EXPLICIT */
+       {   ASN1_INTEGER,                       ASN1_DEFAULT,                   OSET(version),          0                                       }, /*    version DEFAULT v1(0) */
+       {  ASN1_INTEGER,                        0,                                              OSET(serial),           0                                       }, /*   serialNumber */
+       {  ASN1_SEQUENCE,                       0,                                              0,                                      0                                       }, /*   signature */
+       {   ASN1_OID,                           0,                                              OSET(sign_alg),         0                                       }, /*    algorithm-oid */
+       {   ASN1_NULL,                          0,                                              0,                                      0                                       }, /*    parameters */
+       {  ASN1_END,                            0,                                              0,                                      0                                       }, /*   signature */
+       {  ASN1_SEQUENCE,                       ASN1_OF,                                0,                                      0                                       }, /*   issuer */
+//     {   ASN1_SET,                           ASN1_OF,                                0,                                      0,                                      }, /*    RelativeDistinguishedName */
+//     {    ASN1_SEQUENCE,                     0,                                              0,                                      0,                                      }, /*     AttributeTypeAndValue */
+//     {     ASN1_OID,                         0,                                              0,                                      0                                       }, /*      AttributeType */
+//     {     ASN1_ANY,                         0,                                              0,                                      0                                       }, /*      AttributeValue */
+//     {    ASN1_END,                          0,                                              0,                                      0                                       }, /*     AttributeTypeAndValue */
+//     {   ASN1_END,                           0,                                              0,                                      0                                       }, /*    RelativeDistinguishedName */
+       {  ASN1_END,                            0,                                              0,                                      0                                       }, /*   issuer */
+       {  ASN1_SEQUENCE,                       0,                                              0,                                      0                                       }, /*   validity */
+       {   ASN1_CHOICE,                        0,                                              0,                                      0                                       }, /*    notBefore */
+       {     ASN1_UTCTIME,             0,                                              OSET(not_before),       0                                       }, /*     utcTime */
+       {     ASN1_GENERALIZEDTIME, 0,                                          OSET(not_before),       0                                       }, /*     generalTime */
+       {   ASN1_END,                           0,                                              0,                                      0                                       }, /*    notBefore */
+       {   ASN1_CHOICE,                        0,                                              0,                                      0                                       }, /*    notAfter */
+       {    ASN1_UTCTIME,                      0,                                              OSET(not_after),        0                                       }, /*     utcTime */
+       {    ASN1_GENERALIZEDTIME,      0,                                              OSET(not_after),        0                                       }, /*     generalTime */
+       {   ASN1_END,                           0,                                              0,                                      0                                       }, /*    notAfter */
+       {  ASN1_END,                            0,                                              0,                                      0                                       }, /*   validity */
+       {  ASN1_SEQUENCE,                       ASN1_OF,                                0,                                      0                                       }, /*   subject */
+//     {   ASN1_SET,                           ASN1_OF,                                0,                                      0,                                      }, /*    RelativeDistinguishedName */
+//     {    ASN1_SEQUENCE,                     0,                                              0,                                      0,                                      }, /*     AttributeTypeAndValue */
+//     {     ASN1_OID,                         0,                                              0,                                      0                                       }, /*      AttributeType */
+//     {     ASN1_ANY,                         0,                                              0,                                      0                                       }, /*      AttributeValue */
+//     {    ASN1_END,                          0,                                              0,                                      0                                       }, /*     AttributeTypeAndValue */
+//     {   ASN1_END,                           0,                                              0,                                      0                                       }, /*    RelativeDistinguishedName */
+       {  ASN1_END,                            0,                                              0,                                      0                                       }, /*   subject */
+       {  ASN1_SEQUENCE,                       0,                                              0,                                      0                                       }, /*   subjectPublicKeyInfo */
+       {   ASN1_SEQUENCE,                      0,                                              0,                                      0                                       }, /*    algorithm */
+       {    ASN1_OID,                          0,                                              OSET(pubkey_alg),       0                                       }, /*     algorithm-oid */
+       {    ASN1_NULL,                         0,                                              0,                                      0                                       }, /*     parameters */
+       {   ASN1_END,                           0,                                              0,                                      0                                       }, /*    algorithm */
+       {   ASN1_BITSTRING,             0,                                              OSET(pubkey),           0                                       }, /*    subjectPublicKey */
+       {  ASN1_END,                            0,                                              0,                                      0                                       }, /*   subjectPublicKeyInfo */
+       {  ASN1_TAG_I_1,                        ASN1_OPTIONAL,                  0,                                      OSET(has_issuer_uid)}, /*   IMPLICIT */
+       {   ASN1_BITSTRING,                     ASN1_OPTIONAL,                  OSET(issuer_uid),       0                                       }, /*    issuerUniqueID OPTIONAL */
+       {  ASN1_TAG_I_2,                        ASN1_OPTIONAL,                  0,                                      OSET(has_subject_uid)},/*   IMPLICIT */
+       {   ASN1_BITSTRING,                     ASN1_OPTIONAL,                  OSET(subject_uid),      0                                       }, /*    subjectUniqueID OPTIONAL */
+       {  ASN1_TAG_E_3,                        ASN1_OPTIONAL,                  0,                                      0                                       }, /*   EXPLICIT */
+       {   ASN1_SEQUENCE,                      ASN1_OF|ASN1_OPTIONAL,  0,                                      0                                       }, /*    extensions OPTIONAL */
+//     {    ASN1_SEQUENCE,                     0,                                              0,                                      0,                                      }, /*     extension */
+//     {     ASN1_OID,                         0,                                              0,                                      0                                       }, /*      extnID */
+//     {     ASN1_BOOLEAN,                     ASN1_DEFAULT,                   0,                                      FALSE                           }, /*      critical */
+//     {     ASN1_OCTETSTRING,         0,                                              0,                                      0,                                      }, /*      extnValue */
+//     {    ASN1_END,                          0,                                              0,                                      0,                                      }, /*     extension */
+       {   ASN1_END,                           0,                                              0,                                      0,                                      }, /*    extensions */
+       { ASN1_END,                             0,                                              0,                                      0                                       }, /*  tbsCertificate */
+       { ASN1_SEQUENCE,                        0,                                              0,                                      0                                       }, /*  signatureAlgorithm */
+       {  ASN1_OID,                            0,                                              OSET(sign_alg),         0                                       }, /*   algorithm-oid */
+       {  ASN1_NULL,                           0,                                              0,                                      0                                       }, /*   parameters */
+       { ASN1_END,                             0,                                              0,                                      0                                       }, /*  signatureAlgorithm */
+       { ASN1_BITSTRING,                       0,                                              OSET(signature),        0                                       }, /*  signatureValue */
+       {ASN1_END,                                      0,                                              0,                                      0                                       }, /* certificate */
+};
 
 /**
- * Implementation of certificate.get_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.
+ * Implementation of certificate.get_public_key.
  */
-static status_t load_key(private_certificate_t *this, char *file)
+static rsa_public_key_t *get_public_key(private_certificate_t *this)
 {
-       return NOT_SUPPORTED;
+       return this->public_key->clone(this->public_key);
 }
 
+
 /**
- * Implementation of certificate.save_key.
+ * Implementation of certificate.destroy.
  */
-static status_t save_key(private_certificate_t *this, char *file)
+static void destroy(private_certificate_t *this)
 {
-       return NOT_SUPPORTED;
+       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);
 }
 
-/**
- * Implementation of certificate.generate_key.
+/*
+ * Described in header.
  */
-static status_t generate_key(private_certificate_t *this, size_t key_size)
+certificate_t *certificate_create_from_chunk(chunk_t chunk)
 {
-       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);
+       private_certificate_t *this = allocator_alloc_thing(private_certificate_t);
+       der_decoder_t *dd;
        
-       key_size = key_size / 8;
+       /* public functions */
+       this->public.get_public_key = (rsa_public_key_t *(*) (certificate_t*))get_public_key;
+       this->public.destroy = (void (*) (certificate_t*))destroy;
        
-       mpz_init(t);    
-       mpz_init(n);
-       mpz_init(d);
-       mpz_init(exp1);
-       mpz_init(exp2);
-       mpz_init(coeff);
+       /* initialize */
+       this->pubkey = CHUNK_INITIALIZER;
+       this->signature = CHUNK_INITIALIZER;
+       this->tbs_cert = CHUNK_INITIALIZER;
        
-       /* 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);
-       }
+       dd = der_decoder_create(certificate_rules);
        
-       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 */
+       if (dd->decode(dd, chunk, this) != SUCCESS)
        {
-               mpz_add(d, d, m);
+               allocator_free(this);
+               dd->destroy(dd);
+               return NULL;
        }
-       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 */
+       dd->destroy(dd);
        
-       mpz_invert(coeff, q, p);                                /* coeff = q^-1 mod p */
-       if (mpz_cmp_ui(coeff, 0) < 0)                   /* make coeff d is positive */
+       this->public_key = rsa_public_key_create_from_chunk(this->pubkey);
+       if (this->public_key == NULL)
        {
-               mpz_add(coeff, coeff, p);
+               allocator_free(this->pubkey.ptr);
+               allocator_free(this);
+               return NULL;
        }
-
-       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;
+       return &this->public;
 }
 
-/**
- * Implementation of certificate.get_public_key.
+/*
+ * Described in header.
  */
-rsa_public_key_t *get_public_key(private_certificate_t *this)
+certificate_t *certificate_create_from_file(char *filename)
 {
-       rsa_public_key_t *public_key;
-       //chunk_t key;
-       
-       public_key = rsa_public_key_create();
-       
-       if (this->is_key_set)
-       {       
+       struct stat stb;
+       FILE *file;
+       char *buffer;
+       chunk_t chunk;
        
-               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);
-
+       if (stat(filename, &stb) == -1)
+       {
+               return NULL;
        }
        
-       return public_key;
-}
-
-
-/**
- * Implementation of certificate.destroy.
- */
-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);
-       allocator_free(this);
-}
-
-/*
- * Described in header.
- */
-certificate_t *certificate_create(hash_algorithm_t hash_algoritm)
-{
-       private_certificate_t *this = allocator_alloc_thing(private_certificate_t);
+       buffer = alloca(stb.st_size);
        
-       /* 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;
+       file = fopen(filename, "r");
+       if (file == NULL)
+       {
+               return NULL;
+       }
        
-       /* private functions */
-       this->rsadp = rsadp;
-       this->rsasp1 = rsadp; /* same algorithm */
-       this->compute_prime = compute_prime;
+       if (fread(buffer, stb.st_size, 1, file) == -1)
+       {
+               return NULL;
+       }
        
-       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;
+       chunk.ptr = buffer;
+       chunk.len = stb.st_size;
        
-       return &(this->public);
+       return certificate_create_from_chunk(chunk);
 }
index 3cbe7f9..69baed0 100755 (executable)
@@ -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_ */
index 22315e9..4da3baf 100644 (file)
@@ -21,6 +21,8 @@
  */
 
 #include <gmp.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "rsa_private_key.h"
 
@@ -64,11 +66,6 @@ struct private_rsa_private_key_t {
        u_int version;
        
        /**
-        * Is the key already set ?
-        */
-       bool is_key_set;
-       
-       /**
         * Public modulus.
         */
        mpz_t n;
@@ -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,36 +360,41 @@ static status_t get_key(private_rsa_private_key_t *this, chunk_t *key)
        
        return SUCCESS;
 }
-       
+
 /**
- * Implementation of rsa_private_key.load_key.
+ * Implementation of rsa_private_key.save_key.
  */
-static status_t load_key(private_rsa_private_key_t *this, char *file)
+static status_t save_key(private_rsa_private_key_t *this, char *file)
 {
        return NOT_SUPPORTED;
 }
 
 /**
- * Implementation of rsa_private_key.save_key.
+ * Implementation of rsa_private_key.get_public_key.
  */
-static status_t save_key(private_rsa_private_key_t *this, char *file)
+rsa_public_key_t *get_public_key(private_rsa_private_key_t *this)
 {
-       return NOT_SUPPORTED;
+       return NULL;
 }
 
 /**
- * Implementation of rsa_private_key.generate_key.
+ * Implementation of rsa_private_key.belongs_to.
  */
-static status_t generate_key(private_rsa_private_key_t *this, size_t key_size)
+bool belongs_to(private_rsa_private_key_t *this, rsa_public_key_t *public)
 {
-       mpz_t p, q, n, e, d, exp1, exp2, coeff;
-       mpz_t m, q1, t;
-       
-       if (key_size < 0) 
+       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,96 +503,73 @@ 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;
+       return &this->public;
 }
 
-/**
- * Implementation of rsa_private_key.get_public_key.
+/*
+ * see header
  */
-rsa_public_key_t *get_public_key(private_rsa_private_key_t *this)
+rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk)
 {
-       rsa_public_key_t *public_key;
-       //chunk_t key;
+       private_rsa_private_key_t *this;
+       der_decoder_t *dd;
+       status_t status;
        
-       public_key = rsa_public_key_create();
+       this = rsa_private_key_create_empty();
        
-       if (this->is_key_set)
-       {       
+       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);
        
-               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);
-
+       dd = der_decoder_create(rsa_private_key_rules);
+       status = dd->decode(dd, chunk, this);
+       dd->destroy(dd);
+       if (status != SUCCESS)
+       {
+               destroy(this);
+               return NULL;
        }
-       
-       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);
+       this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
+       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_file(char *filename, char *passphrase)
 {
-       private_rsa_private_key_t *this = allocator_alloc_thing(private_rsa_private_key_t);
+       chunk_t chunk;
+       struct stat stb;
+       FILE *file;
+       char *buffer;
        
-       /* 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;
+       if (stat(filename, &stb) == -1)
+       {
+               return NULL;
+       }
        
-       /* private functions */
-       this->rsadp = rsadp;
-       this->rsasp1 = rsadp; /* same algorithm */
-       this->compute_prime = compute_prime;
+       buffer = alloca(stb.st_size);
        
-       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;
+       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 &(this->public);
+       return rsa_private_key_create_from_chunk(chunk);
 }
index 094c3e2..ffbe419 100644 (file)
@@ -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
  */
@@ -66,26 +68,9 @@ 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)
@@ -96,17 +81,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.
         * 
         * Not implemented!
@@ -140,6 +114,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.
         * 
         * @param this                          private key to destroy
@@ -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.
+ * 
+ * @param key_size                     size of the key in bits
+ * @return                                     generated rsa_private_key_t.
+ * 
+ * @ingroup rsa
+ */
+rsa_private_key_t *rsa_private_key_create(size_t key_size);
+
+/**
+ * @brief Load an RSA private key from a chunk.
+ * 
+ * Load a key from a chunk, encoded as described in PKCS#1
+ * (ASN1 DER encoded).
+ * 
+ * @param chunk                                chunk containing the DER encoded key
+ * @return                                     loaded rsa_private_key_t, or NULL
+ * 
+ * @ingroup rsa
+ */
+rsa_private_key_t *rsa_private_key_create_from_chunk(chunk_t chunk);
+
+/**
+ * @brief Load an RSA private key from a file.
+ * 
+ * Load a key from a file, which is either in a unencrypted binary
+ * format (DER), or in a (encrypted) PEM format. The supplied 
+ * passphrase is used to decrypt an ecrypted key.
+ * 
+ * @param filename                     filename which holds the key
+ * @param passphrase           optional passphase for decryption
+ * @return                                     loaded rsa_private_key_t, or NULL
  * 
- * @return created rsa_private_key_t.
+ * @todo Implement PEM file loading
+ * @todo Implement key decryption
  * 
  * @ingroup rsa
  */
-rsa_private_key_t *rsa_private_key_create();
+rsa_private_key_t *rsa_private_key_create_from_file(char *filename, char *passphrase);
 
 #endif /*RSA_PRIVATE_KEY_H_*/
index fb3fe3c..5a3df1f 100644 (file)
@@ -21,6 +21,8 @@
  */
  
 #include <gmp.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "rsa_public_key.h"
 
@@ -85,11 +87,6 @@ struct private_rsa_public_key_t {
        rsa_public_key_t public;
        
        /**
-        * Is the key already set ?
-        */
-       bool is_key_set;
-       
-       /**
         * Public modulus.
         */
        mpz_t n;
@@ -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 
  */
@@ -134,6 +149,21 @@ static asn1_rule_t rsa_public_key_rules[] = {
 };
 
 /**
+ * Rules for de-/encoding of a PublicKeyInfo from/in ASN1 
+ */
+static asn1_rule_t rsa_public_key_info_rules[] = {
+       {ASN1_SEQUENCE, 0, 0, 0},
+       {       ASN1_SEQUENCE, 0, 0, 0},
+       {               ASN1_OID, 0, offsetof(rsa_public_key_info_t, algorithm_oid), 0},
+       {               ASN1_NULL, 0, 0, 0},
+       {       ASN1_END, 0, 0, 0},
+       {       ASN1_BITSTRING, 0, offsetof(rsa_public_key_info_t, public_key), 0},
+       {ASN1_END, 0, 0, 0},
+};
+
+private_rsa_public_key_t *rsa_public_key_create_empty();
+
+/**
  * Implementation of private_rsa_public_key_t.rsaep and private_rsa_public_key_t.rsavp1
  */
 static chunk_t rsaep(private_rsa_public_key_t *this, chunk_t data)
@@ -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;     
@@ -286,36 +311,10 @@ static status_t verify_emsa_pkcs1_signature(private_rsa_public_key_t *this, chun
 }
        
 /**
- * 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,21 +331,35 @@ static status_t get_key(private_rsa_public_key_t *this, chunk_t *key)
        
        return SUCCESS;
 }
-       
+
 /**
- * Implementation of rsa_public_key.load_key.
+ * Implementation of rsa_public_key.save_key.
  */
-static status_t load_key(private_rsa_public_key_t *this, char *file)
+static status_t save_key(private_rsa_public_key_t *this, char *file)
 {
        return NOT_SUPPORTED;
 }
 
 /**
- * Implementation of rsa_public_key.save_key.
+ * Implementation of rsa_public_key.get_modulus.
  */
-static status_t save_key(private_rsa_public_key_t *this, char *file)
+static mpz_t *get_modulus(private_rsa_public_key_t *this)
 {
-       return NOT_SUPPORTED;
+       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;
 }
 
 /**
@@ -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;
 }
index a4671b1..ef79153 100644 (file)
@@ -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
@@ -68,20 +70,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.
         * 
         * Currently uses a proprietary format which is only inteded
@@ -98,26 +86,31 @@ struct rsa_public_key_t {
        status_t (*get_key) (rsa_public_key_t *this, chunk_t *key);
        
        /**
-        * @brief Loads a key from a file.
+        * @brief Saves a key to a file.
         * 
         * Not implemented!
         * 
         * @param this                          calling object
-        * @param file                          file from which key should be read
+        * @param file                          file to which the key should be written.
         * @return                                      NOT_SUPPORTED
         */
-       status_t (*load_key) (rsa_public_key_t *this, char *file);
+       status_t (*save_key) (rsa_public_key_t *this, char *file);
        
        /**
-        * @brief Saves a key to a file.
-        * 
-        * Not implemented!
+        * @brief Get the modulus of the key.
         * 
         * @param this                          calling object
-        * @param file                          file to which the key should be written.
-        * @return                                      NOT_SUPPORTED
+        * @return                                      modulus (n) of the key
         */
-       status_t (*save_key) (rsa_public_key_t *this, char *file);
+       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.
+ * 
+ * Load a key from a chunk, encoded in the more frequently
+ * used PublicKeyInfo struct (ASN1 DER encoded).
+ * 
+ * @param chunk                                chunk containing the DER encoded key
+ * @return                                     loaded rsa_public_key_t, or NULL
+ * 
+ * @todo Check OID in PublicKeyInfo
+ * 
+ * @ingroup rsa
+ */
+rsa_public_key_t *rsa_public_key_create_from_chunk(chunk_t chunk);
+
+/**
+ * @brief Load an RSA public key from a file.
+ * 
+ * Load a key from a file, which is either in binary
+ * format (DER), or in PEM format. 
+ * 
+ * @param filename                     filename which holds the key
+ * @return                                     loaded rsa_public_key_t, or NULL
  * 
- * @return created rsa_public_key_t.
+ * @todo Implement PEM file loading
  * 
  * @ingroup rsa
  */
-rsa_public_key_t *rsa_public_key_create();
+rsa_public_key_t *rsa_public_key_create_from_file(char *filename);
 
 #endif /*RSA_PUBLIC_KEY_H_*/
index 51efa2b..c66de48 100644 (file)
@@ -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");
                }
        
@@ -294,6 +294,14 @@ static void disable_level(private_logger_t *this, log_level_t log_level)
 }
 
 /**
+ * Implementation of logger_t.set_output.
+ */
+static void set_output(private_logger_t *this, FILE * output)
+{
+       this->output = output;
+}
+
+/**
  * Implementation of logger_t.get_level.
  */
 static log_level_t get_level(private_logger_t *this)
@@ -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 */
index bdf5e18..637915e 100644 (file)
@@ -157,6 +157,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.
         *
         * @param this          logger_t object
index 05824e6..f5c71fc 100644 (file)
@@ -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++)
index 3614204..bc8f0e6 100644 (file)
@@ -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
         */