Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs7/pkcs7_attributes.c, revision 1.1.1.1
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>
23: #include <collections/linked_list.h>
24:
25: #include "pkcs7_attributes.h"
26:
27: typedef struct private_pkcs7_attributes_t private_pkcs7_attributes_t;
28: typedef struct attribute_t attribute_t;
29:
30: /**
31: * Private data of a pkcs7_attributes_t attribute list.
32: */
33: struct private_pkcs7_attributes_t {
34: /**
35: * Public interface
36: */
37: pkcs7_attributes_t public;
38:
39: /**
40: * DER encoding of PKCS#9 attributes
41: */
42: chunk_t encoding;
43:
44: /**
45: * Linked list of PKCS#9 attributes
46: */
47: linked_list_t *attributes;
48: };
49:
50: /**
51: * Definition of an attribute_t object.
52: */
53: struct attribute_t {
54:
55: /**
56: * Object Identifier (OID)
57: */
58: int oid;
59:
60: /**
61: * Attribute value
62: */
63: chunk_t value;
64:
65: /**
66: * ASN.1 encoding
67: */
68: chunk_t encoding;
69: };
70:
71: /**
72: * Destroy an attribute_t object.
73: */
74: static void attribute_destroy(attribute_t *this)
75: {
76: free(this->value.ptr);
77: free(this);
78: }
79:
80: /**
81: * Create an attribute_t object.
82: */
83: static attribute_t *attribute_create(int oid, chunk_t value)
84: {
85: attribute_t *this;
86:
87: INIT(this,
88: .oid = oid,
89: .value = chunk_clone(value),
90: );
91:
92: return this;
93: }
94:
95: /**
96: * Build encoding of the attribute list
97: */
98: static void build_encoding(private_pkcs7_attributes_t *this)
99: {
100: enumerator_t *enumerator;
101: attribute_t *attribute;
102: u_int len = 0, count, i = 0;
103: chunk_t *chunks;
104: u_char *pos;
105:
106: count = this->attributes->get_count(this->attributes);
107: chunks = malloc(sizeof(chunk_t) * count);
108:
109: enumerator = this->attributes->create_enumerator(this->attributes);
110: while (enumerator->enumerate(enumerator, &attribute))
111: {
112: chunks[i] = asn1_wrap(ASN1_SEQUENCE, "mm",
113: asn1_build_known_oid(attribute->oid),
114: asn1_wrap(ASN1_SET, "c", attribute->value));
115: len += chunks[i].len;
116: i++;
117: }
118: enumerator->destroy(enumerator);
119:
120: pos = asn1_build_object(&this->encoding, ASN1_SET, len);
121: for (i = 0; i < count; i++)
122: {
123: memcpy(pos, chunks[i].ptr, chunks[i].len);
124: pos += chunks[i].len;
125: free(chunks[i].ptr);
126: }
127: free(chunks);
128: }
129:
130: METHOD(pkcs7_attributes_t, get_encoding, chunk_t,
131: private_pkcs7_attributes_t *this)
132: {
133: if (!this->encoding.len)
134: {
135: build_encoding(this);
136: }
137: return this->encoding;
138: }
139:
140: METHOD(pkcs7_attributes_t, get_attribute, chunk_t,
141: private_pkcs7_attributes_t *this, int oid)
142: {
143: enumerator_t *enumerator;
144: chunk_t value = chunk_empty;
145: attribute_t *attribute;
146:
147: enumerator = this->attributes->create_enumerator(this->attributes);
148: while (enumerator->enumerate(enumerator, &attribute))
149: {
150: if (attribute->oid == oid)
151: {
152: value = attribute->value;
153: break;
154: }
155: }
156: enumerator->destroy(enumerator);
157: if (value.len && asn1_unwrap(&value, &value) != ASN1_INVALID)
158: {
159: return value;
160: }
161: return chunk_empty;
162: }
163:
164: METHOD(pkcs7_attributes_t, add_attribute, void,
165: private_pkcs7_attributes_t *this, int oid, chunk_t value)
166: {
167: this->attributes->insert_last(this->attributes,
168: attribute_create(oid, value));
169: chunk_free(&value);
170:
171: /* rebuild encoding when adding attributes */
172: chunk_free(&this->encoding);
173: }
174:
175: METHOD(pkcs7_attributes_t, destroy, void,
176: private_pkcs7_attributes_t *this)
177: {
178: this->attributes->destroy_function(this->attributes,
179: (void*)attribute_destroy);
180: free(this->encoding.ptr);
181: free(this);
182: }
183:
184: /*
185: * Described in header.
186: */
187: pkcs7_attributes_t *pkcs7_attributes_create(void)
188: {
189: private_pkcs7_attributes_t *this;
190:
191: INIT(this,
192: .public = {
193: .get_encoding = _get_encoding,
194: .get_attribute = _get_attribute,
195: .add_attribute = _add_attribute,
196: .destroy = _destroy,
197: },
198: .attributes = linked_list_create(),
199: );
200:
201: return &this->public;
202: }
203:
204: /**
205: * ASN.1 definition of the X.501 attribute type
206: */
207: static const asn1Object_t attributesObjects[] = {
208: { 0, "attributes", ASN1_SET, ASN1_LOOP }, /* 0 */
209: { 1, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
210: { 2, "type", ASN1_OID, ASN1_BODY }, /* 2 */
211: { 2, "values", ASN1_SET, ASN1_LOOP }, /* 3 */
212: { 3, "value", ASN1_EOC, ASN1_RAW }, /* 4 */
213: { 2, "end loop", ASN1_EOC, ASN1_END }, /* 5 */
214: { 0, "end loop", ASN1_EOC, ASN1_END }, /* 6 */
215: { 0, "exit", ASN1_EOC, ASN1_EXIT }
216: };
217: #define ATTRIBUTE_OBJ_TYPE 2
218: #define ATTRIBUTE_OBJ_VALUE 4
219:
220: /**
221: * Parse a PKCS#9 attribute list
222: */
223: static bool parse_attributes(chunk_t chunk, int level0,
224: private_pkcs7_attributes_t* this)
225: {
226: asn1_parser_t *parser;
227: chunk_t object;
228: int objectID;
229: int oid = OID_UNKNOWN;
230: bool success = FALSE;
231:
232: parser = asn1_parser_create(attributesObjects, chunk);
233: parser->set_top_level(parser, level0);
234:
235: while (parser->iterate(parser, &objectID, &object))
236: {
237: switch (objectID)
238: {
239: case ATTRIBUTE_OBJ_TYPE:
240: oid = asn1_known_oid(object);
241: break;
242: case ATTRIBUTE_OBJ_VALUE:
243: if (oid != OID_UNKNOWN)
244: {
245: this->attributes->insert_last(this->attributes,
246: attribute_create(oid, object));
247: }
248: break;
249: }
250: }
251: success = parser->success(parser);
252:
253: parser->destroy(parser);
254: return success;
255: }
256:
257: /*
258: * Described in header.
259: */
260: pkcs7_attributes_t *pkcs7_attributes_create_from_chunk(chunk_t chunk,
261: u_int level)
262: {
263: private_pkcs7_attributes_t *this;
264:
265: this = (private_pkcs7_attributes_t*)pkcs7_attributes_create();
266: this->encoding = chunk_clone(chunk);
267: if (!parse_attributes(chunk, level, this))
268: {
269: destroy(this);
270: return NULL;
271: }
272: return &this->public;
273: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>