extended asn1_algorithmIdentifier() to SHA-2
authorAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 22 Jan 2008 10:32:37 +0000 (10:32 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Tue, 22 Jan 2008 10:32:37 +0000 (10:32 -0000)
12 files changed:
src/libstrongswan/asn1/asn1.c
src/libstrongswan/asn1/asn1.h
src/libstrongswan/crypto/hashers/hasher.c
src/libstrongswan/crypto/hashers/hasher.h
src/libstrongswan/crypto/ocsp.c
src/libstrongswan/crypto/pkcs7.c
src/libstrongswan/crypto/pkcs7.h
src/libstrongswan/crypto/rsa/rsa_private_key.c
src/libstrongswan/crypto/rsa/rsa_private_key.h
src/libstrongswan/crypto/rsa/rsa_public_key.c
src/libstrongswan/crypto/rsa/rsa_public_key.h
src/libstrongswan/crypto/x509.c

index e2ffd8c..59d848b 100644 (file)
@@ -1,6 +1,15 @@
-/* Simple ASN.1 parser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- * Copyright (C) 2006 Martin Will, Hochschule fuer Technik Rapperswil
+/**
+ * @file asn1.c
+ *
+ * @brief Simple ASN.1 parser
+ *
+ */
+
+/*
+ * Copyright (C) 2006 Martin Will
+ * Copyright (C) 2000-2008 Andreas Steffen
+ *
+ * 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
@@ -91,6 +100,27 @@ static u_char ASN1_sha1WithRSA_id_str[] = {
                  0x05, 0x00
 };
 
+static u_char ASN1_sha256WithRSA_id_str[] = {
+       0x30, 0x0D,
+                 0x06, 0x09,
+                               0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
+                 0x05, 0x00
+};
+
+static u_char ASN1_sha384WithRSA_id_str[] = {
+       0x30, 0x0D,
+                 0x06, 0x09,
+                               0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0C,
+                 0x05, 0x00
+};
+
+static u_char ASN1_sha512WithRSA_id_str[] = {
+       0x30, 0x0D,
+                 0x06, 0x09,
+                               0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0D,
+                 0x05, 0x00
+};
+
 static u_char ASN1_rsaEncryption_id_str[] = {
        0x30, 0x0D,
                  0x06, 0x09,
@@ -98,15 +128,18 @@ static u_char ASN1_rsaEncryption_id_str[] = {
                  0x05, 0x00
 };
 
-const chunk_t ASN1_md2_id    = chunk_from_buf(ASN1_md2_id_str);
-const chunk_t ASN1_md5_id    = chunk_from_buf(ASN1_md5_id_str);
-const chunk_t ASN1_sha1_id   = chunk_from_buf(ASN1_sha1_id_str);
-const chunk_t ASN1_sha256_id = chunk_from_buf(ASN1_sha256_id_str);
-const chunk_t ASN1_sha384_id = chunk_from_buf(ASN1_sha384_id_str);
-const chunk_t ASN1_sha512_id = chunk_from_buf(ASN1_sha512_id_str);
-const chunk_t ASN1_rsaEncryption_id = chunk_from_buf(ASN1_rsaEncryption_id_str);
-const chunk_t ASN1_md5WithRSA_id = chunk_from_buf(ASN1_md5WithRSA_id_str);
-const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_id_str);
+static const chunk_t ASN1_md2_id    = chunk_from_buf(ASN1_md2_id_str);
+static const chunk_t ASN1_md5_id    = chunk_from_buf(ASN1_md5_id_str);
+static const chunk_t ASN1_sha1_id   = chunk_from_buf(ASN1_sha1_id_str);
+static const chunk_t ASN1_sha256_id = chunk_from_buf(ASN1_sha256_id_str);
+static const chunk_t ASN1_sha384_id = chunk_from_buf(ASN1_sha384_id_str);
+static const chunk_t ASN1_sha512_id = chunk_from_buf(ASN1_sha512_id_str);
+static const chunk_t ASN1_rsaEncryption_id = chunk_from_buf(ASN1_rsaEncryption_id_str);
+static const chunk_t ASN1_md5WithRSA_id = chunk_from_buf(ASN1_md5WithRSA_id_str);
+static const chunk_t ASN1_sha1WithRSA_id = chunk_from_buf(ASN1_sha1WithRSA_id_str);
+static const chunk_t ASN1_sha256WithRSA_id = chunk_from_buf(ASN1_sha256WithRSA_id_str);
+static const chunk_t ASN1_sha384WithRSA_id = chunk_from_buf(ASN1_sha384WithRSA_id_str);
+static const chunk_t ASN1_sha512WithRSA_id = chunk_from_buf(ASN1_sha512WithRSA_id_str);
 
 /* ASN.1 definiton of an algorithmIdentifier */
 static const asn1Object_t algorithmIdentifierObjects[] = {
@@ -132,10 +165,24 @@ chunk_t asn1_algorithmIdentifier(int oid)
                        return ASN1_md5WithRSA_id;
                case OID_SHA1_WITH_RSA:
                        return ASN1_sha1WithRSA_id;
+               case OID_SHA256_WITH_RSA:
+                       return ASN1_sha256WithRSA_id;
+               case OID_SHA384_WITH_RSA:
+                       return ASN1_sha384WithRSA_id;
+               case OID_SHA512_WITH_RSA:
+                       return ASN1_sha512WithRSA_id;
+               case OID_MD2:
+                       return ASN1_md2_id;
                case OID_MD5:
                        return ASN1_md5_id;
                case OID_SHA1:
                        return ASN1_sha1_id;
+               case OID_SHA256:
+                       return ASN1_sha256_id;
+               case OID_SHA384:
+                       return ASN1_sha384_id;
+               case OID_SHA512:
+                       return ASN1_sha512_id;
                default:
                        return chunk_empty;
        }
@@ -706,6 +753,23 @@ chunk_t asn1_simple_object(asn1_t tag, chunk_t content)
 }
 
 /**
+ * Build an ASN.1 BITSTRING object
+ */
+chunk_t asn1_bitstring(const char *mode, chunk_t content)
+{
+       chunk_t object;
+       u_char *pos = build_asn1_object(&object, ASN1_BIT_STRING, 1 + content.len);
+
+       *pos++ = 0x00;
+       memcpy(pos, content.ptr, content.len);
+       if (*mode == 'm')
+       {
+               free(content.ptr);
+       }
+       return object;
+}
+
+/**
  * Build an ASN.1 object from a variable number of individual chunks.
  * Depending on the mode, chunks either are moved ('m') or copied ('c').
  */
