2 * Copyright (C) 2013 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
17 #include "ntru_plugin.h"
19 #include "ntru_crypto/ntru_crypto.h"
21 #include <crypto/diffie_hellman.h>
22 #include <utils/debug.h>
24 typedef struct private_ntru_ke_t private_ntru_ke_t
;
25 typedef struct param_set_t param_set_t
;
28 * Defines an NTRU parameter set by ID or OID
31 NTRU_ENCRYPT_PARAM_SET_ID id
;
36 /* Best bandwidth and speed, no X9.98 compatibility */
37 static param_set_t param_sets_optimum
[] = {
38 { NTRU_EES401EP2
, {0x00, 0x02, 0x10}, "ees401ep2" },
39 { NTRU_EES439EP1
, {0x00, 0x03, 0x10}, "ees439ep1" },
40 { NTRU_EES593EP1
, {0x00, 0x05, 0x10}, "ees593ep1" },
41 { NTRU_EES743EP1
, {0x00, 0x06, 0x10}, "ees743ep1" }
44 /* X9.98/IEEE 1363.1 parameter sets for best speed */
45 static param_set_t param_sets_x9_98_speed
[] = {
46 { NTRU_EES659EP1
, {0x00, 0x02, 0x06}, "ees659ep1" },
47 { NTRU_EES761EP1
, {0x00, 0x03, 0x05}, "ees761ep1" },
48 { NTRU_EES1087EP1
, {0x00, 0x05, 0x05}, "ees1087ep1" },
49 { NTRU_EES1499EP1
, {0x00, 0x06, 0x05}, "ees1499ep1" }
52 /* X9.98/IEEE 1363.1 parameter sets for best bandwidth (smallest size) */
53 static param_set_t param_sets_x9_98_bandwidth
[] = {
54 { NTRU_EES401EP1
, {0x00, 0x02, 0x04}, "ees401ep1" },
55 { NTRU_EES449EP1
, {0x00, 0x03, 0x03}, "ees449ep1" },
56 { NTRU_EES677EP1
, {0x00, 0x05, 0x03}, "ees677ep1" },
57 { NTRU_EES1087EP2
, {0x00, 0x06, 0x03}, "ees1087ep2" }
60 /* X9.98/IEEE 1363.1 parameter sets balancing speed and bandwidth */
61 static param_set_t param_sets_x9_98_balance
[] = {
62 { NTRU_EES541EP1
, {0x00, 0x02, 0x05}, "ees541ep1" },
63 { NTRU_EES613EP1
, {0x00, 0x03, 0x04}, "ees613ep1" },
64 { NTRU_EES887EP1
, {0x00, 0x05, 0x04}, "ees887ep1" },
65 { NTRU_EES1171EP1
, {0x00, 0x06, 0x04}, "ees1171ep1" }
69 * Private data of an ntru_ke_t object.
71 struct private_ntru_ke_t
{
73 * Public ntru_ke_t interface.
78 * Diffie Hellman group number.
85 param_set_t
*param_set
;
88 * Cryptographical strength in bits of the NTRU Parameter Set
103 * NTRU encrypted shared secret
110 chunk_t shared_secret
;
113 * True if peer is responder
118 * True if shared secret is computed
123 * Deterministic Random Bit Generator
128 METHOD(diffie_hellman_t
, get_my_public_value
, void,
129 private_ntru_ke_t
*this, chunk_t
*value
)
131 uint16_t pub_key_len
, priv_key_len
;
133 *value
= chunk_empty
;
137 if (this->ciphertext
.len
)
139 *value
= chunk_clone(this->ciphertext
);
144 if (this->pub_key
.len
== 0)
146 /* determine the NTRU public and private key sizes */
147 if (ntru_crypto_ntru_encrypt_keygen(this->drbg
, this->param_set
->id
,
149 &priv_key_len
, NULL
) != NTRU_OK
)
151 DBG1(DBG_LIB
, "error determining NTRU public and private key "
155 this->pub_key
= chunk_alloc(pub_key_len
);
156 this->priv_key
= chunk_alloc(priv_key_len
);
158 /* generate a random NTRU public/private key pair */
159 if (ntru_crypto_ntru_encrypt_keygen(this->drbg
, this->param_set
->id
,
160 &pub_key_len
, this->pub_key
.ptr
,
161 &priv_key_len
, this->priv_key
.ptr
) != NTRU_OK
)
163 DBG1(DBG_LIB
, "NTRU keypair generation failed");
164 chunk_free(&this->priv_key
);
165 chunk_free(&this->pub_key
);
168 DBG3(DBG_LIB
, "NTRU public key: %B", &this->pub_key
);
169 DBG4(DBG_LIB
, "NTRU private key: %B", &this->priv_key
);
171 *value
= chunk_clone(this->pub_key
);
175 METHOD(diffie_hellman_t
, get_shared_secret
, status_t
,
176 private_ntru_ke_t
*this, chunk_t
*secret
)
178 if (!this->computed
|| !this->shared_secret
.len
)
182 *secret
= chunk_clone(this->shared_secret
);
188 METHOD(diffie_hellman_t
, set_other_public_value
, void,
189 private_ntru_ke_t
*this, chunk_t value
)
191 u_int16_t plaintext_len
, ciphertext_len
;
193 if (this->priv_key
.len
)
195 /* initiator decrypting shared secret */
196 this->ciphertext
= chunk_clone(value
);
197 DBG3(DBG_LIB
, "NTRU ciphertext: %B", &this->ciphertext
);
199 /* determine the size of the maximum plaintext */
200 if (ntru_crypto_ntru_decrypt(this->priv_key
.len
, this->priv_key
.ptr
,
201 this->ciphertext
.len
, this->ciphertext
.ptr
,
202 &plaintext_len
, NULL
) != NTRU_OK
)
204 DBG1(DBG_LIB
, "error determining maximum plaintext size");
207 this->shared_secret
= chunk_alloc(plaintext_len
);
209 /* decrypt the shared secret */
210 if (ntru_crypto_ntru_decrypt(this->priv_key
.len
, this->priv_key
.ptr
,
211 this->ciphertext
.len
, this->ciphertext
.ptr
,
212 &plaintext_len
, this->shared_secret
.ptr
) != NTRU_OK
)
214 DBG1(DBG_LIB
, "NTRU decryption of shared secret failed");
215 chunk_free(&this->shared_secret
);
218 this->shared_secret
.len
= plaintext_len
;
219 this->computed
= TRUE
;
223 /* responder generating and encrypting the shared secret */
224 this->responder
= TRUE
;
226 /* check the NTRU public key format */
227 if (value
.len
< 5 || value
.ptr
[0] != 1 || value
.ptr
[1] != 3)
229 DBG1(DBG_LIB
, "received NTRU public key with invalid header");
232 if (!memeq(value
.ptr
+ 2, this->param_set
->oid
, 3))
234 DBG1(DBG_LIB
, "received NTRU public key with wrong OID");
237 this->pub_key
= chunk_clone(value
);
239 /* shared secret size is chosen as twice the cryptographical strength */
240 this->shared_secret
= chunk_alloc(2 * this->strength
/ BITS_PER_BYTE
);
242 /* generate the random shared secret */
243 if (ntru_crypto_drbg_generate(this->drbg
, this->strength
,
244 this->shared_secret
.len
, this->shared_secret
.ptr
) != DRBG_OK
)
246 DBG1(DBG_LIB
, "generation of shared secret failed");
247 chunk_free(&this->shared_secret
);
250 this->computed
= TRUE
;
252 /* determine the size of the ciphertext */
253 if (ntru_crypto_ntru_encrypt(this->drbg
,
254 this->pub_key
.len
, this->pub_key
.ptr
,
255 this->shared_secret
.len
, this->shared_secret
.ptr
,
256 &ciphertext_len
, NULL
) != NTRU_OK
)
258 DBG1(DBG_LIB
, "error determining ciphertext size");
261 this->ciphertext
= chunk_alloc(ciphertext_len
);
263 /* encrypt the shared secret */
264 if (ntru_crypto_ntru_encrypt(this->drbg
,
265 this->pub_key
.len
, this->pub_key
.ptr
,
266 this->shared_secret
.len
, this->shared_secret
.ptr
,
267 &ciphertext_len
, this->ciphertext
.ptr
) != NTRU_OK
)
269 DBG1(DBG_LIB
, "NTRU encryption of shared secret failed");
270 chunk_free(&this->ciphertext
);
273 DBG3(DBG_LIB
, "NTRU ciphertext: %B", &this->ciphertext
);
277 METHOD(diffie_hellman_t
, get_dh_group
, diffie_hellman_group_t
,
278 private_ntru_ke_t
*this)
283 METHOD(diffie_hellman_t
, destroy
, void,
284 private_ntru_ke_t
*this)
286 if (ntru_crypto_drbg_uninstantiate(this->drbg
) != DRBG_OK
)
288 DBG1(DBG_LIB
, "error uninstantiating DRBG");
290 chunk_free(&this->pub_key
);
291 chunk_free(&this->ciphertext
);
292 chunk_clear(&this->priv_key
);
293 chunk_clear(&this->shared_secret
);
298 * Described in header.
300 ntru_ke_t
*ntru_ke_create(diffie_hellman_group_t group
, chunk_t g
, chunk_t p
)
302 private_ntru_ke_t
*this;
303 char personalization_str
[] = "strongSwan NTRU-KE";
304 param_set_t
*param_sets
, *param_set
;
309 parameter_set
= lib
->settings
->get_str(lib
->settings
,
310 "libstrongswan.plugins.ntru.parameter_set", "optimum");
312 if (streq(parameter_set
, "x9_98_speed"))
314 param_sets
= param_sets_x9_98_speed
;
316 else if (streq(parameter_set
, "x9_98_bandwidth"))
318 param_sets
= param_sets_x9_98_bandwidth
;
320 else if (streq(parameter_set
, "x9_98_balance"))
322 param_sets
= param_sets_x9_98_balance
;
326 param_sets
= param_sets_optimum
;
333 param_set
= ¶m_sets
[0];
337 param_set
= ¶m_sets
[1];
341 param_set
= ¶m_sets
[2];
345 param_set
= ¶m_sets
[3];
350 DBG1(DBG_LIB
, "%u bit %s NTRU parameter set %s selected", strength
,
351 parameter_set
, param_set
->name
);
353 if (ntru_crypto_drbg_instantiate(strength
,
354 personalization_str
, strlen(personalization_str
),
355 (ENTROPY_FN
) &ntru_plugin_get_entropy
, &drbg
) != DRBG_OK
)
357 DBG1(DBG_LIB
, "error instantiating DRBG at %u bit security", strength
);
364 .get_shared_secret
= _get_shared_secret
,
365 .set_other_public_value
= _set_other_public_value
,
366 .get_my_public_value
= _get_my_public_value
,
367 .get_dh_group
= _get_dh_group
,
372 .param_set
= param_set
,
373 .strength
= strength
,
377 return &this->public;