Return to pkcs7_attributes.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / pkcs7 |
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: }