Annotation of embedaddon/strongswan/src/libstrongswan/plugins/ntru/ntru_ke.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2013-2014 Andreas Steffen
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "ntru_ke.h"
        !            17: #include "ntru_param_set.h"
        !            18: #include "ntru_private_key.h"
        !            19: #include "ntru_public_key.h"
        !            20: 
        !            21: #include <crypto/diffie_hellman.h>
        !            22: #include <crypto/drbgs/drbg.h>
        !            23: #include <utils/debug.h>
        !            24: 
        !            25: typedef struct private_ntru_ke_t private_ntru_ke_t;
        !            26: 
        !            27: /* Best bandwidth and speed, no X9.98 compatibility */
        !            28: static const ntru_param_set_id_t param_sets_optimum[] = {
        !            29:        NTRU_EES401EP2, NTRU_EES439EP1, NTRU_EES593EP1, NTRU_EES743EP1
        !            30: };
        !            31: 
        !            32: /* X9.98/IEEE 1363.1 parameter sets for best speed */
        !            33: static const ntru_param_set_id_t param_sets_x9_98_speed[] = {
        !            34:        NTRU_EES659EP1, NTRU_EES761EP1, NTRU_EES1087EP1, NTRU_EES1499EP1
        !            35: };
        !            36: 
        !            37: /* X9.98/IEEE 1363.1 parameter sets for best bandwidth (smallest size) */
        !            38: static const ntru_param_set_id_t param_sets_x9_98_bandwidth[] = {
        !            39:        NTRU_EES401EP1, NTRU_EES449EP1, NTRU_EES677EP1, NTRU_EES1087EP2
        !            40: };
        !            41: 
        !            42: /* X9.98/IEEE 1363.1 parameter sets balancing speed and bandwidth */
        !            43: static const ntru_param_set_id_t param_sets_x9_98_balance[] = {
        !            44:        NTRU_EES541EP1, NTRU_EES613EP1, NTRU_EES887EP1, NTRU_EES1171EP1
        !            45: };
        !            46: 
        !            47: /**
        !            48:  * Private data of an ntru_ke_t object.
        !            49:  */
        !            50: struct private_ntru_ke_t {
        !            51:        /**
        !            52:         * Public ntru_ke_t interface.
        !            53:         */
        !            54:        ntru_ke_t public;
        !            55: 
        !            56:        /**
        !            57:         * Diffie Hellman group number.
        !            58:         */
        !            59:        diffie_hellman_group_t group;
        !            60: 
        !            61:        /**
        !            62:         * NTRU Parameter Set
        !            63:         */
        !            64:        const ntru_param_set_t *param_set;
        !            65: 
        !            66:        /**
        !            67:         * Cryptographical strength in bits of the NTRU Parameter Set
        !            68:         */
        !            69:        uint32_t strength;
        !            70: 
        !            71:        /**
        !            72:         * NTRU Public Key
        !            73:         */
        !            74:        ntru_public_key_t *pubkey;
        !            75: 
        !            76:        /**
        !            77:         * NTRU Private Key
        !            78:         */
        !            79:        ntru_private_key_t *privkey;
        !            80: 
        !            81:        /**
        !            82:         * NTRU encrypted shared secret
        !            83:         */
        !            84:        chunk_t ciphertext;
        !            85: 
        !            86:        /**
        !            87:         * Shared secret
        !            88:         */
        !            89:        chunk_t shared_secret;
        !            90: 
        !            91:        /**
        !            92:         * True if peer is responder
        !            93:         */
        !            94:        bool responder;
        !            95: 
        !            96:        /**
        !            97:         * True if shared secret is computed
        !            98:         */
        !            99:        bool computed;
        !           100: 
        !           101:        /**
        !           102:         * True Random Generator
        !           103:         */
        !           104:        rng_t *entropy;
        !           105: 
        !           106:        /**
        !           107:         * Deterministic Random Bit Generator
        !           108:         */
        !           109:        drbg_t *drbg;
        !           110: };
        !           111: 
        !           112: METHOD(diffie_hellman_t, get_my_public_value, bool,
        !           113:        private_ntru_ke_t *this, chunk_t *value)
        !           114: {
        !           115:        *value = chunk_empty;
        !           116: 
        !           117:        if (this->responder)
        !           118:        {
        !           119:                if (this->ciphertext.len)
        !           120:                {
        !           121:                        *value = chunk_clone(this->ciphertext);
        !           122:                }
        !           123:        }
        !           124:        else
        !           125:        {
        !           126:                if (!this->pubkey)
        !           127:                {
        !           128:                        /* generate a random NTRU public/private key pair */
        !           129:                        this->privkey = ntru_private_key_create(this->drbg, this->param_set);
        !           130:                        if (!this->privkey)
        !           131:                        {
        !           132:                                DBG1(DBG_LIB, "NTRU key pair generation failed");
        !           133:                                return FALSE;
        !           134:                        }
        !           135:                        this->pubkey = this->privkey->get_public_key(this->privkey);
        !           136:                }
        !           137:                *value = chunk_clone(this->pubkey->get_encoding(this->pubkey));
        !           138:                DBG3(DBG_LIB, "NTRU public key: %B", value);
        !           139:        }
        !           140:        return TRUE;
        !           141: }
        !           142: 
        !           143: METHOD(diffie_hellman_t, get_shared_secret, bool,
        !           144:        private_ntru_ke_t *this, chunk_t *secret)
        !           145: {
        !           146:        if (!this->computed || !this->shared_secret.len)
        !           147:        {
        !           148:                *secret = chunk_empty;
        !           149:                return FALSE;
        !           150:        }
        !           151:        *secret = chunk_clone(this->shared_secret);
        !           152: 
        !           153:        return TRUE;
        !           154: }
        !           155: 
        !           156: METHOD(diffie_hellman_t, set_other_public_value, bool,
        !           157:        private_ntru_ke_t *this, chunk_t value)
        !           158: {
        !           159:        if (this->privkey)
        !           160:        {
        !           161:                /* initiator decrypting shared secret */
        !           162:                if (value.len == 0)
        !           163:                {
        !           164:                        DBG1(DBG_LIB, "empty NTRU ciphertext");
        !           165:                        return FALSE;
        !           166:                }
        !           167:                DBG3(DBG_LIB, "NTRU ciphertext: %B", &value);
        !           168: 
        !           169:                /* decrypt the shared secret */
        !           170:                if (!this->privkey->decrypt(this->privkey, value, &this->shared_secret))
        !           171:                {
        !           172:                        DBG1(DBG_LIB, "NTRU decryption of shared secret failed");
        !           173:                        return FALSE;
        !           174:                }
        !           175:                this->computed = TRUE;
        !           176:        }
        !           177:        else
        !           178:        {
        !           179:                ntru_public_key_t *pubkey;
        !           180: 
        !           181:                /* responder generating and encrypting the shared secret */
        !           182:                this->responder = TRUE;
        !           183: 
        !           184:                DBG3(DBG_LIB, "NTRU public key: %B", &value);
        !           185:                pubkey = ntru_public_key_create_from_data(this->drbg, value);
        !           186:                if (!pubkey)
        !           187:                {
        !           188:                        return FALSE;
        !           189:                }
        !           190:                if (pubkey->get_id(pubkey) != this->param_set->id)
        !           191:                {
        !           192:                        DBG1(DBG_LIB, "received NTRU public key with wrong OUI");
        !           193:                        pubkey->destroy(pubkey);
        !           194:                        return FALSE;
        !           195:                }
        !           196:                this->pubkey = pubkey;
        !           197: 
        !           198:                /* shared secret size is chosen as twice the cryptographical strength */
        !           199:                this->shared_secret = chunk_alloc(2 * this->strength / BITS_PER_BYTE);
        !           200: 
        !           201:                /* generate the random shared secret */
        !           202:                if (!this->drbg->generate(this->drbg, this->shared_secret.len,
        !           203:                                                                                          this->shared_secret.ptr))
        !           204:                {
        !           205:                        DBG1(DBG_LIB, "generation of shared secret failed");
        !           206:                        chunk_free(&this->shared_secret);
        !           207:                        return FALSE;
        !           208:                }
        !           209:                this->computed = TRUE;
        !           210: 
        !           211:                /* encrypt the shared secret */
        !           212:                if (!pubkey->encrypt(pubkey, this->shared_secret, &this->ciphertext))
        !           213:                {
        !           214:                        DBG1(DBG_LIB, "NTRU encryption of shared secret failed");
        !           215:                        return FALSE;
        !           216:                }
        !           217:                DBG3(DBG_LIB, "NTRU ciphertext: %B", &this->ciphertext);
        !           218:        }
        !           219:        return this->computed;
        !           220: }
        !           221: 
        !           222: METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
        !           223:        private_ntru_ke_t *this)
        !           224: {
        !           225:        return this->group;
        !           226: }
        !           227: 
        !           228: METHOD(diffie_hellman_t, destroy, void,
        !           229:        private_ntru_ke_t *this)
        !           230: {
        !           231:        DESTROY_IF(this->privkey);
        !           232:        DESTROY_IF(this->pubkey);
        !           233:        this->drbg->destroy(this->drbg);
        !           234:        chunk_free(&this->ciphertext);
        !           235:        chunk_clear(&this->shared_secret);
        !           236:        free(this);
        !           237: }
        !           238: 
        !           239: /*
        !           240:  * Described in header.
        !           241:  */
        !           242: ntru_ke_t *ntru_ke_create(diffie_hellman_group_t group, chunk_t g, chunk_t p)
        !           243: {
        !           244:        private_ntru_ke_t *this;
        !           245:        const ntru_param_set_id_t *param_sets;
        !           246:        ntru_param_set_id_t param_set_id;
        !           247:        rng_t *entropy;
        !           248:        drbg_t *drbg;
        !           249:        char *parameter_set;
        !           250:        uint32_t strength;
        !           251: 
        !           252:        parameter_set = lib->settings->get_str(lib->settings,
        !           253:                                                "%s.plugins.ntru.parameter_set", "optimum", lib->ns);
        !           254: 
        !           255:        if (streq(parameter_set, "x9_98_speed"))
        !           256:        {
        !           257:                param_sets = param_sets_x9_98_speed;
        !           258:        }
        !           259:        else if (streq(parameter_set, "x9_98_bandwidth"))
        !           260:        {
        !           261:                param_sets = param_sets_x9_98_bandwidth;
        !           262:        }
        !           263:        else if (streq(parameter_set, "x9_98_balance"))
        !           264:        {
        !           265:                param_sets = param_sets_x9_98_balance;
        !           266:        }
        !           267:        else
        !           268:        {
        !           269:                param_sets = param_sets_optimum;
        !           270:        }
        !           271: 
        !           272:        switch (group)
        !           273:        {
        !           274:                case NTRU_112_BIT:
        !           275:                        strength = 112;
        !           276:                        param_set_id = param_sets[0];
        !           277:                        break;
        !           278:                case NTRU_128_BIT:
        !           279:                        strength = 128;
        !           280:                        param_set_id = param_sets[1];
        !           281:                        break;
        !           282:                case NTRU_192_BIT:
        !           283:                        strength = 192;
        !           284:                        param_set_id = param_sets[2];
        !           285:                        break;
        !           286:                case NTRU_256_BIT:
        !           287:                        strength = 256;
        !           288:                        param_set_id = param_sets[3];
        !           289:                        break;
        !           290:                default:
        !           291:                        return NULL;
        !           292:        }
        !           293:        DBG1(DBG_LIB, "%u bit %s NTRU parameter set %N selected", strength,
        !           294:                                   parameter_set, ntru_param_set_id_names, param_set_id);
        !           295: 
        !           296:        /* entropy will be owned by drbg */
        !           297:        entropy = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
        !           298:        if (!entropy)
        !           299:        {
        !           300:                DBG1(DBG_LIB, "could not attach entropy source for DRBG");
        !           301:                return NULL;
        !           302:        }
        !           303: 
        !           304:        drbg = lib->crypto->create_drbg(lib->crypto, DRBG_HMAC_SHA256, strength,
        !           305:                                                                        entropy, chunk_from_str("IKE NTRU-KE"));
        !           306:        if (!drbg)
        !           307:        {
        !           308:                DBG1(DBG_LIB, "could not instantiate DRBG at %u bit security", strength);
        !           309:                entropy->destroy(entropy);
        !           310:                return NULL;
        !           311:        }
        !           312: 
        !           313:        INIT(this,
        !           314:                .public = {
        !           315:                        .dh = {
        !           316:                                .get_shared_secret = _get_shared_secret,
        !           317:                                .set_other_public_value = _set_other_public_value,
        !           318:                                .get_my_public_value = _get_my_public_value,
        !           319:                                .get_dh_group = _get_dh_group,
        !           320:                                .destroy = _destroy,
        !           321:                        },
        !           322:                },
        !           323:                .group = group,
        !           324:                .param_set = ntru_param_set_get_by_id(param_set_id),
        !           325:                .strength = strength,
        !           326:                .entropy = entropy,
        !           327:                .drbg = drbg,
        !           328:        );
        !           329: 
        !           330:        return &this->public;
        !           331: }

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