@@ -736,17 +800,12 @@ chunk_t asn1_wrap(asn1_t type, const char *mode, ...)
        {
                chunk_t ch = va_arg(chunks, chunk_t);
                
-               switch (*mode++)
+               memcpy(pos, ch.ptr, ch.len);
+               pos += ch.len;
+
+               if (*mode++ == 'm')
                {
-                       case 'm':
-                               memcpy(pos, ch.ptr, ch.len); 
-                               pos += ch.len;
-                               free(ch.ptr);
-                               break;
-                       case 'c':
-                       default:
-                               memcpy(pos, ch.ptr, ch.len); 
-                               pos += ch.len;
+                       free(ch.ptr);
                }
        }
        va_end(chunks);
index ef19ea0..4eaf1a7 100644 (file)
@@ -1,6 +1,15 @@
-/* Simple ASN.1 parser
- * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur
- * Copyright (C) 2006 Martin Will, Hochschule fuer Technik Rapperswil
+/**
+ * @file asn1.h
+ *
+ * @brief Simple ASN.1 parser
+ *
+ */
+
+/*
+ * Copyright (C) 2006 Martin Will
+ * Copyright (C) 2000-2008 Andreas Steffen
+ *
+ * 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
@@ -114,19 +123,9 @@ extern const chunk_t ASN1_INTEGER_0;
 extern const chunk_t ASN1_INTEGER_1;
 extern const chunk_t ASN1_INTEGER_2;
 
-/* some popular algorithmIdentifiers */
-extern const chunk_t ASN1_md2_id;
-extern const chunk_t ASN1_md5_id;
-extern const chunk_t ASN1_sha1_id;
-extern const chunk_t ASN1_sha256_id;
-extern const chunk_t ASN1_sha384_id;
-extern const chunk_t ASN1_sha512_id;
-
-extern const chunk_t ASN1_rsaEncryption_id;
-extern const chunk_t ASN1_md5WithRSA_id;
-extern const chunk_t ASN1_sha1WithRSA_id;
-
+/* returns some popular algorithmIdentifiers */
 extern chunk_t asn1_algorithmIdentifier(int oid);
