Annotation of embedaddon/strongswan/src/libstrongswan/plugins/wolfssl/wolfssl_ed_public_key.c, revision 1.1.1.2

1.1       misho       1: /*
1.1.1.2 ! misho       2:  * Copyright (C) 2020 Tobias Brunner
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
1.1       misho       5:  * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
                      6:  *
                      7:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      8:  * of this software and associated documentation files (the "Software"), to deal
                      9:  * in the Software without restriction, including without limitation the rights
                     10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     11:  * copies of the Software, and to permit persons to whom the Software is
                     12:  * furnished to do so, subject to the following conditions:
                     13:  *
                     14:  * The above copyright notice and this permission notice shall be included in
                     15:  * all copies or substantial portions of the Software.
                     16:  *
                     17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     20:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     22:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     23:  * THE SOFTWARE.
                     24:  */
                     25: 
                     26: #include "wolfssl_common.h"
                     27: 
1.1.1.2 ! misho      28: #if defined(HAVE_ED25519) || defined(HAVE_ED448)
1.1       misho      29: 
                     30: #include "wolfssl_ed_public_key.h"
                     31: 
                     32: #include <utils/debug.h>
                     33: #include <asn1/asn1.h>
                     34: 
1.1.1.2 ! misho      35: #ifdef HAVE_ED25519
1.1       misho      36: #include <wolfssl/wolfcrypt/ed25519.h>
1.1.1.2 ! misho      37: #endif
        !            38: #ifdef HAVE_ED448
        !            39: #include <wolfssl/wolfcrypt/ed448.h>
        !            40: #endif
        !            41: 
1.1       misho      42: #include <wolfssl/wolfcrypt/asn.h>
                     43: 
                     44: typedef struct private_public_key_t private_public_key_t;
                     45: 
                     46: /**
                     47:  * Private data
                     48:  */
                     49: struct private_public_key_t {
                     50: 
                     51:        /**
                     52:         * Public interface
                     53:         */
                     54:        public_key_t public;
                     55: 
                     56:        /**
                     57:         * Key object
                     58:         */
1.1.1.2 ! misho      59:        wolfssl_ed_key key;
        !            60: 
        !            61:        /**
        !            62:         * Key type
        !            63:         */
        !            64:        key_type_t type;
1.1       misho      65: 
                     66:        /**
                     67:         * Reference count
                     68:         */
                     69:        refcount_t ref;
                     70: };
                     71: 
                     72: METHOD(public_key_t, get_type, key_type_t,
                     73:        private_public_key_t *this)
                     74: {
1.1.1.2 ! misho      75:        return this->type;
1.1       misho      76: }
                     77: 
                     78: METHOD(public_key_t, verify, bool,
                     79:        private_public_key_t *this, signature_scheme_t scheme,
                     80:        void *params, chunk_t data, chunk_t signature)
                     81: {
                     82:        byte dummy[1];
1.1.1.2 ! misho      83:        int ret = -1, res = 0;
1.1       misho      84: 
1.1.1.2 ! misho      85:        if ((this->type == KEY_ED25519 && scheme != SIGN_ED25519) ||
        !            86:                (this->type == KEY_ED448 && scheme != SIGN_ED448))
1.1       misho      87:        {
                     88:                DBG1(DBG_LIB, "signature scheme %N not supported by %N key",
1.1.1.2 ! misho      89:                         signature_scheme_names, scheme, key_type_names, this->type);
1.1       misho      90:                return FALSE;
                     91:        }
                     92: 
                     93:        if (!data.ptr && !data.len)
                     94:        {
                     95:                data.ptr = dummy;
                     96:        }
                     97: 
1.1.1.2 ! misho      98:        if (this->type == KEY_ED25519)
        !            99:        {
        !           100: #ifdef HAVE_ED25519
        !           101:                ret = wc_ed25519_verify_msg(signature.ptr, signature.len, data.ptr,
        !           102:                                                                        data.len, &res, &this->key.ed25519);
        !           103: #endif
        !           104:        }
        !           105:        else if (this->type == KEY_ED448)
        !           106:        {
        !           107: #ifdef HAVE_ED448
        !           108:                ret = wc_ed448_verify_msg(signature.ptr, signature.len, data.ptr,
        !           109:                                                                  data.len, &res, &this->key.ed448, NULL, 0);
        !           110: #endif
        !           111:        }
1.1       misho     112:        return ret == 0 && res == 1;
                    113: }
                    114: 
                    115: METHOD(public_key_t, encrypt, bool,
                    116:        private_public_key_t *this, encryption_scheme_t scheme,
                    117:        chunk_t crypto, chunk_t *plain)
                    118: {
                    119:        DBG1(DBG_LIB, "encryption scheme %N not supported", encryption_scheme_names,
                    120:                 scheme);
                    121:        return FALSE;
                    122: }
                    123: 
