aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/plugins/pkcs7
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/pkcs7')
-rw-r--r--src/libstrongswan/plugins/pkcs7/Makefile.am1
-rw-r--r--src/libstrongswan/plugins/pkcs7/pkcs7_attributes.c273
-rw-r--r--src/libstrongswan/plugins/pkcs7/pkcs7_attributes.h79
-rw-r--r--src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c14
4 files changed, 361 insertions, 6 deletions
diff --git a/src/libstrongswan/plugins/pkcs7/Makefile.am b/src/libstrongswan/plugins/pkcs7/Makefile.am
index 944f22cec..6310daece 100644
--- a/src/libstrongswan/plugins/pkcs7/Makefile.am
+++ b/src/libstrongswan/plugins/pkcs7/Makefile.am
@@ -14,6 +14,7 @@ libstrongswan_pkcs7_la_SOURCES = \
pkcs7_signed_data.h pkcs7_signed_data.c \
pkcs7_enveloped_data.h pkcs7_enveloped_data.c \
pkcs7_data.h pkcs7_data.c \
+ pkcs7_attributes.h pkcs7_attributes.c \
pkcs7_plugin.h pkcs7_plugin.c
libstrongswan_pkcs7_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/pkcs7/pkcs7_attributes.c b/src/libstrongswan/plugins/pkcs7/pkcs7_attributes.c
new file mode 100644
index 000000000..ca6899786
--- /dev/null
+++ b/src/libstrongswan/plugins/pkcs7/pkcs7_attributes.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2008 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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 <library.h>
+#include <utils/debug.h>
+
+#include <asn1/oid.h>
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <collections/linked_list.h>
+
+#include "pkcs7_attributes.h"
+
+typedef struct private_pkcs7_attributes_t private_pkcs7_attributes_t;
+typedef struct attribute_t attribute_t;
+
+/**
+ * Private data of a pkcs7_attributes_t attribute list.
+ */
+struct private_pkcs7_attributes_t {
+ /**
+ * Public interface
+ */
+ pkcs7_attributes_t public;
+
+ /**
+ * DER encoding of PKCS#9 attributes
+ */
+ chunk_t encoding;
+
+ /**
+ * Linked list of PKCS#9 attributes
+ */
+ linked_list_t *attributes;
+};
+
+/**
+ * Definition of an attribute_t object.
+ */
+struct attribute_t {
+
+ /**
+ * Object Identifier (OID)
+ */
+ int oid;
+
+ /**
+ * Attribute value
+ */
+ chunk_t value;
+
+ /**
+ * ASN.1 encoding
+ */
+ chunk_t encoding;
+};
+
+/**
+ * Destroy an attribute_t object.
+ */
+static void attribute_destroy(attribute_t *this)
+{
+ free(this->value.ptr);
+ free(this);
+}
+
+/**
+ * Create an attribute_t object.
+ */
+static attribute_t *attribute_create(int oid, chunk_t value)
+{
+ attribute_t *this;
+
+ INIT(this,
+ .oid = oid,
+ .value = chunk_clone(value),
+ );
+
+ return this;
+}
+
+/**
+ * Build encoding of the attribute list
+ */
+static void build_encoding(private_pkcs7_attributes_t *this)
+{
+ enumerator_t *enumerator;
+ attribute_t *attribute;
+ u_int len = 0, count, i = 0;
+ chunk_t *chunks;
+ u_char *pos;
+
+ count = this->attributes->get_count(this->attributes);
+ chunks = malloc(sizeof(chunk_t) * count);
+
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
+ {
+ chunks[i] = asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(attribute->oid),
+ asn1_wrap(ASN1_SET, "c", attribute->value));
+ len += chunks[i].len;
+ i++;
+ }
+ enumerator->destroy(enumerator);
+
+ pos = asn1_build_object(&this->encoding, ASN1_SET, len);
+ for (i = 0; i < count; i++)
+ {
+ memcpy(pos, chunks[i].ptr, chunks[i].len);
+ pos += chunks[i].len;
+ free(chunks[i].ptr);
+ }
+ free(chunks);
+}
+
+METHOD(pkcs7_attributes_t, get_encoding, chunk_t,
+ private_pkcs7_attributes_t *this)
+{
+ if (!this->encoding.len)
+ {
+ build_encoding(this);
+ }
+ return this->encoding;
+}
+
+METHOD(pkcs7_attributes_t, get_attribute, chunk_t,
+ private_pkcs7_attributes_t *this, int oid)
+{
+ enumerator_t *enumerator;
+ chunk_t value = chunk_empty;
+ attribute_t *attribute;
+
+ enumerator = this->attributes->create_enumerator(this->attributes);
+ while (enumerator->enumerate(enumerator, &attribute))
+ {
+ if (attribute->oid == oid)
+ {
+ value = attribute->value;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (value.len && asn1_unwrap(&value, &value) != ASN1_INVALID)
+ {
+ return value;
+ }
+ return chunk_empty;
+}
+
+METHOD(pkcs7_attributes_t, add_attribute, void,
+ private_pkcs7_attributes_t *this, int oid, chunk_t value)
+{
+ this->attributes->insert_last(this->attributes,
+ attribute_create(oid, value));
+ chunk_free(&value);
+
+ /* rebuild encoding when adding attributes */
+ chunk_free(&this->encoding);
+}
+
+METHOD(pkcs7_attributes_t, destroy, void,
+ private_pkcs7_attributes_t *this)
+{
+ this->attributes->destroy_function(this->attributes,
+ (void*)attribute_destroy);
+ free(this->encoding.ptr);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+pkcs7_attributes_t *pkcs7_attributes_create(void)
+{
+ private_pkcs7_attributes_t *this;
+
+ INIT(this,
+ .public = {
+ .get_encoding = _get_encoding,
+ .get_attribute = _get_attribute,
+ .add_attribute = _add_attribute,
+ .destroy = _destroy,
+ },
+ .attributes = linked_list_create(),
+ );
+
+ return &this->public;
+}
+
+/**
+ * ASN.1 definition of the X.501 atttribute type
+ */
+static const asn1Object_t attributesObjects[] = {
+ { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */
+ { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
+ { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */
+ { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */
+ { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */
+ { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */
+ { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */
+ { 0, "exit", ASN1_EOC, ASN1_EXIT }
+};
+#define ATTRIBUTE_OBJ_TYPE 2
+#define ATTRIBUTE_OBJ_VALUE 4
+
+/**
+ * Parse a PKCS#9 attribute list
+ */
+static bool parse_attributes(chunk_t chunk, int level0,
+ private_pkcs7_attributes_t* this)
+{
+ asn1_parser_t *parser;
+ chunk_t object;
+ int objectID;
+ int oid = OID_UNKNOWN;
+ bool success = FALSE;
+
+ parser = asn1_parser_create(attributesObjects, chunk);
+ parser->set_top_level(parser, level0);
+
+ while (parser->iterate(parser, &objectID, &object))
+ {
+ switch (objectID)
+ {
+ case ATTRIBUTE_OBJ_TYPE:
+ oid = asn1_known_oid(object);
+ break;
+ case ATTRIBUTE_OBJ_VALUE:
+ if (oid != OID_UNKNOWN)
+ {
+ this->attributes->insert_last(this->attributes,
+ attribute_create(oid, object));
+ }
+ break;
+ }
+ }
+ success = parser->success(parser);
+
+ parser->destroy(parser);
+ return success;
+}
+
+ /*
+ * Described in header.
+ */
+pkcs7_attributes_t *pkcs7_attributes_create_from_chunk(chunk_t chunk,
+ u_int level)
+{
+ private_pkcs7_attributes_t *this;
+
+ this = (private_pkcs7_attributes_t*)pkcs7_attributes_create();
+ this->encoding = chunk_clone(chunk);
+ if (!parse_attributes(chunk, level, this))
+ {
+ destroy(this);
+ return NULL;
+ }
+ return &this->public;
+}
diff --git a/src/libstrongswan/plugins/pkcs7/pkcs7_attributes.h b/src/libstrongswan/plugins/pkcs7/pkcs7_attributes.h
new file mode 100644
index 000000000..2959194b0
--- /dev/null
+++ b/src/libstrongswan/plugins/pkcs7/pkcs7_attributes.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2008 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil, Switzerland
+ *
+ * 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.
+ */
+
+/**
+ * @defgroup pkcs7_attributes pkcs7_attributes
+ * @{ @ingroup pkcs7
+ */
+
+#ifndef PKCS7_ATTRIBUTES_H_
+#define PKCS7_ATTRIBUTES_H_
+
+typedef struct pkcs7_attributes_t pkcs7_attributes_t;
+
+#include <library.h>
+
+/**
+ * PKCS#7 attribute lists, aka PKCS#9.
+ */
+struct pkcs7_attributes_t {
+
+ /**
+ * Gets ASN.1 encoding of PKCS#9 attribute list.
+ *
+ * @return ASN.1 encoded PKCSI#9 list
+ */
+ chunk_t (*get_encoding) (pkcs7_attributes_t *this);
+
+ /**
+ * Gets a PKCS#9 attribute from the list.
+ *
+ * @param oid OID of the attribute
+ * @return value of the attribute (internal data)
+ */
+ chunk_t (*get_attribute) (pkcs7_attributes_t *this, int oid);
+
+ /**
+ * Adds a PKCS#9 attribute.
+ *
+ * @param oid OID of the attribute
+ * @param value value of the attribute, with ASN1 type (gets owned)
+ */
+ void (*add_attribute) (pkcs7_attributes_t *this, int oid, chunk_t value);
+
+ /**
+ * Destroys the PKCS#9 attribute list.
+ */
+ void (*destroy) (pkcs7_attributes_t *this);
+};
+
+/**
+ * Read a PKCS#7 attribute list (aka PKCS#9) from a DER encoded chunk.
+ *
+ * @param chunk chunk containing DER encoded data
+ * @param level ASN.1 parsing start level
+ * @return created pkcs9 attribute list, or NULL if invalid.
+ */
+pkcs7_attributes_t *pkcs7_attributes_create_from_chunk(chunk_t chunk, u_int level);
+
+/**
+ * Create an empty PKCS#7 attribute list, aka PKCS#9.
+ *
+ * @return created pkcs9 attribute list.
+ */
+pkcs7_attributes_t *pkcs7_attributes_create(void);
+
+#endif /** PKCS9_H_ @}*/
diff --git a/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c b/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c
index 2ef97084f..48fb5e6a4 100644
--- a/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c
+++ b/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c
@@ -14,6 +14,7 @@
*/
#include "pkcs7_signed_data.h"
+#include "pkcs7_attributes.h"
#include <time.h>
@@ -21,7 +22,6 @@
#include <asn1/oid.h>
#include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
-#include <crypto/pkcs9.h>
#include <credentials/sets/mem_cred.h>
#include <credentials/certificates/x509.h>
#include <credentials/keys/private_key.h>
@@ -67,7 +67,7 @@ typedef struct {
/**
* Signed attributes of signerInfo
*/
- pkcs9_t *attributes;
+ pkcs7_attributes_t *attributes;
/**
* Serial of signing certificate
@@ -455,7 +455,8 @@ static bool parse(private_pkcs7_signed_data_t *this, chunk_t content)
break;
case PKCS7_AUTH_ATTRIBUTES:
*object.ptr = ASN1_SET;
- info->attributes = pkcs9_create_from_chunk(object, level+1);
+ info->attributes = pkcs7_attributes_create_from_chunk(
+ object, level+1);
*object.ptr = ASN1_CONTEXT_C_0;
break;
case PKCS7_DIGEST_ALGORITHM:
@@ -516,7 +517,8 @@ static chunk_t build_issuerAndSerialNumber(certificate_t *cert)
* Generate a new PKCS#7 signed-data container
*/
static bool generate(private_pkcs7_signed_data_t *this, private_key_t *key,
- certificate_t *cert, hash_algorithm_t alg, pkcs9_t *pkcs9)
+ certificate_t *cert, hash_algorithm_t alg,
+ pkcs7_attributes_t *pkcs9)
{
chunk_t authenticatedAttributes = chunk_empty;
chunk_t encryptedDigest = chunk_empty;
@@ -617,11 +619,11 @@ pkcs7_t *pkcs7_signed_data_gen(container_type_t type, va_list args)
hash_algorithm_t alg = HASH_SHA1;
private_key_t *key = NULL;
certificate_t *cert = NULL;
- pkcs9_t *pkcs9;
+ pkcs7_attributes_t *pkcs9;
chunk_t value;
int oid;
- pkcs9 = pkcs9_create();
+ pkcs9 = pkcs7_attributes_create();
while (TRUE)
{