+
 extern int known_oid(chunk_t object);
 extern u_int asn1_length(chunk_t *blob);
 extern bool is_printablestring(chunk_t str);
@@ -144,6 +143,7 @@ extern void code_asn1_length(size_t length, chunk_t *code);
 extern u_char* build_asn1_object(chunk_t *object, asn1_t type, size_t datalen);
 extern chunk_t asn1_integer_from_mpz(const mpz_t value);
 extern chunk_t asn1_simple_object(asn1_t tag, chunk_t content);
+extern chunk_t asn1_bitstring(const char *mode, chunk_t content);
 extern chunk_t asn1_wrap(asn1_t type, const char *mode, ...);
 
 #endif /* _ASN1_H */
index fa91ec2..d8c6ff9 100644 (file)
@@ -6,8 +6,9 @@
  */
 
 /*
- * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ *
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -110,6 +111,39 @@ hash_algorithm_t hasher_algorithm_from_oid(int oid)
 /*
  * Described in header.
  */
+int hasher_algorithm_to_oid(hash_algorithm_t alg)
+{
+       int oid;
+
+       switch (alg)
+       {
+               case HASH_MD2:
+                       oid = OID_MD2;
+                       break;
+               case HASH_MD5:
+                       oid = OID_MD5;
+                       break;
+               case HASH_SHA1:
+                       oid = OID_SHA1;
+                       break;
+               case HASH_SHA256:
+                       oid = OID_SHA256;
+                       break;
+               case HASH_SHA384:
+                       oid = OID_SHA384;
+                       break;
+               case HASH_SHA512:
+                       oid = OID_SHA512;
+                       break;
+               default:
+                       oid = OID_UNKNOWN;
+       }
+       return oid;
+}
+
+/*
+ * Described in header.
+ */
 int hasher_signature_algorithm_to_oid(hash_algorithm_t alg)
 {
        int oid;
index 65c31a0..d6604b8 100644 (file)
@@ -6,8 +6,9 @@
  */
 
 /*
- * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ *
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -171,11 +172,23 @@ hasher_t *hasher_create(hash_algorithm_t hash_algorithm);
 hash_algorithm_t hasher_algorithm_from_oid(int oid);
 
 /**
- * @brief Conversion of hash signature algorithm ASN.1 OID.
+ * @brief Conversion of hash algorithm into ASN.1 OID.
+ * 
+ * @param alg                          hash algorithm
+ * @return
+ *                                                     - ASN.1 hash OID if known hash algorithm
+ *                                                     - OID_UNKNOW
+ * 
+ * @ingroup hashers
+ */
+int hasher_algorithm_to_oid(hash_algorithm_t alg);
+
+/**
+ * @brief Conversion of hash signature algorithm into ASN.1 OID.
  * 
  * @param alg                          hash algorithm
  * @return
- *                                                     - ASN.1 OID if known hash algorithm
+ *                                                     - ASN.1 signature OID if known hash algorithm
  *                                                     - OID_UNKNOW
  * 
  * @ingroup hashers
index e4d9071..627a8aa 100644 (file)
@@ -6,8 +6,11 @@
  */
 
 /* Support of the Online Certificate Status Protocol (OCSP)
+ *
  * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
- * Zuercher Hochschule Winterthur
+ * Copyright (C) 2007 Andreas Steffen
+ *
+ * Hochschule für 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
@@ -325,7 +328,7 @@ static chunk_t build_request(private_ocsp_t *this, certinfo_t *certinfo)
        chunk_t serialNumber = certinfo->get_serialNumber(certinfo);
 
        chunk_t reqCert = asn1_wrap(ASN1_SEQUENCE, "cmmm",
-               ASN1_sha1_id,
+               asn1_algorithmIdentifier(OID_SHA1),
                asn1_simple_object(ASN1_OCTET_STRING, this->authNameID),
                asn1_simple_object(ASN1_OCTET_STRING, this->authKeyID),
                asn1_simple_object(ASN1_INTEGER, serialNumber));
index 6ccb0ef..820cbd5 100644 (file)
@@ -7,7 +7,7 @@
 
 /*
  * Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2005 Andreas Steffen
+ * Copyright (C) 2002-2008 Andreas Steffen
  * Hochschule fuer Technik Rapperswil, Switzerland
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -34,6 +34,8 @@
 #include <crypto/x509.h>
 #include <crypto/hashers/hasher.h>
 #include <crypto/crypters/crypter.h>
+#include <crypto/rsa/rsa_public_key.h>
+#include <utils/randomizer.h>
 #include <utils/linked_list.h>
 
 #include "pkcs7.h"
@@ -262,7 +264,7 @@ static const chunk_t ASN1_messageDigest_oid =
                                                chunk_from_buf(ASN1_messageDigest_oid_str);
 
 /**
- * Implements pkcs7_t.is_signedData.
+ * Implements pkcs7_t.is_data.
  */
 static bool is_data(private_pkcs7_t *this)
 {
@@ -278,7 +280,7 @@ static bool is_signedData(private_pkcs7_t *this)
 }
 
 /**
- * Implements pkcs7_t.is_signedData.
+ * Implements pkcs7_t.is_envelopedData.
  */
 static bool is_envelopedData(private_pkcs7_t *this)
 {
@@ -574,8 +576,9 @@ static bool parse_envelopedData(private_pkcs7_t *this, chunk_t serialNumber,
        }
 
        /* decrypt the content */
+       crypter->set_key(crypter, symmetric_key);
        crypter->decrypt(crypter, encrypted_content, iv, &this->data);
-       DBG4("decrypted content with padding: %B", &this->data);
+       DBG3("decrypted content with padding: %B", &this->data);
 
        /* remove the padding */
        {
@@ -611,7 +614,7 @@ failed:
 }
 
 /**
- * Implements pkcs7_t.get_data
+ * Implements pkcs7_t.get_data.
  */
 static chunk_t get_data(private_pkcs7_t *this)
 {
@@ -619,7 +622,49 @@ static chunk_t get_data(private_pkcs7_t *this)
 }
 
 /**
- * Implements pkcs_t.create_crluri_iterator
+ * Implements pkcs7_t.get_contentInfo.
+ */
+static chunk_t get_contentInfo(private_pkcs7_t *this)
+{
+       chunk_t content_type;
+
+       /* select DER-encoded OID for pkcs7_contentInfo type */
+       switch(this->type)
+       {
+               case OID_PKCS7_DATA:
+                       content_type = ASN1_pkcs7_data_oid;
+                       break;
+               case OID_PKCS7_SIGNED_DATA:
+                       content_type = ASN1_pkcs7_signed_data_oid;
+                       break;
+               case OID_PKCS7_ENVELOPED_DATA:
+                       content_type = ASN1_pkcs7_enveloped_data_oid;
+                       break;
+               case OID_PKCS7_SIGNED_ENVELOPED_DATA:
+                       content_type = ASN1_pkcs7_signed_enveloped_data_oid;
+                       break;
+               case OID_PKCS7_DIGESTED_DATA:
+                       content_type = ASN1_pkcs7_digested_data_oid;
+                       break;
+               case OID_PKCS7_ENCRYPTED_DATA:
+                       content_type = ASN1_pkcs7_encrypted_data_oid;
+                       break;
+               case OID_UNKNOWN:
+               default:
+                       DBG1("invalid pkcs7 contentInfo type");
+                       return chunk_empty;
+       }
+
+       return (this->content.ptr == NULL)
+                       ? asn1_simple_object(ASN1_SEQUENCE, content_type)
+                       : asn1_wrap(ASN1_SEQUENCE, "cc",
+                                       content_type,
+                                       asn1_simple_object(ASN1_CONTEXT_C_0, this->content)
+                         );
+}
+
+/**
+ * Implements pkcs7_t.create_certificate_iterator
  */
 static iterator_t *create_certificate_iterator(const private_pkcs7_t *this)
 {
@@ -627,6 +672,138 @@ static iterator_t *create_certificate_iterator(const private_pkcs7_t *this)
 }
 
 /**
+ * build a DER-encoded issuerAndSerialNumber object
+ */
+chunk_t pkcs7_build_issuerAndSerialNumber(x509_t *cert)
+{
+    return asn1_wrap(ASN1_SEQUENCE, "cm",
+                       cert->get_issuer(cert),
+                       asn1_simple_object(ASN1_INTEGER, cert->get_serialNumber(cert)));
+}
+
+/**
+ * Implements pkcs7_t.build_envelopedData.
+ */
+bool build_envelopedData(private_pkcs7_t *this, x509_t *cert,
+                                                encryption_algorithm_t alg)
+{
+       chunk_t iv, symmetricKey, out, alg_oid;
+       crypter_t *crypter;
+
+       /* select OID of symmetric encryption algorithm */
+       switch (alg)
+       {
+               case ENCR_DES:
+                       alg_oid = ASN1_des_cbc_oid;
+                       break;
+               case ENCR_3DES:
+                       alg_oid = ASN1_3des_ede_cbc_oid;
+                       break;
+               default:
+                       return FALSE;
+       }
+
+       crypter = crypter_create(alg, 0);
+       if (crypter == NULL)
+       {
+               DBG1("could not create crypter for algorithm %N",
+                        encryption_algorithm_names, alg);
+               return FALSE;
+       }
+
+       /* generate a true random symmetric encryption key
+        * and a pseudo-random iv
+        */
+       {
+               randomizer_t *randomizer = randomizer_create();
+
+               randomizer->allocate_random_bytes(randomizer,
+                        crypter->get_key_size(crypter), &symmetricKey);
+               DBG4("symmetric encryption key: %B", &symmetricKey);
+
+               randomizer->allocate_pseudo_random_bytes(randomizer,
+                       crypter->get_block_size(crypter), &iv);
+               DBG4("initialization vector: %B", &iv);
+
+               randomizer->destroy(randomizer);
+       }
+
+       /* pad the data so that the total length becomes
+        * a multiple of the block size
+        */
+       {
+               size_t block_size = crypter->get_block_size(crypter);
+               size_t padding = this->data.len % block_size;
+
+               if (padding == 0)
+               {
+                       padding += block_size;
+               }
+
+               out.len = this->data.len + padding;
+               out.ptr = malloc(out.len);
+
+               DBG2("padding %d bytes of data to multiple block size of %d bytes",
+                       (int)this->data.len, (int)out.len);
+
+               /* copy data */
+               memcpy(out.ptr, this->data.ptr, this->data.len);
+               /* append padding */
+               memset(out.ptr + this->data.len, padding, padding);
+       }
+       DBG3("padded unencrypted data: %B", &out);
+
+       /* symmetric encryption of data object */
+       crypter->set_key(crypter, symmetricKey);
+       crypter->encrypt(crypter, this->data, iv, &out);
+       crypter->destroy(crypter);
+    DBG3("encrypted data: %B", &out);
+
+       /* build pkcs7 enveloped data object */ 
+       {
+               chunk_t contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "cm",
+                                       alg_oid,
+                                       asn1_wrap(ASN1_OCTET_STRING, "m", iv));
+       
+               chunk_t encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "cmm",
+                                       ASN1_pkcs7_data_oid,
+                                       contentEncryptionAlgorithm,
+                                       asn1_wrap(ASN1_CONTEXT_S_0, "m", out));
+
+               chunk_t wrappedKey, encryptedKey, recipientInfo;
+
+               rsa_public_key_t *public_key = cert->get_public_key(cert);
+
+               public_key->pkcs1_encrypt(public_key, symmetricKey, &wrappedKey);
+               chunk_free_randomized(&symmetricKey);
+
+               encryptedKey = asn1_wrap(ASN1_OCTET_STRING, "m", wrappedKey);
+
+               recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmcm",
+                                       ASN1_INTEGER_0,
+                                       pkcs7_build_issuerAndSerialNumber(cert),
+                                       asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+                                       encryptedKey);
+
+               this->content = asn1_wrap(ASN1_SEQUENCE, "cmm",
+                                       ASN1_INTEGER_0,
+                                       asn1_wrap(ASN1_SET, "m", recipientInfo),
+                                       encryptedContentInfo);
+               this->type = OID_PKCS7_ENVELOPED_DATA;
+    }
+       return TRUE;
+}
+
+/**
+ * Implements pkcs7_t.build_signedData.
+ */
+bool build_signedData(private_pkcs7_t *this, rsa_private_key_t *key,
+                                         hash_algorithm_t alg)
+{
+       return FALSE;
+}
+
+/**
  * Implements pkcs7_t.destroy
  */
 static void destroy(private_pkcs7_t *this)