1.1.1.2 ! misho     124: /**
        !           125:  * Returns the key size in bytes for the given type, also used in private key.
        !           126:  */
        !           127: int wolfssl_ed_keysize(key_type_t type)
        !           128: {
        !           129:        if (type == KEY_ED25519)
        !           130:        {
        !           131: #ifdef HAVE_ED25519
        !           132:                return ED25519_KEY_SIZE * 8;
        !           133: #endif
        !           134:        }
        !           135:        else if (type == KEY_ED448)
        !           136:        {
        !           137: #ifdef HAVE_ED448
        !           138:                return ED448_KEY_SIZE * 8;
        !           139: #endif
        !           140:        }
        !           141:        return 0;
        !           142: }
        !           143: 
1.1       misho     144: METHOD(public_key_t, get_keysize, int,
                    145:        private_public_key_t *this)
                    146: {
1.1.1.2 ! misho     147:        return wolfssl_ed_keysize(this->type);
1.1       misho     148: }
                    149: 
                    150: /**
                    151:  * Encode the given public key as ASN.1 DER with algorithm identifier
                    152:  */
1.1.1.2 ! misho     153: static bool encode_pubkey(wolfssl_ed_key *key, key_type_t type,
        !           154:                                                  chunk_t *encoding)
1.1       misho     155: {
1.1.1.2 ! misho     156:        int ret = -1;
1.1       misho     157: 
                    158:        /* account for algorithmIdentifier/bitString */
1.1.1.2 ! misho     159:        if (type == KEY_ED25519)
        !           160:        {
        !           161: #ifdef HAVE_ED25519
        !           162:                *encoding = chunk_alloc(ED25519_PUB_KEY_SIZE + 2 * MAX_SEQ_SZ +
        !           163:                                                                MAX_ALGO_SZ + TRAILING_ZERO);
        !           164:                ret = wc_Ed25519PublicKeyToDer(&key->ed25519, encoding->ptr,
        !           165:                                                                           encoding->len, 1);
        !           166: #endif
        !           167:        }
        !           168:        else if (type == KEY_ED448)
        !           169:        {
        !           170: #ifdef HAVE_ED448
        !           171:                *encoding = chunk_alloc(ED448_PUB_KEY_SIZE + 2 * MAX_SEQ_SZ +
        !           172:                                                                MAX_ALGO_SZ + TRAILING_ZERO);
        !           173:                ret = wc_Ed448PublicKeyToDer(&key->ed448, encoding->ptr,
        !           174:                                                                           encoding->len, 1);
        !           175: #endif
        !           176:        }
1.1       misho     177:        if (ret < 0)
                    178:        {
                    179:                return FALSE;
                    180:        }
                    181:        encoding->len = ret;
                    182:        return TRUE;
                    183: }
                    184: 
                    185: /**
1.1.1.2 ! misho     186:  * Export the raw public key of the given key, also used in ed private key.
        !           187:  */
        !           188: bool wolfssl_ed_public_key(wolfssl_ed_key *key, key_type_t type, chunk_t *raw)
        !           189: {
        !           190:        word32 len;
        !           191: 
        !           192:        *raw = chunk_empty;
        !           193:        if (type == KEY_ED25519)
        !           194:        {
        !           195: #ifdef HAVE_ED25519
        !           196:                len = ED25519_PUB_KEY_SIZE;
        !           197:                *raw = chunk_alloc(len);
        !           198:                if (wc_ed25519_export_public(&key->ed25519, raw->ptr, &len) != 0)
        !           199:                {
        !           200:                        chunk_free(raw);
        !           201:                        return FALSE;
        !           202:                }
        !           203: #endif
        !           204:        }
        !           205:        else if (type == KEY_ED448)
        !           206:        {
        !           207: #ifdef HAVE_ED448
        !           208:                len = ED448_PUB_KEY_SIZE;
        !           209:                *raw = chunk_alloc(len);
        !           210:                if (wc_ed448_export_public(&key->ed448, raw->ptr, &len) != 0)
        !           211:                {
        !           212:                        chunk_free(raw);
        !           213:                        return FALSE;
        !           214:                }
        !           215: #endif
        !           216:        }
        !           217:        return TRUE;
        !           218: }
        !           219: 
        !           220: /**
1.1       misho     221:  * Calculate fingerprint from an EdDSA key, also used in ed private key.
                    222:  */
1.1.1.2 ! misho     223: bool wolfssl_ed_fingerprint(wolfssl_ed_key *key, key_type_t key_type,
        !           224:                                                        cred_encoding_type_t type, chunk_t *fp)
