Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2008-2016 Tobias Brunner
        !             3:  * Copyright (C) 2008-2009 Martin Willi
        !             4:  * Copyright (C) 2000-2008 Andreas Steffen
        !             5:  * HSR Hochschule fuer Technik Rapperswil
        !             6:  *
        !             7:  * This program is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2 of the License, or (at your
        !            10:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            11:  *
        !            12:  * This program is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            14:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            15:  * for more details.
        !            16:  */
        !            17: 
        !            18: #include "pkcs1_builder.h"
        !            19: 
        !            20: #include <utils/debug.h>
        !            21: #include <asn1/oid.h>
        !            22: #include <asn1/asn1.h>
        !            23: #include <asn1/asn1_parser.h>
        !            24: #include <credentials/keys/private_key.h>
        !            25: 
        !            26: /**
        !            27:  * ASN.1 definition of a subjectPublicKeyInfo structure
        !            28:  */
        !            29: static const asn1Object_t pkinfoObjects[] = {
        !            30:        { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE,              ASN1_NONE       }, /* 0 */
        !            31:        { 1,   "algorithm",                     ASN1_EOC,                       ASN1_RAW        }, /* 1 */
        !            32:        { 1,   "subjectPublicKey",      ASN1_BIT_STRING,        ASN1_BODY       }, /* 2 */
        !            33:        { 0, "exit",                            ASN1_EOC,                       ASN1_EXIT       }
        !            34: };
        !            35: #define PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM    1
        !            36: #define PKINFO_SUBJECT_PUBLIC_KEY                      2
        !            37: 
        !            38: /**
        !            39:  * Load a generic public key from an ASN.1 encoded blob
        !            40:  */
        !            41: static public_key_t *parse_public_key(chunk_t blob)
        !            42: {
        !            43:        asn1_parser_t *parser;
        !            44:        chunk_t object;
        !            45:        int objectID;
        !            46:        public_key_t *key = NULL;
        !            47:        key_type_t type = KEY_ANY;
        !            48: 
        !            49:        parser = asn1_parser_create(pkinfoObjects, blob);
        !            50: 
        !            51:        while (parser->iterate(parser, &objectID, &object))
        !            52:        {
        !            53:                switch (objectID)
        !            54:                {
        !            55:                        case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
        !            56:                        {
        !            57:                                int oid = asn1_parse_algorithmIdentifier(object,
        !            58:                                                                                parser->get_level(parser)+1, NULL);
        !            59: 
        !            60:                                if (oid == OID_RSA_ENCRYPTION || oid == OID_RSAES_OAEP ||
        !            61:                                        oid == OID_RSASSA_PSS)
        !            62:                                {
        !            63:                                        /* TODO: we should parse parameters for PSS and pass them
        !            64:                                         * (and the type), or the complete subjectPublicKeyInfo,
        !            65:                                         * along so we can treat these as restrictions when
        !            66:                                         * generating signatures with the associated private key */
        !            67:                                        type = KEY_RSA;
        !            68:                                }
        !            69:                                else if (oid == OID_EC_PUBLICKEY)
        !            70:                                {
        !            71:                                        /* Need the whole subjectPublicKeyInfo for EC public keys */
        !            72:                                        key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
        !            73:                                                                KEY_ECDSA, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
        !            74:                                        goto end;
        !            75:                                }
        !            76:                                else if (oid == OID_BLISS_PUBLICKEY)
        !            77:                                {
        !            78:                                        /* Need the whole subjectPublicKeyInfo for BLISS public keys */
        !            79:                                        key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
        !            80:                                                                KEY_BLISS, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
        !            81:                                        goto end;
        !            82:                                }
        !            83:                                else if (oid == OID_ED25519)
        !            84:                                {
        !            85:                                        /* Need the whole subjectPublicKeyInfo for Ed25519 public keys */
        !            86:                                        key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
        !            87:                                                                KEY_ED25519, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
        !            88:                                        goto end;
        !            89:                                }
        !            90:                                else if (oid == OID_ED448)
        !            91:                                {
        !            92:                                        /* Need the whole subjectPublicKeyInfo for Ed448 public keys */
        !            93:                                        key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
        !            94:                                                                KEY_ED448, BUILD_BLOB_ASN1_DER, blob, BUILD_END);
        !            95:                                        goto end;
        !            96:                                }
        !            97:                                else
        !            98:                                {
        !            99:                                        /* key type not supported */
        !           100:                                        goto end;
        !           101:                                }
        !           102:                                break;
        !           103:                        }
        !           104:                        case PKINFO_SUBJECT_PUBLIC_KEY:
        !           105:                                if (object.len > 0 && *object.ptr == 0x00)
        !           106:                                {
        !           107:                                        /* skip initial bit string octet defining 0 unused bits */
        !           108:                                        object = chunk_skip(object, 1);
        !           109:                                }
        !           110:                                DBG2(DBG_ASN, "-- > --");
        !           111:                                key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
        !           112:                                                                                 BUILD_BLOB_ASN1_DER, object, BUILD_END);
        !           113:                                DBG2(DBG_ASN, "-- < --");
        !           114:                                break;
        !           115:                }
        !           116:        }
        !           117: 
        !           118: end:
        !           119:        parser->destroy(parser);
        !           120:        return key;
        !           121: }
        !           122: 
        !           123: /**
        !           124:  * ASN.1 definition of RSApublicKey
        !           125:  */
        !           126: static const asn1Object_t pubkeyObjects[] = {
        !           127:        { 0, "RSAPublicKey",            ASN1_SEQUENCE,  ASN1_OBJ  }, /*  0 */
        !           128:        { 1,   "modulus",                       ASN1_INTEGER,   ASN1_BODY }, /*  1 */
        !           129:        { 1,   "publicExponent",        ASN1_INTEGER,   ASN1_BODY }, /*  2 */
        !           130:        { 0, "exit",                            ASN1_EOC,               ASN1_EXIT }
        !           131: };
        !           132: #define PUB_KEY_RSA_PUBLIC_KEY         0
        !           133: #define PUB_KEY_MODULUS                                1
        !           134: #define PUB_KEY_EXPONENT                       2
        !           135: 
        !           136: /**
        !           137:  * Load a RSA public key from an ASN.1 encoded blob.
        !           138:  */
        !           139: static public_key_t *parse_rsa_public_key(chunk_t blob)
        !           140: {
        !           141:        chunk_t n, e;
        !           142:        asn1_parser_t *parser;
        !           143:        chunk_t object;
        !           144:        int objectID;
        !           145:        bool success = FALSE;
        !           146: 
        !           147:        parser = asn1_parser_create(pubkeyObjects, blob);
        !           148: 
        !           149:        while (parser->iterate(parser, &objectID, &object))
        !           150:        {
        !           151:                switch (objectID)
        !           152:                {
        !           153:                        case PUB_KEY_MODULUS:
        !           154:                                n = object;
        !           155:                                break;
        !           156:                        case PUB_KEY_EXPONENT:
        !           157:                                e = object;
        !           158:                                break;
        !           159:                }
        !           160:        }
        !           161:        success = parser->success(parser);
        !           162:        parser->destroy(parser);
        !           163: 
        !           164:        if (!success)
        !           165:        {
        !           166:                return NULL;
        !           167:        }
        !           168:        return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
        !           169:                                                BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END);
        !           170: }
        !           171: 
        !           172: /**
        !           173:  * ASN.1 definition of a PKCS#1 RSA private key
        !           174:  */
        !           175: static const asn1Object_t privkeyObjects[] = {
        !           176:        { 0, "RSAPrivateKey",           ASN1_SEQUENCE,     ASN1_NONE }, /*  0 */
        !           177:        { 1,   "version",                       ASN1_INTEGER,      ASN1_BODY }, /*  1 */
        !           178:        { 1,   "modulus",                       ASN1_INTEGER,      ASN1_BODY }, /*  2 */
        !           179:        { 1,   "publicExponent",        ASN1_INTEGER,      ASN1_BODY }, /*  3 */
        !           180:        { 1,   "privateExponent",       ASN1_INTEGER,      ASN1_BODY }, /*  4 */
        !           181:        { 1,   "prime1",                        ASN1_INTEGER,      ASN1_BODY }, /*  5 */
        !           182:        { 1,   "prime2",                        ASN1_INTEGER,      ASN1_BODY }, /*  6 */
        !           183:        { 1,   "exponent1",                     ASN1_INTEGER,      ASN1_BODY }, /*  7 */
        !           184:        { 1,   "exponent2",                     ASN1_INTEGER,      ASN1_BODY }, /*  8 */
        !           185:        { 1,   "coefficient",           ASN1_INTEGER,      ASN1_BODY }, /*  9 */
        !           186:        { 1,   "otherPrimeInfos",       ASN1_SEQUENCE,     ASN1_OPT |
        !           187:                                                                                                   ASN1_LOOP }, /* 10 */
        !           188:        { 2,     "otherPrimeInfo",      ASN1_SEQUENCE,     ASN1_NONE }, /* 11 */
        !           189:        { 3,       "prime",                     ASN1_INTEGER,      ASN1_BODY }, /* 12 */
        !           190:        { 3,       "exponent",          ASN1_INTEGER,      ASN1_BODY }, /* 13 */
        !           191:        { 3,       "coefficient",       ASN1_INTEGER,      ASN1_BODY }, /* 14 */
        !           192:        { 1,   "end opt or loop",       ASN1_EOC,          ASN1_END  }, /* 15 */
        !           193:        { 0, "exit",                            ASN1_EOC,          ASN1_EXIT }
        !           194: };
        !           195: #define PRIV_KEY_VERSION                1
        !           196: #define PRIV_KEY_MODULUS                2
        !           197: #define PRIV_KEY_PUB_EXP                3
        !           198: #define PRIV_KEY_PRIV_EXP               4
        !           199: #define PRIV_KEY_PRIME1                         5
        !           200: #define PRIV_KEY_PRIME2                         6
        !           201: #define PRIV_KEY_EXP1                   7
        !           202: #define PRIV_KEY_EXP2                   8
        !           203: #define PRIV_KEY_COEFF                  9
        !           204: 
        !           205: /**
        !           206:  * Load a RSA private key from a ASN1 encoded blob.
        !           207:  */
        !           208: static private_key_t *parse_rsa_private_key(chunk_t blob)
        !           209: {
        !           210:        chunk_t n, e, d, p, q, exp1, exp2, coeff;
        !           211:        asn1_parser_t *parser;
        !           212:        chunk_t object;
        !           213:        int objectID ;
        !           214:        bool success = FALSE;
        !           215: 
        !           216:        parser = asn1_parser_create(privkeyObjects, blob);
        !           217:        parser->set_flags(parser, FALSE, TRUE);
        !           218: 
        !           219:        while (parser->iterate(parser, &objectID, &object))
        !           220:        {
        !           221:                switch (objectID)
        !           222:                {
        !           223:                        case PRIV_KEY_VERSION:
        !           224:                                if (object.len > 0 && *object.ptr != 0)
        !           225:                                {
        !           226:                                        goto end;
        !           227:                                }
        !           228:                                break;
        !           229:                        case PRIV_KEY_MODULUS:
        !           230:                                n = object;
        !           231:                                break;
        !           232:                        case PRIV_KEY_PUB_EXP:
        !           233:                                e = object;
        !           234:                                break;
        !           235:                        case PRIV_KEY_PRIV_EXP:
        !           236:                                d = object;
        !           237:                                break;
        !           238:                        case PRIV_KEY_PRIME1:
        !           239:                                p = object;
        !           240:                                break;
        !           241:                        case PRIV_KEY_PRIME2:
        !           242:                                q = object;
        !           243:                                break;
        !           244:                        case PRIV_KEY_EXP1:
        !           245:                                exp1 = object;
        !           246:                                break;
        !           247:                        case PRIV_KEY_EXP2:
        !           248:                                exp2 = object;
        !           249:                                break;
        !           250:                        case PRIV_KEY_COEFF:
        !           251:                                coeff = object;
        !           252:                                break;
        !           253:                }
        !           254:        }
        !           255:        success = parser->success(parser);
        !           256: 
        !           257: end:
        !           258:        parser->destroy(parser);
        !           259:        if (!success)
        !           260:        {
        !           261:                return NULL;
        !           262:        }
        !           263:        return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
        !           264:                        BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_RSA_PRIV_EXP, d,
        !           265:                        BUILD_RSA_PRIME1, p,  BUILD_RSA_PRIME2, q, BUILD_RSA_EXP1, exp1,
        !           266:                        BUILD_RSA_EXP2, exp2, BUILD_RSA_COEFF, coeff, BUILD_END);
        !           267: }
        !           268: 
        !           269: /**
        !           270:  * Check if the ASN.1 structure looks like an EC private key according to
        !           271:  * RFC 5915.
        !           272:  *
        !           273:  * ECPrivateKey :=: SEQUENCE {
        !           274:  *   version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
        !           275:  *   privateKey     OCTET STRING,
        !           276:  *   parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
        !           277:  *   publicKey  [1] BIT STRING OPTIONAL
        !           278:  * }
        !           279:  *
        !           280:  * While the parameters and publicKey fields are OPTIONAL, RFC 5915 says that
        !           281:  * parameters MUST be included (an errata clarifies this, so this is only the
        !           282:  * case for plain private keys, not encoded in PKCS#8) and publicKey SHOULD be.
        !           283:  */
        !           284: static bool is_ec_private_key(chunk_t blob)
        !           285: {
        !           286:        chunk_t data;
        !           287:        return asn1_unwrap(&blob, &blob) == ASN1_SEQUENCE &&
        !           288:                   asn1_unwrap(&blob, &data) == ASN1_INTEGER &&
        !           289:                   asn1_parse_integer_uint64(data) == 1 &&
        !           290:                   asn1_unwrap(&blob, &data) == ASN1_OCTET_STRING &&
        !           291:                   asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_0 &&
        !           292:                   asn1_unwrap(&data, &data) == ASN1_OID &&
        !           293:                   (!blob.len || (asn1_unwrap(&blob, &data) == ASN1_CONTEXT_C_1));
        !           294: }
        !           295: 
        !           296: /**
        !           297:  * Check if the ASN.1 structure looks like a BLISS private key.
        !           298:  */
        !           299: static bool is_bliss_private_key(chunk_t blob)
        !           300: {
        !           301:        chunk_t data;
        !           302:        return asn1_unwrap(&blob, &blob) == ASN1_SEQUENCE &&
        !           303:                   asn1_unwrap(&blob, &data) == ASN1_OID &&
        !           304:                   asn1_unwrap(&blob, &data) == ASN1_BIT_STRING &&
        !           305:                   asn1_unwrap(&blob, &data) == ASN1_BIT_STRING &&
        !           306:                   asn1_unwrap(&blob, &data) == ASN1_BIT_STRING;
        !           307: }
        !           308: 
        !           309: /**
        !           310:  * Load a private key from an ASN.1 encoded blob trying to detect the type
        !           311:  * automatically.
        !           312:  */
        !           313: static private_key_t *parse_private_key(chunk_t blob)
        !           314: {
        !           315:        if (is_ec_private_key(blob))
        !           316:        {
        !           317:                return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
        !           318:                                                                  BUILD_BLOB_ASN1_DER, blob, BUILD_END);
        !           319:        }
        !           320:        else if (is_bliss_private_key(blob))
        !           321:        {
        !           322:                return lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
        !           323:                                                                  BUILD_BLOB_ASN1_DER, blob, BUILD_END);
        !           324:        }
        !           325:        return parse_rsa_private_key(blob);
        !           326: }
        !           327: 
        !           328: /**
        !           329:  * See header.
        !           330:  */
        !           331: public_key_t *pkcs1_public_key_load(key_type_t type, va_list args)
        !           332: {
        !           333:        chunk_t blob = chunk_empty;
        !           334: 
        !           335:        while (TRUE)
        !           336:        {
        !           337:                switch (va_arg(args, builder_part_t))
        !           338:                {
        !           339:                        case BUILD_BLOB_ASN1_DER:
        !           340:                                blob = va_arg(args, chunk_t);
        !           341:                                continue;
        !           342:                        case BUILD_END:
        !           343:                                break;
        !           344:                        default:
        !           345:                                return NULL;
        !           346:                }
        !           347:                break;
        !           348:        }
        !           349:        switch (type)
        !           350:        {
        !           351:                case KEY_ANY:
        !           352:                        return parse_public_key(blob);
        !           353:                case KEY_RSA:
        !           354:                        return parse_rsa_public_key(blob);
        !           355:                default:
        !           356:                        return NULL;
        !           357:        }
        !           358: }
        !           359: 
        !           360: /**
        !           361:  * See header.
        !           362:  */
        !           363: private_key_t *pkcs1_private_key_load(key_type_t type, va_list args)
        !           364: {
        !           365:        chunk_t blob = chunk_empty;
        !           366: 
        !           367:        while (TRUE)
        !           368:        {
        !           369:                switch (va_arg(args, builder_part_t))
        !           370:                {
        !           371:                        case BUILD_BLOB_ASN1_DER:
        !           372:                                blob = va_arg(args, chunk_t);
        !           373:                                continue;
        !           374:                        case BUILD_END:
        !           375:                                break;
        !           376:                        default:
        !           377:                                return NULL;
        !           378:                }
        !           379:                break;
        !           380:        }
        !           381:        switch (type)
        !           382:        {
        !           383:                case KEY_ANY:
        !           384:                        return parse_private_key(blob);
        !           385:                case KEY_RSA:
        !           386:                        return parse_rsa_private_key(blob);
        !           387:                default:
        !           388:                        return NULL;
        !           389:        }
        !           390: }
        !           391: 

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