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