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>