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
;
27 * Private data of an ntru_ke_t object.
29 struct private_ntru_ke_t
{
31 * Public ntru_ke_t interface.
36 * Diffie Hellman group number.
41 * NTRU Parameter Set ID
43 NTRU_ENCRYPT_PARAM_SET_ID param_set_id
;
46 * Cryptographical strength in bits of the NTRU Parameter Set
61 * NTRU encrypted shared secret
68 chunk_t shared_secret
;
71 * True if peer is responder
76 * True if shared secret is computed
81 * Deterministic Random Bit Generator
86 METHOD(diffie_hellman_t
, get_my_public_value
, void,
87 private_ntru_ke_t
*this, chunk_t
*value
)
89 uint16_t pub_key_len
, priv_key_len
;
95 if (this->ciphertext
.len
)
97 *value
= chunk_clone(this->ciphertext
);
102 if (this->pub_key
.len
== 0)
104 /* determine the NTRU public and private key sizes */
105 if (ntru_crypto_ntru_encrypt_keygen(this->drbg
, this->param_set_id
,
107 &priv_key_len
, NULL
) != NTRU_OK
)
109 DBG1(DBG_LIB
, "error determining NTRU public and private key "
113 this->pub_key
= chunk_alloc(pub_key_len
);
114 this->priv_key
= chunk_alloc(priv_key_len
);
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
)
121 DBG1(DBG_LIB
, "NTRU keypair generation failed");
122 chunk_free(&this->priv_key
);
123 chunk_free(&this->pub_key
);
126 DBG3(DBG_LIB
, "NTRU public key: %B", &this->pub_key
);
127 DBG4(DBG_LIB
, "NTRU private key: %B", &this->priv_key
);
129 *value
= chunk_clone(this->pub_key
);
133 METHOD(diffie_hellman_t
, get_shared_secret
, status_t
,
134 private_ntru_ke_t
*this, chunk_t
*secret
)
136 if (!this->computed
|| !this->shared_secret
.len
)
140 *secret
= chunk_clone(this->shared_secret
);
146 METHOD(diffie_hellman_t
, set_other_public_value
, void,
147 private_ntru_ke_t
*this, chunk_t value
)
149 u_int16_t plaintext_len
, ciphertext_len
;
151 if (this->priv_key
.len
)
153 /* initiator decrypting shared secret */
154 this->ciphertext
= chunk_clone(value
);
155 DBG3(DBG_LIB
, "NTRU ciphertext: %B", &this->ciphertext
);
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
)
162 DBG1(DBG_LIB
, "error determining maximum plaintext size");
165 this->shared_secret
= chunk_alloc(plaintext_len
);
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
)
172 DBG1(DBG_LIB
, "NTRU decryption of shared secret failed");
173 chunk_free(&this->shared_secret
);
176 this->shared_secret
.len
= plaintext_len
;
177 this->computed
= TRUE
;
181 /* responder generating and encrypting the shared secret */
182 this->responder
= TRUE
;
183 this->pub_key
= chunk_clone(value
);
185 /* shared secret size is chosen as twice the cryptographical strength */
186 this->shared_secret
= chunk_alloc(2 * this->strength
/ BITS_PER_BYTE
);
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
)
192 DBG1(DBG_LIB
, "generation of shared secret failed");
193 chunk_free(&this->shared_secret
);
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
)
203 DBG1(DBG_LIB
, "error determining ciphertext size");
206 this->ciphertext
= chunk_alloc(ciphertext_len
);
207 this->computed
= TRUE
;
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
)
215 DBG1(DBG_LIB
, "NTRU encryption of shared secret failed");
216 chunk_free(&this->ciphertext
);
219 DBG3(DBG_LIB
, "NTRU ciphertext: %B", &this->ciphertext
);
223 METHOD(diffie_hellman_t
, get_dh_group
, diffie_hellman_group_t
,
224 private_ntru_ke_t
*this)
229 METHOD(diffie_hellman_t
, destroy
, void,
230 private_ntru_ke_t
*this)
232 if (ntru_crypto_drbg_uninstantiate(this->drbg
) != DRBG_OK
)
234 DBG1(DBG_LIB
, "error uninstantiating DRBG");
236 chunk_free(&this->pub_key
);
237 chunk_free(&this->ciphertext
);
238 chunk_clear(&this->priv_key
);
239 chunk_clear(&this->shared_secret
);
244 * Described in header.
246 ntru_ke_t
*ntru_ke_create(diffie_hellman_group_t group
, chunk_t g
, chunk_t p
)
248 private_ntru_ke_t
*this;
249 char personalization_str
[] = "strongSwan NTRU-KE";
250 NTRU_ENCRYPT_PARAM_SET_ID param_set_id
;
255 * We are selecting the X9.98 / IEEE 1363.1 parameter sets
256 * which balance speed and bandwidth
262 /* param_set_id = NTRU_EES541EP1; */
263 param_set_id
= NTRU_EES401EP2
;
267 /* param_set_id = NTRU_EES613EP1; */
268 param_set_id
= NTRU_EES439EP1
;
272 /* param_set_id = NTRU_EES887EP1; */
273 param_set_id
= NTRU_EES593EP1
;
277 /* param_set_id = NTRU_EES1171EP1; */
278 param_set_id
= NTRU_EES743EP1
;
284 if (ntru_crypto_drbg_instantiate(strength
,
285 personalization_str
, strlen(personalization_str
),
286 (ENTROPY_FN
) &ntru_plugin_get_entropy
, &drbg
) != DRBG_OK
)
288 DBG1(DBG_LIB
, "error instantiating DRBG at %u bit security", strength
);
293 DBG2(DBG_LIB
, "instantiated DRBG at %u bit security", strength
);
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
,
307 .param_set_id
= param_set_id
,
308 .strength
= strength
,
312 return &this->public;