Annotation of embedaddon/strongswan/src/libstrongswan/plugins/wolfssl/wolfssl_ec_private_key.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
                      3:  *
                      4:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      5:  * of this software and associated documentation files (the "Software"), to deal
                      6:  * in the Software without restriction, including without limitation the rights
                      7:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                      8:  * copies of the Software, and to permit persons to whom the Software is
                      9:  * furnished to do so, subject to the following conditions:
                     10:  *
                     11:  * The above copyright notice and this permission notice shall be included in
                     12:  * all copies or substantial portions of the Software.
                     13:  *
                     14:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     15:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     17:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     18:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     19:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     20:  * THE SOFTWARE.
                     21:  */
                     22: 
                     23: #include "wolfssl_common.h"
                     24: 
                     25: #ifdef HAVE_ECC_SIGN
                     26: 
                     27: #include "wolfssl_ec_private_key.h"
                     28: #include "wolfssl_ec_public_key.h"
                     29: #include "wolfssl_util.h"
                     30: 
                     31: #include <asn1/asn1.h>
                     32: #include <asn1/oid.h>
                     33: 
                     34: #include <utils/debug.h>
                     35: 
                     36: #include <wolfssl/wolfcrypt/ecc.h>
                     37: #include <wolfssl/wolfcrypt/asn.h>
                     38: 
                     39: typedef struct private_wolfssl_ec_private_key_t private_wolfssl_ec_private_key_t;
                     40: 
                     41: /**
                     42:  * Private data of a wolfssl_ec_private_key_t object.
                     43:  */
                     44: struct private_wolfssl_ec_private_key_t {
                     45: 
                     46:        /**
                     47:         * Public interface
                     48:         */
                     49:        wolfssl_ec_private_key_t public;
                     50: 
                     51:        /**
                     52:         * Key size
                     53:         */
                     54:        int keysize;
                     55: 
                     56:        /**
                     57:         * EC key object
                     58:         */
                     59:        ecc_key ec;
                     60: 
                     61:        /**
                     62:         * Random number generator
                     63:         */
                     64:        WC_RNG rng;
                     65: 
                     66:        /**
                     67:         * Reference count
                     68:         */
                     69:        refcount_t ref;
                     70: };
                     71: 
                     72: /* from ec public key */
                     73: bool wolfssl_ec_fingerprint(ecc_key *ec, cred_encoding_type_t type, chunk_t *fp);
                     74: 
                     75: /**
                     76:  * Build a signature as in RFC 4754
                     77:  */
                     78: static bool build_signature(private_wolfssl_ec_private_key_t *this,
                     79:                                                        chunk_t hash, chunk_t *signature)
                     80: {
                     81:        bool success = FALSE;
                     82:        mp_int r, s;
                     83: 
                     84:        if (mp_init(&r) != 0)
                     85:        {
                     86:                return FALSE;
                     87:        }
                     88:        if (mp_init(&s) != 0)
                     89:        {
                     90:                mp_free(&r);
                     91:                return FALSE;
                     92:        }
                     93:        if (wc_ecc_sign_hash_ex(hash.ptr, hash.len, &this->rng, &this->ec, &r,
                     94:                                                        &s) == 0)
                     95:        {
                     96:                success = wolfssl_mp_cat(this->ec.dp->size * 2, &r, &s, signature);
                     97:        }
                     98: 
                     99:        mp_free(&s);
                    100:        mp_free(&r);
                    101:        return success;
                    102: }
                    103: 
                    104: /**
                    105:  * Build a RFC 4754 signature for a specified curve and hash algorithm
                    106:  */
                    107: static bool build_curve_signature(private_wolfssl_ec_private_key_t *this,
                    108:                                                                  signature_scheme_t scheme,
                    109:                                                                  enum wc_HashType hash, ecc_curve_id curve_id,
                    110:                                                                  chunk_t data, chunk_t *signature)
                    111: {
                    112:        chunk_t dgst = chunk_empty;
                    113:        bool success = FALSE;
                    114: 
                    115:        if (curve_id != this->ec.dp->id)
                    116:        {
                    117:                DBG1(DBG_LIB, "signature scheme %N not supported by private key",
                    118:                         signature_scheme_names, scheme);
                    119:                return FALSE;
                    120:        }
                    121:        if (wolfssl_hash_chunk(hash, data, &dgst))
                    122:        {
                    123:                success = build_signature(this, dgst, signature);
                    124:        }
                    125:        chunk_free(&dgst);
                    126:        return success;
                    127: }
                    128: 
                    129: /**
                    130:  * Build a DER encoded signature as in RFC 3279
                    131:  */
                    132: static bool build_der_signature(private_wolfssl_ec_private_key_t *this,
                    133:                                                                enum wc_HashType hash, chunk_t data,
                    134:                                                                chunk_t *signature)
                    135: {
                    136:        chunk_t dgst = chunk_empty;
                    137:        bool success = FALSE;
                    138:        word32 len;
                    139: 
                    140:        if (wolfssl_hash_chunk(hash, data, &dgst))
                    141:        {
                    142:                *signature = chunk_alloc(wc_ecc_sig_size(&this->ec));
                    143:                len = signature->len;
                    144:                if (wc_ecc_sign_hash(dgst.ptr, dgst.len, signature->ptr, &len,
                    145:                                                           &this->rng, &this->ec) == 0)
                    146:                {
                    147:                        signature->len = len;
                    148:                        success = TRUE;
                    149:                }
                    150:                else
                    151:                {
                    152:                        chunk_free(signature);
                    153:                }
                    154:        }
                    155:        chunk_free(&dgst);
                    156:        return success;
                    157: }
                    158: 
                    159: METHOD(private_key_t, sign, bool,
                    160:        private_wolfssl_ec_private_key_t *this, signature_scheme_t scheme,
                    161:        void *params, chunk_t data, chunk_t *signature)
                    162: {
                    163:        switch (scheme)
                    164:        {
                    165:                case SIGN_ECDSA_WITH_NULL:
                    166:                        return build_signature(this, data, signature);
                    167: #ifndef NO_SHA
                    168:                case SIGN_ECDSA_WITH_SHA1_DER:
                    169:                        return build_der_signature(this, WC_HASH_TYPE_SHA, data, signature);
                    170: #endif
                    171: #ifndef NO_SHA256
                    172:                case SIGN_ECDSA_WITH_SHA256_DER:
                    173:                        return build_der_signature(this, WC_HASH_TYPE_SHA256, data,
                    174:                                                                           signature);
                    175: #endif
                    176: #ifdef WOLFSSL_SHA384
                    177:                case SIGN_ECDSA_WITH_SHA384_DER:
                    178:                        return build_der_signature(this, WC_HASH_TYPE_SHA384, data,
                    179:                                                                           signature);
                    180: #endif
                    181: #ifdef WOLFSSL_SHA512
                    182:                case SIGN_ECDSA_WITH_SHA512_DER:
                    183:                        return build_der_signature(this, WC_HASH_TYPE_SHA512, data,
                    184:                                                                           signature);
                    185: #endif
                    186: #ifndef NO_SHA256
                    187:                case SIGN_ECDSA_256:
                    188:                        return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA256,
                    189:                                                                                 ECC_SECP256R1, data, signature);
                    190: #endif
                    191: #ifdef WOLFSSL_SHA384
                    192:                case SIGN_ECDSA_384:
                    193:                        return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA384,
                    194:                                                                                 ECC_SECP384R1, data, signature);
                    195: #endif
                    196: #ifdef WOLFSSL_SHA512
                    197:                case SIGN_ECDSA_521:
                    198:                        return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA512,
                    199:                                                                                 ECC_SECP521R1, data, signature);
                    200: #endif
                    201:                default:
                    202:                        DBG1(DBG_LIB, "signature scheme %N not supported",
                    203:                                 signature_scheme_names, scheme);
                    204:                        return FALSE;
                    205:        }
                    206: }
                    207: 
                    208: METHOD(private_key_t, decrypt, bool,
                    209:        private_wolfssl_ec_private_key_t *this, encryption_scheme_t scheme,
                    210:        chunk_t crypto, chunk_t *plain)
                    211: {
                    212:        DBG1(DBG_LIB, "EC private key decryption not implemented");
                    213:        return FALSE;
                    214: }
                    215: 
                    216: METHOD(private_key_t, get_keysize, int,
                    217:        private_wolfssl_ec_private_key_t *this)
                    218: {
                    219:        return this->keysize;
                    220: }
                    221: 
                    222: METHOD(private_key_t, get_type, key_type_t,
                    223:        private_wolfssl_ec_private_key_t *this)
                    224: {
                    225:        return KEY_ECDSA;
                    226: }
                    227: 
                    228: METHOD(private_key_t, get_public_key, public_key_t*,
                    229:        private_wolfssl_ec_private_key_t *this)
                    230: {
                    231:        public_key_t *public;
                    232:        chunk_t key;
                    233:        int len;
                    234: 
                    235:        /* space for algorithmIdentifier/bitString + one byte for the point type */
                    236:        key = chunk_alloc(2 * this->ec.dp->size + 2 * MAX_SEQ_SZ + 2 * MAX_ALGO_SZ +
                    237:                                          TRAILING_ZERO + 1);
                    238:        len = wc_EccPublicKeyToDer(&this->ec, key.ptr, key.len, 1);
                    239:        if (len < 0)
                    240:        {
                    241:                chunk_free(&key);
                    242:                return NULL;
                    243:        }
                    244:        key.len = len;
                    245: 
                    246:        public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
                    247:                                                                BUILD_BLOB_ASN1_DER, key, BUILD_END);
                    248:        free(key.ptr);
                    249:        return public;
                    250: }
                    251: 
                    252: METHOD(private_key_t, get_fingerprint, bool,
                    253:        private_wolfssl_ec_private_key_t *this, cred_encoding_type_t type,
                    254:        chunk_t *fingerprint)
                    255: {
                    256:        return wolfssl_ec_fingerprint(&this->ec, type, fingerprint);
                    257: }
                    258: 
                    259: METHOD(private_key_t, get_encoding, bool,
                    260:        private_wolfssl_ec_private_key_t *this, cred_encoding_type_t type,
                    261:        chunk_t *encoding)
                    262: {
                    263:        bool success = TRUE;
                    264:        int len;
                    265: 
                    266:        switch (type)
                    267:        {
                    268:                case PRIVKEY_ASN1_DER:
                    269:                case PRIVKEY_PEM:
                    270:                        /* include space for parameters, public key and contexts */
                    271:                        *encoding = chunk_alloc(3 * this->ec.dp->size + 4 * MAX_SEQ_SZ +
                    272:                                                                        MAX_VERSION_SZ + MAX_ALGO_SZ);
                    273:                        len = wc_EccKeyToDer(&this->ec, encoding->ptr, encoding->len);
                    274:                        if (len < 0)
                    275:                        {
                    276:                                chunk_free(encoding);
                    277:                                return FALSE;
                    278:                        }
                    279:                        encoding->len = len;
                    280: 
                    281:                        if (type == PRIVKEY_PEM)
                    282:                        {
                    283:                                chunk_t asn1_encoding = *encoding;
                    284: 
                    285:                                success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
                    286:                                                                NULL, encoding, CRED_PART_ECDSA_PRIV_ASN1_DER,
                    287:                                                                asn1_encoding, CRED_PART_END);
                    288:                                chunk_clear(&asn1_encoding);
                    289:                        }
                    290:                        return success;
                    291:                default:
                    292:                        return FALSE;
                    293:        }
                    294: }
                    295: 
                    296: METHOD(private_key_t, get_ref, private_key_t*,
                    297:        private_wolfssl_ec_private_key_t *this)
                    298: {
                    299:        ref_get(&this->ref);
                    300:        return &this->public.key;
                    301: }
                    302: 
                    303: METHOD(private_key_t, destroy, void,
                    304:        private_wolfssl_ec_private_key_t *this)
                    305: {
                    306:        if (ref_put(&this->ref))
                    307:        {
                    308:                lib->encoding->clear_cache(lib->encoding, &this->ec);
                    309:                wc_FreeRng(&this->rng);
                    310:                wc_ecc_free(&this->ec);
                    311:                free(this);
                    312:        }
                    313: }
                    314: 
                    315: /**
                    316:  * Internal generic constructor
                    317:  */
                    318: static private_wolfssl_ec_private_key_t *create_empty(void)
                    319: {
                    320:        private_wolfssl_ec_private_key_t *this;
                    321: 
                    322:        INIT(this,
                    323:                .public = {
                    324:                        .key = {
                    325:                                .get_type = _get_type,
                    326:                                .sign = _sign,
                    327:                                .decrypt = _decrypt,
                    328:                                .get_keysize = _get_keysize,
                    329:                                .get_public_key = _get_public_key,
                    330:                                .equals = private_key_equals,
                    331:                                .belongs_to = private_key_belongs_to,
                    332:                                .get_fingerprint = _get_fingerprint,
                    333:                                .has_fingerprint = private_key_has_fingerprint,
                    334:                                .get_encoding = _get_encoding,
                    335:                                .get_ref = _get_ref,
                    336:                                .destroy = _destroy,
                    337:                        },
                    338:                },
                    339:                .ref = 1,
                    340:        );
                    341: 
                    342:        if (wc_InitRng(&this->rng) < 0)
                    343:        {
                    344:                DBG1(DBG_LIB, "RNG init failed");
                    345:                free(this);
                    346:                return NULL;
                    347:        }
                    348:        return this;
                    349: }
                    350: 
                    351: /*
                    352:  * Described in header
                    353:  */
                    354: wolfssl_ec_private_key_t *wolfssl_ec_private_key_gen(key_type_t type,
                    355:                                                                                                         va_list args)
                    356: {
                    357:        private_wolfssl_ec_private_key_t *this;
                    358:        u_int key_size = 0;
                    359:        ecc_curve_id curve_id;
                    360: 
                    361:        while (TRUE)
                    362:        {
                    363:                switch (va_arg(args, builder_part_t))
                    364:                {
                    365:                        case BUILD_KEY_SIZE:
                    366:                                key_size = va_arg(args, u_int);
                    367:                                continue;
                    368:                        case BUILD_END:
                    369:                                break;
                    370:                        default:
                    371:                                return NULL;
                    372:                }
                    373:                break;
                    374:        }
                    375:        if (!key_size)
                    376:        {
                    377:                return NULL;
                    378:        }
                    379:        this = create_empty();
                    380:        if (!this)
                    381:        {
                    382:                return NULL;
                    383:        }
                    384: 
                    385:        this->keysize = key_size;
                    386:        switch (key_size)
                    387:        {
                    388:                case 256:
                    389:                        curve_id = ECC_SECP256R1;
                    390:                        break;
                    391:                case 384:
                    392:                        curve_id = ECC_SECP384R1;
                    393:                        break;
                    394:                case 521:
                    395:                        curve_id = ECC_SECP521R1;
                    396:                        break;
                    397:                default:
                    398:                        DBG1(DBG_LIB, "EC private key size %d not supported", key_size);
                    399:                        destroy(this);
                    400:                        return NULL;
                    401:        }
                    402: 
                    403:        if (wc_ecc_make_key_ex(&this->rng, (key_size + 7) / 8, &this->ec,
                    404:                                                   curve_id) < 0)
                    405:        {
                    406:                DBG1(DBG_LIB, "EC private key generation failed");
                    407:                destroy(this);
                    408:                return NULL;
                    409:        }
                    410:        return &this->public;
                    411: }
                    412: 
                    413: /*
                    414:  * Described in header
                    415:  */
                    416: wolfssl_ec_private_key_t *wolfssl_ec_private_key_load(key_type_t type,
                    417:                                                                                                          va_list args)
                    418: {
                    419:        private_wolfssl_ec_private_key_t *this;
                    420:        chunk_t params = chunk_empty, key = chunk_empty;
                    421:        word32 idx;
                    422:        int oid = OID_UNKNOWN;
                    423: 
                    424:        while (TRUE)
                    425:        {
                    426:                switch (va_arg(args, builder_part_t))
                    427:                {
                    428:                        case BUILD_BLOB_ALGID_PARAMS:
                    429:                                params = va_arg(args, chunk_t);
                    430:                                continue;
                    431:                        case BUILD_BLOB_ASN1_DER:
                    432:                                key = va_arg(args, chunk_t);
                    433:                                continue;
                    434:                        case BUILD_END:
                    435:                                break;
                    436:                        default:
                    437:                                return NULL;
                    438:                }
                    439:                break;
                    440:        }
                    441:        if (!key.ptr)
                    442:        {
                    443:                return NULL;
                    444:        }
                    445:        this = create_empty();
                    446:        if (!this)
                    447:        {
                    448:                return NULL;
                    449:        }
                    450: 
                    451:        idx = 0;
                    452:        if (wc_EccPrivateKeyDecode(key.ptr, &idx, &this->ec, key.len) < 0)
                    453:        {
                    454:                destroy(this);
                    455:                return NULL;
                    456:        }
                    457:        switch (this->ec.dp->id)
                    458:        {
                    459:                case ECC_SECP256R1:
                    460:                        this->keysize = 256;
                    461:                        break;
                    462:                case ECC_SECP384R1:
                    463:                        this->keysize = 384;
                    464:                        break;
                    465:                case ECC_SECP521R1:
                    466:                        this->keysize = 521;
                    467:                        break;
                    468:                default:
                    469:                        break;
                    470:        }
                    471: 
                    472:        if (params.ptr)
                    473:        {
                    474:                /* if ECParameters is passed, ensure we guessed correctly */
                    475:                if (asn1_unwrap(&params, &params) == ASN1_OID)
                    476:                {
                    477:                        oid = asn1_known_oid(params);
                    478:                        switch (oid)
                    479:                        {
                    480:                                case OID_PRIME256V1:
                    481:                                        if (this->ec.dp->id != ECC_SECP256R1)
                    482:                                        {
                    483:                                                oid = OID_UNKNOWN;
                    484:                                        }
                    485:                                        break;
                    486:                                case OID_SECT384R1:
                    487:                                        if (this->ec.dp->id != ECC_SECP384R1)
                    488:                                        {
                    489:                                                oid = OID_UNKNOWN;
                    490:                                        }
                    491:                                        break;
                    492:                                case OID_SECT521R1:
                    493:                                        if (this->ec.dp->id != ECC_SECP521R1)
                    494:                                        {
                    495:                                                oid = OID_UNKNOWN;
                    496:                                        }
                    497:                                        break;
                    498:                                default:
                    499:                                        oid = OID_UNKNOWN;
                    500:                                        break;
                    501:                        }
                    502:                }
                    503:                if (oid == OID_UNKNOWN)
                    504:                {
                    505:                        DBG1(DBG_LIB, "parameters do not match private key data");
                    506:                        destroy(this);
                    507:                        return NULL;
                    508:                }
                    509:        }
                    510:        return &this->public;
                    511: }
                    512: 
                    513: #endif /* HAVE_ECC_SIGN */

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