1.1       misho     225: {
                    226:        hasher_t *hasher;
                    227:        chunk_t blob;
                    228:        bool success = FALSE;
                    229: 
                    230:        if (lib->encoding->get_cache(lib->encoding, type, key, fp))
                    231:        {
                    232:                return TRUE;
                    233:        }
                    234:        switch (type)
                    235:        {
                    236:                case KEYID_PUBKEY_SHA1:
1.1.1.2 ! misho     237:                        if (!wolfssl_ed_public_key(key, key_type, &blob))
1.1       misho     238:                        {
                    239:                                return FALSE;
                    240:                        }
                    241:                        break;
                    242:                case KEYID_PUBKEY_INFO_SHA1:
1.1.1.2 ! misho     243:                        if (!encode_pubkey(key, key_type, &blob))
1.1       misho     244:                        {
                    245:                                return FALSE;
                    246:                        }
                    247:                        break;
                    248:                default:
                    249:                        return FALSE;
                    250:        }
                    251:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
                    252:        if (!hasher || !hasher->allocate_hash(hasher, blob, fp))
                    253:        {
                    254:                DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
                    255:        }
                    256:        else
                    257:        {
                    258:                lib->encoding->cache(lib->encoding, type, key, *fp);
                    259:                success = TRUE;
                    260:        }
                    261:        DESTROY_IF(hasher);
                    262:        chunk_free(&blob);
                    263:        return success;
                    264: }
                    265: 
                    266: METHOD(public_key_t, get_fingerprint, bool,
                    267:        private_public_key_t *this, cred_encoding_type_t type, chunk_t *fingerprint)
                    268: {
1.1.1.2 ! misho     269:        return wolfssl_ed_fingerprint(&this->key, this->type, type, fingerprint);
1.1       misho     270: }
                    271: 
                    272: METHOD(public_key_t, get_encoding, bool,
                    273:        private_public_key_t *this, cred_encoding_type_t type, chunk_t *encoding)
                    274: {
                    275:        bool success = TRUE;
                    276: 
1.1.1.2 ! misho     277:        if (!encode_pubkey(&this->key, this->type, encoding))
1.1       misho     278:        {
                    279:                return FALSE;
                    280:        }
                    281: 
                    282:        if (type != PUBKEY_SPKI_ASN1_DER)
                    283:        {
                    284:                chunk_t asn1_encoding = *encoding;
                    285: 
                    286:                success = lib->encoding->encode(lib->encoding, type,
                    287:                                                                NULL, encoding, CRED_PART_EDDSA_PUB_ASN1_DER,
                    288:                                                                asn1_encoding, CRED_PART_END);
                    289:                chunk_free(&asn1_encoding);
                    290:        }
                    291:        return success;
                    292: }
                    293: 
                    294: METHOD(public_key_t, get_ref, public_key_t*,
                    295:        private_public_key_t *this)
                    296: {
                    297:        ref_get(&this->ref);
                    298:        return &this->public;
                    299: }
                    300: 
1.1.1.2 ! misho     301: /**
        !           302:  * Destroy an EdDSA key of the given type, also used by ed private key.
        !           303:  */
        !           304: void wolfssl_ed_destroy(wolfssl_ed_key *key, key_type_t type)
        !           305: {
        !           306:        if (type == KEY_ED25519)
        !           307:        {
        !           308: #ifdef HAVE_ED25519
        !           309:                wc_ed25519_free(&key->ed25519);
        !           310: #endif
        !           311:        }
        !           312:        else if (type == KEY_ED448)
        !           313:        {
        !           314: #ifdef HAVE_ED448
        !           315:                wc_ed448_free(&key->ed448);
        !           316: #endif
        !           317:        }
        !           318: }
        !           319: 
1.1       misho     320: METHOD(public_key_t, destroy, void,
                    321:        private_public_key_t *this)
                    322: {
                    323:        if (ref_put(&this->ref))
                    324:        {
                    325:                lib->encoding->clear_cache(lib->encoding, &this->key);
1.1.1.2 ! misho     326:                wolfssl_ed_destroy(&this->key, this->type);
1.1       misho     327:                free(this);
                    328:        }
                    329: }
                    330: 
                    331: /**
1.1.1.2 ! misho     332:  * Initialized an EdDSA key of the given type, also used by ed private key.
        !           333:  */
        !           334: bool wolfssl_ed_create(wolfssl_ed_key *key, key_type_t type)
        !           335: {
        !           336:        if (type == KEY_ED25519)
        !           337:        {
        !           338: #ifdef HAVE_ED25519
        !           339:                if (wc_ed25519_init(&key->ed25519) != 0)
        !           340:                {
        !           341:                        return FALSE;
        !           342:                }
        !           343: #endif
        !           344:        }
        !           345:        else if (type == KEY_ED448)
        !           346:        {
        !           347: #ifdef HAVE_ED448
        !           348:                if (wc_ed448_init(&key->ed448) != 0)
        !           349:                {
        !           350:                        return FALSE;
        !           351:                }
        !           352: #endif
        !           353:        }
        !           354:        else
        !           355:        {
        !           356:                return FALSE;
        !           357:        }
        !           358:        return TRUE;
        !           359: }
        !           360: 
        !           361: /**
1.1       misho     362:  * Generic private constructor
                    363:  */
