Prototype implementation of IKE key exchange via NTRU encryption
[strongswan.git] / src / libstrongswan / plugins / ntru / ntru_crypto / ntru_crypto_ntru_encrypt.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.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.c
28 *
29 * Contents: Routines implementing NTRUEncrypt encryption and decryption and
30 * key generation.
31 *
32 *****************************************************************************/
33
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <assert.h>
38 #include "ntru_crypto.h"
39 #include "ntru_crypto_ntru_encrypt_param_sets.h"
40 #include "ntru_crypto_ntru_encrypt_key.h"
41 #include "ntru_crypto_ntru_convert.h"
42 #include "ntru_crypto_ntru_poly.h"
43 #include "ntru_crypto_ntru_mgf1.h"
44 #include "ntru_crypto_drbg.h"
45
46
47 /* ntru_crypto_ntru_encrypt
48 *
49 * Implements NTRU encryption (SVES) for the parameter set specified in
50 * the public key blob.
51 *
52 * Before invoking this function, a DRBG must be instantiated using
53 * ntru_crypto_drbg_instantiate() to obtain a DRBG handle, and in that
54 * instantiation the requested security strength must be at least as large
55 * as the security strength of the NTRU parameter set being used.
56 * Failure to instantiate the DRBG with the proper security strength will
57 * result in this function returning DRBG_ERROR_BASE + DRBG_BAD_LENGTH.
58 *
59 * The required minimum size of the output ciphertext buffer (ct) may be
60 * queried by invoking this function with ct = NULL. In this case, no
61 * encryption is performed, NTRU_OK is returned, and the required minimum
62 * size for ct is returned in ct_len.
63 *
64 * When ct != NULL, at invocation *ct_len must be the size of the ct buffer.
65 * Upon return it is the actual size of the ciphertext.
66 *
67 * Returns NTRU_OK if successful.
68 * Returns DRBG_ERROR_BASE + DRBG_BAD_PARAMETER if the DRBG handle is invalid.
69 * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
70 * (other than ct) is NULL.
71 * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
72 * (pubkey_blob_len or pt_len) is zero, or if pt_len exceeds the
73 * maximum plaintext length for the parameter set.
74 * Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
75 * invalid (unknown format, corrupt, bad length).
76 * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the ciphertext buffer
77 * is too small.
78 * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
79 * allocated from the heap.
80 */
81
82 uint32_t
83 ntru_crypto_ntru_encrypt(
84 DRBG_HANDLE drbg_handle, /* in - handle of DRBG */
85 uint16_t pubkey_blob_len, /* in - no. of octets in public key
86 blob */
87 uint8_t const *pubkey_blob, /* in - pointer to public key */
88 uint16_t pt_len, /* in - no. of octets in plaintext */
89 uint8_t const *pt, /* in - pointer to plaintext */
90 uint16_t *ct_len, /* in/out - no. of octets in ct, addr for
91 no. of octets in ciphertext */
92 uint8_t *ct) /* out - address for ciphertext */
93 {
94 NTRU_ENCRYPT_PARAM_SET *params = NULL;
95 uint8_t const *pubkey_packed = NULL;
96 uint8_t pubkey_pack_type = 0x00;
97 uint16_t packed_ct_len;
98 size_t scratch_buf_len;
99 uint32_t dr;
100 uint32_t dr1 = 0;
101 uint32_t dr2 = 0;
102 uint32_t dr3 = 0;
103 uint16_t ring_mult_tmp_len;
104 int16_t m1 = 0;
105 uint16_t *scratch_buf = NULL;
106 uint16_t *ringel_buf = NULL;
107 uint16_t *r_buf = NULL;
108 uint8_t *b_buf = NULL;
109 uint8_t *tmp_buf = NULL;
110 bool msg_rep_good = FALSE;
111 NTRU_CRYPTO_HASH_ALGID hash_algid;
112 uint8_t md_len;
113 uint16_t mprime_len = 0;
114 uint16_t mod_q_mask;
115 uint32_t result = NTRU_OK;
116
117 /* check for bad parameters */
118
119 if (!pubkey_blob || !pt || !ct_len)
120 NTRU_RET(NTRU_BAD_PARAMETER);
121 if ((pubkey_blob_len == 0) || (pt_len == 0))
122 NTRU_RET(NTRU_BAD_LENGTH);
123
124 /* get a pointer to the parameter-set parameters, the packing type for
125 * the public key, and a pointer to the packed public key
126 */
127
128 if (!ntru_crypto_ntru_encrypt_key_parse(TRUE /* pubkey */, pubkey_blob_len,
129 pubkey_blob, &pubkey_pack_type,
130 NULL, &params, &pubkey_packed,
131 NULL))
132 NTRU_RET(NTRU_BAD_PUBLIC_KEY);
133
134 /* return the ciphertext size if requested */
135
136 packed_ct_len = (params->N * params->q_bits + 7) >> 3;
137 if (!ct) {
138 *ct_len = packed_ct_len;
139 NTRU_RET(NTRU_OK);
140 }
141
142 /* check the ciphertext buffer size */
143
144 if (*ct_len < packed_ct_len) {
145 NTRU_RET(NTRU_BUFFER_TOO_SMALL);
146 }
147
148 /* check the plaintext length */
149
150 if (pt_len > params->m_len_max) {
151 NTRU_RET(NTRU_BAD_LENGTH);
152 }
153
154 /* allocate memory for all operations */
155
156 if (params->is_product_form) {
157 ring_mult_tmp_len = params->N << 1; /* 2N 16-bit word buffer */
158 dr1 = params->dF_r & 0xff;
159 dr2 = (params->dF_r >> 8) & 0xff;
160 dr3 = (params->dF_r >> 16) & 0xff;
161 dr = dr1 + dr2 + dr3;
162 } else {
163 ring_mult_tmp_len = params->N; /* N 16-bit word buffer */
164 dr = params->dF_r;
165 }
166 scratch_buf_len = (ring_mult_tmp_len << 1) +
167 /* X-byte temp buf for ring mult and
168 other intermediate results */
169 (params->N << 1) + /* 2N-byte buffer for ring elements
170 and overflow from temp buffer */
171 (dr << 2) + /* buffer for r indices */
172 params->sec_strength_len;
173 /* buffer for b */
174 scratch_buf = malloc(scratch_buf_len);
175 if (!scratch_buf) {
176 NTRU_RET(NTRU_OUT_OF_MEMORY);
177 }
178 ringel_buf = scratch_buf + ring_mult_tmp_len;
179 r_buf = ringel_buf + params->N;
180 b_buf = (uint8_t *)(r_buf + (dr << 1));
181 tmp_buf = (uint8_t *)scratch_buf;
182
183 /* set hash algorithm based on security strength */
184
185 if (params->sec_strength_len <= 20) {
186 hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA1;
187 md_len = 20;
188 } else {
189 hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA256;
190 md_len = 32;
191 }
192
193 /* set constants */
194
195 mod_q_mask = params->q - 1;
196
197 /* loop until a message representative with proper weight is achieved */
198
199 do {
200 uint8_t *ptr = tmp_buf;
201
202 /* get b */
203 result = ntru_crypto_drbg_generate(drbg_handle,
204 params->sec_strength_len << 3,
205 params->sec_strength_len, b_buf);
206
207 if (result == NTRU_OK) {
208
209 /* form sData (OID || m || b || hTrunc) */
210
211 memcpy(ptr, params->OID, 3);
212 ptr += 3;
213 memcpy(ptr, pt, pt_len);
214 ptr += pt_len;
215 memcpy(ptr, b_buf, params->sec_strength_len);
216 ptr += params->sec_strength_len;
217 memcpy(ptr, pubkey_packed, params->sec_strength_len);
218 ptr += params->sec_strength_len;
219
220
221 /* generate r */
222
223 result = ntru_gen_poly(hash_algid, md_len,
224 params->min_IGF_hash_calls,
225 (uint16_t)(ptr - tmp_buf),
226 tmp_buf, tmp_buf,
227 params->N, params->c_bits,
228 params->no_bias_limit,
229 params->is_product_form,
230 params->dF_r << 1, r_buf);
231 }
232
233 if (result == NTRU_OK) {
234 uint16_t pubkey_packed_len;
235
236 /* unpack the public key */
237
238 assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS);
239 pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
240 ntru_octets_2_elements(pubkey_packed_len, pubkey_packed,
241 params->q_bits, ringel_buf);
242
243 /* form R = h * r */
244
245 if (params->is_product_form)
246 ntru_ring_mult_product_indices(ringel_buf, (uint16_t)dr1,
247 (uint16_t)dr2, (uint16_t)dr3,
248 r_buf, params->N, params->q,
249 scratch_buf, ringel_buf);
250 else
251 ntru_ring_mult_indices(ringel_buf, (uint16_t)dr, (uint16_t)dr,
252 r_buf, params->N, params->q,
253 scratch_buf, ringel_buf);
254
255 /* form R mod 4 */
256
257 ntru_coeffs_mod4_2_octets(params->N, ringel_buf, tmp_buf);
258
259 /* form mask */
260
261 result = ntru_mgftp1(hash_algid, md_len,
262 params->min_MGF_hash_calls,
263 (params->N + 3) / 4, tmp_buf,
264 tmp_buf + params->N, params->N, tmp_buf);
265 }
266 if (result == NTRU_OK) {
267 uint8_t *Mtrin_buf = tmp_buf + params->N;
268 uint8_t *M_buf = Mtrin_buf + params->N -
269 (params->sec_strength_len + params->m_len_len +
270 params->m_len_max + 2);
271 uint16_t i;
272
273 /* form the padded message M */
274
275 ptr = M_buf;
276 memcpy(ptr, b_buf, params->sec_strength_len);
277 ptr += params->sec_strength_len;
278 if (params->m_len_len == 2)
279 *ptr++ = (uint8_t)((pt_len >> 8) & 0xff);
280 *ptr++ = (uint8_t)(pt_len & 0xff);
281 memcpy(ptr, pt, pt_len);
282 ptr += pt_len;
283
284 /* add an extra zero byte in case without it the bit string
285 * is not a multiple of 3 bits and therefore might not be
286 * able to produce enough trits
287 */
288
289 memset(ptr, 0, params->m_len_max - pt_len + 2);
290
291 /* convert M to trits (Mbin to Mtrin) */
292
293 mprime_len = params->N;
294 if (params->is_product_form)
295 --mprime_len;
296
297 ntru_bits_2_trits(M_buf, mprime_len, Mtrin_buf);
298
299 /* form the msg representative m' by adding Mtrin to mask, mod p */
300
301 if (params->is_product_form) {
302 for (i = 0; i < mprime_len; i++) {
303 tmp_buf[i] = tmp_buf[i] + Mtrin_buf[i];
304 if (tmp_buf[i] >= 3)
305 tmp_buf[i] -= 3;
306 if (tmp_buf[i] == 1)
307 ++m1;
308 else if (tmp_buf[i] == 2)
309 --m1;
310 }
311 } else {
312 for (i = 0; i < mprime_len; i++) {
313 tmp_buf[i] = tmp_buf[i] + Mtrin_buf[i];
314 if (tmp_buf[i] >= 3)
315 tmp_buf[i] -= 3;
316 }
317 }
318
319 /* check that message representative meets minimum weight
320 * requirements
321 */
322
323 if (params->is_product_form)
324 msg_rep_good = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) :
325 (bool)( m1 <= params->min_msg_rep_wt);
326 else
327 msg_rep_good = ntru_poly_check_min_weight(mprime_len, tmp_buf,
328 params->min_msg_rep_wt);
329 msg_rep_good = TRUE;
330 }
331 } while ((result == NTRU_OK) && !msg_rep_good);
332
333 if (result == NTRU_OK) {
334 uint16_t i;
335
336 /* form ciphertext e by adding m' to R mod q */
337
338 for (i = 0; i < mprime_len; i++) {
339 if (tmp_buf[i] == 1)
340 ringel_buf[i] = (ringel_buf[i] + 1) & mod_q_mask;
341 else if (tmp_buf[i] == 2)
342 ringel_buf[i] = (ringel_buf[i] - 1) & mod_q_mask;
343 }
344 if (params->is_product_form)
345 ringel_buf[i] = (ringel_buf[i] - m1) & mod_q_mask;
346
347 /* pack ciphertext */
348
349 ntru_elements_2_octets(params->N, ringel_buf, params->q_bits, ct);
350 *ct_len = packed_ct_len;
351 }
352
353 /* cleanup */
354
355 memset(scratch_buf, 0, scratch_buf_len);
356 free(scratch_buf);
357
358 return result;
359 }
360
361
362 /* ntru_crypto_ntru_decrypt
363 *
364 * Implements NTRU decryption (SVES) for the parameter set specified in
365 * the private key blob.
366 *
367 * The maximum size of the output plaintext may be queried by invoking
368 * this function with pt = NULL. In this case, no decryption is performed,
369 * NTRU_OK is returned, and the maximum size the plaintext could be is
370 * returned in pt_len.
371 * Note that until the decryption is performed successfully, the actual size
372 * of the resulting plaintext cannot be known.
373 *
374 * When pt != NULL, at invocation *pt_len must be the size of the pt buffer.
375 * Upon return it is the actual size of the plaintext.
376 *
377 * Returns NTRU_OK if successful.
378 * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
379 * (other than pt) is NULL.
380 * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument
381 * (privkey_blob) is zero, or if ct_len is invalid for the parameter set.
382 * Returns NTRU_ERROR_BASE + NTRU_BAD_PRIVATE_KEY if the private-key blob is
383 * invalid (unknown format, corrupt, bad length).
384 * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the plaintext buffer
385 * is too small.
386 * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
387 * allocated from the heap.
388 * Returns NTRU_ERROR_BASE + NTRU_FAIL if a decryption error occurs.
389 */
390
391 uint32_t
392 ntru_crypto_ntru_decrypt(
393 uint16_t privkey_blob_len, /* in - no. of octets in private key
394 blob */
395 uint8_t const *privkey_blob, /* in - pointer to private key */
396 uint16_t ct_len, /* in - no. of octets in ciphertext */
397 uint8_t const *ct, /* in - pointer to ciphertext */
398 uint16_t *pt_len, /* in/out - no. of octets in pt, addr for
399 no. of octets in plaintext */
400 uint8_t *pt) /* out - address for plaintext */
401 {
402 NTRU_ENCRYPT_PARAM_SET *params = NULL;
403 uint8_t const *privkey_packed = NULL;
404 uint8_t const *pubkey_packed = NULL;
405 uint8_t privkey_pack_type = 0x00;
406 uint8_t pubkey_pack_type = 0x00;
407 size_t scratch_buf_len;
408 uint32_t dF_r;
409 uint32_t dF_r1 = 0;
410 uint32_t dF_r2 = 0;
411 uint32_t dF_r3 = 0;
412 uint16_t ring_mult_tmp_len;
413 int16_t m1 = 0;
414 uint16_t *scratch_buf = NULL;
415 uint16_t *ringel_buf1 = NULL;
416 uint16_t *ringel_buf2 = NULL;
417 uint16_t *i_buf = NULL;
418 uint8_t *m_buf = NULL;
419 uint8_t *tmp_buf = NULL;
420 uint8_t *Mtrin_buf = NULL;
421 uint8_t *M_buf = NULL;
422 uint8_t *ptr = NULL;
423 NTRU_CRYPTO_HASH_ALGID hash_algid;
424 uint8_t md_len;
425 uint16_t cmprime_len;
426 uint16_t mod_q_mask;
427 uint16_t q_mod_p;
428 uint16_t cm_len = 0;
429 uint16_t num_zeros;
430 uint16_t i;
431 bool decryption_ok = TRUE;
432 uint32_t result = NTRU_OK;
433
434 /* check for bad parameters */
435
436 if (!privkey_blob || !ct || !pt_len)
437 NTRU_RET(NTRU_BAD_PARAMETER);
438 if ((privkey_blob_len == 0) || (ct_len == 0))
439 NTRU_RET(NTRU_BAD_LENGTH);
440
441 /* get a pointer to the parameter-set parameters, the packing types for
442 * the public and private keys, and pointers to the packed public and
443 * private keys
444 */
445
446 if (!ntru_crypto_ntru_encrypt_key_parse(FALSE /* privkey */,
447 privkey_blob_len,
448 privkey_blob, &pubkey_pack_type,
449 &privkey_pack_type, &params,
450 &pubkey_packed, &privkey_packed))
451 NTRU_RET(NTRU_BAD_PRIVATE_KEY);
452
453 /* return the max plaintext size if requested */
454
455 if (!pt) {
456 *pt_len = params->m_len_max;
457 NTRU_RET(NTRU_OK);
458 }
459
460 /* cannot check the plaintext buffer size until after the plaintext
461 * is derived, if we allow plaintext buffers only as large as the
462 * actual plaintext
463 */
464
465 /* check the ciphertext length */
466
467 if (ct_len != (params->N * params->q_bits + 7) >> 3)
468 NTRU_RET(NTRU_BAD_LENGTH);
469
470 /* allocate memory for all operations */
471
472 if (params->is_product_form) {
473 ring_mult_tmp_len = params->N << 1; /* 2N 16-bit word buffer */
474 dF_r1 = params->dF_r & 0xff;
475 dF_r2 = (params->dF_r >> 8) & 0xff;
476 dF_r3 = (params->dF_r >> 16) & 0xff;
477 dF_r = dF_r1 + dF_r2 + dF_r3;
478 } else {
479 ring_mult_tmp_len = params->N; /* N 16-bit word buffer */
480 dF_r = params->dF_r;
481 }
482 scratch_buf_len = (ring_mult_tmp_len << 1) +
483 /* X-byte temp buf for ring mult and
484 other intermediate results */
485 (params->N << 2) + /* 2 2N-byte bufs for ring elements
486 and overflow from temp buffer */
487 (dF_r << 2) + /* buffer for F, r indices */
488 params->m_len_max; /* buffer for plaintext */
489 scratch_buf = malloc(scratch_buf_len);
490 if (!scratch_buf) {
491 NTRU_RET(NTRU_OUT_OF_MEMORY);
492 }
493 ringel_buf1 = scratch_buf + ring_mult_tmp_len;
494 ringel_buf2 = ringel_buf1 + params->N;
495 i_buf = ringel_buf2 + params->N;
496 m_buf = (uint8_t *)(i_buf + (dF_r << 1));
497 tmp_buf = (uint8_t *)scratch_buf;
498 Mtrin_buf = (uint8_t *)ringel_buf1;
499 M_buf = Mtrin_buf + params->N;
500
501 /* set hash algorithm based on security strength */
502
503 if (params->sec_strength_len <= 20) {
504 hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA1;
505 md_len = 20;
506 } else {
507 hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA256;
508 md_len = 32;
509 }
510
511 /* set constants */
512
513 mod_q_mask = params->q - 1;
514 q_mod_p = params->q % 3;
515
516 /* unpack the ciphertext */
517
518 ntru_octets_2_elements(ct_len, ct, params->q_bits, ringel_buf2);
519
520 /* unpack the private key */
521
522 if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_TRITS) {
523 ntru_packed_trits_2_indices(privkey_packed, params->N, i_buf,
524 i_buf + dF_r);
525
526 } else if (privkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_INDICES) {
527 ntru_octets_2_elements(
528 (((uint16_t)dF_r << 1) * params->N_bits + 7) >> 3,
529 privkey_packed, params->N_bits, i_buf);
530
531 } else {
532 assert(FALSE);
533 }
534
535 /* form cm':
536 * F * e
537 * A = e * (1 + pF) mod q = e + pFe mod q
538 * a = A in the range [-q/2, q/2)
539 * cm' = a mod p
540 */
541
542 cmprime_len = params->N;
543 if (params->is_product_form) {
544 --cmprime_len;
545 ntru_ring_mult_product_indices(ringel_buf2, (uint16_t)dF_r1,
546 (uint16_t)dF_r2, (uint16_t)dF_r3,
547 i_buf, params->N, params->q,
548 scratch_buf, ringel_buf1);
549 for (i = 0; i < cmprime_len; i++) {
550 ringel_buf1[i] = (ringel_buf2[i] + 3 * ringel_buf1[i]) & mod_q_mask;
551 if (ringel_buf1[i] >= (params->q >> 1))
552 ringel_buf1[i] = ringel_buf1[i] - q_mod_p;
553 Mtrin_buf[i] = (uint8_t)(ringel_buf1[i] % 3);
554 if (Mtrin_buf[i] == 1)
555 ++m1;
556 else if (Mtrin_buf[i] == 2)
557 --m1;
558 }
559 } else {
560 ntru_ring_mult_indices(ringel_buf2, (uint16_t)dF_r, (uint16_t)dF_r,
561 i_buf, params->N, params->q,
562 scratch_buf, ringel_buf1);
563 for (i = 0; i < cmprime_len; i++) {
564 ringel_buf1[i] = (ringel_buf2[i] + 3 * ringel_buf1[i]) & mod_q_mask;
565 if (ringel_buf1[i] >= (params->q >> 1))
566 ringel_buf1[i] = ringel_buf1[i] - q_mod_p;
567 Mtrin_buf[i] = (uint8_t)(ringel_buf1[i] % 3);
568 }
569 }
570
571 /* check that the candidate message representative meets minimum weight
572 * requirements
573 */
574
575 if (params->is_product_form)
576 decryption_ok = m1 < 0 ? (bool)(-m1 <= params->min_msg_rep_wt) :
577 (bool)( m1 <= params->min_msg_rep_wt);
578 else
579 decryption_ok = ntru_poly_check_min_weight(cmprime_len, Mtrin_buf,
580 params->min_msg_rep_wt);
581
582 /* form cR = e - cm' mod q */
583
584 for (i = 0; i < cmprime_len; i++) {
585 if (Mtrin_buf[i] == 1)
586 ringel_buf2[i] = --ringel_buf2[i] & mod_q_mask;
587 else if (Mtrin_buf[i] == 2)
588 ringel_buf2[i] = ++ringel_buf2[i] & mod_q_mask;
589 }
590 if (params->is_product_form)
591 ringel_buf2[i] = (ringel_buf2[i] + m1) & mod_q_mask;
592
593
594 /* form cR mod 4 */
595
596 ntru_coeffs_mod4_2_octets(params->N, ringel_buf2, tmp_buf);
597
598 /* form mask */
599
600 result = ntru_mgftp1(hash_algid, md_len,
601 params->min_MGF_hash_calls,
602 (params->N + 3) / 4, tmp_buf,
603 tmp_buf + params->N, params->N, tmp_buf);
604
605 if (result == NTRU_OK) {
606
607 /* form cMtrin by subtracting mask from cm', mod p */
608
609 for (i = 0; i < cmprime_len; i++) {
610 Mtrin_buf[i] = Mtrin_buf[i] - tmp_buf[i];
611 if (Mtrin_buf[i] >= 3)
612 Mtrin_buf[i] += 3;
613 }
614 if (params->is_product_form)
615
616 /* set the last trit to zero since that's what it was, and
617 * because it can't be calculated from (cm' - mask) since
618 * we don't have the correct value for the last cm' trit
619 */
620
621 Mtrin_buf[i] = 0;
622
623 /* convert cMtrin to cM (Mtrin to Mbin) */
624
625 if (!ntru_trits_2_bits(Mtrin_buf, params->N, M_buf))
626 decryption_ok = FALSE;
627
628 /* validate the padded message cM and copy cm to m_buf */
629
630 ptr = M_buf + params->sec_strength_len;
631 if (params->m_len_len == 2)
632 cm_len = (uint16_t)(*ptr++) << 16;
633 cm_len |= (uint16_t)(*ptr++);
634 if (cm_len > params->m_len_max) {
635 cm_len = params->m_len_max;
636 decryption_ok = FALSE;
637 }
638 memcpy(m_buf, ptr, cm_len);
639 ptr += cm_len;
640 num_zeros = params->m_len_max - cm_len + 1;
641 for (i = 0; i < num_zeros; i++) {
642 if (ptr[i] != 0)
643 decryption_ok = FALSE;
644 }
645
646 /* form sData (OID || m || b || hTrunc) */
647
648 ptr = tmp_buf;
649 memcpy(ptr, params->OID, 3);
650 ptr += 3;
651 memcpy(ptr, m_buf, cm_len);
652 ptr += cm_len;
653 memcpy(ptr, M_buf, params->sec_strength_len);
654 ptr += params->sec_strength_len;
655 memcpy(ptr, pubkey_packed, params->sec_strength_len);
656 ptr += params->sec_strength_len;
657
658 /* generate cr */
659
660 result = ntru_gen_poly(hash_algid, md_len,
661 params->min_IGF_hash_calls,
662 (uint16_t)(ptr - tmp_buf),
663 tmp_buf, tmp_buf,
664 params->N, params->c_bits,
665 params->no_bias_limit,
666 params->is_product_form,
667 params->dF_r << 1, i_buf);
668 }
669
670 if (result == NTRU_OK) {
671
672 /* unpack the public key */
673
674 {
675 uint16_t pubkey_packed_len;
676
677 assert(pubkey_pack_type == NTRU_ENCRYPT_KEY_PACKED_COEFFICIENTS);
678 pubkey_packed_len = (params->N * params->q_bits + 7) >> 3;
679 ntru_octets_2_elements(pubkey_packed_len, pubkey_packed,
680 params->q_bits, ringel_buf1);
681 }
682
683 /* form cR' = h * cr */
684
685 if (params->is_product_form)
686 ntru_ring_mult_product_indices(ringel_buf1, (uint16_t)dF_r1,
687 (uint16_t)dF_r2, (uint16_t)dF_r3,
688 i_buf, params->N, params->q,
689 scratch_buf, ringel_buf1);
690 else
691 ntru_ring_mult_indices(ringel_buf1, (uint16_t)dF_r, (uint16_t)dF_r,
692 i_buf, params->N, params->q,
693 scratch_buf, ringel_buf1);
694
695 /* compare cR' to cR */
696
697 for (i = 0; i < params->N; i++) {
698 if (ringel_buf1[i] != ringel_buf2[i])
699 decryption_ok = FALSE;
700 }
701
702 /* output plaintext and plaintext length */
703
704 if (decryption_ok) {
705 if (*pt_len < cm_len)
706 NTRU_RET(NTRU_BUFFER_TOO_SMALL);
707 memcpy(pt, m_buf, cm_len);
708 *pt_len = cm_len;
709 }
710 }
711
712 /* cleanup */
713
714 memset(scratch_buf, 0, scratch_buf_len);
715 free(scratch_buf);
716
717 if (!decryption_ok)
718 NTRU_RET(NTRU_FAIL);
719 return result;
720 }
721
722
723 /* ntru_crypto_ntru_encrypt_keygen
724 *
725 * Implements key generation for NTRUEncrypt for the parameter set specified.
726 *
727 * Before invoking this function, a DRBG must be instantiated using
728 * ntru_crypto_drbg_instantiate() to obtain a DRBG handle, and in that
729 * instantiation the requested security strength must be at least as large
730 * as the security strength of the NTRU parameter set being used.
731 * Failure to instantiate the DRBG with the proper security strength will
732 * result in this function returning DRBG_ERROR_BASE + DRBG_BAD_LENGTH.
733 *
734 * The required minimum size of the output public-key buffer (pubkey_blob)
735 * may be queried by invoking this function with pubkey_blob = NULL.
736 * In this case, no key generation is performed, NTRU_OK is returned, and
737 * the required minimum size for pubkey_blob is returned in pubkey_blob_len.
738 *
739 * The required minimum size of the output private-key buffer (privkey_blob)
740 * may be queried by invoking this function with privkey_blob = NULL.
741 * In this case, no key generation is performed, NTRU_OK is returned, and
742 * the required minimum size for privkey_blob is returned in privkey_blob_len.
743 *
744 * The required minimum sizes of both pubkey_blob and privkey_blob may be
745 * queried as described above, in a single invocation of this function.
746 *
747 * When pubkey_blob != NULL and privkey_blob != NULL, at invocation
748 * *pubkey_blob_len must be the size of the pubkey_blob buffer and
749 * *privkey_blob_len must be the size of the privkey_blob buffer.
750 * Upon return, *pubkey_blob_len is the actual size of the public-key blob
751 * and *privkey_blob_len is the actual size of the private-key blob.
752 *
753 * Returns NTRU_OK if successful.
754 * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
755 * (other than pubkey_blob or privkey_blob) is NULL.
756 * Returns NTRU_ERROR_BASE + NTRU_INVALID_PARAMETER_SET if the parameter-set
757 * ID is invalid.
758 * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if a length argument is invalid.
759 * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if either the pubkey_blob
760 * buffer or the privkey_blob buffer is too small.
761 * Returns NTRU_ERROR_BASE + NTRU_NO_MEMORY if memory needed cannot be
762 * allocated from the heap.
763 * Returns NTRU_ERROR_BASE + NTRU_FAIL if the polynomial generated for f is
764 * not invertible in (Z/qZ)[X]/(X^N - 1), which is extremely unlikely.
765 * Should this occur, this function should simply be invoked again.
766 */
767
768 uint32_t
769 ntru_crypto_ntru_encrypt_keygen(
770 DRBG_HANDLE drbg_handle, /* in - handle of DRBG */
771 NTRU_ENCRYPT_PARAM_SET_ID param_set_id, /* in - parameter set ID */
772 uint16_t *pubkey_blob_len, /* in/out - no. of octets in
773 pubkey_blob, addr
774 for no. of octets
775 in pubkey_blob */
776 uint8_t *pubkey_blob, /* out - address for
777 public key blob */
778 uint16_t *privkey_blob_len, /* in/out - no. of octets in
779 privkey_blob, addr
780 for no. of octets
781 in privkey_blob */
782 uint8_t *privkey_blob) /* out - address for
783 private key blob */
784 {
785 NTRU_ENCRYPT_PARAM_SET *params = NULL;
786 uint16_t public_key_blob_len;
787 uint16_t private_key_blob_len;
788 uint8_t pubkey_pack_type;
789 uint8_t privkey_pack_type;
790 size_t scratch_buf_len;
791 uint32_t dF;
792 uint32_t dF1 = 0;
793 uint32_t dF2 = 0;
794 uint32_t dF3 = 0;
795 uint16_t *scratch_buf = NULL;
796 uint16_t *ringel_buf1 = NULL;
797 uint16_t *ringel_buf2 = NULL;
798 uint16_t *F_buf = NULL;
799 uint8_t *tmp_buf = NULL;
800 uint16_t mod_q_mask;
801 NTRU_CRYPTO_HASH_ALGID hash_algid;
802 uint8_t md_len;
803 uint16_t seed_len;
804 uint32_t result = NTRU_OK;
805
806 /* get a pointer to the parameter-set parameters */
807
808 if ((params = ntru_encrypt_get_params_with_id(param_set_id)) == NULL)
809 NTRU_RET(NTRU_INVALID_PARAMETER_SET);
810
811 /* check for bad parameters */
812
813 if (!pubkey_blob_len || !privkey_blob_len)
814 NTRU_RET(NTRU_BAD_PARAMETER);
815
816 /* get public and private key packing types and blob lengths */
817
818 ntru_crypto_ntru_encrypt_key_get_blob_params(params, &pubkey_pack_type,
819 &public_key_blob_len,
820 &privkey_pack_type,
821 &private_key_blob_len);
822
823 /* return the pubkey_blob size and/or privkey_blob size if requested */
824
825 if (!pubkey_blob || !privkey_blob) {
826 if (!pubkey_blob)
827 *pubkey_blob_len = public_key_blob_len;
828 if (!privkey_blob)
829 *privkey_blob_len = private_key_blob_len;
830 NTRU_RET(NTRU_OK);
831 }
832
833 /* check size of output buffers */
834
835 if ((*pubkey_blob_len < public_key_blob_len) ||
836 (*privkey_blob_len < private_key_blob_len))
837 NTRU_RET(NTRU_BUFFER_TOO_SMALL);
838
839 /* allocate memory for all operations */
840
841 if (params->is_product_form) {
842 dF1 = params->dF_r & 0xff;
843 dF2 = (params->dF_r >> 8) & 0xff;
844 dF3 = (params->dF_r >> 16) & 0xff;
845 dF = dF1 + dF2 + dF3;
846 } else {
847 dF = params->dF_r;
848 }
849
850 scratch_buf_len = (params->N * 8) + /* 4N-byte temp buffer for ring inv
851 and other intermediate results,
852 2N-byte buffer for f, g indices
853 and overflow from temp buffer,
854 2N-byte buffer for f^-1 */
855 (dF << 2); /* buffer for F indices */
856 scratch_buf = malloc(scratch_buf_len);
857 if (!scratch_buf) {
858 NTRU_RET(NTRU_OUT_OF_MEMORY);
859 }
860 ringel_buf1 = scratch_buf + (params->N << 1);
861 ringel_buf2 = ringel_buf1 + params->N;
862 F_buf = ringel_buf2 + params->N;
863 tmp_buf = (uint8_t *)scratch_buf;
864
865 /* set hash algorithm and seed length based on security strength */
866
867 if (params->sec_strength_len <= 20) {
868 hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA1;
869 md_len = 20;
870 } else {
871 hash_algid = NTRU_CRYPTO_HASH_ALGID_SHA256;
872 md_len = 32;
873 }
874 seed_len = params->sec_strength_len + 8;
875
876 /* set constants */
877
878 mod_q_mask = params->q - 1;
879
880 /* get random bytes for seed for generating trinary F
881 * as a list of indices
882 */
883
884 result = ntru_crypto_drbg_generate(drbg_handle,
885 params->sec_strength_len << 3,
886 seed_len, tmp_buf);
887
888 if (result == NTRU_OK) {
889
890 /* generate F */
891
892 result = ntru_gen_poly(hash_algid, md_len,
893 params->min_IGF_hash_calls,
894 seed_len, tmp_buf, tmp_buf,
895 params->N, params->c_bits,
896 params->no_bias_limit,
897 params->is_product_form,
898 params->dF_r << 1, F_buf);
899 }
900
901 if (result == NTRU_OK) {
902 uint32_t i;
903
904 memset(ringel_buf1, 0, params->N * sizeof(uint16_t));
905
906 /* form F as a ring element */
907
908 if (params->is_product_form) {
909 uint32_t dF3_offset = (dF1 + dF2) << 1;
910
911 /* form F1 as a ring element */
912
913 for (i = 0; i < dF1; i++)
914 ringel_buf1[F_buf[i]] = 1;
915 for (; i < (dF1 << 1); i++)
916 ringel_buf1[F_buf[i]] = mod_q_mask;
917
918 /* form F1 * F2 */
919
920 ntru_ring_mult_indices(ringel_buf1, (uint16_t)dF2, (uint16_t)dF2,
921 F_buf + (dF1 << 1), params->N, params->q,
922 scratch_buf, ringel_buf1);
923
924 /* form (F1 * F2) + F3 */
925
926 for (i = 0; i < dF3; i++) {
927 uint16_t index = F_buf[dF3_offset + i];
928 ringel_buf1[index] = ++ringel_buf1[index] & mod_q_mask;
929 }
930 for (; i < (dF3 << 1); i++) {
931 uint16_t index = F_buf[dF3_offset + i];
932 ringel_buf1[index] = --ringel_buf1[index] & mod_q_mask;
933 }
934
935 } else {
936
937 /* form F as a ring element */
938
939 for (i = 0; i < dF; i++)
940 ringel_buf1[F_buf[i]] = 1;
941 for (; i < (dF << 1); i++)
942 ringel_buf1[F_buf[i]] = mod_q_mask;
943 }
944
945 /* form f = 1 + pF */
946
947 for (i = 0; i < params->N; i++)
948 ringel_buf1[i] = (ringel_buf1[i] * 3) & mod_q_mask;
949 ringel_buf1[0] = (ringel_buf1[0] + 1) & mod_q_mask;
950
951 /* find f^-1 in (Z/qZ)[X]/(X^N - 1) */
952
953 if (!ntru_ring_inv(ringel_buf1, params->N, params->q,
954 scratch_buf, ringel_buf2))
955 result = NTRU_ERROR_BASE + NTRU_FAIL;
956 }
957
958 if (result == NTRU_OK) {
959
960 /* get random bytes for seed for generating trinary g
961 * as a list of indices
962 */
963 result = ntru_crypto_drbg_generate(drbg_handle,
964 params->sec_strength_len << 3,
965 seed_len, tmp_buf);
966 }
967
968 if (result == NTRU_OK) {
969 uint16_t min_IGF_hash_calls =
970 ((((params->dg << 2) + 2) * params->N_bits) + (md_len << 3) - 1) /
971 (md_len << 3);
972
973 /* generate g */
974
975 result = ntru_gen_poly(hash_algid, md_len,
976 (uint8_t)min_IGF_hash_calls,
977 seed_len, tmp_buf, tmp_buf,
978 params->N, params->c_bits,
979 params->no_bias_limit, FALSE,
980 (params->dg << 1) + 1, ringel_buf1);
981 }
982
983 if (result == NTRU_OK) {
984 uint16_t i;
985
986 /* compute h = p * (f^-1 * g) mod q */
987
988 ntru_ring_mult_indices(ringel_buf2, params->dg + 1, params->dg,
989 ringel_buf1, params->N, params->q, scratch_buf,
990 ringel_buf2);
991
992 for (i = 0; i < params->N; i++)
993 ringel_buf2[i] = (ringel_buf2[i] * 3) & mod_q_mask;
994
995 /* create public key blob */
996
997 ntru_crypto_ntru_encrypt_key_create_pubkey_blob(params, ringel_buf2,
998 pubkey_pack_type,
999 pubkey_blob);
1000 *pubkey_blob_len = public_key_blob_len;
1001
1002 /* create private key blob */
1003
1004 ntru_crypto_ntru_encrypt_key_create_privkey_blob(params, ringel_buf2,
1005 F_buf,
1006 privkey_pack_type,
1007 tmp_buf, privkey_blob);
1008 *privkey_blob_len = private_key_blob_len;
1009 }
1010
1011 /* cleanup */
1012
1013 memset(scratch_buf, 0, scratch_buf_len);
1014 free(scratch_buf);
1015
1016 return result;
1017 }
1018
1019
1020 /* DER-encoding prefix template for NTRU public keys,
1021 * with parameter-set-specific fields nomalized
1022 */
1023
1024 static uint8_t const der_prefix_template[] = {
1025 0x30, 0x82,
1026 0x00, 0x23, /* add pubkey length */
1027 0x30, 0x18, 0x06, 0x0a, 0x2b, 0x06, 0x01,
1028 0x04, 0x01, 0xc1, 0x70, 0x01, 0x01, 0x02, /* end of NTRU OID compare */
1029 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01,
1030 0xc1, 0x70, 0x01, 0x02,
1031 0x00, /* set param-set DER id */
1032 0x03, 0x82,
1033 0x00, 0x05, /* add pubkey length */
1034 0x00, 0x04, 0x82,
1035 0x00, 0x00, /* add pubkey length */
1036 };
1037
1038
1039 /* add_16_to_8s
1040 *
1041 * adds a 16-bit value to two bytes
1042 */
1043
1044 static void
1045 add_16_to_8s(
1046 uint16_t a,
1047 uint8_t *b)
1048 {
1049 uint16_t tmp = ((uint16_t)b[0] << 8) + b[1];
1050
1051 tmp = tmp + a;
1052 b[0] = (uint8_t)((tmp >> 8) & 0xff);
1053 b[1] = (uint8_t)(tmp & 0xff);
1054 }
1055
1056
1057 /* sub_16_from_8s
1058 *
1059 * subtracts a 16-bit value from two bytes
1060 */
1061
1062 static void
1063 sub_16_from_8s(
1064 uint16_t a,
1065 uint8_t *b)
1066 {
1067 uint16_t tmp = ((uint16_t)b[0] << 8) + b[1];
1068
1069 tmp = tmp - a;
1070 b[0] = (uint8_t)((tmp >> 8) & 0xff);
1071 b[1] = (uint8_t)(tmp & 0xff);
1072 }
1073
1074
1075 /* ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo
1076 *
1077 * DER-encodes an NTRUEncrypt public-key from a public-key blob into a
1078 * SubjectPublicKeyInfo field for inclusion in an X.509 certificate.
1079 *
1080 * The required minimum size of the output SubjectPublicKeyInfo buffer
1081 * (encoded_subjectPublicKeyInfo) may be queried by invoking this function
1082 * with encoded_subjectPublicKeyInfo = NULL. In this case, no encoding is
1083 * performed, NTRU_OK is returned, and the required minimum size for
1084 * encoded_subjectPublicKeyInfo is returned in encoded_subjectPublicKeyInfo_len.
1085 *
1086 * When encoded_subjectPublicKeyInfo != NULL, at invocation
1087 * *encoded_subjectPublicKeyInfo_len must be the size of the
1088 * encoded_subjectPublicKeyInfo buffer.
1089 * Upon return, it is the actual size of the encoded public key.
1090 *
1091 * Returns NTRU_OK if successful.
1092 * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
1093 * (other than encoded_subjectPublicKeyInfo) is NULL.
1094 * Returns NTRU_ERROR_BASE + NTRU_BAD_LENGTH if pubkey_blob_len is zero.
1095 * Returns NTRU_ERROR_BASE + NTRU_BAD_PUBLIC_KEY if the public-key blob is
1096 * invalid (unknown format, corrupt, bad length).
1097 * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the SubjectPublicKeyInfo
1098 * buffer is too small.
1099 */
1100
1101 uint32_t
1102 ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(
1103 uint16_t pubkey_blob_len, /* in - no. of octets in public-key
1104 blob */
1105 uint8_t const *pubkey_blob, /* in - ptr to public-key blob */
1106 uint16_t *encoded_subjectPublicKeyInfo_len,
1107 /* in/out - no. of octets in encoded info,
1108 address for no. of octets in
1109 encoded info */
1110 uint8_t *encoded_subjectPublicKeyInfo)
1111 /* out - address for encoded info */
1112 {
1113 NTRU_ENCRYPT_PARAM_SET *params = NULL;
1114 uint8_t const *pubkey_packed = NULL;
1115 uint8_t pubkey_pack_type;
1116 uint16_t packed_pubkey_len;
1117 uint16_t encoded_len;
1118
1119 /* check for bad parameters */
1120
1121 if (!pubkey_blob || !encoded_subjectPublicKeyInfo_len)
1122 NTRU_RET(NTRU_BAD_PARAMETER);
1123 if (pubkey_blob_len == 0)
1124 NTRU_RET(NTRU_BAD_LENGTH);
1125
1126 /* get a pointer to the parameter-set parameters, the packing type for
1127 * the public key, and a pointer to the packed public key
1128 */
1129
1130 if (!ntru_crypto_ntru_encrypt_key_parse(TRUE /* pubkey */, pubkey_blob_len,
1131 pubkey_blob, &pubkey_pack_type,
1132 NULL, &params, &pubkey_packed,
1133 NULL))
1134 NTRU_RET(NTRU_BAD_PUBLIC_KEY);
1135
1136 /* return the encoded_subjectPublicKeyInfo size if requested */
1137
1138 packed_pubkey_len = (params->N * params->q_bits + 7) >> 3;
1139 encoded_len = sizeof(der_prefix_template) + packed_pubkey_len;
1140 if (!encoded_subjectPublicKeyInfo) {
1141 *encoded_subjectPublicKeyInfo_len = encoded_len;
1142 NTRU_RET(NTRU_OK);
1143 }
1144
1145 /* check the encoded_subjectPublicKeyInfo buffer size */
1146
1147 if (*encoded_subjectPublicKeyInfo_len < encoded_len) {
1148 NTRU_RET(NTRU_BUFFER_TOO_SMALL);
1149 }
1150
1151 /* form the encoded subjectPublicKey */
1152
1153 memcpy(encoded_subjectPublicKeyInfo, der_prefix_template,
1154 sizeof(der_prefix_template));
1155 add_16_to_8s(packed_pubkey_len, encoded_subjectPublicKeyInfo + 2);
1156 add_16_to_8s(packed_pubkey_len, encoded_subjectPublicKeyInfo + 32);
1157 add_16_to_8s(packed_pubkey_len, encoded_subjectPublicKeyInfo + 37);
1158 encoded_subjectPublicKeyInfo[29] = params->der_id;
1159 memcpy(encoded_subjectPublicKeyInfo + sizeof(der_prefix_template),
1160 pubkey_packed, packed_pubkey_len);
1161
1162 *encoded_subjectPublicKeyInfo_len = encoded_len;
1163
1164 NTRU_RET(NTRU_OK);
1165 }
1166
1167
1168 /* ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey
1169 *
1170 * Decodes a DER-encoded NTRUEncrypt public-key from a
1171 * SubjectPublicKeyInfo field in an X.509 certificate and returns the
1172 * public-key blob itself.
1173 *
1174 * The required minimum size of the output public-key buffer (pubkey_blob)
1175 * may be queried by invoking this function with pubkey_blob = NULL.
1176 * In this case, no decoding is performed, NTRU_OK is returned, and the
1177 * required minimum size for pubkey_blob is returned in pubkey_blob_len.
1178 *
1179 * When pubkey_blob != NULL, at invocation *pubkey_blob_len must be the
1180 * size of the pubkey_blob buffer.
1181 * Upon return, it is the actual size of the public-key blob.
1182 *
1183 * Returns NTRU_OK if successful.
1184 * Returns NTRU_ERROR_BASE + NTRU_BAD_PARAMETER if an argument pointer
1185 * (other than pubkey_blob) is NULL.
1186 * Returns NTRU_ERROR_BASE + NTRU_BAD_ENCODING if the encoded data is
1187 * an invalid encoding of an NTRU public key.
1188 * Returns NTRU_ERROR_BASE + NTRU_OID_NOT_RECOGNIZED if the
1189 * encoded data contains an OID that identifies an object other than
1190 * an NTRU public key.
1191 * Returns NTRU_ERROR_BASE + NTRU_BUFFER_TOO_SMALL if the pubkey_blob buffer
1192 * is too small.
1193 */
1194
1195 uint32_t
1196 ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(
1197 uint8_t const *encoded_data, /* in - ptr to subjectPublicKeyInfo
1198 in the encoded data */
1199 uint16_t *pubkey_blob_len, /* in/out - no. of octets in pubkey blob,
1200 address for no. of octets in
1201 pubkey blob */
1202 uint8_t *pubkey_blob, /* out - address for pubkey blob */
1203 uint8_t **next) /* out - address for ptr to encoded
1204 data following the
1205 subjectPublicKeyInfo */
1206 {
1207 NTRU_ENCRYPT_PARAM_SET *params = NULL;
1208 uint8_t prefix_buf[39];
1209 bool der_id_valid;
1210 uint16_t packed_pubkey_len = 0;
1211 uint8_t pubkey_pack_type;
1212 uint16_t public_key_blob_len;
1213
1214 /* check for bad parameters */
1215
1216 if (!encoded_data || !pubkey_blob_len || !next)
1217 NTRU_RET(NTRU_BAD_PARAMETER);
1218
1219 /* determine if data to be decoded is a valid encoding of an NTRU
1220 * public key
1221 */
1222
1223 memcpy(prefix_buf, encoded_data, sizeof(prefix_buf));
1224
1225 /* get a pointer to the parameter-set parameters */
1226
1227 if ((params = ntru_encrypt_get_params_with_DER_id(encoded_data[29])) ==
1228 NULL) {
1229 der_id_valid = FALSE;
1230
1231 /* normalize the prefix-buffer data used in an NTRU OID comparison */
1232
1233 prefix_buf[2] = der_prefix_template[2];
1234 prefix_buf[3] = der_prefix_template[3];
1235
1236 } else {
1237 der_id_valid = TRUE;
1238
1239 /* normalize the prefix-buffer data for the specific parameter set */
1240
1241 packed_pubkey_len = (params->N * params->q_bits + 7) >> 3;
1242 sub_16_from_8s(packed_pubkey_len, prefix_buf + 2);
1243 sub_16_from_8s(packed_pubkey_len, prefix_buf + 32);
1244 sub_16_from_8s(packed_pubkey_len, prefix_buf + 37);
1245 prefix_buf[29] = 0;
1246 }
1247
1248 /* validate the DER prefix encoding */
1249
1250 if (!der_id_valid || memcmp(prefix_buf, der_prefix_template,
1251 sizeof(der_prefix_template))) {
1252
1253 /* bad DER prefix, so determine if this is a bad NTRU encoding or an
1254 * unknown OID by comparing the first 18 octets
1255 */
1256
1257 if (memcmp(prefix_buf, der_prefix_template, 18))
1258 NTRU_RET(NTRU_OID_NOT_RECOGNIZED);
1259 else
1260 NTRU_RET(NTRU_BAD_ENCODING);
1261 }
1262
1263 /* get public key packing type and blob length */
1264
1265 ntru_crypto_ntru_encrypt_key_get_blob_params(params, &pubkey_pack_type,
1266 &public_key_blob_len, NULL,
1267 NULL);
1268
1269 /* return the pubkey_blob size if requested */
1270
1271 if (!pubkey_blob) {
1272 *pubkey_blob_len = public_key_blob_len;
1273 NTRU_RET(NTRU_OK);
1274 }
1275
1276 /* check size of output buffer */
1277
1278 if (*pubkey_blob_len < public_key_blob_len)
1279 NTRU_RET(NTRU_BUFFER_TOO_SMALL);
1280
1281 /* create the public-key blob */
1282
1283 ntru_crypto_ntru_encrypt_key_recreate_pubkey_blob(params, packed_pubkey_len,
1284 encoded_data + sizeof(der_prefix_template),
1285 pubkey_pack_type, pubkey_blob);
1286 *pubkey_blob_len = public_key_blob_len;
1287
1288 *next = *next + sizeof(der_prefix_template) + packed_pubkey_len;
1289
1290 NTRU_RET(NTRU_OK);
1291 }
1292