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> 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: }