diff options
Diffstat (limited to 'src/libstrongswan/plugins/pkcs7')
-rw-r--r-- | src/libstrongswan/plugins/pkcs7/Makefile.am | 1 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pkcs7/pkcs7_attributes.c | 273 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pkcs7/pkcs7_attributes.h | 79 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c | 14 |
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) { |