Annotation of embedaddon/strongswan/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2008-2016 Tobias Brunner
                      3:  * Copyright (C) 2009 Martin Willi
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include <openssl/opensslconf.h>
                     18: 
                     19: #ifndef OPENSSL_NO_ECDSA
                     20: 
                     21: #include "openssl_ec_private_key.h"
                     22: #include "openssl_ec_public_key.h"
                     23: #include "openssl_util.h"
                     24: 
                     25: #include <utils/debug.h>
                     26: 
                     27: #include <openssl/evp.h>
                     28: #include <openssl/ecdsa.h>
                     29: #include <openssl/x509.h>
                     30: 
                     31: #if OPENSSL_VERSION_NUMBER < 0x10100000L
                     32: OPENSSL_KEY_FALLBACK(ECDSA_SIG, r, s)
                     33: #endif
                     34: 
                     35: typedef struct private_openssl_ec_private_key_t private_openssl_ec_private_key_t;
                     36: 
                     37: /**
                     38:  * Private data of a openssl_ec_private_key_t object.
                     39:  */
                     40: struct private_openssl_ec_private_key_t {
                     41:        /**
                     42:         * Public interface for this signer.
                     43:         */
                     44:        openssl_ec_private_key_t public;
                     45: 
                     46:        /**
                     47:         * EC key object
                     48:         */
                     49:        EC_KEY *ec;
                     50: 
                     51:        /**
                     52:         * TRUE if the key is from an OpenSSL ENGINE and might not be readable
                     53:         */
                     54:        bool engine;
                     55: 
                     56:        /**
                     57:         * reference count
                     58:         */
                     59:        refcount_t ref;
                     60: };
                     61: 
                     62: /* from ec public key */
                     63: bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp);
                     64: 
                     65: /**
                     66:  * Build a signature as in RFC 4754
                     67:  */
                     68: static bool build_signature(private_openssl_ec_private_key_t *this,
                     69:                                                        chunk_t hash, chunk_t *signature)
                     70: {
                     71:        const BIGNUM *r, *s;
                     72:        ECDSA_SIG *sig;
                     73:        bool built = FALSE;
                     74: 
                     75:        sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec);
                     76:        if (sig)
                     77:        {
                     78:                ECDSA_SIG_get0(sig, &r, &s);
                     79:                /* concatenate BNs r/s to a signature chunk */
                     80:                built = openssl_bn_cat(EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)),
                     81:                                                           r, s, signature);
                     82:                ECDSA_SIG_free(sig);
                     83:        }
                     84:        return built;
                     85: }
                     86: 
                     87: /**
                     88:  * Build a RFC 4754 signature for a specified curve and hash algorithm
                     89:  */
                     90: static bool build_curve_signature(private_openssl_ec_private_key_t *this,
                     91:                                                                signature_scheme_t scheme, int nid_hash,
                     92:                                                                int nid_curve, chunk_t data, chunk_t *signature)
                     93: {
                     94:        const EC_GROUP *my_group;
                     95:        EC_GROUP *req_group;
                     96:        chunk_t hash;
                     97:        bool built;
                     98: 
                     99:        req_group = EC_GROUP_new_by_curve_name(nid_curve);
                    100:        if (!req_group)
                    101:        {
                    102:                DBG1(DBG_LIB, "signature scheme %N not supported in EC (required curve "
                    103:                         "not supported)", signature_scheme_names, scheme);
                    104:                return FALSE;
                    105:        }
                    106:        my_group = EC_KEY_get0_group(this->ec);
                    107:        if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
                    108:        {
                    109:                DBG1(DBG_LIB, "signature scheme %N not supported by private key",
                    110:                         signature_scheme_names, scheme);
                    111:                return FALSE;
                    112:        }
                    113:        EC_GROUP_free(req_group);
                    114:        if (!openssl_hash_chunk(nid_hash, data, &hash))
                    115:        {
                    116:                return FALSE;
                    117:        }
                    118:        built = build_signature(this, hash, signature);
                    119:        chunk_free(&hash);
                    120:        return built;
                    121: }
                    122: 
                    123: /**
                    124:  * Build a DER encoded signature as in RFC 3279
                    125:  */
                    126: static bool build_der_signature(private_openssl_ec_private_key_t *this,
                    127:                                                                int hash_nid, chunk_t data, chunk_t *signature)
                    128: {
                    129:        chunk_t hash, sig;
                    130:        int siglen = 0;
                    131:        bool built;
                    132: 
                    133:        if (!openssl_hash_chunk(hash_nid, data, &hash))
                    134:        {
                    135:                return FALSE;
                    136:        }
                    137:        sig = chunk_alloc(ECDSA_size(this->ec));
                    138:        built = ECDSA_sign(0, hash.ptr, hash.len, sig.ptr, &siglen, this->ec) == 1;
                    139:        sig.len = siglen;
                    140:        if (built)
                    141:        {
                    142:                *signature = sig;
                    143:        }
                    144:        else
                    145:        {
                    146:                free(sig.ptr);
                    147:        }
                    148:        free(hash.ptr);
                    149:        return built;
                    150: }
                    151: 
                    152: METHOD(private_key_t, sign, bool,
                    153:        private_openssl_ec_private_key_t *this, signature_scheme_t scheme,
                    154:        void *params, chunk_t data, chunk_t *signature)
                    155: {
                    156:        switch (scheme)
                    157:        {
                    158:                case SIGN_ECDSA_WITH_NULL:
                    159:                        return build_signature(this, data, signature);
                    160:                case SIGN_ECDSA_WITH_SHA1_DER:
                    161:                        return build_der_signature(this, NID_sha1, data, signature);
                    162:                case SIGN_ECDSA_WITH_SHA256_DER:
                    163:                        return build_der_signature(this, NID_sha256, data, signature);
                    164:                case SIGN_ECDSA_WITH_SHA384_DER:
                    165:                        return build_der_signature(this, NID_sha384, data, signature);
                    166:                case SIGN_ECDSA_WITH_SHA512_DER:
                    167:                        return build_der_signature(this, NID_sha512, data, signature);
                    168:                case SIGN_ECDSA_256:
                    169:                        return build_curve_signature(this, scheme, NID_sha256,
                    170:                                                                                 NID_X9_62_prime256v1, data, signature);
                    171:                case SIGN_ECDSA_384:
                    172:                        return build_curve_signature(this, scheme, NID_sha384,
                    173:                                                                                 NID_secp384r1, data, signature);
                    174:                case SIGN_ECDSA_521:
                    175:                        return build_curve_signature(this, scheme, NID_sha512,
                    176:                                                                                 NID_secp521r1, data, signature);
                    177:                default:
                    178:                        DBG1(DBG_LIB, "signature scheme %N not supported",
                    179:                                 signature_scheme_names, scheme);
                    180:                        return FALSE;
                    181:        }
                    182: }
                    183: 
                    184: METHOD(private_key_t, decrypt, bool,
                    185:        private_openssl_ec_private_key_t *this, encryption_scheme_t scheme,
                    186:        chunk_t crypto, chunk_t *plain)
                    187: {
                    188:        DBG1(DBG_LIB, "EC private key decryption not implemented");
                    189:        return FALSE;
                    190: }
                    191: 
                    192: METHOD(private_key_t, get_keysize, int,
                    193:        private_openssl_ec_private_key_t *this)
                    194: {
                    195:        return EC_GROUP_get_degree(EC_KEY_get0_group(this->ec));
                    196: }
                    197: 
                    198: METHOD(private_key_t, get_type, key_type_t,
                    199:        private_openssl_ec_private_key_t *this)
                    200: {
                    201:        return KEY_ECDSA;
                    202: }
                    203: 
                    204: METHOD(private_key_t, get_public_key, public_key_t*,
                    205:        private_openssl_ec_private_key_t *this)
                    206: {
                    207:        public_key_t *public;
                    208:        chunk_t key;
                    209:        u_char *p;
                    210: 
                    211:        key = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL));
                    212:        p = key.ptr;
                    213:        i2d_EC_PUBKEY(this->ec, &p);
                    214: 
                    215:        public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
                    216:                                                                BUILD_BLOB_ASN1_DER, key, BUILD_END);
                    217:        free(key.ptr);
                    218:        return public;
                    219: }
                    220: 
                    221: METHOD(private_key_t, get_fingerprint, bool,
                    222:        private_openssl_ec_private_key_t *this, cred_encoding_type_t type,
                    223:        chunk_t *fingerprint)
                    224: {
                    225:        return openssl_ec_fingerprint(this->ec, type, fingerprint);
                    226: }
                    227: 
                    228: METHOD(private_key_t, get_encoding, bool,
                    229:        private_openssl_ec_private_key_t *this, cred_encoding_type_t type,
                    230:        chunk_t *encoding)
                    231: {
                    232:        u_char *p;
                    233: 
                    234:        if (this->engine)
                    235:        {
                    236:                return FALSE;
                    237:        }
                    238: 
                    239:        switch (type)
                    240:        {
                    241:                case PRIVKEY_ASN1_DER:
                    242:                case PRIVKEY_PEM:
                    243:                {
                    244:                        bool success = TRUE;
                    245: 
                    246:                        *encoding = chunk_alloc(i2d_ECPrivateKey(this->ec, NULL));
                    247:                        p = encoding->ptr;
                    248:                        i2d_ECPrivateKey(this->ec, &p);
                    249: 
                    250:                        if (type == PRIVKEY_PEM)
                    251:                        {
                    252:                                chunk_t asn1_encoding = *encoding;
                    253: 
                    254:                                success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
                    255:                                                                NULL, encoding, CRED_PART_ECDSA_PRIV_ASN1_DER,
                    256:                                                                asn1_encoding, CRED_PART_END);
                    257:                                chunk_clear(&asn1_encoding);
                    258:                        }
                    259:                        return success;
                    260:                }
                    261:                default:
                    262:                        return FALSE;
                    263:        }
                    264: }
                    265: 
                    266: METHOD(private_key_t, get_ref, private_key_t*,
                    267:        private_openssl_ec_private_key_t *this)
                    268: {
                    269:        ref_get(&this->ref);
                    270:        return &this->public.key;
                    271: }
                    272: 
                    273: METHOD(private_key_t, destroy, void,
                    274:        private_openssl_ec_private_key_t *this)
                    275: {
                    276:        if (ref_put(&this->ref))
                    277:        {
                    278:                if (this->ec)
                    279:                {
                    280:                        lib->encoding->clear_cache(lib->encoding, this->ec);
                    281:                        EC_KEY_free(this->ec);
                    282:                }
                    283:                free(this);
                    284:        }
                    285: }
                    286: 
                    287: /**
                    288:  * Internal generic constructor
                    289:  */
                    290: static private_openssl_ec_private_key_t *create_empty(void)
                    291: {
                    292:        private_openssl_ec_private_key_t *this;
                    293: 
                    294:        INIT(this,
                    295:                .public = {
                    296:                        .key = {
                    297:                                .get_type = _get_type,
                    298:                                .sign = _sign,
                    299:                                .decrypt = _decrypt,
                    300:                                .get_keysize = _get_keysize,
                    301:                                .get_public_key = _get_public_key,
                    302:                                .equals = private_key_equals,
                    303:                                .belongs_to = private_key_belongs_to,
                    304:                                .get_fingerprint = _get_fingerprint,
                    305:                                .has_fingerprint = private_key_has_fingerprint,
                    306:                                .get_encoding = _get_encoding,
                    307:                                .get_ref = _get_ref,
                    308:                                .destroy = _destroy,
                    309:                        },
                    310:                },
                    311:                .ref = 1,
                    312:        );
                    313: 
                    314:        return this;
                    315: }
                    316: 
                    317: /*
                    318:  * See header.
                    319:  */
                    320: private_key_t *openssl_ec_private_key_create(EVP_PKEY *key, bool engine)
                    321: {
                    322:        private_openssl_ec_private_key_t *this;
                    323:        EC_KEY *ec;
                    324: 
                    325:        ec = EVP_PKEY_get1_EC_KEY(key);
                    326:        EVP_PKEY_free(key);
                    327:        if (!ec)
                    328:        {
                    329:                return NULL;
                    330:        }
                    331:        this = create_empty();
                    332:        this->ec = ec;
                    333:        this->engine = engine;
                    334:        return &this->public.key;
                    335: }
                    336: 
                    337: /*
                    338:  * See header.
                    339:  */
                    340: openssl_ec_private_key_t *openssl_ec_private_key_gen(key_type_t type,
                    341:                                                                                                         va_list args)
                    342: {
                    343:        private_openssl_ec_private_key_t *this;
                    344:        u_int key_size = 0;
                    345: 
                    346:        while (TRUE)
                    347:        {
                    348:                switch (va_arg(args, builder_part_t))
                    349:                {
                    350:                        case BUILD_KEY_SIZE:
                    351:                                key_size = va_arg(args, u_int);
                    352:                                continue;
                    353:                        case BUILD_END:
                    354:                                break;
                    355:                        default:
                    356:                                return NULL;
                    357:                }
                    358:                break;
                    359:        }
                    360:        if (!key_size)
                    361:        {
                    362:                return NULL;
                    363:        }
                    364:        this = create_empty();
                    365:        switch (key_size)
                    366:        {
                    367:                case 256:
                    368:                        this->ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
                    369:                        break;
                    370:                case 384:
                    371:                        this->ec = EC_KEY_new_by_curve_name(NID_secp384r1);
                    372:                        break;
                    373:                case 521:
                    374:                        this->ec = EC_KEY_new_by_curve_name(NID_secp521r1);
                    375:                        break;
                    376:                default:
                    377:                        DBG1(DBG_LIB, "EC private key size %d not supported", key_size);
                    378:                        destroy(this);
                    379:                        return NULL;
                    380:        }
                    381:        if (EC_KEY_generate_key(this->ec) != 1)
                    382:        {
                    383:                DBG1(DBG_LIB, "EC private key generation failed", key_size);
                    384:                destroy(this);
                    385:                return NULL;
                    386:        }
                    387:        /* encode as a named curve key (no parameters), uncompressed public key */
                    388:        EC_KEY_set_asn1_flag(this->ec, OPENSSL_EC_NAMED_CURVE);
                    389:        EC_KEY_set_conv_form(this->ec, POINT_CONVERSION_UNCOMPRESSED);
                    390:        return &this->public;
                    391: }
                    392: 
                    393: /**
                    394:  * See header.
                    395:  */
                    396: openssl_ec_private_key_t *openssl_ec_private_key_load(key_type_t type,
                    397:                                                                                                          va_list args)
                    398: {
                    399:        private_openssl_ec_private_key_t *this;
                    400:        chunk_t par = chunk_empty, key = chunk_empty;
                    401: 
                    402:        while (TRUE)
                    403:        {
                    404:                switch (va_arg(args, builder_part_t))
                    405:                {
                    406:                        case BUILD_BLOB_ALGID_PARAMS:
                    407:                                par = va_arg(args, chunk_t);
                    408:                                continue;
                    409:                        case BUILD_BLOB_ASN1_DER:
                    410:                                key = va_arg(args, chunk_t);
                    411:                                continue;
                    412:                        case BUILD_END:
                    413:                                break;
                    414:                        default:
                    415:                                return NULL;
                    416:                }
                    417:                break;
                    418:        }
                    419: 
                    420:        this = create_empty();
                    421: 
                    422:        if (par.ptr)
                    423:        {
                    424:                this->ec = d2i_ECParameters(NULL, (const u_char**)&par.ptr, par.len);
                    425:                if (!this->ec)
                    426:                {
                    427:                        goto error;
                    428:                }
                    429:                if (!d2i_ECPrivateKey(&this->ec, (const u_char**)&key.ptr, key.len))
                    430:                {
                    431:                        goto error;
                    432:                }
                    433:        }
                    434:        else
                    435:        {
                    436:                this->ec = d2i_ECPrivateKey(NULL, (const u_char**)&key.ptr, key.len);
                    437:                if (!this->ec)
                    438:                {
                    439:                        goto error;
                    440:                }
                    441:        }
                    442:        if (!EC_KEY_check_key(this->ec))
                    443:        {
                    444:                goto error;
                    445:        }
                    446:        return &this->public;
                    447: 
                    448: error:
                    449:        destroy(this);
                    450:        return NULL;
                    451: }
                    452: #endif /* OPENSSL_NO_ECDSA */

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