2 * Copyright (C) 2013-2014 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_drbg.h"
18 #include "ntru_param_set.h"
19 #include "ntru_private_key.h"
20 #include "ntru_public_key.h"
22 #include "ntru_crypto/ntru_crypto.h"
24 #include <crypto/diffie_hellman.h>
25 #include <utils/debug.h>
27 typedef struct private_ntru_ke_t private_ntru_ke_t
;
29 /* Best bandwidth and speed, no X9.98 compatibility */
30 static ntru_param_set_id_t param_sets_optimum
[] = {
31 NTRU_EES401EP2
, NTRU_EES439EP1
, NTRU_EES593EP1
, NTRU_EES743EP1
34 /* X9.98/IEEE 1363.1 parameter sets for best speed */
35 static ntru_param_set_id_t param_sets_x9_98_speed
[] = {
36 NTRU_EES659EP1
, NTRU_EES761EP1
, NTRU_EES1087EP1
, NTRU_EES1499EP1
39 /* X9.98/IEEE 1363.1 parameter sets for best bandwidth (smallest size) */
40 static ntru_param_set_id_t param_sets_x9_98_bandwidth
[] = {
41 NTRU_EES401EP1
, NTRU_EES449EP1
, NTRU_EES677EP1
, NTRU_EES1087EP2
44 /* X9.98/IEEE 1363.1 parameter sets balancing speed and bandwidth */
45 static ntru_param_set_id_t param_sets_x9_98_balance
[] = {
46 NTRU_EES541EP1
, NTRU_EES613EP1
, NTRU_EES887EP1
, NTRU_EES1171EP1
50 * Private data of an ntru_ke_t object.
52 struct private_ntru_ke_t
{
54 * Public ntru_ke_t interface.
59 * Diffie Hellman group number.
66 ntru_param_set_t
*param_set
;
69 * Cryptographical strength in bits of the NTRU Parameter Set
76 ntru_public_key_t
*pubkey
;
81 ntru_private_key_t
*privkey
;
84 * NTRU Public Key Encoding
89 * NTRU encrypted shared secret
96 chunk_t shared_secret
;
99 * True if peer is responder
104 * True if shared secret is computed
109 * True Random Generator
114 * Deterministic Random Bit Generator
119 METHOD(diffie_hellman_t
, get_my_public_value
, void,
120 private_ntru_ke_t
*this, chunk_t
*value
)
122 *value
= chunk_empty
;
126 if (this->ciphertext
.len
)
128 *value
= chunk_clone(this->ciphertext
);
135 /* generate a random NTRU public/private key pair */
136 this->privkey
= ntru_private_key_create(this->drbg
, this->param_set
);
139 DBG1(DBG_LIB
, "NTRU keypair generation failed");
142 this->pubkey
= this->privkey
->get_public_key(this->privkey
);
143 this->pubkey_enc
= this->pubkey
->get_encoding(this->pubkey
);
144 this->pubkey_enc
= chunk_clone(this->pubkey_enc
);
145 DBG3(DBG_LIB
, "NTRU public key: %B", &this->pubkey_enc
);
147 *value
= chunk_clone(this->pubkey_enc
);
151 METHOD(diffie_hellman_t
, get_shared_secret
, status_t
,
152 private_ntru_ke_t
*this, chunk_t
*secret
)
154 if (!this->computed
|| !this->shared_secret
.len
)
156 *secret
= chunk_empty
;
159 *secret
= chunk_clone(this->shared_secret
);
165 METHOD(diffie_hellman_t
, set_other_public_value
, void,
166 private_ntru_ke_t
*this, chunk_t value
)
168 u_int16_t ciphertext_len
;
172 /* initiator decrypting shared secret */
175 DBG1(DBG_LIB
, "empty NTRU ciphertext");
178 DBG3(DBG_LIB
, "NTRU ciphertext: %B", &value
);
180 /* decrypt the shared secret */
181 if (!this->privkey
->decrypt(this->privkey
, value
, &this->shared_secret
))
183 DBG1(DBG_LIB
, "NTRU decryption of shared secret failed");
186 this->computed
= TRUE
;
190 /* responder generating and encrypting the shared secret */
191 this->responder
= TRUE
;
193 /* check the NTRU public key format */
195 value
.ptr
[0] != NTRU_PUBKEY_TAG
||
196 value
.ptr
[1] != NTRU_OID_LEN
)
198 DBG1(DBG_LIB
, "received NTRU public key with invalid header");
201 if (!memeq(value
.ptr
+ 2, this->param_set
->oid
, NTRU_OID_LEN
))
203 DBG1(DBG_LIB
, "received NTRU public key with wrong OID");
206 this->pubkey_enc
= chunk_clone(value
);
208 /* shared secret size is chosen as twice the cryptographical strength */
209 this->shared_secret
= chunk_alloc(2 * this->strength
/ BITS_PER_BYTE
);
211 /* generate the random shared secret */
212 if (!this->drbg
->generate(this->drbg
, this->strength
,
213 this->shared_secret
.len
, this->shared_secret
.ptr
))
215 DBG1(DBG_LIB
, "generation of shared secret failed");
216 chunk_free(&this->shared_secret
);
219 this->computed
= TRUE
;
221 /* determine the size of the ciphertext */
222 if (ntru_crypto_ntru_encrypt(this->drbg
,
223 this->pubkey_enc
.len
, this->pubkey_enc
.ptr
,
224 this->shared_secret
.len
, this->shared_secret
.ptr
,
225 &ciphertext_len
, NULL
) != NTRU_OK
)
227 DBG1(DBG_LIB
, "error determining ciphertext size");
230 this->ciphertext
= chunk_alloc(ciphertext_len
);
232 /* encrypt the shared secret */
233 if (ntru_crypto_ntru_encrypt(this->drbg
,
234 this->pubkey_enc
.len
, this->pubkey_enc
.ptr
,
235 this->shared_secret
.len
, this->shared_secret
.ptr
,
236 &ciphertext_len
, this->ciphertext
.ptr
) != NTRU_OK
)
238 DBG1(DBG_LIB
, "NTRU encryption of shared secret failed");
239 chunk_free(&this->ciphertext
);
242 DBG3(DBG_LIB
, "NTRU ciphertext: %B", &this->ciphertext
);
246 METHOD(diffie_hellman_t
, get_dh_group
, diffie_hellman_group_t
,
247 private_ntru_ke_t
*this)
252 METHOD(diffie_hellman_t
, destroy
, void,
253 private_ntru_ke_t
*this)
255 DESTROY_IF(this->privkey
);
256 DESTROY_IF(this->pubkey
);
257 this->drbg
->destroy(this->drbg
);
258 this->entropy
->destroy(this->entropy
);
259 chunk_free(&this->pubkey_enc
);
260 chunk_free(&this->ciphertext
);
261 chunk_clear(&this->shared_secret
);
266 * Described in header.
268 ntru_ke_t
*ntru_ke_create(diffie_hellman_group_t group
, chunk_t g
, chunk_t p
)
270 private_ntru_ke_t
*this;
271 ntru_param_set_id_t
*param_sets
, param_set_id
;
277 parameter_set
= lib
->settings
->get_str(lib
->settings
,
278 "%s.plugins.ntru.parameter_set", "optimum", lib
->ns
);
280 if (streq(parameter_set
, "x9_98_speed"))
282 param_sets
= param_sets_x9_98_speed
;
284 else if (streq(parameter_set
, "x9_98_bandwidth"))
286 param_sets
= param_sets_x9_98_bandwidth
;
288 else if (streq(parameter_set
, "x9_98_balance"))
290 param_sets
= param_sets_x9_98_balance
;
294 param_sets
= param_sets_optimum
;
301 param_set_id
= param_sets
[0];
305 param_set_id
= param_sets
[1];
309 param_set_id
= param_sets
[2];
313 param_set_id
= param_sets
[3];
318 DBG1(DBG_LIB
, "%u bit %s NTRU parameter set %N selected", strength
,
319 parameter_set
, ntru_param_set_id_names
, param_set_id
);
321 entropy
= lib
->crypto
->create_rng(lib
->crypto
, RNG_TRUE
);
324 DBG1(DBG_LIB
, "could not attach entropy source for DRBG");
328 drbg
= ntru_drbg_create(strength
, chunk_from_str("IKE NTRU-KE"), entropy
);
331 DBG1(DBG_LIB
, "could not instantiate DRBG at %u bit security", strength
);
332 entropy
->destroy(entropy
);
339 .get_shared_secret
= _get_shared_secret
,
340 .set_other_public_value
= _set_other_public_value
,
341 .get_my_public_value
= _get_my_public_value
,
342 .get_dh_group
= _get_dh_group
,
347 .param_set
= ntru_param_set_get_by_id(param_set_id
),
348 .strength
= strength
,
353 return &this->public;