1.1.1.2 ! misho     364: static private_public_key_t *create_empty(key_type_t type)
1.1       misho     365: {
                    366:        private_public_key_t *this;
                    367: 
                    368:        INIT(this,
                    369:                .public = {
                    370:                        .get_type = _get_type,
                    371:                        .verify = _verify,
                    372:                        .encrypt = _encrypt,
                    373:                        .get_keysize = _get_keysize,
                    374:                        .equals = public_key_equals,
                    375:                        .get_fingerprint = _get_fingerprint,
                    376:                        .has_fingerprint = public_key_has_fingerprint,
                    377:                        .get_encoding = _get_encoding,
                    378:                        .get_ref = _get_ref,
                    379:                        .destroy = _destroy,
                    380:                },
1.1.1.2 ! misho     381:                .type = type,
1.1       misho     382:                .ref = 1,
                    383:        );
                    384: 
1.1.1.2 ! misho     385:        if (!wolfssl_ed_create(&this->key, type))
1.1       misho     386:        {
                    387:                free(this);
1.1.1.2 ! misho     388:                this = NULL;
1.1       misho     389:        }
                    390:        return this;
                    391: }
                    392: 
                    393: /*
                    394:  * Described in header
                    395:  */
                    396: public_key_t *wolfssl_ed_public_key_load(key_type_t type, va_list args)
                    397: {
                    398:        private_public_key_t *this;
                    399:        chunk_t blob = chunk_empty, pub = chunk_empty;
                    400:        int idx;
                    401:        int ret = -1;
                    402: 
                    403:        while (TRUE)
                    404:        {
                    405:                switch (va_arg(args, builder_part_t))
                    406:                {
                    407:                        case BUILD_BLOB_ASN1_DER:
                    408:                                blob = va_arg(args, chunk_t);
                    409:                                continue;
                    410:                        case BUILD_EDDSA_PUB:
                    411:                                pub = va_arg(args, chunk_t);
                    412:                                continue;
                    413:                        case BUILD_END:
                    414:                                break;
                    415:                        default:
                    416:                                return NULL;
                    417:                }
                    418:                break;
                    419:        }
                    420: 
1.1.1.2 ! misho     421:        this = create_empty(type);
1.1       misho     422:        if (!this)
                    423:        {
                    424:                return NULL;
                    425:        }
                    426: 
1.1.1.2 ! misho     427:        if (type == KEY_ED25519)
1.1       misho     428:        {
1.1.1.2 ! misho     429: #ifdef HAVE_ED25519
        !           430:                if (pub.len)
        !           431:                {
        !           432:                        ret = wc_ed25519_import_public(pub.ptr, pub.len,
        !           433:                                                                                   &this->key.ed25519);
        !           434:                }
        !           435:                else if (blob.len)
        !           436:                {
        !           437:                        idx = 0;
        !           438:                        ret = wc_Ed25519PublicKeyDecode(blob.ptr, &idx, &this->key.ed25519,
        !           439:                                                                                        blob.len);
        !           440:                }
        !           441: #endif
1.1       misho     442:        }
1.1.1.2 ! misho     443:        else if (type == KEY_ED448)
1.1       misho     444:        {
1.1.1.2 ! misho     445: #ifdef HAVE_ED448
        !           446:                if (pub.len)
        !           447:                {
        !           448:                        ret = wc_ed448_import_public(pub.ptr, pub.len, &this->key.ed448);
        !           449:                }
        !           450:                else if (blob.len)
        !           451:                {
        !           452:                        idx = 0;
        !           453:                        ret = wc_Ed448PublicKeyDecode(blob.ptr, &idx, &this->key.ed448,
        !           454:                                                                                  blob.len);
        !           455:                }
        !           456: #endif
1.1       misho     457:        }
1.1.1.2 ! misho     458: 
1.1       misho     459:        if (ret != 0)
                    460:        {
                    461:                destroy(this);
                    462:                return NULL;
                    463:        }
                    464:        return &this->public;
                    465: }
                    466: 
                    467: #endif /* HAVE_ED25519 */

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