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>