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>