Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs7/pkcs7_attributes.c, revision 1.1.1.2
1.1 misho 1: /*
2: * Copyright (C) 2012 Tobias Brunner
3: * Copyright (C) 2008 Andreas Steffen
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include <library.h>
18: #include <utils/debug.h>
19:
20: #include <asn1/oid.h>
21: #include <asn1/asn1.h>
22: #include <asn1/asn1_parser.h>
1.1.1.2 ! misho 23: #include <collections/array.h>
1.1 misho 24: #include <collections/linked_list.h>
25:
26: #include "pkcs7_attributes.h"
27:
28: typedef struct private_pkcs7_attributes_t private_pkcs7_attributes_t;
29: typedef struct attribute_t attribute_t;
30:
31: /**
32: * Private data of a pkcs7_attributes_t attribute list.
33: */
34: struct private_pkcs7_attributes_t {
35: /**
36: * Public interface
37: */
38: pkcs7_attributes_t public;
39:
40: /**
41: * DER encoding of PKCS#9 attributes
42: */
43: chunk_t encoding;
44:
45: /**
46: * Linked list of PKCS#9 attributes
47: */
48: linked_list_t *attributes;
49: };
50:
51: /**
52: * Definition of an attribute_t object.
53: */
54: struct attribute_t {
55:
56: /**
57: * Object Identifier (OID)
58: */
59: int oid;
60:
61: /**
62: * Attribute value
63: */
64: chunk_t value;
65:
66: /**
67: * ASN.1 encoding
68: */
69: chunk_t encoding;
70: };
71:
72: /**
73: * Destroy an attribute_t object.
74: */
75: static void attribute_destroy(attribute_t *this)
76: {
77: free(this->value.ptr);
78: free(this);
79: }
80:
81: /**
82: * Create an attribute_t object.
83: */
84: static attribute_t *attribute_create(int oid, chunk_t value)
85: {
86: attribute_t *this;
87:
88: INIT(this,
89: .oid = oid,
90: .value = chunk_clone(value),
91: );
92:
93: return this;
94: }
95:
96: /**
1.1.1.2 ! misho 97: * Compare two encoded attributes
! 98: */
! 99: static int cmp_attributes(const chunk_t *a, const chunk_t *b, void *unused)
! 100: {
! 101: return chunk_compare(*a, *b);
! 102: }
! 103:
! 104: /**
1.1 misho 105: * Build encoding of the attribute list
106: */
107: static void build_encoding(private_pkcs7_attributes_t *this)
108: {
109: enumerator_t *enumerator;
110: attribute_t *attribute;
111: u_int len = 0, count, i = 0;
1.1.1.2 ! misho 112: array_t *chunks;
! 113: chunk_t chunk;
1.1 misho 114: u_char *pos;
115:
116: count = this->attributes->get_count(this->attributes);
1.1.1.2 ! misho 117: chunks = array_create(sizeof(chunk_t), count);
1.1 misho 118:
119: enumerator = this->attributes->create_enumerator(this->attributes);
120: while (enumerator->enumerate(enumerator, &attribute))
121: {
1.1.1.2 ! misho 122: chunk = asn1_wrap(ASN1_SEQUENCE, "mm",
! 123: asn1_build_known_oid(attribute->oid),
! 124: asn1_wrap(ASN1_SET, "c", attribute->value));
! 125: array_insert(chunks, ARRAY_TAIL, &chunk);
! 126: len += chunk.len;
1.1 misho 127: }
128: enumerator->destroy(enumerator);
129:
1.1.1.2 ! misho 130: array_sort(chunks, (void*)cmp_attributes, NULL);
! 131:
1.1 misho 132: pos = asn1_build_object(&this->encoding, ASN1_SET, len);
133: for (i = 0; i < count; i++)
134: {
1.1.1.2 ! misho 135: array_get(chunks, i, &chunk);
! 136: memcpy(pos, chunk.ptr, chunk.len);
! 137: pos += chunk.len;
! 138: free(chunk.ptr);
1.1 misho 139: }
1.1.1.2 ! misho 140: array_destroy(chunks);
1.1 misho 141: }
142:
143: METHOD(pkcs7_attributes_t, get_encoding, chunk_t,
144: private_pkcs7_attributes_t *this)
145: {
146: if (!this->encoding.len)
147: {
148: build_encoding(this);
149: }
150: return this->encoding;
151: }
152:
153: METHOD(pkcs7_attributes_t, get_attribute, chunk_t,
154: private_pkcs7_attributes_t *this, int oid)
155: {
156: enumerator_t *enumerator;
157: chunk_t value = chunk_empty;
158: attribute_t *attribute;
159:
160: enumerator = this->attributes->create_enumerator(this->attributes);
161: while (enumerator->enumerate(enumerator, &attribute))
162: {
163: if (attribute->oid == oid)
164: {
165: value = attribute->value;
166: break;
167: }
168: }
169: enumerator->destroy(enumerator);
170: if (value.len && asn1_unwrap(&value, &value) != ASN1_INVALID)
171: {
172: return value;
173: }
174: return chunk_empty;
175: }
176:
177: METHOD(pkcs7_attributes_t, add_attribute, void,
178: private_pkcs7_attributes_t *this, int oid, chunk_t value)
179: {
180: this->attributes->insert_last(this->attributes,
181: attribute_create(oid, value));
182: chunk_free(&value);
183:
184: /* rebuild encoding when adding attributes */
185: chunk_free(&this->encoding);
186: }
187:
188: METHOD(pkcs7_attributes_t, destroy, void,
189: private_pkcs7_attributes_t *this)
190: {
191: this->attributes->destroy_function(this->attributes,
192: (void*)attribute_destroy);
193: free(this->encoding.ptr);
194: free(this);
195: }
196:
197: /*
198: * Described in header.
199: */
200: pkcs7_attributes_t *pkcs7_attributes_create(void)
201: {
202: private_pkcs7_attributes_t *this;
203:
204: INIT(this,
205: .public = {
206: .get_encoding = _get_encoding,
207: .get_attribute = _get_attribute,
208: .add_attribute = _add_attribute,
209: .destroy = _destroy,
210: },
211: .attributes = linked_list_create(),
212: );
213:
214: return &this->public;
215: }
216:
217: /**
218: * ASN.1 definition of the X.501 attribute type
219: */
220: static const asn1Object_t attributesObjects[] = {
221: { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */
222: { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
223: { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */
224: { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */
225: { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */
226: { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */
227: { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */
228: { 0, "exit", ASN1_EOC, ASN1_EXIT }
229: };
230: #define ATTRIBUTE_OBJ_TYPE 2
231: #define ATTRIBUTE_OBJ_VALUE 4
232:
233: /**
234: * Parse a PKCS#9 attribute list
235: */
236: static bool parse_attributes(chunk_t chunk, int level0,
237: private_pkcs7_attributes_t* this)
238: {
239: asn1_parser_t *parser;
240: chunk_t object;
241: int objectID;
242: int oid = OID_UNKNOWN;
243: bool success = FALSE;
244:
245: parser = asn1_parser_create(attributesObjects, chunk);
246: parser->set_top_level(parser, level0);
247:
248: while (parser->iterate(parser, &objectID, &object))
249: {
250: switch (objectID)
251: {
252: case ATTRIBUTE_OBJ_TYPE:
253: oid = asn1_known_oid(object);
254: break;
255: case ATTRIBUTE_OBJ_VALUE:
256: if (oid != OID_UNKNOWN)
257: {
258: this->attributes->insert_last(this->attributes,
259: attribute_create(oid, object));
260: }
261: break;
262: }
263: }
264: success = parser->success(parser);
265:
266: parser->destroy(parser);
267: return success;
268: }
269:
270: /*
271: * Described in header.
272: */
273: pkcs7_attributes_t *pkcs7_attributes_create_from_chunk(chunk_t chunk,
274: u_int level)
275: {
276: private_pkcs7_attributes_t *this;
277:
278: this = (private_pkcs7_attributes_t*)pkcs7_attributes_create();
279: this->encoding = chunk_clone(chunk);
280: if (!parse_attributes(chunk, level, this))
281: {
282: destroy(this);
283: return NULL;
284: }
285: return &this->public;
286: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>