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>