Annotation of embedaddon/strongswan/src/libstrongswan/plugins/wolfssl/wolfssl_ed_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_ED25519
                     26: 
                     27: #include "wolfssl_ed_public_key.h"
                     28: 
                     29: #include <utils/debug.h>
                     30: #include <asn1/asn1.h>
                     31: 
                     32: #include <wolfssl/wolfcrypt/ed25519.h>
                     33: #include <wolfssl/wolfcrypt/asn.h>
                     34: 
                     35: typedef struct private_public_key_t private_public_key_t;
                     36: 
                     37: /**
                     38:  * Private data
                     39:  */
                     40: struct private_public_key_t {
                     41: 
                     42:        /**
                     43:         * Public interface
                     44:         */
                     45:        public_key_t public;
                     46: 
                     47:        /**
                     48:         * Key object
                     49:         */
                     50:        ed25519_key key;
                     51: 
                     52:        /**
                     53:         * Reference count
                     54:         */
                     55:        refcount_t ref;
                     56: };
                     57: 
                     58: METHOD(public_key_t, get_type, key_type_t,
                     59:        private_public_key_t *this)
                     60: {
                     61:        return KEY_ED25519;
                     62: }
                     63: 
                     64: METHOD(public_key_t, verify, bool,
                     65:        private_public_key_t *this, signature_scheme_t scheme,
                     66:        void *params, chunk_t data, chunk_t signature)
                     67: {
                     68:        byte dummy[1];
                     69:        int ret, res;
                     70: 
                     71:        if (scheme != SIGN_ED25519)
                     72:        {
                     73:                DBG1(DBG_LIB, "signature scheme %N not supported by %N key",
                     74:                         signature_scheme_names, scheme, key_type_names, KEY_ED25519);
                     75:                return FALSE;
                     76:        }
                     77: 
                     78:        if (!data.ptr && !data.len)
                     79:        {
                     80:                data.ptr = dummy;
                     81:        }
                     82: 
                     83:        ret = wc_ed25519_verify_msg(signature.ptr, signature.len, data.ptr,
                     84:                                                                data.len, &res, &this->key);
                     85:        return ret == 0 && res == 1;
                     86: }
                     87: 
                     88: METHOD(public_key_t, encrypt, bool,
                     89:        private_public_key_t *this, encryption_scheme_t scheme,
                     90:        chunk_t crypto, chunk_t *plain)
                     91: {
                     92:        DBG1(DBG_LIB, "encryption scheme %N not supported", encryption_scheme_names,
                     93:                 scheme);
                     94:        return FALSE;
                     95: }
                     96: 
                     97: METHOD(public_key_t, get_keysize, int,
                     98:        private_public_key_t *this)
                     99: {
                    100:        return ED25519_KEY_SIZE * 8;
                    101: }
                    102: 
                    103: /**
                    104:  * Encode the given public key as ASN.1 DER with algorithm identifier
                    105:  */
                    106: static bool encode_pubkey(ed25519_key *key, chunk_t *encoding)
                    107: {
                    108:        int ret;
                    109: 
                    110:        /* account for algorithmIdentifier/bitString */
                    111:        *encoding = chunk_alloc(ED25519_PUB_KEY_SIZE + 2 * MAX_SEQ_SZ +
                    112:                                                        MAX_ALGO_SZ + TRAILING_ZERO);
                    113:        ret = wc_Ed25519PublicKeyToDer(key, encoding->ptr, encoding->len, 1);
                    114:        if (ret < 0)
                    115:        {
                    116:                return FALSE;
                    117:        }
                    118:        encoding->len = ret;
                    119:        return TRUE;
                    120: }
                    121: 
                    122: /**
                    123:  * Calculate fingerprint from an EdDSA key, also used in ed private key.
                    124:  */
                    125: bool wolfssl_ed_fingerprint(ed25519_key *key, cred_encoding_type_t type,
                    126:                                                        chunk_t *fp)
                    127: {
                    128:        hasher_t *hasher;
                    129:        chunk_t blob;
                    130:        word32 len;
                    131:        bool success = FALSE;
                    132: 
                    133:        if (lib->encoding->get_cache(lib->encoding, type, key, fp))
                    134:        {
                    135:                return TRUE;
                    136:        }
                    137:        switch (type)
                    138:        {
                    139:                case KEYID_PUBKEY_SHA1:
                    140:                        len = ED25519_PUB_KEY_SIZE;
                    141:                        blob = chunk_alloc(len);
                    142:                        if (wc_ed25519_export_public(key, blob.ptr, &len) != 0)
                    143:                        {
                    144:                                return FALSE;
                    145:                        }
                    146:                        break;
                    147:                case KEYID_PUBKEY_INFO_SHA1:
                    148:                        if (!encode_pubkey(key, &blob))
                    149:                        {
                    150:                                return FALSE;
                    151:                        }
                    152:                        break;
                    153:                default:
                    154:                        return FALSE;
                    155:        }
                    156:        hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
                    157:        if (!hasher || !hasher->allocate_hash(hasher, blob, fp))
                    158:        {
                    159:                DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
                    160:        }
                    161:        else
                    162:        {
                    163:                lib->encoding->cache(lib->encoding, type, key, *fp);
                    164:                success = TRUE;
                    165:        }
                    166:        DESTROY_IF(hasher);
                    167:        chunk_free(&blob);
                    168:        return success;
                    169: }
                    170: 
                    171: METHOD(public_key_t, get_fingerprint, bool,
                    172:        private_public_key_t *this, cred_encoding_type_t type, chunk_t *fingerprint)
                    173: {
                    174:        return wolfssl_ed_fingerprint(&this->key, type, fingerprint);
                    175: }
                    176: 
                    177: METHOD(public_key_t, get_encoding, bool,
                    178:        private_public_key_t *this, cred_encoding_type_t type, chunk_t *encoding)
                    179: {
                    180:        bool success = TRUE;
                    181: 
                    182:        if (!encode_pubkey(&this->key, encoding))
                    183:        {
                    184:                return FALSE;
                    185:        }
                    186: 
                    187:        if (type != PUBKEY_SPKI_ASN1_DER)
                    188:        {
                    189:                chunk_t asn1_encoding = *encoding;
                    190: 
                    191:                success = lib->encoding->encode(lib->encoding, type,
                    192:                                                                NULL, encoding, CRED_PART_EDDSA_PUB_ASN1_DER,
                    193:                                                                asn1_encoding, CRED_PART_END);
                    194:                chunk_free(&asn1_encoding);
                    195:        }
                    196:        return success;
                    197: }
                    198: 
                    199: METHOD(public_key_t, get_ref, public_key_t*,
                    200:        private_public_key_t *this)
                    201: {
                    202:        ref_get(&this->ref);
                    203:        return &this->public;
                    204: }
                    205: 
                    206: METHOD(public_key_t, destroy, void,
                    207:        private_public_key_t *this)
                    208: {
                    209:        if (ref_put(&this->ref))
                    210:        {
                    211:                lib->encoding->clear_cache(lib->encoding, &this->key);
                    212:                wc_ed25519_free(&this->key);
                    213:                free(this);
                    214:        }
                    215: }
                    216: 
                    217: /**
                    218:  * Generic private constructor
                    219:  */
                    220: static private_public_key_t *create_empty()
                    221: {
                    222:        private_public_key_t *this;
                    223: 
                    224:        INIT(this,
                    225:                .public = {
                    226:                        .get_type = _get_type,
                    227:                        .verify = _verify,
                    228:                        .encrypt = _encrypt,
                    229:                        .get_keysize = _get_keysize,
                    230:                        .equals = public_key_equals,
                    231:                        .get_fingerprint = _get_fingerprint,
                    232:                        .has_fingerprint = public_key_has_fingerprint,
                    233:                        .get_encoding = _get_encoding,
                    234:                        .get_ref = _get_ref,
                    235:                        .destroy = _destroy,
                    236:                },
                    237:                .ref = 1,
                    238:        );
                    239: 
                    240:        if (wc_ed25519_init(&this->key) != 0)
                    241:        {
                    242:                free(this);
                    243:                return NULL;
                    244:        }
                    245:        return this;
                    246: }
                    247: 
                    248: /*
                    249:  * Described in header
                    250:  */
                    251: public_key_t *wolfssl_ed_public_key_load(key_type_t type, va_list args)
                    252: {
                    253:        private_public_key_t *this;
                    254:        chunk_t blob = chunk_empty, pub = chunk_empty;
                    255:        int idx;
                    256:        int ret = -1;
                    257: 
                    258:        while (TRUE)
                    259:        {
                    260:                switch (va_arg(args, builder_part_t))
                    261:                {
                    262:                        case BUILD_BLOB_ASN1_DER:
                    263:                                blob = va_arg(args, chunk_t);
                    264:                                continue;
                    265:                        case BUILD_EDDSA_PUB:
                    266:                                pub = va_arg(args, chunk_t);
                    267:                                continue;
                    268:                        case BUILD_END:
                    269:                                break;
                    270:                        default:
                    271:                                return NULL;
                    272:                }
                    273:                break;
                    274:        }
                    275: 
                    276:        this = create_empty();
                    277:        if (!this)
                    278:        {
                    279:                return NULL;
                    280:        }
                    281: 
                    282:        if (pub.len)
                    283:        {
                    284:                ret = wc_ed25519_import_public(pub.ptr, pub.len, &this->key);
                    285:        }
                    286:        else if (blob.len)
                    287:        {
                    288:                idx = 0;
                    289:                ret = wc_Ed25519PublicKeyDecode(blob.ptr, &idx, &this->key, blob.len);
                    290:        }
                    291:        if (ret != 0)
                    292:        {
                    293:                destroy(this);
                    294:                return NULL;
                    295:        }
                    296:        return &this->public;
                    297: }
                    298: 
                    299: #endif /* HAVE_ED25519 */

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