@@ -674,10 +851,10 @@ static bool parse_contentInfo(chunk_t blob, u_int level0, private_pkcs7_t *cInfo
        return TRUE;
 }
 
-/*
- * Described in header.
+/**
+ * Generic private constructor
  */
-pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
+static private_pkcs7_t *pkcs7_create_empty(void)
 {
        private_pkcs7_t *this = malloc_thing(private_pkcs7_t);
        
@@ -685,7 +862,7 @@ pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
        this->type = OID_UNKNOWN;
        this->content = chunk_empty;
        this->parsed = FALSE;
-       this->level = level + 2;
+       this->level = 0;
        this->data = chunk_empty;
        this->attributes = chunk_empty;
        this->certs = linked_list_create();
@@ -698,9 +875,23 @@ pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
        this->public.parse_signedData = (bool (*) (pkcs7_t*,x509_t*))parse_signedData;
        this->public.parse_envelopedData = (bool (*) (pkcs7_t*,chunk_t,rsa_private_key_t*))parse_envelopedData;
        this->public.get_data = (chunk_t (*) (pkcs7_t*))get_data;
+       this->public.get_contentInfo = (chunk_t (*) (pkcs7_t*))get_contentInfo;
        this->public.create_certificate_iterator = (iterator_t* (*) (pkcs7_t*))create_certificate_iterator;
+       this->public.build_envelopedData = (bool (*) (pkcs7_t*,x509_t*,encryption_algorithm_t))build_envelopedData;
+       this->public.build_signedData = (bool (*) (pkcs7_t*,rsa_private_key_t*,hash_algorithm_t))build_signedData;
        this->public.destroy = (void (*) (pkcs7_t*))destroy;
 
+       return this;
+}
+
+/*
+ * Described in header.
+ */
+pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
+{
+       private_pkcs7_t *this = pkcs7_create_empty();
+       
+       this->level = level + 2;
        if (!parse_contentInfo(chunk, level, this))
        {
                destroy(this);
@@ -708,3 +899,18 @@ pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level)
        }
        return &this->public;
 }
