Annotation of embedaddon/strongswan/src/libstrongswan/plugins/ntru/ntru_ke.c, revision 1.1.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>