Annotation of embedaddon/strongswan/src/libstrongswan/plugins/wolfssl/wolfssl_ec_public_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_VERIFY
                     26: 
                     27: #include "wolfssl_ec_public_key.h"
                     28: #include "wolfssl_util.h"
                     29: 
                     30: #include <utils/debug.h>
                     31: 
                     32: #include <wolfssl/wolfcrypt/ecc.h>
                     33: #include <wolfssl/wolfcrypt/hash.h>
                     34: #include <wolfssl/wolfcrypt/asn.h>
                     35: 
                     36: typedef struct private_wolfssl_ec_public_key_t private_wolfssl_ec_public_key_t;
                     37: 
                     38: /**
                     39:  * Private data structure with signing context.
                     40:  */
                     41: struct private_wolfssl_ec_public_key_t {
                     42: 
                     43:        /**
                     44:         * Public interface
                     45:         */
                     46:        wolfssl_ec_public_key_t public;
                     47: 
                     48:        /**
                     49:         * Key size
                     50:         */
                     51:        int keysize;
                     52: 
                     53:        /**
                     54:         * EC key object
                     55:         */
                     56:        ecc_key ec;
                     57: 
                     58:        /**
                     59:         * Reference count
                     60:         */
                     61:        refcount_t ref;
                     62: };
                     63: 
                     64: /**
                     65:  * Verification of a signature as in RFC 4754
                     66:  */
                     67: static bool verify_signature(private_wolfssl_ec_public_key_t *this,
                     68:                                                         chunk_t hash, chunk_t signature)
                     69: {
                     70:        int stat = 1, ret = -1;
                     71:        mp_int r, s;
                     72: 
                     73:        if (mp_init(&r) < 0)
                     74:        {
                     75:                return FALSE;
                     76:        }
                     77:        if (mp_init(&s) < 0)
                     78:        {
                     79:                mp_free(&r);
                     80:                return FALSE;
                     81:        }
                     82: 
                     83:        if (wolfssl_mp_split(signature, &r, &s))
                     84:        {
                     85:                ret = wc_ecc_verify_hash_ex(&r, &s, hash.ptr, hash.len, &stat,
                     86:                                                                        &this->ec);
                     87:        }
                     88:        mp_free(&s);
                     89:        mp_free(&r);
                     90:        return ret == 0 && stat == 1;
                     91: }
                     92: 
                     93: /**
                     94:  * Verify a RFC 4754 signature for a specified curve and hash algorithm
                     95:  */
                     96: static bool verify_curve_signature(private_wolfssl_ec_public_key_t *this,
                     97:                                                                   signature_scheme_t scheme,
                     98:                                                                   enum wc_HashType hash, ecc_curve_id curve_id,
                     99:                                                                   chunk_t data, chunk_t signature)
                    100: {
                    101:        bool success = FALSE;
                    102:        chunk_t dgst;
                    103: 
                    104:        if (curve_id != this->ec.dp->id)
                    105:        {
                    106:                DBG1(DBG_LIB, "signature scheme %N not supported by private key",
                    107:                         signature_scheme_names, scheme);
                    108:                return FALSE;
                    109:        }
                    110: 
                    111:        if (wolfssl_hash_chunk(hash, data, &dgst))
                    112:        {
                    113:                success = verify_signature(this, dgst, signature);
                    114:        }
                    115: 
                    116:        chunk_free(&dgst);
                    117:        return success;
                    118: }
                    119: 
                    120: /**
                    121:  * Verification of a DER encoded signature as in RFC 3279
                    122:  */
                    123: static bool verify_der_signature(private_wolfssl_ec_public_key_t *this,
                    124:                                                                 enum wc_HashType hash, chunk_t data,
                    125:                                                                 chunk_t signature)
                    126: {
                    127:        chunk_t dgst;
                    128:        int stat = 1, ret = -1;
                    129: 
                    130:        signature = chunk_skip_zero(signature);
                    131:        if (wolfssl_hash_chunk(hash, data, &dgst))
                    132:        {
                    133:                ret = wc_ecc_verify_hash(signature.ptr, signature.len, dgst.ptr,
                    134:                                                                 dgst.len, &stat, &this->ec);
                    135:        }
                    136:        chunk_free(&dgst);
                    137:        return ret == 0 && stat == 1;
                    138: }
                    139: 
                    140: METHOD(public_key_t, get_type, key_type_t,
                    141:        private_wolfssl_ec_public_key_t *this)
                    142: {
                    143:        return KEY_ECDSA;
                    144: }
                    145: 
                    146: METHOD(public_key_t, verify, bool,
                    147:        private_wolfssl_ec_public_key_t *this, signature_scheme_t scheme,
                    148:        void *params, chunk_t data, chunk_t signature)
                    149: {
                    150:        switch (scheme)
                    151:        {
                    152: #ifndef NO_SHA
                    153:                case SIGN_ECDSA_WITH_SHA1_DER:
                    154:                        return verify_der_signature(this, WC_HASH_TYPE_SHA, data,
                    155:                                                                                signature);
                    156: #endif
                    157: #ifndef NO_SHA256
                    158:                case SIGN_ECDSA_WITH_SHA256_DER:
                    159:                        return verify_der_signature(this, WC_HASH_TYPE_SHA256, data,
                    160:                                                                                signature);
                    161: #endif
                    162: #ifdef WOLFSSL_SHA384
                    163:                case SIGN_ECDSA_WITH_SHA384_DER:
                    164:                        return verify_der_signature(this, WC_HASH_TYPE_SHA384, data,
                    165:                                                                                signature);
                    166: #endif
                    167: #ifdef WOLFSSL_SHA512
                    168:                case SIGN_ECDSA_WITH_SHA512_DER:
                    169:                        return verify_der_signature(this, WC_HASH_TYPE_SHA512, data,
                    170:                                                                                signature);
                    171: #endif
                    172:                case SIGN_ECDSA_WITH_NULL:
                    173:                        return verify_signature(this, data, signature);
                    174: #ifndef NO_SHA256
                    175:                case SIGN_ECDSA_256:
                    176:                        return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA256,
                    177:                                                                                  ECC_SECP256R1, data, signature);
                    178: #endif
                    179: #ifdef WOLFSSL_SHA384
                    180:                case SIGN_ECDSA_384:
                    181:                        return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA384,
                    182:                                                                                  ECC_SECP384R1, data, signature);
                    183: #endif
                    184: #ifdef WOLFSSL_SHA512
                    185:                case SIGN_ECDSA_521:
                    186:                        return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA512,
                    187:                                                                                  ECC_SECP521R1, data, signature);
                    188: #endif
                    189:                default:
                    190:                        DBG1(DBG_LIB, "signature scheme %N not supported via wolfssl",
                    191:                                 signature_scheme_names, scheme);
                    192:                        return FALSE;
                    193:        }
                    194: }
                    195: 
                    196: METHOD(public_key_t, encrypt, bool,
                    197:        private_wolfssl_ec_public_key_t *this, encryption_scheme_t scheme,
                    198:        chunk_t crypto, chunk_t *plain)
                    199: {
                    200:        DBG1(DBG_LIB, "EC public key encryption not implemented");
                    201:        return FALSE;
                    202: }
                    203: 
                    204: METHOD(public_key_t, get_keysize, int,
                    205:        private_wolfssl_ec_public_key_t *this)
                    206: {
                    207:        return this->keysize;
                    208: }
                    209: 
                    210: /**
                    211:  * Calculate fingerprint from an EC key, also used in ec private key.
                    212:  */
                    213: bool wolfssl_ec_fingerprint(ecc_key *ec, cred_encoding_type_t type, chunk_t *fp)
                    214: {
                    215:        hasher_t *hasher;
                    216:        chunk_t key;
                    217:        int len;
                    218: 
                    219:        if (lib->encoding->get_cache(lib->encoding, type, ec, fp))
                    220:        {
                    221:                return TRUE;
                    222:        }
                    223: 
                    224:        switch (type)
                    225:        {
                    226:                case KEYID_PUBKEY_SHA1:
                    227:                case KEYID_PUBKEY_INFO_SHA1:
                    228:                        /* need an additional byte for the point type */
                    229:                        len = ec->dp->size * 2 + 1;
                    230:                        if (type == KEYID_PUBKEY_INFO_SHA1)
                    231:                        {
                    232:                                /* additional space for algorithmIdentifier/bitString */
                    233:                                len += 2 * MAX_SEQ_SZ + 2 * MAX_ALGO_SZ + TRAILING_ZERO;
                    234:                        }
                    235:                        key = chunk_alloca(len);
                    236:                        len = wc_EccPublicKeyToDer(ec, key.ptr, key.len,
                    237:                                                                           type == KEYID_PUBKEY_INFO_SHA1);
                    238:                        break;
                    239:                default:
                    240:                        return FALSE;
                    241:        }
                    242:        if (len < 0)
                    243:        {
                    244:                return FALSE;
                    245:        }
                    246:        key.len = len;
                    247: 
                    248:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
                    249:        if (!hasher || !hasher->allocate_hash(hasher, key, fp))
                    250:        {
                    251:                DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
                    252:                DESTROY_IF(hasher);
                    253:                return FALSE;
                    254:        }
                    255:        hasher->destroy(hasher);
                    256:        lib->encoding->cache(lib->encoding, type, ec, *fp);
                    257:        return TRUE;
                    258: }
                    259: 
                    260: METHOD(public_key_t, get_fingerprint, bool,
                    261:        private_wolfssl_ec_public_key_t *this, cred_encoding_type_t type,
                    262:        chunk_t *fingerprint)
                    263: {
                    264:        return wolfssl_ec_fingerprint(&this->ec, type, fingerprint);
                    265: }
                    266: 
                    267: METHOD(public_key_t, get_encoding, bool,
                    268:        private_wolfssl_ec_public_key_t *this, cred_encoding_type_t type,
                    269:        chunk_t *encoding)
                    270: {
                    271:        bool success = TRUE;
                    272:        int len;
                    273: 
                    274:        /* space for algorithmIdentifier/bitString + one byte for the point type */
                    275:        *encoding = chunk_alloc(2 * this->ec.dp->size + 2 * MAX_SEQ_SZ +
                    276:                                                        2 * MAX_ALGO_SZ + TRAILING_ZERO + 1);
                    277:        len = wc_EccPublicKeyToDer(&this->ec, encoding->ptr, encoding->len, 1);
                    278:        if (len < 0)
                    279:        {
                    280:                chunk_free(encoding);
                    281:                return FALSE;
                    282:        }
                    283:        encoding->len = len;
                    284: 
                    285:        if (type != PUBKEY_SPKI_ASN1_DER)
                    286:        {
                    287:                chunk_t asn1_encoding = *encoding;
                    288: 
                    289:                success = lib->encoding->encode(lib->encoding, type,
                    290:                                                NULL, encoding, CRED_PART_ECDSA_PUB_ASN1_DER,
                    291:                                                asn1_encoding, CRED_PART_END);
                    292:                chunk_clear(&asn1_encoding);
                    293:        }
                    294:        return success;
                    295: }
                    296: 
                    297: METHOD(public_key_t, get_ref, public_key_t*,
                    298:        private_wolfssl_ec_public_key_t *this)
                    299: {
                    300:        ref_get(&this->ref);
                    301:        return &this->public.key;
                    302: }
                    303: 
                    304: METHOD(public_key_t, destroy, void,
                    305:        private_wolfssl_ec_public_key_t *this)
                    306: {
                    307:        if (ref_put(&this->ref))
                    308:        {
                    309:                lib->encoding->clear_cache(lib->encoding, &this->ec);
                    310:                wc_ecc_free(&this->ec);
                    311:                free(this);
                    312:        }
                    313: }
                    314: 
                    315: /**
                    316:  * Generic private constructor
                    317:  */
                    318: static private_wolfssl_ec_public_key_t *create_empty()
                    319: {
                    320:        private_wolfssl_ec_public_key_t *this;
                    321: 
                    322:        INIT(this,
                    323:                .public = {
                    324:                        .key = {
                    325:                                .get_type = _get_type,
                    326:                                .verify = _verify,
                    327:                                .encrypt = _encrypt,
                    328:                                .get_keysize = _get_keysize,
                    329:                                .equals = public_key_equals,
                    330:                                .get_fingerprint = _get_fingerprint,
                    331:                                .has_fingerprint = public_key_has_fingerprint,
                    332:                                .get_encoding = _get_encoding,
                    333:                                .get_ref = _get_ref,
                    334:                                .destroy = _destroy,
                    335:                        },
                    336:                },
                    337:                .ref = 1,
                    338:        );
                    339: 
                    340:        if (wc_ecc_init(&this->ec) < 0)
                    341:        {
                    342:                free(this);
                    343:                return NULL;
                    344:        }
                    345:        return this;
                    346: }
                    347: 
                    348: /*
                    349:  * Described in header
                    350:  */
                    351: wolfssl_ec_public_key_t *wolfssl_ec_public_key_load(key_type_t type,
                    352:                                                                                                        va_list args)
                    353: {
                    354:        private_wolfssl_ec_public_key_t *this;
                    355:        chunk_t blob = chunk_empty;
                    356:        word32 idx;
                    357:        int ret;
                    358: 
                    359:        while (TRUE)
                    360:        {
                    361:                switch (va_arg(args, builder_part_t))
                    362:                {
                    363:                        case BUILD_BLOB_ASN1_DER:
                    364:                                blob = va_arg(args, chunk_t);
                    365:                                continue;
                    366:                        case BUILD_END:
                    367:                                break;
                    368:                        default:
                    369:                                return NULL;
                    370:                }
                    371:                break;
                    372:        }
                    373:        this = create_empty();
                    374:        if (!this)
                    375:        {
                    376:                return NULL;
                    377:        }
                    378: 
                    379:        idx = 0;
                    380:        ret = wc_EccPublicKeyDecode(blob.ptr, &idx, &this->ec, blob.len);
                    381:        if (ret < 0)
                    382:        {
                    383:                destroy(this);
                    384:                return NULL;
                    385:        }
                    386:        switch (this->ec.dp->id)
                    387:        {
                    388:                case ECC_SECP256R1:
                    389:                        this->keysize = 256;
                    390:                        break;
                    391:                case ECC_SECP384R1:
                    392:                        this->keysize = 384;
                    393:                        break;
                    394:                case ECC_SECP521R1:
                    395:                        this->keysize = 521;
                    396:                        break;
                    397:                default:
                    398:                        break;
                    399:        }
                    400:        return &this->public;
                    401: }
                    402: 
                    403: #endif /* HAVE_ECC_VERIFY */

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