+
+/*
+ * Described in header.
+ */
+pkcs7_t *pkcs7_create_from_data(chunk_t data, chunk_t attributes, x509_t *cert)
+{
+       private_pkcs7_t *this = pkcs7_create_empty();
+
+       this->data = chunk_clone(data);
+       this->attributes = attributes;
+       this->certs->insert_last(this->certs, cert);
+       this->parsed = TRUE;
+
+       return &this->public;
+}
index 9886e77..8e5166d 100644 (file)
@@ -7,7 +7,7 @@
 
 /*
  * Copyright (C) 2005 Jan Hutter, Martin Willi
- * Copyright (C) 2002-2007 Andreas Steffen
+ * Copyright (C) 2002-2008 Andreas Steffen
  *
  * Hochschule fuer Technik Rapperswil, Switzerland
  *
@@ -32,6 +32,7 @@ typedef struct pkcs7_t pkcs7_t;
 #include <library.h>
 #include <crypto/x509.h>
 #include <crypto/rsa/rsa_private_key.h>
+#include <crypto/crypters/crypter.h>
 #include <utils/iterator.h>
 
 /**
@@ -39,6 +40,7 @@ typedef struct pkcs7_t pkcs7_t;
  * 
  * @b Constructors:
  *  -pkcs7_create_from_chunk()
+ *  -pkcs7_create()
  *
  * @ingroup crypto
  */
