dec6bbc8efb3689845ec6e08a3081739e4e900a5
[strongswan.git] / src / libstrongswan / plugins / ntru / ntru_crypto / ntru_crypto_ntru_encrypt_key.c
1 /******************************************************************************
2 * NTRU Cryptography Reference Source Code
3 * Copyright (c) 2009-2013, by Security Innovation, Inc. All rights reserved.
4 *
5 * ntru_crypto_ntru_encrypt_key.c is a component of ntru-crypto.
6 *
7 * Copyright (C) 2009-2013 Security Innovation
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 *
23 *****************************************************************************/
24
25 /******************************************************************************
26 *
27 * File: ntru_crypto_ntru_encrypt_key.c
28 *
29 * Contents: Routines for exporting and importing public and private keys
30 * for NTRUEncrypt.
31 *
32 *****************************************************************************/
33
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <assert.h>
38 #include "ntru_crypto_ntru_encrypt_key.h"
39
40
41 /* ntru_crypto_ntru_encrypt_key_parse
42 *
43 * Parses an NTRUEncrypt key blob.
44 * If the blob is not corrupt, returns packing types for public and private
45 * keys, a pointer to the parameter set, a pointer to the public key, and
46 * a pointer to the private key if it exists.
47 *
48 * Returns TRUE if successful.
49 * Returns FALSE if the blob is invalid.
50 */
51
52 bool
53 ntru_crypto_ntru_encrypt_key_parse(
54 bool pubkey_parse, /* in - if parsing pubkey
55 blob */
56 uint16_t key_blob_len, /* in - no. octets in key
57 blob */
58 uint8_t const *key_blob, /* in - pointer to key blob */
59 uint8_t *pubkey_pack_type, /* out - addr for pubkey
60 packing type */
61 uint8_t *privkey_pack_type, /* out - addr for privkey
62 packing type */
63 ntru_param_set_t **params, /* out - addr for ptr to
64 parameter set */
65 uint8_t const **pubkey, /* out - addr for ptr to
66 packed pubkey */
67 uint8_t const **privkey) /* out - addr for ptr to
68 packed privkey */
69 {
70 uint8_t tag;
71
72 /* parse key blob based on tag */
73 tag = key_blob[0];
74 switch (tag) {
75 case NTRU_ENCRYPT_PUBKEY_TAG:
76 if (!pubkey_parse)
77 return FALSE;
78 break;
79 case NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG:
80 case NTRU_ENCRYPT_PRIVKEY_TRITS_TAG:
81 case NTRU_ENCRYPT_PRIVKEY_INDICES_TAG:
82 assert(privkey_pack_type);
83 assert(privkey);
84 if (pubkey_parse)
85 return FALSE;
86 break;
87 default:
88 return FALSE;
89 }
90
91 switch (tag) {
92 case NTRU_ENCRYPT_PUBKEY_TAG:
93 case NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG:
94 case NTRU_ENCRYPT_PRIVKEY_TRITS_TAG:
95 case NTRU_ENCRYPT_PRIVKEY_INDICES_TAG:
96
97 /* Version 0:
98 * byte 0: tag
99 * byte 1: no. of octets in OID
100 * bytes 2-4: OID
101 * bytes 5- : packed pubkey
102 * [packed privkey]
103 */
104
105 {
106 ntru_param_set_t *p = NULL;
107 uint16_t pubkey_packed_len;
108
109 /* check OID length and minimum blob length for tag and OID */
110
111 if ((key_blob_len < 5) || (key_blob[1] != 3))
112 return FALSE;
113
114 /* get a pointer to the parameter set corresponding to the OID */
115 p = ntru_param_set_get_by_oid(key_blob + 2);
116 if (!p)
117 {
118 return FALSE;
119 }
120
121 /* check blob length and assign pointers to blob fields */
122
123 pubkey_packed_len = (p->N * p->q_bits + 7) / 8;
124 if (pubkey_parse) { /* public-key parsing */
125 if (key_blob_len != 5 + pubkey_packed_len)
126 return FALSE;
127
128 *pubkey = key_blob + 5;
129
130 } else { /* private-key parsing */
131 uint16_t privkey_packed_len;
132 uint16_t privkey_packed_trits_len = (p->N + 4) / 5;
133 uint16_t privkey_packed_indices_len;
134 uint16_t dF;
135
136 /* check packing type for product-form private keys */
137
138 if (p->is_product_form &&
139 (tag == NTRU_ENCRYPT_PRIVKEY_TRITS_TAG))
140 return FALSE;
141
142 /* set packed-key length for packed indices */
143
144 if (p->is_product_form)
145 dF = (uint16_t)( (p->dF_r & 0xff) + /* df1 */
146 ((p->dF_r >> 8) & 0xff) + /* df2 */
147 ((p->dF_r >> 16) & 0xff)); /* df3 */
148 else
149 dF = (uint16_t)p->dF_r;
150 privkey_packed_indices_len = ((dF << 1) * p->N_bits + 7) >> 3;
151
152 /* set private-key packing type if defaulted */
153
154 if (tag == NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG) {
155 if (p->is_product_form ||
156 (privkey_packed_indices_len <=
157 privkey_packed_trits_len))
158 tag = NTRU_ENCRYPT_PRIVKEY_INDICES_TAG;
159 else
160 tag = NTRU_ENCRYPT_PRIVKEY_TRITS_TAG;
161 }
162
163 if (tag == NTRU_ENCRYPT_PRIVKEY_TRITS_TAG)
164 privkey_packed_len = privkey_packed_trits_len;
165 else
166 privkey_packed_len = privkey_packed_indices_len;
167
168 if (key_blob_len != 5 + pubkey_packed_len + privkey_packed_len)
169 return FALSE;
170
171 *pubkey = key_blob + 5;
172 *privkey = *pubkey + pubkey_packed_len;
173 *privkey_pack_type = (tag == NTRU_ENCRYPT_PRIVKEY_TRITS_TAG) ?
174 NTRU_ENCRYPT_KEY_PACKED_TRITS :
175 NTRU_ENCRYPT_KEY_PACKED_INDICES;
176 }
177
178 /* return parameter set pointer */
179
180 *pubkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS;
181 *params = p;
182 }
183 default:
184 break; /* can't get here */
185 }
186 return TRUE;
187 }
188
189
190 /* ntru_crypto_ntru_encrypt_key_get_blob_params
191 *
192 * Returns public and private key packing types and blob lengths given
193 * a packing format. For now, only a default packing format exists.
194 *
195 * Only public-key params may be returned by setting privkey_pack_type
196 * and privkey_blob_len to NULL.
197 */
198
199 void
200 ntru_crypto_ntru_encrypt_key_get_blob_params(
201 ntru_param_set_t *params, /* in - pointer to
202 param set
203 parameters */
204 uint8_t *pubkey_pack_type, /* out - addr for pubkey
205 packing type */
206 uint16_t *pubkey_blob_len, /* out - addr for no. of
207 bytes in
208 pubkey blob */
209 uint8_t *privkey_pack_type, /* out - addr for privkey
210 packing type */
211 uint16_t *privkey_blob_len) /* out - addr for no. of
212 bytes in
213 privkey blob */
214 {
215 uint16_t pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
216
217 assert(params);
218 assert(pubkey_pack_type);
219 assert(pubkey_blob_len);
220
221 *pubkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS;
222 *pubkey_blob_len = 5 + pubkey_packed_len;
223
224 if (privkey_pack_type && privkey_blob_len) {
225 uint16_t privkey_packed_trits_len = (params->N + 4) / 5;
226 uint16_t privkey_packed_indices_len;
227 uint16_t dF;
228
229 if (params->is_product_form)
230 dF = (uint16_t)( (params->dF_r & 0xff) + /* df1 */
231 ((params->dF_r >> 8) & 0xff) + /* df2 */
232 ((params->dF_r >> 16) & 0xff)); /* df3 */
233 else
234 dF = (uint16_t)params->dF_r;
235 privkey_packed_indices_len = ((dF << 1) * params->N_bits + 7) >> 3;
236
237 if (params->is_product_form ||
238 (privkey_packed_indices_len <= privkey_packed_trits_len)) {
239 *privkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_INDICES;
240 *privkey_blob_len =
241 5 + pubkey_packed_len + privkey_packed_indices_len;
242 } else {
243 *privkey_pack_type = NTRU_ENCRYPT_KEY_PACKED_TRITS;
244 *privkey_blob_len =
245 5 + pubkey_packed_len + privkey_packed_trits_len;
246 }
247 }
248 }
249
250
251 /* ntru_crypto_ntru_encrypt_key_create_pubkey_blob
252 *
253 * Returns a public key blob, packed according to the packing type provided.
254 */
255
256 void
257 ntru_crypto_ntru_encrypt_key_create_pubkey_blob(
258 ntru_param_set_t *params, /* in - pointer to
259 param set
260 parameters */
261 uint16_t const *pubkey, /* in - pointer to the
262 coefficients
263 of the pubkey */
264 uint8_t pubkey_pack_type, /* out - pubkey packing
265 type */
266 uint8_t *pubkey_blob) /* out - addr for the
267 pubkey blob */
268 {
269 assert(params);
270 assert(pubkey);
271 assert(pubkey_blob);
272
273 switch (pubkey_pack_type) {
274 case NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS:
275 *pubkey_blob++ = NTRU_ENCRYPT_PUBKEY_TAG;
276 *pubkey_blob++ = (uint8_t)sizeof(params->oid);
277 memcpy(pubkey_blob, params->oid, sizeof(params->oid));
278 pubkey_blob += sizeof(params->oid);
279 ntru_elements_2_octets(params->N, pubkey, params->q_bits,
280 pubkey_blob);
281 break;
282 default:
283 assert(FALSE);
284 }
285 }
286
287
288 /* ntru_crypto_ntru_encrypt_key_create_privkey_blob
289 *
290 * Returns a private key blob, packed according to the packing type provided.
291 */
292
293 void
294 ntru_crypto_ntru_encrypt_key_create_privkey_blob(
295 ntru_param_set_t *params, /* in - pointer to
296 param set
297 parameters */
298 uint16_t const *pubkey, /* in - pointer to the
299 coefficients
300 of the pubkey */
301 uint16_t const *privkey, /* in - pointer to the
302 indices of the
303 privkey */
304 uint8_t privkey_pack_type, /* in - privkey packing
305 type */
306 uint8_t *buf, /* in - temp, N bytes */
307 uint8_t *privkey_blob) /* out - addr for the
308 privkey blob */
309 {
310 assert(params);
311 assert(pubkey);
312 assert(privkey);
313 assert(privkey_blob);
314
315 switch (privkey_pack_type) {
316 case NTRU_ENCRYPT_KEY_PACKED_TRITS:
317 case NTRU_ENCRYPT_KEY_PACKED_INDICES:
318
319 /* format header and packed public key */
320
321 *privkey_blob++ = NTRU_ENCRYPT_PRIVKEY_DEFAULT_TAG;
322 *privkey_blob++ = (uint8_t)sizeof(params->oid);
323 memcpy(privkey_blob, params->oid, sizeof(params->oid));
324 privkey_blob += sizeof(params->oid);
325 ntru_elements_2_octets(params->N, pubkey, params->q_bits,
326 privkey_blob);
327 privkey_blob += (params->N * params->q_bits + 7) >> 3;
328
329 /* add packed private key */
330
331 if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_TRITS) {
332 ntru_indices_2_packed_trits(privkey, (uint16_t)params->dF_r,
333 (uint16_t)params->dF_r,
334 params->N, buf, privkey_blob);
335 } else {
336 uint32_t dF;
337
338 if (params->is_product_form) {
339 dF = (params->dF_r & 0xff) +
340 ((params->dF_r >> 8) & 0xff) +
341 ((params->dF_r >> 16) & 0xff);
342 } else {
343 dF = params->dF_r;
344 }
345 ntru_elements_2_octets((uint16_t)dF << 1, privkey,
346 params->N_bits, privkey_blob);
347 }
348 break;
349 default:
350 assert(FALSE);
351 break;
352 }
353 }
354
355