Return to pkcs7_enveloped_data.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / pkcs7 |
1.1 misho 1: /* 2: * Copyright (C) 2012 Martin Willi 3: * Copyright (C) 2012 revosec AG 4: * Copyright (C) 2012 Tobias Brunner 5: * Copyright (C) 2002-2008 Andreas Steffen 6: * Copyright (C) 2005 Jan Hutter, Martin Willi 7: * HSR Hochschule fuer Technik Rapperswil 8: * 9: * This program is free software; you can redistribute it and/or modify it 10: * under the terms of the GNU General Public License as published by the 11: * Free Software Foundation; either version 2 of the License, or (at your 12: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 13: * 14: * This program is distributed in the hope that it will be useful, but 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17: * for more details. 18: */ 19: 20: #include "pkcs7_enveloped_data.h" 21: 22: #include <asn1/asn1.h> 23: #include <asn1/asn1_parser.h> 24: #include <asn1/oid.h> 25: #include <credentials/certificates/x509.h> 26: #include <utils/debug.h> 27: 28: typedef struct private_pkcs7_enveloped_data_t private_pkcs7_enveloped_data_t; 29: 30: /** 31: * Private data of a PKCS#7 signed-data container. 32: */ 33: struct private_pkcs7_enveloped_data_t { 34: 35: /** 36: * Implements pkcs7_t. 37: */ 38: pkcs7_t public; 39: 40: /** 41: * Decrypted content 42: */ 43: chunk_t content; 44: 45: /** 46: * Encrypted and encoded PKCS#7 enveloped-data 47: */ 48: chunk_t encoding; 49: }; 50: 51: /** 52: * ASN.1 definition of the PKCS#7 envelopedData type 53: */ 54: static const asn1Object_t envelopedDataObjects[] = { 55: { 0, "envelopedData", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ 56: { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ 57: { 1, "recipientInfos", ASN1_SET, ASN1_LOOP }, /* 2 */ 58: { 2, "recipientInfo", ASN1_SEQUENCE, ASN1_BODY }, /* 3 */ 59: { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 4 */ 60: { 3, "issuerAndSerialNumber", ASN1_SEQUENCE, ASN1_BODY }, /* 5 */ 61: { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ 62: { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 7 */ 63: { 3, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 8 */ 64: { 3, "encryptedKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 9 */ 65: { 1, "end loop", ASN1_EOC, ASN1_END }, /* 10 */ 66: { 1, "encryptedContentInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 11 */ 67: { 2, "contentType", ASN1_OID, ASN1_BODY }, /* 12 */ 68: { 2, "contentEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 13 */ 69: { 2, "encryptedContent", ASN1_CONTEXT_S_0, ASN1_BODY }, /* 14 */ 70: { 0, "exit", ASN1_EOC, ASN1_EXIT } 71: }; 72: #define PKCS7_VERSION 1 73: #define PKCS7_RECIPIENT_INFO_VERSION 4 74: #define PKCS7_ISSUER 6 75: #define PKCS7_SERIAL_NUMBER 7 76: #define PKCS7_ENCRYPTION_ALG 8 77: #define PKCS7_ENCRYPTED_KEY 9 78: #define PKCS7_CONTENT_TYPE 12 79: #define PKCS7_CONTENT_ENC_ALGORITHM 13 80: #define PKCS7_ENCRYPTED_CONTENT 14 81: 82: /** 83: * Find a private key for issuerAndSerialNumber 84: */ 85: static private_key_t *find_private(identification_t *issuer, 86: identification_t *serial) 87: { 88: enumerator_t *enumerator; 89: certificate_t *cert; 90: public_key_t *public; 91: private_key_t *private = NULL; 92: identification_t *id; 93: chunk_t fp; 94: 95: enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, 96: CERT_X509, KEY_RSA, serial, FALSE); 97: while (enumerator->enumerate(enumerator, &cert)) 98: { 99: if (issuer->equals(issuer, cert->get_issuer(cert))) 100: { 101: public = cert->get_public_key(cert); 102: if (public) 103: { 104: if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &fp)) 105: { 106: id = identification_create_from_encoding(ID_KEY_ID, fp); 107: private = lib->credmgr->get_private(lib->credmgr, 108: KEY_ANY, id, NULL); 109: id->destroy(id); 110: } 111: public->destroy(public); 112: } 113: } 114: if (private) 115: { 116: break; 117: } 118: } 119: enumerator->destroy(enumerator); 120: return private; 121: } 122: 123: /** 124: * Decrypt content using a private key from "issuer" 125: */ 126: static bool decrypt(private_key_t *private, chunk_t key, chunk_t iv, int oid, 127: chunk_t encrypted, chunk_t *plain) 128: { 129: encryption_algorithm_t alg; 130: chunk_t plain_key; 131: crypter_t *crypter; 132: size_t key_size; 133: 134: alg = encryption_algorithm_from_oid(oid, &key_size); 135: if (alg == ENCR_UNDEFINED) 136: { 137: DBG1(DBG_LIB, "unsupported content encryption algorithm"); 138: return FALSE; 139: } 140: if (!private->decrypt(private, ENCRYPT_RSA_PKCS1, key, &plain_key)) 141: { 142: DBG1(DBG_LIB, "symmetric key could not be decrypted with rsa"); 143: return FALSE; 144: } 145: crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8); 146: if (!crypter) 147: { 148: DBG1(DBG_LIB, "crypter %N-%d not available", 149: encryption_algorithm_names, alg, key_size); 150: free(plain_key.ptr); 151: return FALSE; 152: } 153: if (plain_key.len != crypter->get_key_size(crypter)) 154: { 155: DBG1(DBG_LIB, "symmetric key length %d is wrong", plain_key.len); 156: free(plain_key.ptr); 157: crypter->destroy(crypter); 158: return FALSE; 159: } 160: if (iv.len != crypter->get_iv_size(crypter)) 161: { 162: DBG1(DBG_LIB, "IV length %d is wrong", iv.len); 163: free(plain_key.ptr); 164: crypter->destroy(crypter); 165: return FALSE; 166: } 167: if (!crypter->set_key(crypter, plain_key) || 168: !crypter->decrypt(crypter, encrypted, iv, plain)) 169: { 170: free(plain_key.ptr); 171: crypter->destroy(crypter); 172: return FALSE; 173: } 174: DBG4(DBG_LIB, "decrypted content with padding: %B", plain); 175: free(plain_key.ptr); 176: crypter->destroy(crypter); 177: return TRUE; 178: } 179: 180: /** 181: * Remove the padding from plain data 182: */ 183: static bool remove_padding(private_pkcs7_enveloped_data_t *this) 184: { 185: u_char *pos = this->content.ptr + this->content.len - 1; 186: u_char pattern = *pos; 187: size_t padding = pattern; 188: 189: if (padding > this->content.len) 190: { 191: DBG1(DBG_LIB, "padding greater than data length"); 192: return FALSE; 193: } 194: this->content.len -= padding; 195: 196: while (padding-- > 0) 197: { 198: if (*pos-- != pattern) 199: { 200: DBG1(DBG_LIB, "wrong padding pattern"); 201: return FALSE; 202: } 203: } 204: return TRUE; 205: } 206: 207: /** 208: * Parse and decrypt enveloped-data 209: */ 210: static bool parse(private_pkcs7_enveloped_data_t *this, chunk_t content) 211: { 212: asn1_parser_t *parser; 213: chunk_t object; 214: int objectID, version, alg = OID_UNKNOWN; 215: bool success = FALSE; 216: identification_t *issuer = NULL, *serial = NULL; 217: private_key_t *private = NULL; 218: chunk_t iv = chunk_empty, key = chunk_empty, encrypted = chunk_empty; 219: 220: parser = asn1_parser_create(envelopedDataObjects, content); 221: parser->set_top_level(parser, 0); 222: 223: while (parser->iterate(parser, &objectID, &object)) 224: { 225: u_int level = parser->get_level(parser); 226: 227: switch (objectID) 228: { 229: case PKCS7_VERSION: 230: version = object.len ? (int)*object.ptr : 0; 231: DBG2(DBG_LIB, " v%d", version); 232: if (version != 0) 233: { 234: DBG1(DBG_LIB, "envelopedData version is not 0"); 235: goto end; 236: } 237: break; 238: case PKCS7_RECIPIENT_INFO_VERSION: 239: version = object.len ? (int)*object.ptr : 0; 240: DBG2(DBG_LIB, " v%d", version); 241: if (version != 0) 242: { 243: DBG1(DBG_LIB, "recipient info version is not 0"); 244: goto end; 245: } 246: break; 247: case PKCS7_ISSUER: 248: if (!issuer) 249: { 250: issuer = identification_create_from_encoding(ID_DER_ASN1_DN, 251: object); 252: } 253: break; 254: case PKCS7_SERIAL_NUMBER: 255: if (!serial) 256: { 257: serial = identification_create_from_encoding(ID_KEY_ID, 258: object); 259: } 260: break; 261: case PKCS7_ENCRYPTION_ALG: 262: if (asn1_parse_algorithmIdentifier(object, level, 263: NULL) != OID_RSA_ENCRYPTION) 264: { 265: DBG1(DBG_LIB, "only rsa encryption supported"); 266: goto end; 267: } 268: break; 269: case PKCS7_ENCRYPTED_KEY: 270: key = object; 271: break; 272: case PKCS7_CONTENT_TYPE: 273: if (asn1_known_oid(object) != OID_PKCS7_DATA) 274: { 275: DBG1(DBG_LIB, "encrypted content not of type pkcs7 data"); 276: goto end; 277: } 278: break; 279: case PKCS7_CONTENT_ENC_ALGORITHM: 280: alg = asn1_parse_algorithmIdentifier(object, level, &iv); 281: if (!asn1_parse_simple_object(&iv, ASN1_OCTET_STRING, 282: level + 1, "IV")) 283: { 284: DBG1(DBG_LIB, "IV could not be parsed"); 285: goto end; 286: } 287: break; 288: case PKCS7_ENCRYPTED_CONTENT: 289: encrypted = object; 290: break; 291: } 292: } 293: success = parser->success(parser); 294: 295: end: 296: parser->destroy(parser); 297: if (!success) 298: { 299: goto failed; 300: } 301: success = FALSE; 302: if (!issuer) 303: { 304: goto failed; 305: } 306: private = find_private(issuer, serial); 307: if (!private) 308: { 309: DBG1(DBG_LIB, "no private key found to decrypt pkcs7"); 310: goto failed; 311: } 312: if (!decrypt(private, key, iv, alg, encrypted, &this->content)) 313: { 314: goto failed; 315: } 316: if (!remove_padding(this)) 317: { 318: goto failed; 319: } 320: 321: success = TRUE; 322: failed: 323: DESTROY_IF(issuer); 324: DESTROY_IF(serial); 325: DESTROY_IF(private); 326: return success; 327: } 328: 329: METHOD(container_t, get_type, container_type_t, 330: private_pkcs7_enveloped_data_t *this) 331: { 332: return CONTAINER_PKCS7_ENVELOPED_DATA; 333: } 334: 335: METHOD(container_t, create_signature_enumerator, enumerator_t*, 336: private_pkcs7_enveloped_data_t *this) 337: { 338: return enumerator_create_empty(); 339: } 340: 341: METHOD(container_t, get_data, bool, 342: private_pkcs7_enveloped_data_t *this, chunk_t *data) 343: { 344: if (this->content.len) 345: { 346: *data = chunk_clone(this->content); 347: return TRUE; 348: } 349: return FALSE; 350: } 351: 352: METHOD(container_t, get_encoding, bool, 353: private_pkcs7_enveloped_data_t *this, chunk_t *data) 354: { 355: *data = chunk_clone(this->encoding); 356: return TRUE; 357: } 358: 359: METHOD(container_t, destroy, void, 360: private_pkcs7_enveloped_data_t *this) 361: { 362: free(this->content.ptr); 363: free(this->encoding.ptr); 364: free(this); 365: } 366: 367: /** 368: * Generic constructor 369: */ 370: static private_pkcs7_enveloped_data_t* create_empty() 371: { 372: private_pkcs7_enveloped_data_t *this; 373: 374: INIT(this, 375: .public = { 376: .container = { 377: .get_type = _get_type, 378: .create_signature_enumerator = _create_signature_enumerator, 379: .get_data = _get_data, 380: .get_encoding = _get_encoding, 381: .destroy = _destroy, 382: }, 383: .create_cert_enumerator = (void*)enumerator_create_empty, 384: .get_attribute = (void*)return_false, 385: }, 386: ); 387: 388: return this; 389: } 390: 391: /** 392: * See header. 393: */ 394: pkcs7_t *pkcs7_enveloped_data_load(chunk_t encoding, chunk_t content) 395: { 396: private_pkcs7_enveloped_data_t *this = create_empty(); 397: 398: this->encoding = chunk_clone(encoding); 399: if (!parse(this, content)) 400: { 401: destroy(this); 402: return NULL; 403: } 404: 405: return &this->public; 406: } 407: 408: /** 409: * Allocate data with an RNG 410: */ 411: static bool get_random(rng_quality_t quality, size_t size, chunk_t *out) 412: { 413: rng_t *rng; 414: 415: rng = lib->crypto->create_rng(lib->crypto, quality); 416: if (!rng) 417: { 418: return FALSE; 419: } 420: if (!rng->allocate_bytes(rng, size, out)) 421: { 422: rng->destroy(rng); 423: return FALSE; 424: } 425: rng->destroy(rng); 426: return TRUE; 427: } 428: 429: /** 430: * Encrypt symmetric key using a public key from a certificate 431: */ 432: static bool encrypt_key(certificate_t *cert, chunk_t in, chunk_t *out) 433: { 434: public_key_t *key; 435: 436: key = cert->get_public_key(cert); 437: if (!key) 438: { 439: return FALSE; 440: } 441: if (!key->encrypt(key, ENCRYPT_RSA_PKCS1, in, out)) 442: { 443: key->destroy(key); 444: return FALSE; 445: } 446: key->destroy(key); 447: return TRUE; 448: } 449: 450: /** 451: * build a DER-encoded issuerAndSerialNumber object 452: */ 453: static chunk_t build_issuerAndSerialNumber(certificate_t *cert) 454: { 455: identification_t *issuer = cert->get_issuer(cert); 456: chunk_t serial = chunk_empty; 457: 458: if (cert->get_type(cert) == CERT_X509) 459: { 460: x509_t *x509 = (x509_t*)cert; 461: serial = x509->get_serial(x509); 462: } 463: 464: return asn1_wrap(ASN1_SEQUENCE, "cm", 465: issuer->get_encoding(issuer), 466: asn1_integer("c", serial)); 467: } 468: 469: /** 470: * Generate a new PKCS#7 enveloped-data container 471: */ 472: static bool generate(private_pkcs7_enveloped_data_t *this, 473: certificate_t *cert, encryption_algorithm_t alg, int key_size) 474: { 475: chunk_t contentEncryptionAlgorithm, encryptedContentInfo, recipientInfo; 476: chunk_t iv, symmetricKey, protectedKey, content; 477: crypter_t *crypter; 478: size_t bs, padding; 479: int alg_oid; 480: 481: alg_oid = encryption_algorithm_to_oid(alg, key_size); 482: if (alg_oid == OID_UNKNOWN) 483: { 484: DBG1(DBG_LIB, " encryption algorithm %N not supported", 485: encryption_algorithm_names, alg); 486: return FALSE; 487: } 488: crypter = lib->crypto->create_crypter(lib->crypto, alg, key_size / 8); 489: if (crypter == NULL) 490: { 491: DBG1(DBG_LIB, " could not create crypter for algorithm %N", 492: encryption_algorithm_names, alg); 493: return FALSE; 494: } 495: 496: if (!get_random(RNG_TRUE, crypter->get_key_size(crypter), &symmetricKey)) 497: { 498: DBG1(DBG_LIB, " failed to allocate symmetric encryption key"); 499: crypter->destroy(crypter); 500: return FALSE; 501: } 502: DBG4(DBG_LIB, " symmetric encryption key: %B", &symmetricKey); 503: 504: if (!get_random(RNG_WEAK, crypter->get_iv_size(crypter), &iv)) 505: { 506: DBG1(DBG_LIB, " failed to allocate initialization vector"); 507: crypter->destroy(crypter); 508: return FALSE; 509: } 510: DBG4(DBG_LIB, " initialization vector: %B", &iv); 511: 512: bs = crypter->get_block_size(crypter); 513: padding = bs - this->content.len % bs; 514: content = chunk_alloc(this->content.len + padding); 515: memcpy(content.ptr, this->content.ptr, this->content.len); 516: memset(content.ptr + this->content.len, padding, padding); 517: DBG3(DBG_LIB, " padded unencrypted data: %B", &content); 518: 519: /* symmetric inline encryption of content */ 520: if (!crypter->set_key(crypter, symmetricKey) || 521: !crypter->encrypt(crypter, content, iv, NULL)) 522: { 523: crypter->destroy(crypter); 524: chunk_clear(&symmetricKey); 525: chunk_free(&iv); 526: return FALSE; 527: } 528: crypter->destroy(crypter); 529: DBG3(DBG_LIB, " encrypted data: %B", &content); 530: 531: if (!encrypt_key(cert, symmetricKey, &protectedKey)) 532: { 533: DBG1(DBG_LIB, " encrypting symmetric key failed"); 534: chunk_clear(&symmetricKey); 535: chunk_free(&iv); 536: chunk_free(&content); 537: return FALSE; 538: } 539: chunk_clear(&symmetricKey); 540: 541: contentEncryptionAlgorithm = asn1_wrap(ASN1_SEQUENCE, "mm", 542: asn1_build_known_oid(alg_oid), 543: asn1_wrap(ASN1_OCTET_STRING, "m", iv)); 544: 545: encryptedContentInfo = asn1_wrap(ASN1_SEQUENCE, "mmm", 546: asn1_build_known_oid(OID_PKCS7_DATA), 547: contentEncryptionAlgorithm, 548: asn1_wrap(ASN1_CONTEXT_S_0, "m", content)); 549: 550: recipientInfo = asn1_wrap(ASN1_SEQUENCE, "cmmm", 551: ASN1_INTEGER_0, 552: build_issuerAndSerialNumber(cert), 553: asn1_algorithmIdentifier(OID_RSA_ENCRYPTION), 554: asn1_wrap(ASN1_OCTET_STRING, "m", protectedKey)); 555: 556: this->encoding = asn1_wrap(ASN1_SEQUENCE, "mm", 557: asn1_build_known_oid(OID_PKCS7_ENVELOPED_DATA), 558: asn1_wrap(ASN1_CONTEXT_C_0, "m", 559: asn1_wrap(ASN1_SEQUENCE, "cmm", 560: ASN1_INTEGER_0, 561: asn1_wrap(ASN1_SET, "m", recipientInfo), 562: encryptedContentInfo))); 563: 564: return TRUE; 565: } 566: 567: /** 568: * See header. 569: */ 570: pkcs7_t *pkcs7_enveloped_data_gen(container_type_t type, va_list args) 571: { 572: private_pkcs7_enveloped_data_t *this; 573: chunk_t blob = chunk_empty; 574: encryption_algorithm_t alg = ENCR_AES_CBC; 575: certificate_t *cert = NULL; 576: int key_size = 128; 577: 578: while (TRUE) 579: { 580: switch (va_arg(args, builder_part_t)) 581: { 582: case BUILD_CERT: 583: cert = va_arg(args, certificate_t*); 584: continue; 585: case BUILD_ENCRYPTION_ALG: 586: alg = va_arg(args, int); 587: continue; 588: case BUILD_KEY_SIZE: 589: key_size = va_arg(args, int); 590: continue; 591: case BUILD_BLOB: 592: blob = va_arg(args, chunk_t); 593: continue; 594: case BUILD_END: 595: break; 596: default: 597: return NULL; 598: } 599: break; 600: } 601: if (blob.len && cert) 602: { 603: this = create_empty(); 604: 605: this->content = chunk_clone(blob); 606: if (generate(this, cert, alg, key_size)) 607: { 608: return &this->public; 609: } 610: destroy(this); 611: } 612: return NULL; 613: }