@@ -103,6 +105,14 @@ struct pkcs7_t {
        chunk_t (*get_data) (pkcs7_t *this);
 
        /**
+        * @brief Returns the a DER-encoded contentInfo object
+        *
+        * @param this                  calling object
+        * @return                              chunk containing the contentInfo object
+        */
+       chunk_t (*get_contentInfo) (pkcs7_t *this);
+
+       /**
         * @brief Create an iterator for the certificates.
         * 
         * @param this                          calling object
@@ -111,6 +121,26 @@ struct pkcs7_t {
        iterator_t *(*create_certificate_iterator) (pkcs7_t *this);
 
        /**
+        * @brief Build an envelopedData object
+        *
+        * @param this                  PKCS#7 data object to envelop
+        * @param cert                  receivers's certificate
+        * @param alg                   encryption algorithm
+        * @return                              TRUE if build was successful
+        */
+       bool (*build_envelopedData) (pkcs7_t *this, x509_t *cert, encryption_algorithm_t alg);
+
+       /**
+        * @brief Build an signedData object
+        *
+        * @param this                  PKCS#7 data object to sign
+        * @param key                   signer's RSA private key
+        * @param alg                   digest algorithm used for signature
+        * @return                              TRUE if build was successful
+        */
+       bool (*build_signedData) (pkcs7_t *this, rsa_private_key_t *key, hash_algorithm_t alg);
+
+       /**
         * @brief Destroys the contentInfo object.
         *
         * @param this                  PKCS#7 contentInfo object to destroy
@@ -129,4 +159,16 @@ struct pkcs7_t {
  */
 pkcs7_t *pkcs7_create_from_chunk(chunk_t chunk, u_int level);
 
+/**
+ * @brief Create a PKCS#7 contentInfo object
+ * 
+ * @param chunk                        chunk containing data
+ * @param attributes   chunk containing attributes
+ * @param cert                 certificate to be included in the pkcs7_contentInfo object
+ * @return                             created pkcs7_contentInfo object.
+ * 
+ * @ingroup crypto
+ */
+pkcs7_t *pkcs7_create_from_data(chunk_t data, chunk_t attributes, x509_t *cert);
+
 #endif /* _PKCS7_H */
index 40c63fa..efbe8e8 100644 (file)
@@ -6,8 +6,10 @@
  */
 
 /*
- * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -202,7 +204,7 @@ static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_len,
                if (status != SUCCESS)
                {
                        randomizer->destroy(randomizer);
-                       mpz_clear_randomized(*prime);
+                       mpz_clear(*prime);
                        return FAILED;
                }
                
@@ -219,7 +221,7 @@ static status_t compute_prime(private_rsa_private_key_t *this, size_t prime_len,
                chunk_free_randomized(&random_bytes);
        }
        /* check if it isnt too large */
-       while (((mpz_sizeinbase(*prime, 2) + 7) / 8) > prime_len);
+       while (((mpz_sizeinbase(*prime, 2) + 7) / BITS_PER_BYTE) > prime_len);
        
        randomizer->destroy(randomizer);
        return SUCCESS;
@@ -308,47 +310,14 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this,
                                                                                   chunk_t data, chunk_t *signature)
 {
        hasher_t *hasher;
-       chunk_t em, digestInfo, hash_id, hash;
-       
-       /* get oid string prepended to hash */
-       switch (hash_algorithm)
-       {       
-               case HASH_MD2:
-               {
-                       hash_id =ASN1_md2_id;
-                       break;
-               }
-               case HASH_MD5:
-               {
-                       hash_id = ASN1_md5_id;
-                       break;
-               }
-               case HASH_SHA1:
-               {
-                       hash_id = ASN1_sha1_id;
-                       break;
-               }
-               case HASH_SHA256:
-               {
-                       hash_id = ASN1_sha256_id;
-                       break;
-               }
-               case HASH_SHA384:
-               {
-                       hash_id = ASN1_sha384_id;
-                       break;
-               }
-               case HASH_SHA512:
-               {
-                       hash_id = ASN1_sha512_id;
-                       break;
-               }
-               default:
-               {
-                       return NOT_SUPPORTED;   
-               }
+       chunk_t em, digestInfo, hash;
+       int hash_oid = hasher_algorithm_to_oid(hash_algorithm);
+
+       if (hash_oid == OID_UNKNOWN)
+       {
+               return NOT_SUPPORTED;
        }
-       
+
        /* get hasher */
        hasher = hasher_create(hash_algorithm);
        if (hasher == NULL)
@@ -362,7 +331,7 @@ static status_t build_emsa_pkcs1_signature(private_rsa_private_key_t *this,
        
        /* build DER-encoded digestInfo */
        digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
-                                       hash_id,
+                                       asn1_algorithmIdentifier(hash_oid),
                                        asn1_simple_object(ASN1_OCTET_STRING, hash)
                                  );
        chunk_free(&hash);
index f5ff335..5f66458 100644 (file)
@@ -6,8 +6,10 @@
  */
 
 /*
- * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
index 4ce365e..2105d8f 100644 (file)
@@ -6,8 +6,10 @@
  */
 
 /*
- * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -295,19 +297,13 @@ static size_t get_keysize(const private_rsa_public_key_t *this)
  */
 chunk_t rsa_public_key_info_to_asn1(const mpz_t n, const mpz_t e)
 {
-       chunk_t rawKey = asn1_wrap(ASN1_SEQUENCE, "mm",
+       chunk_t publicKey = asn1_wrap(ASN1_SEQUENCE, "mm",
                                                                 asn1_integer_from_mpz(n),
                                                                 asn1_integer_from_mpz(e));
-       chunk_t publicKey;
-
-       u_char *pos = build_asn1_object(&publicKey, ASN1_BIT_STRING, 1 + rawKey.len);
-
-       *pos++ = 0x00;
-       memcpy(pos, rawKey.ptr, rawKey.len);
-       free(rawKey.ptr);
 
-       return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_rsaEncryption_id,
-                                                                                 publicKey);
+       return asn1_wrap(ASN1_SEQUENCE, "cm",
+                               asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+                               asn1_bitstring("m", publicKey));
 }
 
 /**
index 3a03463..1c15169 100644 (file)
@@ -6,8 +6,10 @@
  */
 
 /*
- * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2007-2008 Andreas Steffen
+ *
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
index 022f15c..ff490a0 100755 (executable)
@@ -1381,39 +1381,14 @@ static chunk_t x509_build_tbs(private_x509_t *this)
 static void build_encoding(private_x509_t *this, hash_algorithm_t alg,
                                                   rsa_private_key_t *private_key)
 {
-       switch (alg)
-       {
-               case HASH_MD5:
-                       this->signatureAlgorithm = OID_MD5_WITH_RSA;
-                       break;
-               case HASH_SHA1:
-               default:
-                       this->signatureAlgorithm = OID_SHA1_WITH_RSA;
-                       break;
-               case HASH_SHA256:
-                       this->signatureAlgorithm = OID_SHA256_WITH_RSA;
-                       break;
-               case HASH_SHA384:
-                       this->signatureAlgorithm = OID_SHA384_WITH_RSA;
-                       break;
-               case HASH_SHA512:
-                       this->signatureAlgorithm = OID_SHA512_WITH_RSA;
-       }
-       this->tbsCertificate = x509_build_tbs(this);
-       {
-               chunk_t rawSignature;
-               u_char *pos;
-
-               private_key->build_emsa_pkcs1_signature(private_key, alg,
-                                               this->tbsCertificate,   &rawSignature);
+       chunk_t signature;
 
-               pos = build_asn1_object(&this->signature, ASN1_BIT_STRING,
-                                                1 + rawSignature.len);
-               *pos++ = 0x00;
-               memcpy(pos, rawSignature.ptr, rawSignature.len);
-               free(rawSignature.ptr);
-       }
-    this->certificate = asn1_wrap(ASN1_SEQUENCE, "mcm",
+       this->signatureAlgorithm = hasher_signature_algorithm_to_oid(alg);
+       this->tbsCertificate = x509_build_tbs(this);
+       private_key->build_emsa_pkcs1_signature(private_key, alg,
+                                               this->tbsCertificate, &signature);
+       this->signature = asn1_bitstring("m", signature);
+       this->certificate = asn1_wrap(ASN1_SEQUENCE, "mcm",
                                this->tbsCertificate,
                                asn1_algorithmIdentifier(this->signatureAlgorithm),
                                this->signature);