Return to ntru_ke.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / ntru |
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: }