Return to pkcs8_builder.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / pkcs8 |
1.1 misho 1: /* 2: * Copyright (C) 2012 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 "pkcs8_builder.h" 17: 18: #include <utils/debug.h> 19: #include <asn1/oid.h> 20: #include <asn1/asn1.h> 21: #include <asn1/asn1_parser.h> 22: #include <crypto/pkcs5.h> 23: #include <credentials/keys/private_key.h> 24: 25: /** 26: * ASN.1 definition of a privateKeyInfo structure 27: */ 28: static const asn1Object_t pkinfoObjects[] = { 29: { 0, "privateKeyInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ 30: { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */ 31: { 1, "privateKeyAlgorithm", ASN1_EOC, ASN1_RAW }, /* 2 */ 32: { 1, "privateKey", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */ 33: { 1, "attributes", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ 34: { 1, "end opt", ASN1_EOC, ASN1_END }, /* 5 */ 35: { 0, "exit", ASN1_EOC, ASN1_EXIT } 36: }; 37: #define PKINFO_PRIVATE_KEY_ALGORITHM 2 38: #define PKINFO_PRIVATE_KEY 3 39: 40: /** 41: * Load a generic private key from an ASN.1 encoded blob 42: */ 43: static private_key_t *parse_private_key(chunk_t blob) 44: { 45: asn1_parser_t *parser; 46: chunk_t object, params = chunk_empty; 47: int objectID; 48: private_key_t *key = NULL; 49: key_type_t type = KEY_ANY; 50: builder_part_t part = BUILD_BLOB_ASN1_DER; 51: 52: parser = asn1_parser_create(pkinfoObjects, blob); 53: parser->set_flags(parser, FALSE, TRUE); 54: 55: while (parser->iterate(parser, &objectID, &object)) 56: { 57: switch (objectID) 58: { 59: case PKINFO_PRIVATE_KEY_ALGORITHM: 60: { 61: int oid = asn1_parse_algorithmIdentifier(object, 62: parser->get_level(parser) + 1, ¶ms); 63: 64: switch (oid) 65: { 66: case OID_RSASSA_PSS: 67: /* TODO: parameters associated with such keys should be 68: * treated as restrictions later when signing (the type 69: * itself is already a restriction). However, the 70: * builders currently don't expect any parameters for 71: * RSA keys (we also only pass along the params, not the 72: * exact type, so we'd have to guess that params 73: * indicate RSA/PSS, but they are optional so that won't 74: * work for keys without specific restrictions) */ 75: params = chunk_empty; 76: /* fall-through */ 77: case OID_RSA_ENCRYPTION: 78: type = KEY_RSA; 79: break; 80: case OID_EC_PUBLICKEY: 81: type = KEY_ECDSA; 82: break; 83: case OID_ED25519: 84: type = KEY_ED25519; 85: part = BUILD_EDDSA_PRIV_ASN1_DER; 86: break; 87: case OID_ED448: 88: type = KEY_ED448; 89: part = BUILD_EDDSA_PRIV_ASN1_DER; 90: break; 91: default: 92: /* key type not supported */ 93: goto end; 94: } 95: break; 96: } 97: case PKINFO_PRIVATE_KEY: 98: { 99: DBG2(DBG_ASN, "-- > --"); 100: if (params.ptr) 101: { 102: key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, 103: type, BUILD_BLOB_ALGID_PARAMS, 104: params, part, object, BUILD_END); 105: } 106: else 107: { 108: key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, 109: type, part, object, BUILD_END); 110: } 111: DBG2(DBG_ASN, "-- < --"); 112: break; 113: } 114: } 115: } 116: 117: end: 118: parser->destroy(parser); 119: return key; 120: } 121: 122: /** 123: * Try to decrypt the given blob with multiple passwords using the given 124: * pkcs5 object. 125: */ 126: static private_key_t *decrypt_private_key(pkcs5_t *pkcs5, chunk_t blob) 127: { 128: enumerator_t *enumerator; 129: shared_key_t *shared; 130: private_key_t *private_key = NULL; 131: 132: enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, 133: SHARED_PRIVATE_KEY_PASS, NULL, NULL); 134: while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) 135: { 136: chunk_t decrypted; 137: 138: if (!pkcs5->decrypt(pkcs5, shared->get_key(shared), blob, &decrypted)) 139: { 140: continue; 141: } 142: private_key = parse_private_key(decrypted); 143: if (private_key) 144: { 145: chunk_clear(&decrypted); 146: break; 147: } 148: chunk_free(&decrypted); 149: } 150: enumerator->destroy(enumerator); 151: 152: return private_key; 153: } 154: 155: /** 156: * ASN.1 definition of an encryptedPrivateKeyInfo structure 157: */ 158: static const asn1Object_t encryptedPKIObjects[] = { 159: { 0, "encryptedPrivateKeyInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ 160: { 1, "encryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */ 161: { 1, "encryptedData", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */ 162: { 0, "exit", ASN1_EOC, ASN1_EXIT } 163: }; 164: #define EPKINFO_ENCRYPTION_ALGORITHM 1 165: #define EPKINFO_ENCRYPTED_DATA 2 166: 167: /** 168: * Load an encrypted private key from an ASN.1 encoded blob 169: * Schemes per PKCS#5 (RFC 2898) 170: */ 171: static private_key_t *parse_encrypted_private_key(chunk_t blob) 172: { 173: asn1_parser_t *parser; 174: chunk_t object; 175: int objectID; 176: private_key_t *key = NULL; 177: pkcs5_t *pkcs5 = NULL; 178: 179: parser = asn1_parser_create(encryptedPKIObjects, blob); 180: 181: while (parser->iterate(parser, &objectID, &object)) 182: { 183: switch (objectID) 184: { 185: case EPKINFO_ENCRYPTION_ALGORITHM: 186: { 187: pkcs5 = pkcs5_from_algorithmIdentifier(object, 188: parser->get_level(parser) + 1); 189: if (!pkcs5) 190: { 191: goto end; 192: } 193: break; 194: } 195: case EPKINFO_ENCRYPTED_DATA: 196: { 197: key = decrypt_private_key(pkcs5, object); 198: break; 199: } 200: } 201: } 202: 203: end: 204: DESTROY_IF(pkcs5); 205: parser->destroy(parser); 206: return key; 207: } 208: 209: /** 210: * See header. 211: */ 212: private_key_t *pkcs8_private_key_load(key_type_t type, va_list args) 213: { 214: chunk_t blob = chunk_empty; 215: private_key_t *key; 216: 217: while (TRUE) 218: { 219: switch (va_arg(args, builder_part_t)) 220: { 221: case BUILD_BLOB_ASN1_DER: 222: blob = va_arg(args, chunk_t); 223: continue; 224: case BUILD_END: 225: break; 226: default: 227: return NULL; 228: } 229: break; 230: } 231: /* we don't know whether it is encrypted or not, try both ways */ 232: key = parse_encrypted_private_key(blob); 233: if (!key) 234: { 235: key = parse_private_key(blob); 236: } 237: return key; 238: } 239: