Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c, revision 1.1.1.1

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, &params);
                     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: 

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