]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/plugins/ntru/ntru_ke.c
18f3b4cb476a8de640170232dd79801c68c7d9e2
[thirdparty/strongswan.git] / src / libstrongswan / plugins / ntru / ntru_ke.c
1 /*
2 * Copyright (C) 2013 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_plugin.h"
18
19 #include "ntru_crypto/ntru_crypto.h"
20
21 #include <crypto/diffie_hellman.h>
22 #include <utils/debug.h>
23
24 typedef struct private_ntru_ke_t private_ntru_ke_t;
25
26 /**
27 * Private data of an ntru_ke_t object.
28 */
29 struct private_ntru_ke_t {
30 /**
31 * Public ntru_ke_t interface.
32 */
33 ntru_ke_t public;
34
35 /**
36 * Diffie Hellman group number.
37 */
38 u_int16_t group;
39
40 /**
41 * NTRU Parameter Set ID
42 */
43 NTRU_ENCRYPT_PARAM_SET_ID param_set_id;
44
45 /**
46 * Cryptographical strength in bits of the NTRU Parameter Set
47 */
48 u_int32_t strength;
49
50 /**
51 * NTRU Public Key
52 */
53 chunk_t pub_key;
54
55 /**
56 * NTRU Private Key
57 */
58 chunk_t priv_key;
59
60 /**
61 * NTRU encrypted shared secret
62 */
63 chunk_t ciphertext;
64
65 /**
66 * Shared secret
67 */
68 chunk_t shared_secret;
69
70 /**
71 * True if peer is responder
72 */
73 bool responder;
74
75 /**
76 * True if shared secret is computed
77 */
78 bool computed;
79
80 /**
81 * Deterministic Random Bit Generator
82 */
83 DRBG_HANDLE drbg;
84 };
85
86 METHOD(diffie_hellman_t, get_my_public_value, void,
87 private_ntru_ke_t *this, chunk_t *value)
88 {
89 uint16_t pub_key_len, priv_key_len;
90
91 *value = chunk_empty;
92
93 if (this->responder)
94 {
95 if (this->ciphertext.len)
96 {
97 *value = chunk_clone(this->ciphertext);
98 }
99 }
100 else
101 {
102 if (this->pub_key.len == 0)
103 {
104 /* determine the NTRU public and private key sizes */
105 if (ntru_crypto_ntru_encrypt_keygen(this->drbg, this->param_set_id,
106 &pub_key_len, NULL,
107 &priv_key_len, NULL) != NTRU_OK)
108 {
109 DBG1(DBG_LIB, "error determining NTRU public and private key "
110 "sizes");
111 return;
112 }
113 this->pub_key = chunk_alloc(pub_key_len);
114 this->priv_key = chunk_alloc(priv_key_len);
115
116 /* generate a random NTRU public/private key pair */
117 if (ntru_crypto_ntru_encrypt_keygen(this->drbg, this->param_set_id,
118 &pub_key_len, this->pub_key.ptr,
119 &priv_key_len, this->priv_key.ptr) != NTRU_OK)
120 {
121 DBG1(DBG_LIB, "NTRU keypair generation failed");
122 chunk_free(&this->priv_key);
123 chunk_free(&this->pub_key);
124 return;
125 }
126 DBG3(DBG_LIB, "NTRU public key: %B", &this->pub_key);
127 DBG4(DBG_LIB, "NTRU private key: %B", &this->priv_key);
128 }
129 *value = chunk_clone(this->pub_key);
130 }
131 }
132
133 METHOD(diffie_hellman_t, get_shared_secret, status_t,
134 private_ntru_ke_t *this, chunk_t *secret)
135 {
136 if (!this->computed || !this->shared_secret.len)
137 {
138 return FAILED;
139 }
140 *secret = chunk_clone(this->shared_secret);
141
142 return SUCCESS;
143 }
144
145
146 METHOD(diffie_hellman_t, set_other_public_value, void,
147 private_ntru_ke_t *this, chunk_t value)
148 {
149 u_int16_t plaintext_len, ciphertext_len;
150
151 if (this->priv_key.len)
152 {
153 /* initiator decrypting shared secret */
154 this->ciphertext = chunk_clone(value);
155 DBG3(DBG_LIB, "NTRU ciphertext: %B", &this->ciphertext);
156
157 /* determine the size of the maximum plaintext */
158 if (ntru_crypto_ntru_decrypt(this->priv_key.len, this->priv_key.ptr,
159 this->ciphertext.len, this->ciphertext.ptr,
160 &plaintext_len, NULL) != NTRU_OK)
161 {
162 DBG1(DBG_LIB, "error determining maximum plaintext size");
163 return;
164 }
165 this->shared_secret = chunk_alloc(plaintext_len);
166
167 /* decrypt the shared secret */
168 if (ntru_crypto_ntru_decrypt(this->priv_key.len, this->priv_key.ptr,
169 this->ciphertext.len, this->ciphertext.ptr,
170 &plaintext_len, this->shared_secret.ptr) != NTRU_OK)
171 {
172 DBG1(DBG_LIB, "NTRU decryption of shared secret failed");
173 chunk_free(&this->shared_secret);
174 return;
175 }
176 this->shared_secret.len = plaintext_len;
177 this->computed = TRUE;
178 }
179 else
180 {
181 /* responder generating and encrypting the shared secret */
182 this->responder = TRUE;
183 this->pub_key = chunk_clone(value);
184
185 /* shared secret size is chosen as twice the cryptographical strength */
186 this->shared_secret = chunk_alloc(2 * this->strength / BITS_PER_BYTE);
187
188 /* generate the random shared secret */
189 if (ntru_crypto_drbg_generate(this->drbg, this->strength,
190 this->shared_secret.len, this->shared_secret.ptr) != DRBG_OK)
191 {
192 DBG1(DBG_LIB, "generation of shared secret failed");
193 chunk_free(&this->shared_secret);
194 return;
195 }
196
197 /* determine the size of the ciphertext */
198 if (ntru_crypto_ntru_encrypt(this->drbg,
199 this->pub_key.len, this->pub_key.ptr,
200 this->shared_secret.len, this->shared_secret.ptr,
201 &ciphertext_len, NULL) != NTRU_OK)
202 {
203 DBG1(DBG_LIB, "error determining ciphertext size");
204 return;
205 }
206 this->ciphertext = chunk_alloc(ciphertext_len);
207 this->computed = TRUE;
208
209 /* encrypt the shared secret */
210 if (ntru_crypto_ntru_encrypt(this->drbg,
211 this->pub_key.len, this->pub_key.ptr,
212 this->shared_secret.len, this->shared_secret.ptr,
213 &ciphertext_len, this->ciphertext.ptr) != NTRU_OK)
214 {
215 DBG1(DBG_LIB, "NTRU encryption of shared secret failed");
216 chunk_free(&this->ciphertext);
217 return;
218 }
219 DBG3(DBG_LIB, "NTRU ciphertext: %B", &this->ciphertext);
220 }
221 }
222
223 METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
224 private_ntru_ke_t *this)
225 {
226 return this->group;
227 }
228
229 METHOD(diffie_hellman_t, destroy, void,
230 private_ntru_ke_t *this)
231 {
232 if (ntru_crypto_drbg_uninstantiate(this->drbg) != DRBG_OK)
233 {
234 DBG1(DBG_LIB, "error uninstantiating DRBG");
235 }
236 chunk_free(&this->pub_key);
237 chunk_free(&this->ciphertext);
238 chunk_clear(&this->priv_key);
239 chunk_clear(&this->shared_secret);
240 free(this);
241 }
242
243 /*
244 * Described in header.
245 */
246 ntru_ke_t *ntru_ke_create(diffie_hellman_group_t group, chunk_t g, chunk_t p)
247 {
248 private_ntru_ke_t *this;
249 char personalization_str[] = "strongSwan NTRU-KE";
250 NTRU_ENCRYPT_PARAM_SET_ID param_set_id;
251 DRBG_HANDLE drbg;
252 u_int32_t strength;
253
254 /**
255 * We are selecting the X9.98 / IEEE 1363.1 parameter sets
256 * which balance speed and bandwidth
257 */
258 switch (group)
259 {
260 case NTRU_112_BIT:
261 strength = 112;
262 /* param_set_id = NTRU_EES541EP1; */
263 param_set_id = NTRU_EES401EP2;
264 break;
265 case NTRU_128_BIT:
266 strength = 128;
267 /* param_set_id = NTRU_EES613EP1; */
268 param_set_id = NTRU_EES439EP1;
269 break;
270 case NTRU_192_BIT:
271 strength = 192;
272 /* param_set_id = NTRU_EES887EP1; */
273 param_set_id = NTRU_EES593EP1;
274 break;
275 case NTRU_256_BIT:
276 strength = 256;
277 /* param_set_id = NTRU_EES1171EP1; */
278 param_set_id = NTRU_EES743EP1;
279 break;
280 default:
281 return NULL;
282 }
283
284 if (ntru_crypto_drbg_instantiate(strength,
285 personalization_str, strlen(personalization_str),
286 (ENTROPY_FN) &ntru_plugin_get_entropy, &drbg) != DRBG_OK)
287 {
288 DBG1(DBG_LIB, "error instantiating DRBG at %u bit security", strength);
289 return NULL;
290 }
291 else
292 {
293 DBG2(DBG_LIB, "instantiated DRBG at %u bit security", strength);
294 }
295
296 INIT(this,
297 .public = {
298 .dh = {
299 .get_shared_secret = _get_shared_secret,
300 .set_other_public_value = _set_other_public_value,
301 .get_my_public_value = _get_my_public_value,
302 .get_dh_group = _get_dh_group,
303 .destroy = _destroy,
304 },
305 },
306 .group = group,
307 .param_set_id = param_set_id,
308 .strength = strength,
309 .drbg = drbg,
310 );
311
312 return &this->public;
313 }
314