Return to pkcs7_encrypted_data.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / pkcs7 |
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: }