Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs7/pkcs7_encrypted_data.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2013 Tobias Brunner
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "pkcs7_encrypted_data.h"
        !            17: 
        !            18: #include <asn1/asn1.h>
        !            19: #include <asn1/asn1_parser.h>
        !            20: #include <asn1/oid.h>
        !            21: #include <crypto/pkcs5.h>
        !            22: #include <utils/debug.h>
        !            23: 
        !            24: typedef struct private_pkcs7_encrypted_data_t private_pkcs7_encrypted_data_t;
        !            25: 
        !            26: /**
        !            27:  * Private data of a PKCS#7 signed-data container.
        !            28:  */
        !            29: struct private_pkcs7_encrypted_data_t {
        !            30: 
        !            31:        /**
        !            32:         * Implements pkcs7_t.
        !            33:         */
        !            34:        pkcs7_t public;
        !            35: 
        !            36:        /**
        !            37:         * Decrypted content
        !            38:         */
        !            39:        chunk_t content;
        !            40: 
        !            41:        /**
        !            42:         * Encrypted and encoded PKCS#7 encrypted-data
        !            43:         */
        !            44:        chunk_t encoding;
        !            45: };
        !            46: 
        !            47: /**
        !            48:  * Decrypt encrypted-data with available passwords
        !            49:  */
        !            50: static bool decrypt(pkcs5_t *pkcs5, chunk_t data, chunk_t *decrypted)
        !            51: {
        !            52:        enumerator_t *enumerator;
        !            53:        shared_key_t *shared;
        !            54:        bool success = FALSE;
        !            55: 
        !            56:        enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
        !            57:                                                                                SHARED_PRIVATE_KEY_PASS, NULL, NULL);
        !            58:        while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
        !            59:        {
        !            60:                if (pkcs5->decrypt(pkcs5, shared->get_key(shared), data, decrypted))
        !            61:                {
        !            62:                        success = TRUE;
        !            63:                        break;
        !            64:                }
        !            65:        }
        !            66:        enumerator->destroy(enumerator);
        !            67:        return success;
        !            68: }
        !            69: 
        !            70: /**
        !            71:  * ASN.1 definition of the PKCS#7 encrypted-data type
        !            72:  */
        !            73: static const asn1Object_t encryptedDataObjects[] = {
        !            74:        { 0, "encryptedData",                                   ASN1_SEQUENCE,          ASN1_NONE }, /* 0 */
        !            75:        { 1,   "version",                                               ASN1_INTEGER,           ASN1_BODY }, /* 1 */
        !            76:        { 1,   "encryptedContentInfo",                  ASN1_SEQUENCE,          ASN1_OBJ  }, /* 2 */
        !            77:        { 2,     "contentType",                                 ASN1_OID,                       ASN1_BODY }, /* 3 */
        !            78:        { 2,     "contentEncryptionAlgorithm",  ASN1_EOC,                       ASN1_RAW  }, /* 4 */
        !            79:        { 2,     "encryptedContent",                    ASN1_CONTEXT_S_0,       ASN1_BODY }, /* 5 */
        !            80:        { 0, "exit",                                                    ASN1_EOC,                       ASN1_EXIT }
        !            81: };
        !            82: #define PKCS7_VERSION                                  1
        !            83: #define PKCS7_CONTENT_TYPE                             3
        !            84: #define PKCS7_CONTENT_ENC_ALGORITHM            4
        !            85: #define PKCS7_ENCRYPTED_CONTENT                        5
        !            86: 
        !            87: /**
        !            88:  * Parse and decrypt encrypted-data
        !            89:  */
        !            90: static bool parse(private_pkcs7_encrypted_data_t *this, chunk_t content)
        !            91: {
        !            92:        asn1_parser_t *parser;
        !            93:        chunk_t object;
        !            94:        int objectID, version;
        !            95:        bool success = FALSE;
        !            96:        chunk_t encrypted = chunk_empty;
        !            97:        pkcs5_t *pkcs5 = NULL;
        !            98: 
        !            99:        parser = asn1_parser_create(encryptedDataObjects, content);
        !           100: 
        !           101:        while (parser->iterate(parser, &objectID, &object))
        !           102:        {
        !           103:                int level = parser->get_level(parser);
        !           104: 
        !           105:                switch (objectID)
        !           106:                {
        !           107:                        case PKCS7_VERSION:
        !           108:                                version = object.len ? (int)*object.ptr : 0;
        !           109:                                DBG2(DBG_LIB, "  v%d", version);
        !           110:                                if (version != 0)
        !           111:                                {
        !           112:                                        DBG1(DBG_LIB, "encryptedData version is not 0");
        !           113:                                        goto end;
        !           114:                                }
        !           115:                                break;
        !           116:                        case PKCS7_CONTENT_TYPE:
        !           117:                                if (asn1_known_oid(object) != OID_PKCS7_DATA)
        !           118:                                {
        !           119:                                        DBG1(DBG_LIB, "encrypted content not of type pkcs7 data");
        !           120:                                        goto end;
        !           121:                                }
        !           122:                                break;
        !           123:                        case PKCS7_CONTENT_ENC_ALGORITHM:
        !           124:                                pkcs5 = pkcs5_from_algorithmIdentifier(object, level + 1);
        !           125:                                if (!pkcs5)
        !           126:                                {
        !           127:                                        DBG1(DBG_LIB, "failed to detect PKCS#5 scheme");
        !           128:                                        goto end;
        !           129:                                }
        !           130:                                break;
        !           131:                        case PKCS7_ENCRYPTED_CONTENT:
        !           132:                                encrypted = object;
        !           133:                                break;
        !           134:                }
        !           135:        }
        !           136:        success = parser->success(parser);
        !           137: 
        !           138: end:
        !           139:        parser->destroy(parser);
        !           140:        success = success && decrypt(pkcs5, encrypted, &this->content);
        !           141:        DESTROY_IF(pkcs5);
        !           142:        return success;
        !           143: }
        !           144: 
        !           145: METHOD(container_t, get_type, container_type_t,
        !           146:        private_pkcs7_encrypted_data_t *this)
        !           147: {
        !           148:        return CONTAINER_PKCS7_ENCRYPTED_DATA;
        !           149: }
        !           150: 
        !           151: METHOD(container_t, get_data, bool,
        !           152:        private_pkcs7_encrypted_data_t *this, chunk_t *data)
        !           153: {
        !           154:        if (this->content.len)
        !           155:        {
        !           156:                *data = chunk_clone(this->content);
        !           157:                return TRUE;
        !           158:        }
        !           159:        return FALSE;
        !           160: }
        !           161: 
        !           162: METHOD(container_t, get_encoding, bool,
        !           163:        private_pkcs7_encrypted_data_t *this, chunk_t *data)
        !           164: {
        !           165:        *data = chunk_clone(this->encoding);
        !           166:        return TRUE;
        !           167: }
        !           168: 
        !           169: METHOD(container_t, destroy, void,
        !           170:        private_pkcs7_encrypted_data_t *this)
        !           171: {
        !           172:        free(this->content.ptr);
        !           173:        free(this->encoding.ptr);
        !           174:        free(this);
        !           175: }
        !           176: 
        !           177: /**
        !           178:  * Generic constructor
        !           179:  */
        !           180: static private_pkcs7_encrypted_data_t* create_empty()
        !           181: {
        !           182:        private_pkcs7_encrypted_data_t *this;
        !           183: 
        !           184:        INIT(this,
        !           185:                .public = {
        !           186:                        .container = {
        !           187:                                .get_type = _get_type,
        !           188:                                .create_signature_enumerator = (void*)enumerator_create_empty,
        !           189:                                .get_data = _get_data,
        !           190:                                .get_encoding = _get_encoding,
        !           191:                                .destroy = _destroy,
        !           192:                        },
        !           193:                        .create_cert_enumerator = (void*)enumerator_create_empty,
        !           194:                        .get_attribute = (void*)return_false,
        !           195:                },
        !           196:        );
        !           197: 
        !           198:        return this;
        !           199: }
        !           200: 
        !           201: /**
        !           202:  * See header.
        !           203:  */
        !           204: pkcs7_t *pkcs7_encrypted_data_load(chunk_t encoding, chunk_t content)
        !           205: {
        !           206:        private_pkcs7_encrypted_data_t *this = create_empty();
        !           207: 
        !           208:        this->encoding = chunk_clone(encoding);
        !           209:        if (!parse(this, content))
        !           210:        {
        !           211:                destroy(this);
        !           212:                return NULL;
        !           213:        }
        !           214: 
        !           215:        return &this->public;
        !           216: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>