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>