]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/bliss/bliss_private_key.c
Allow SHA256 and SHA384 data hash for BLISS signatures.
[thirdparty/strongswan.git] / src / libstrongswan / plugins / bliss / bliss_private_key.c
CommitLineData
9d5b91d1
AS
1/*
2 * Copyright (C) 2014 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16#include "bliss_private_key.h"
e71813e5 17#include "bliss_public_key.h"
73a32740 18#include "bliss_param_set.h"
e71813e5 19#include "bliss_utils.h"
edd72b6b 20#include "bliss_sampler.h"
e71813e5 21#include "bliss_signature.h"
443346f5 22#include "bliss_bitpacker.h"
8c751b61
AS
23#include "bliss_fft.h"
24
64a5cacd 25#include <crypto/mgf1/mgf1_bitspender.h>
56009f20
AS
26#include <asn1/asn1.h>
27#include <asn1/asn1_parser.h>
28#include <asn1/oid.h>
64a5cacd 29
8c751b61
AS
30#define _GNU_SOURCE
31#include <stdlib.h>
9d5b91d1
AS
32
33typedef struct private_bliss_private_key_t private_bliss_private_key_t;
34
e71813e5 35#define SECRET_KEY_TRIALS_MAX 50
56009f20 36
9d5b91d1
AS
37/**
38 * Private data of a bliss_private_key_t object.
39 */
40struct private_bliss_private_key_t {
41 /**
42 * Public interface for this signer.
43 */
44 bliss_private_key_t public;
45
9d5b91d1 46 /**
73a32740 47 * BLISS signature parameter set
9d5b91d1 48 */
73a32740 49 bliss_param_set_t *set;
9d5b91d1 50
56009f20
AS
51 /**
52 * BLISS secret key S1 (coefficients of polynomial f)
53 */
54 int8_t *s1;
55
56 /**
57 * BLISS secret key S2 (coefficients of polynomial 2g + 1)
58 */
59 int8_t *s2;
60
61 /**
5a50e364 62 * NTT of BLISS public key a (coefficients of polynomial (2g + 1)/f)
56009f20 63 */
5a50e364 64 uint32_t *A;
56009f20 65
9d5b91d1
AS
66 /**
67 * reference count
68 */
69 refcount_t ref;
70};
71
72METHOD(private_key_t, get_type, key_type_t,
73 private_bliss_private_key_t *this)
74{
75 return KEY_BLISS;
76}
77
e71813e5
AS
78/**
79 * Multiply secret vector s with binary challenge vector c
80 */
81static void multiply_by_c(int8_t *s, int n, uint16_t *c_indices,
82 uint16_t kappa, int32_t *product)
83{
84 int i, j, index;
85
86 for (i = 0; i < n; i++)
87 {
88 product[i] = 0;
89
90 for (j = 0; j < kappa; j++)
91 {
92 index = c_indices[j];
93 if (i - index < 0)
94 {
95 product[i] -= s[i - index + n];
96 }
97 else
98 {
99 product[i] += s[i - index];
100 }
101 }
102 }
103}
104
c2aca9ee
AS
105/**
106 * BLISS-B GreedySC algorithm
107 */
108static void greedy_sc(int8_t *s1, int8_t *s2, int n, uint16_t *c_indices,
109 uint16_t kappa, int32_t *v1, int32_t *v2)
110{
111 int i, j, index;
112 int32_t sign;
113
114 for (i = 0; i < n; i++)
115 {
116 v1[i] = v2[i] = 0;
117 }
118 for (j = 0; j < kappa; j++)
119 {
120 index = c_indices[j];
121 sign = 0;
122
123 for (i = 0; i < index; i++)
124 {
125 sign -= (v1[i] * s1[i - index + n] + v2[i] * s2[i - index + n]);
126 }
127 for (i = index; i < n; i++)
128 {
129 sign += (v1[i] * s1[i - index] + v2[i] * s2[i - index]);
130 }
131 for (i = 0; i < index; i++)
132 {
133 if (sign > 0)
134 {
135 v1[i] += s1[i - index + n];
136 v2[i] += s2[i - index + n];
137 }
138 else
139 {
140 v1[i] -= s1[i - index + n];
141 v2[i] -= s2[i - index + n];
142 }
143 }
144 for (i = index; i < n; i++)
145 {
146 if (sign > 0)
147 {
148 v1[i] -= s1[i - index];
149 v2[i] -= s2[i - index];
150 }
151 else
152 {
153 v1[i] += s1[i - index];
154 v2[i] += s2[i - index];
155 }
156 }
157 }
158}
159
e71813e5 160/**
27bd0fed 161 * Compute a BLISS signature
e71813e5 162 */
27bd0fed
AS
163static bool sign_bliss(private_bliss_private_key_t *this, hash_algorithm_t alg,
164 chunk_t data, chunk_t *signature)
edd72b6b 165{
e71813e5
AS
166 bliss_fft_t *fft;
167 bliss_signature_t *sig;
168 bliss_sampler_t *sampler = NULL;
27bd0fed
AS
169 rng_t *rng;
170 hasher_t *hasher;
171 hash_algorithm_t mgf1_alg;
172 size_t mgf1_seed_len;
173 uint8_t mgf1_seed_buf[HASH_SIZE_SHA512], data_hash_buf[HASH_SIZE_SHA512];
174 chunk_t mgf1_seed, data_hash;
e71813e5 175 uint16_t q, q2, p, p2, *c_indices, tests = 0;
5a50e364 176 uint32_t *ay;
e71813e5 177 int32_t *y1, *y2, *z1, *z2, *u, *s1c, *s2c;
f55a03a2
TB
178 int32_t y1_min = 0, y1i, y1_max = 0, y2_min = 0, y2i, y2_max = 0;
179 int32_t scalar, norm, ui;
e71813e5
AS
180 int16_t *ud, *uz2d, *z2d, value;
181 int i, n;
e71813e5 182 double mean1 = 0, mean2 = 0, sigma1 = 0, sigma2 = 0;
c2aca9ee 183 bool accepted, positive, success = FALSE, use_bliss_b;
e71813e5
AS
184
185 /* Initialize signature */
186 *signature = chunk_empty;
187
188 /* Create data hash */
27bd0fed 189 hasher = lib->crypto->create_hasher(lib->crypto, alg);
a8e82ace 190 if (!hasher)
e71813e5
AS
191 {
192 return FALSE;
193 }
27bd0fed
AS
194 data_hash = chunk_create(data_hash_buf, hasher->get_hash_size(hasher));
195
e71813e5
AS
196 if (!hasher->get_hash(hasher, data, data_hash_buf))
197 {
198 hasher->destroy(hasher);
199 return FALSE;
200 }
27bd0fed
AS
201 hasher->destroy(hasher);
202
203 /* Create SHA512 hasher for c_indices oracle */
204 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512);
205 if (!hasher)
206 {
207 return FALSE;
208 }
edd72b6b
AS
209
210 /* Set MGF1 hash algorithm and seed length based on security strength */
211 if (this->set->strength > 160)
212 {
27bd0fed
AS
213 mgf1_alg = HASH_SHA256;
214 mgf1_seed_len = HASH_SIZE_SHA256;
edd72b6b
AS
215 }
216 else
217 {
27bd0fed
AS
218 mgf1_alg = HASH_SHA1;
219 mgf1_seed_len = HASH_SIZE_SHA1;
edd72b6b 220 }
27bd0fed 221 mgf1_seed = chunk_create(mgf1_seed_buf, mgf1_seed_len);
edd72b6b 222
e71813e5 223 rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
edd72b6b
AS
224 if (!rng)
225 {
e71813e5 226 hasher->destroy(hasher);
edd72b6b
AS
227 return FALSE;
228 }
edd72b6b 229
e71813e5
AS
230 /* Initialize a couple of needed variables */
231 n = this->set->n;
232 q = this->set->q;
233 p = this->set->p;
234 q2 = 2 * q;
235 p2 = p / 2;
e71813e5
AS
236 ay = malloc(n * sizeof(uint32_t));
237 z2 = malloc(n * sizeof(int32_t));
238 s1c = malloc(n * sizeof(int32_t));
239 s2c = malloc(n * sizeof(int32_t));
240 u = malloc(n * sizeof(int32_t));
241 uz2d = malloc(n * sizeof(int16_t));
242
243 sig = bliss_signature_create(this->set);
244 sig->get_parameters(sig, &z1, &z2d, &c_indices);
245 y1 = z1;
246 y2 = z2;
247 ud = z2d;
248
249 fft = bliss_fft_create(this->set->fft_params);
e71813e5 250
c2aca9ee
AS
251 /* Use of the enhanced BLISS-B signature algorithm? */
252 switch (this->set->id)
253 {
254 case BLISS_I:
255 case BLISS_II:
256 case BLISS_III:
257 case BLISS_IV:
258 use_bliss_b = FALSE;
259 break;
260 case BLISS_B_I:
261 case BLISS_B_II:
262 case BLISS_B_III:
263 case BLISS_B_IV:
264 use_bliss_b = TRUE;
265 break;
266 }
267
e71813e5 268 while (true)
edd72b6b 269 {
e71813e5 270 tests++;
edd72b6b 271
27bd0fed 272 if (!rng->get_bytes(rng, mgf1_seed_len, mgf1_seed_buf))
e71813e5
AS
273 {
274 goto end;
275 }
276 DESTROY_IF(sampler);
edd72b6b 277
27bd0fed 278 sampler = bliss_sampler_create(mgf1_alg, mgf1_seed, this->set);
e71813e5 279 if (!sampler)
edd72b6b 280 {
e71813e5 281 goto end;
edd72b6b 282 }
e71813e5
AS
283
284 /* Gaussian sampling for vectors y1 and y2 */
285 for (i = 0; i < n; i++)
286 {
287 if (!sampler->gaussian(sampler, &y1i) ||
288 !sampler->gaussian(sampler, &y2i))
289 {
290 goto end;
291 }
292 y1[i] = y1i;
293 y2[i] = y2i;
294
295 /* Collect statistical data on rejection sampling */
296 if (i == 0)
297 {
298 y1_min = y1_max = y1i;
299 y2_min = y2_max = y2i;
300 }
301 else
302 {
303 if (y1i < y1_min)
304 {
305 y1_min = y1i;
306 }
307 else if (y1i > y1_max)
308 {
309 y1_max = y1i;
310 }
311 if (y2i < y2_min)
312 {
313 y2_min = y2i;
314 }
315 else if (y2i > y2_max)
316 {
317 y2_max = y2i;
318 }
319 }
320 mean1 += y1i;
321 mean2 += y2i;
322 sigma1 += y1i * y1i;
323 sigma2 += y2i * y2i;
324
325 ay[i] = y1i < 0 ? q + y1i : y1i;
326 }
327
328 /* Compute statistics on vectors y1 and y2 */
329 mean1 /= n;
330 mean2 /= n;
331 sigma1 /= n;
332 sigma2 /= n;
333 sigma2 -= mean1 * mean1;
334 sigma2 -= mean2 * mean2;
335 DBG2(DBG_LIB, "y1 = %d..%d (sigma2 = %5.0f, mean = %4.1f)",
336 y1_min, y1_max, sigma1, mean1);
337 DBG2(DBG_LIB, "y2 = %d..%d (sigma2 = %5.0f, mean = %4.1f)",
338 y2_min, y2_max, sigma2, mean2);
339
340 fft->transform(fft, ay, ay, FALSE);
341
342 for (i = 0; i < n; i++)
edd72b6b 343 {
5a50e364 344 ay[i] = (this->A[i] * ay[i]) % q;
edd72b6b 345 }
e71813e5 346 fft->transform(fft, ay, ay, TRUE);
edd72b6b 347
e71813e5
AS
348 for (i = 0; i < n; i++)
349 {
350 ui = 2 * this->set->q2_inv * (int32_t)ay[i] + y2[i];
351 u[i] = ((ui < 0) ? q2 + ui : ui) % q2;
352 }
353 bliss_utils_round_and_drop(this->set, u, ud);
edd72b6b 354
e71813e5
AS
355 /* Detailed debugging information */
356 DBG3(DBG_LIB, " i u[i] ud[i]");
357 for (i = 0; i < n; i++)
358 {
359 DBG3(DBG_LIB, "%3d %6d %4d", i, u[i], ud[i]);
360 }
361
362 if (!bliss_utils_generate_c(hasher, data_hash, ud, n, this->set->kappa,
363 c_indices))
364 {
365 goto end;
366 }
edd72b6b 367
c2aca9ee
AS
368 if (use_bliss_b)
369 {
370 /* Compute v = (s1c, s2c) with the GreedySC algorithm */
371 greedy_sc(this->s1, this->s2, n, c_indices, this->set->kappa,
372 s1c, s2c);
373
374 /* Compute norm = ||v||^2 = ||Sc'||^2 */
375 norm = bliss_utils_scalar_product(s1c, s1c, n) +
376 bliss_utils_scalar_product(s2c, s2c, n);
377
378 /* Just in case. ||v||^2 <= P_max should always be fulfilled */
379 if (norm > this->set->p_max)
380 {
381 goto end;
382 }
383 }
384 else
385 {
386 /* Compute s*c */
387 multiply_by_c(this->s1, n, c_indices, this->set->kappa, s1c);
388 multiply_by_c(this->s2, n, c_indices, this->set->kappa, s2c);
e71813e5 389
c2aca9ee
AS
390 /* Compute norm = |Sc||^2 */
391 norm = bliss_utils_scalar_product(s1c, s1c, n) +
392 bliss_utils_scalar_product(s2c, s2c, n);
393 }
e71813e5
AS
394
395 if (!sampler->bernoulli_exp(sampler, this->set->M - norm, &accepted))
396 {
397 goto end;
398 }
c2aca9ee
AS
399 if (use_bliss_b)
400 {
401 DBG2(DBG_LIB, "norm2(s1*c') + norm2(s2*c') = %u (%u max), %s",
402 norm, this->set->p_max, accepted ? "accepted" : "rejected");
403
404 }
405 else
406 {
407 DBG2(DBG_LIB, "norm2(s1*c) + norm2(s2*c) = %u, %s",
408 norm, accepted ? "accepted" : "rejected");
409 }
e71813e5
AS
410 if (!accepted)
411 {
412 continue;
413 }
414
415 /* Compute z */
416 if (!sampler->sign(sampler, &positive))
417 {
418 goto end;
419 }
420 for (i = 0; i < n; i++)
421 {
422 if (positive)
423 {
424 z1[i] = y1[i] + s1c[i];
425 z2[i] = y2[i] + s2c[i];
426 }
427 else
428 {
429 z1[i] = y1[i] - s1c[i];
430 z2[i] = y2[i] - s2c[i];
431 }
432 }
433 /* Reject with probability 1/cosh(scalar/sigma^2) */
434 scalar = bliss_utils_scalar_product(z1, s1c, n) +
435 bliss_utils_scalar_product(z2, s2c, n);
436
437 if (!sampler->bernoulli_cosh(sampler, scalar, &accepted))
438 {
439 goto end;
440 }
441 DBG2(DBG_LIB, "scalar(z1,s1*c) + scalar(z2,s2*c) = %d, %s",
442 scalar, accepted ? "accepted" : "rejected");
443 if (!accepted)
444 {
445 continue;
446 }
447
448 /* Compute z2 with dropped bits */
449 for (i = 0; i < n; i++)
450 {
451 u[i] -= z2[i];
452 if (u[i] < 0)
453 {
454 u[i] += q2;
455 }
456 else if (u[i] >= q2)
457 {
458 u[i] -= q2;
459 }
460 }
461 bliss_utils_round_and_drop(this->set, u, uz2d);
462
463 for (i = 0; i < n; i++)
464 {
465 value = ud[i] - uz2d[i];
466 if (value <= -p2)
467 {
468 value += p;
469 }
470 else if (value > p2)
471 {
472 value -= p;
473 }
474 z2d[i] = value;
475 }
476
477 if (!bliss_utils_check_norms(this->set, z1, z2d))
478 {
479 continue;
480 }
83447555
AS
481
482 *signature = sig->get_encoding(sig);
483 if (signature->len == 0)
484 {
485 DBG1(DBG_LIB, "inefficient Huffman coding of signature");
486 continue;
487 }
e71813e5
AS
488 DBG2(DBG_LIB, "signature generation needed %u round%s", tests,
489 (tests == 1) ? "" : "s");
490 break;
491 }
492 success = TRUE;
493
e71813e5
AS
494end:
495 /* cleanup */
a8e82ace 496 DESTROY_IF(sampler);
e71813e5
AS
497 hasher->destroy(hasher);
498 sig->destroy(sig);
499 fft->destroy(fft);
500 rng->destroy(rng);
bf749fa1
AS
501 memwipe(s1c, n * sizeof(int32_t));
502 memwipe(s2c, n * sizeof(int32_t));
e71813e5
AS
503 free(s1c);
504 free(s2c);
bf749fa1
AS
505 free(ay);
506 free(z2);
e71813e5
AS
507 free(u);
508 free(uz2d);
509
510 return success;
edd72b6b
AS
511}
512
9d5b91d1
AS
513METHOD(private_key_t, sign, bool,
514 private_bliss_private_key_t *this, signature_scheme_t scheme,
515 chunk_t data, chunk_t *signature)
516{
517 switch (scheme)
518 {
27bd0fed
AS
519 case SIGN_BLISS_WITH_SHA256:
520 return sign_bliss(this, HASH_SHA256, data, signature);
521 case SIGN_BLISS_WITH_SHA384:
522 return sign_bliss(this, HASH_SHA384, data, signature);
f673966b 523 case SIGN_BLISS_WITH_SHA512:
27bd0fed 524 return sign_bliss(this, HASH_SHA512, data, signature);
9d5b91d1
AS
525 default:
526 DBG1(DBG_LIB, "signature scheme %N not supported with BLISS",
527 signature_scheme_names, scheme);
528 return FALSE;
529 }
530}
531
532METHOD(private_key_t, decrypt, bool,
533 private_bliss_private_key_t *this, encryption_scheme_t scheme,
534 chunk_t crypto, chunk_t *plain)
535{
536 DBG1(DBG_LIB, "encryption scheme %N not supported",
537 encryption_scheme_names, scheme);
538 return FALSE;
539}
540
541METHOD(private_key_t, get_keysize, int,
542 private_bliss_private_key_t *this)
543{
73a32740 544 return this->set->strength;
9d5b91d1
AS
545}
546
547METHOD(private_key_t, get_public_key, public_key_t*,
548 private_bliss_private_key_t *this)
549{
56009f20
AS
550 public_key_t *public;
551 chunk_t pubkey;
552
0d8a3f5d 553 pubkey = bliss_public_key_info_encode(this->set->oid, this->A, this->set);
56009f20
AS
554 public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_BLISS,
555 BUILD_BLOB_ASN1_DER, pubkey, BUILD_END);
556 free(pubkey.ptr);
9d5b91d1
AS
557
558 return public;
559}
560
561METHOD(private_key_t, get_encoding, bool,
562 private_bliss_private_key_t *this, cred_encoding_type_t type,
563 chunk_t *encoding)
564{
56009f20
AS
565 switch (type)
566 {
567 case PRIVKEY_ASN1_DER:
568 case PRIVKEY_PEM:
569 {
443346f5
AS
570 chunk_t s1, s2, pubkey;
571 bliss_bitpacker_t *packer;
572 size_t s_bits;
573 int8_t value;
56009f20 574 bool success = TRUE;
443346f5 575 int i;
9d5b91d1 576
0d8a3f5d 577 pubkey = bliss_public_key_encode(this->A, this->set);
9d5b91d1 578
443346f5
AS
579 /* Use either 2 or 3 bits per array element */
580 s_bits = 2 + (this->set->non_zero2 > 0);
581
582 /* Encode secret s1 */
583 packer = bliss_bitpacker_create(s_bits * this->set->n);
584 for (i = 0; i < this->set->n; i++)
585 {
586 packer->write_bits(packer, this->s1[i], s_bits);
587 }
588 s1 = packer->extract_buf(packer);
589 packer->destroy(packer);
590
591 /* Encode secret s2 */
592 packer = bliss_bitpacker_create(s_bits * this->set->n);
593 for (i = 0; i < this->set->n; i++)
594 {
595 value = this->s2[i];
596 if (i == 0)
597 {
598 value -= 1;
599 }
600 value /= 2;
601 packer->write_bits(packer, value, s_bits);
602 }
603 s2 = packer->extract_buf(packer);
604 packer->destroy(packer);
56009f20
AS
605
606 *encoding = asn1_wrap(ASN1_SEQUENCE, "mmss",
607 asn1_build_known_oid(this->set->oid),
0d8a3f5d 608 asn1_bitstring("m", pubkey),
443346f5
AS
609 asn1_bitstring("m", s1),
610 asn1_bitstring("m", s2)
56009f20 611 );
56009f20
AS
612 if (type == PRIVKEY_PEM)
613 {
614 chunk_t asn1_encoding = *encoding;
615
616 success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
617 NULL, encoding, CRED_PART_BLISS_PRIV_ASN1_DER,
618 asn1_encoding, CRED_PART_END);
619 chunk_clear(&asn1_encoding);
620 }
621 return success;
622 }
623 default:
624 return FALSE;
625 }
9d5b91d1
AS
626}
627
628METHOD(private_key_t, get_fingerprint, bool,
629 private_bliss_private_key_t *this, cred_encoding_type_t type, chunk_t *fp)
630{
56009f20
AS
631 bool success;
632
633 if (lib->encoding->get_cache(lib->encoding, type, this, fp))
634 {
635 return TRUE;
636 }
5a50e364 637 success = bliss_public_key_fingerprint(this->set->oid, this->A,
0d8a3f5d 638 this->set, type, fp);
c2aca9ee
AS
639 if (success)
640 {
641 lib->encoding->cache(lib->encoding, type, this, *fp);
642 }
9d5b91d1
AS
643 return success;
644}
645
646METHOD(private_key_t, get_ref, private_key_t*,
647 private_bliss_private_key_t *this)
648{
649 ref_get(&this->ref);
650 return &this->public.key;
651}
652
653METHOD(private_key_t, destroy, void,
654 private_bliss_private_key_t *this)
655{
656 if (ref_put(&this->ref))
657 {
56009f20 658 lib->encoding->clear_cache(lib->encoding, this);
bfb708ea
AS
659 if (this->s1)
660 {
661 memwipe(this->s1, this->set->n * sizeof(int8_t));
662 free(this->s1);
663 }
664 if (this->s2)
665 {
666 memwipe(this->s2, this->set->n * sizeof(int8_t));
667 free(this->s2);
668 }
5a50e364 669 free(this->A);
9d5b91d1
AS
670 free(this);
671 }
672}
673
674/**
675 * Internal generic constructor
676 */
677static private_bliss_private_key_t *bliss_private_key_create_empty(void)
678{
679 private_bliss_private_key_t *this;
680
681 INIT(this,
682 .public = {
683 .key = {
684 .get_type = _get_type,
685 .sign = _sign,
686 .decrypt = _decrypt,
687 .get_keysize = _get_keysize,
688 .get_public_key = _get_public_key,
689 .equals = private_key_equals,
690 .belongs_to = private_key_belongs_to,
691 .get_fingerprint = _get_fingerprint,
692 .has_fingerprint = private_key_has_fingerprint,
693 .get_encoding = _get_encoding,
694 .get_ref = _get_ref,
695 .destroy = _destroy,
696 },
697 },
698 .ref = 1,
699 );
700 return this;
701}
702
8c751b61
AS
703/**
704 * Compute the scalar product of a vector x with a negative wrapped vector y
705 */
64a5cacd 706static int16_t wrapped_product(int8_t *x, int8_t *y, int n, int shift)
8c751b61
AS
707{
708 int16_t product = 0;
709 int i;
710
711 for (i = 0; i < n - shift; i++)
712 {
713 product += x[i] * y[i + shift];
714 }
715 for (i = n - shift; i < n; i++)
716 {
717 product -= x[i] * y[i + shift - n];
718 }
719 return product;
720}
721
722/**
723 * Apply a negative wrapped rotation to a vector x
724 */
725static void wrap(int16_t *x, int n, int shift, int16_t *x_wrapped)
726{
727 int i;
728
729 for (i = 0; i < n - shift; i++)
730 {
731 x_wrapped[i + shift] = x[i];
732 }
733 for (i = n - shift; i < n; i++)
734 {
735 x_wrapped[i + shift - n] = -x[i];
736 }
737}
738
64a5cacd
AS
739/**
740 * int16_t compare function needed for qsort()
741 */
8c751b61
AS
742static int compare(const int16_t *a, const int16_t *b)
743{
744 int16_t temp = *a - *b;
745
746 if (temp > 0)
747 {
748 return 1;
749 }
750 else if (temp < 0)
751 {
752 return -1;
753 }
754 else
755 {
756 return 0;
757 }
758}
759
760/**
761 * Compute the Nk(S) norm of S = (s1, s2)
762 */
64a5cacd 763static uint32_t nks_norm(int8_t *s1, int8_t *s2, int n, uint16_t kappa)
8c751b61
AS
764{
765 int16_t t[n], t_wrapped[n], max_kappa[n];
766 uint32_t nks = 0;
73a32740 767 int i, j;
8c751b61
AS
768
769 for (i = 0; i < n; i++)
770 {
771 t[i] = wrapped_product(s1, s1, n, i) + wrapped_product(s2, s2, n, i);
8c751b61
AS
772 }
773
774 for (i = 0; i < n; i++)
775 {
776 wrap(t, n, i, t_wrapped);
777 qsort(t_wrapped, n, sizeof(int16_t), (__compar_fn_t)compare);
778 max_kappa[i] = 0;
779
780 for (j = 1; j <= kappa; j++)
781 {
782 max_kappa[i] += t_wrapped[n - j];
783 }
8c751b61
AS
784 }
785 qsort(max_kappa, n, sizeof(int16_t), (__compar_fn_t)compare);
786
787 for (i = 1; i <= kappa; i++)
788 {
789 nks += max_kappa[n - i];
790 }
791 return nks;
792}
793
794/**
795 * Compute the inverse x1 of x modulo q as x^(-1) = x^(q-2) mod q
796 */
797static uint32_t invert(uint32_t x, uint16_t q)
798{
799 uint32_t x1, x2;
800 uint16_t q2;
801 int i, i_max;
802
803 q2 = q - 2;
804 x1 = (q2 & 1) ? x : 1;
805 x2 = x;
806 i_max = 15;
807
808 while ((q2 & (1 << i_max)) == 0)
809 {
810 i_max--;
811 }
812 for (i = 1; i <= i_max; i++)
813 {
814 x2 = (x2 * x2) % q;
815
816 if (q2 & (1 << i))
817 {
818 x1 = (x1 * x2) % q;
819 }
820 }
821
822 return x1;
823}
824
64a5cacd
AS
825/**
826 * Create a vector with sparse and small coefficients from seed
827 */
828static int8_t* create_vector_from_seed(private_bliss_private_key_t *this,
829 hash_algorithm_t alg, chunk_t seed)
830{
831 mgf1_bitspender_t *bitspender;
832 uint32_t index, sign;
833 int8_t *vector;
834 int non_zero;
835
836 bitspender = mgf1_bitspender_create(alg, seed, FALSE);
837 if (!bitspender)
838 {
839 return NULL;
840 }
841
842 vector = malloc(sizeof(int8_t) * this->set->n);
843 memset(vector, 0x00, this->set->n);
844
845 non_zero = this->set->non_zero1;
846 while (non_zero)
847 {
edd72b6b 848 if (!bitspender->get_bits(bitspender, this->set->n_bits, &index))
64a5cacd
AS
849 {
850 free(vector);
851 return NULL;
852 }
853 if (vector[index] != 0)
854 {
855 continue;
856 }
857
edd72b6b 858 if (!bitspender->get_bits(bitspender, 1, &sign))
64a5cacd
AS
859 {
860 free(vector);
861 return NULL;
862 }
863 vector[index] = sign ? 1 : -1;
864 non_zero--;
865 }
866
867 non_zero = this->set->non_zero2;
868 while (non_zero)
869 {
edd72b6b 870 if (!bitspender->get_bits(bitspender, this->set->n_bits, &index))
64a5cacd
AS
871 {
872 free(vector);
873 return NULL;
874 }
875 if (vector[index] != 0)
876 {
877 continue;
878 }
879
edd72b6b 880 if (!bitspender->get_bits(bitspender, 1, &sign))
64a5cacd
AS
881 {
882 free(vector);
883 return NULL;
884 }
edd72b6b 885 vector[index] = sign ? 2 : -2;
64a5cacd
AS
886 non_zero--;
887 }
888 bitspender->destroy(bitspender);
889
890 return vector;
891}
892
893/**
894 * Generate the secret key S = (s1, s2) fulfilling the Nk(S) norm
895 */
896static bool create_secret(private_bliss_private_key_t *this, rng_t *rng,
897 int8_t **s1, int8_t **s2, int *trials)
898{
899 uint8_t seed_buf[32];
900 uint8_t *f, *g;
901 uint32_t l2_norm, nks;
902 int i, n;
903 chunk_t seed;
904 size_t seed_len;
905 hash_algorithm_t alg;
906
907 n = this->set->n;
908 *s1 = NULL;
909 *s2 = NULL;
910
911 /* Set MGF1 hash algorithm and seed length based on security strength */
912 if (this->set->strength > 160)
913 {
914 alg = HASH_SHA256;
915 seed_len = HASH_SIZE_SHA256;
916 }
917 else
918 {
919 alg = HASH_SHA1;
920 seed_len = HASH_SIZE_SHA1;
921 }
922 seed = chunk_create(seed_buf, seed_len);
923
924 while (*trials < SECRET_KEY_TRIALS_MAX)
925 {
926 (*trials)++;
927
928 if (!rng->get_bytes(rng, seed_len, seed_buf))
929 {
930 return FALSE;
931 }
932 f = create_vector_from_seed(this, alg, seed);
933 if (f == NULL)
934 {
935 return FALSE;
936 }
937 if (!rng->get_bytes(rng, seed_len, seed_buf))
938 {
939 free(f);
940 return FALSE;
941 }
942 g = create_vector_from_seed(this, alg, seed);
943 if (g == NULL)
944 {
945 free(f);
946 return FALSE;
947 }
948
949 /* Compute 2g + 1 */
950 for (i = 0; i < n; i++)
951 {
952 g[i] *= 2;
953 }
954 g[0] += 1;
955
956 l2_norm = wrapped_product(f, f, n, 0) + wrapped_product(g, g, n, 0);
957 nks = nks_norm(f, g, n, this->set->kappa);
c2aca9ee
AS
958
959 switch (this->set->id)
64a5cacd 960 {
c2aca9ee
AS
961 case BLISS_I:
962 case BLISS_II:
963 case BLISS_III:
964 case BLISS_IV:
965 DBG2(DBG_LIB, "l2 norm of s1||s2: %d, Nk(S): %u (%u max)",
966 l2_norm, nks, this->set->nks_max);
967 if (nks < this->set->nks_max)
968 {
969 *s1 = f;
970 *s2 = g;
971 return TRUE;
972 }
973 free(f);
974 free(g);
975 break;
976 case BLISS_B_I:
977 case BLISS_B_II:
978 case BLISS_B_III:
979 case BLISS_B_IV:
980 DBG2(DBG_LIB, "l2 norm of s1||s2: %d, Nk(S): %u",
981 l2_norm, nks);
982 *s1 = f;
983 *s2 = g;
984 return TRUE;
64a5cacd 985 }
64a5cacd
AS
986 }
987
988 return FALSE;
989}
990
9d5b91d1
AS
991/**
992 * See header.
993 */
994bliss_private_key_t *bliss_private_key_gen(key_type_t type, va_list args)
995{
996 private_bliss_private_key_t *this;
c2aca9ee 997 u_int key_size = BLISS_B_I;
64a5cacd 998 int i, n, trials = 0;
5a50e364 999 uint32_t *S1, *S2, *a;
64a5cacd 1000 uint16_t q;
64a5cacd 1001 bool success = FALSE;
73a32740 1002 bliss_param_set_t *set;
8c751b61 1003 bliss_fft_t *fft;
64a5cacd 1004 rng_t *rng;
73a32740 1005
9d5b91d1
AS
1006 while (TRUE)
1007 {
1008 switch (va_arg(args, builder_part_t))
1009 {
1010 case BUILD_KEY_SIZE:
1011 key_size = va_arg(args, u_int);
1012 continue;
1013 case BUILD_END:
1014 break;
1015 default:
1016 return NULL;
1017 }
1018 break;
1019 }
1020
c2aca9ee
AS
1021 if (lib->settings->get_bool(lib->settings, "%s.plugins.bliss.use_bliss_b",
1022 TRUE, lib->ns))
1023 {
1024 switch (key_size)
1025 {
1026 case BLISS_I:
1027 key_size = BLISS_B_I;
1028 break;
1029 case BLISS_II:
1030 key_size = BLISS_B_II;
1031 break;
1032 case BLISS_III:
1033 key_size = BLISS_B_III;
1034 break;
1035 case BLISS_IV:
1036 key_size = BLISS_B_IV;
1037 break;
1038 default:
1039 break;
1040 }
1041 }
1042
1043 /* Only BLISS or BLISS-B types I, III, or IV are currently supported */
73a32740
AS
1044 set = bliss_param_set_get_by_id(key_size);
1045 if (!set)
9d5b91d1 1046 {
c2aca9ee 1047 DBG1(DBG_LIB, "BLISS parameter set %u not supported", key_size);
9d5b91d1
AS
1048 return NULL;
1049 }
1050
73a32740
AS
1051 /* Some shortcuts for often used variables */
1052 n = set->n;
1053 q = set->q;
1054
1055 if (set->fft_params->n != n || set->fft_params->q != q)
1056 {
1057 DBG1(DBG_LIB, "FFT parameters do not match BLISS parameters");
1058 return NULL;
1059 }
9d5b91d1 1060 this = bliss_private_key_create_empty();
73a32740 1061 this->set = set;
9d5b91d1 1062
8c751b61 1063 /* We derive the public key from the private key using the FFT */
73a32740 1064 fft = bliss_fft_create(set->fft_params);
8c751b61 1065
64a5cacd
AS
1066 /* Some vectors needed to derive the publi key */
1067 S1 = malloc(n * sizeof(uint32_t));
1068 S2 = malloc(n * sizeof(uint32_t));
5a50e364
AS
1069 a = malloc(n * sizeof(uint32_t));
1070 this->A = malloc(n * sizeof(uint32_t));
8c751b61 1071
64a5cacd
AS
1072 /* Instantiate a true random generator */
1073 rng = lib->crypto->create_rng(lib->crypto, RNG_TRUE);
8c751b61 1074
64a5cacd
AS
1075 /* Loop until we have an invertible polynomial s1 */
1076 do
8c751b61 1077 {
56009f20 1078 if (!create_secret(this, rng, &this->s1, &this->s2, &trials))
64a5cacd
AS
1079 {
1080 break;
1081 }
1082
1083 /* Convert signed arrays to unsigned arrays before FFT */
1084 for (i = 0; i < n; i++)
1085 {
56009f20
AS
1086 S1[i] = (this->s1[i] < 0) ? this->s1[i] + q : this->s1[i];
1087 S2[i] = (this->s2[i] > 0) ? q - this->s2[i] : -this->s2[i];
64a5cacd
AS
1088 }
1089 fft->transform(fft, S1, S1, FALSE);
1090 fft->transform(fft, S2, S2, FALSE);
1091
1092 success = TRUE;
1093 for (i = 0; i < n; i++)
1094 {
1095 if (S1[i] == 0)
1096 {
1097 DBG1(DBG_LIB, "S1[%d] is zero - s1 is not invertible", i);
56009f20
AS
1098 free(this->s1);
1099 free(this->s2);
1100 this->s1 = NULL;
1101 this->s2 = NULL;
64a5cacd
AS
1102 success = FALSE;
1103 break;
1104 }
5a50e364
AS
1105 this->A[i] = invert(S1[i], q);
1106 this->A[i] = (S2[i] * this->A[i]) % q;
64a5cacd 1107 }
8c751b61 1108 }
64a5cacd 1109 while (!success && trials < SECRET_KEY_TRIALS_MAX);
8c751b61 1110
64a5cacd
AS
1111 DBG1(DBG_LIB, "secret key generation %s after %d trial%s",
1112 success ? "succeeded" : "failed", trials, (trials == 1) ? "" : "s");
1113
1114 if (success)
8c751b61 1115 {
5a50e364 1116 fft->transform(fft, this->A, a, TRUE);
64a5cacd
AS
1117
1118 DBG4(DBG_LIB, " i f g a F G A");
1119 for (i = 0; i < n; i++)
8c751b61 1120 {
64a5cacd 1121 DBG4(DBG_LIB, "%4d %3d %3d %5u %5u %5u %5u",
5a50e364 1122 i, this->s1[i], this->s2[i], a[i], S1[i], S2[i], this->A[i]);
8c751b61 1123 }
8c751b61 1124 }
64a5cacd 1125 else
8c751b61 1126 {
64a5cacd 1127 destroy(this);
8c751b61
AS
1128 }
1129
1130 /* Cleanup */
1131 fft->destroy(fft);
64a5cacd 1132 rng->destroy(rng);
bf749fa1
AS
1133 memwipe(S1, n * sizeof(uint32_t));
1134 memwipe(S2, n * sizeof(uint32_t));
64a5cacd
AS
1135 free(S1);
1136 free(S2);
5a50e364 1137 free(a);
8c751b61 1138
64a5cacd 1139 return success ? &this->public : NULL;
9d5b91d1
AS
1140}
1141
56009f20
AS
1142/**
1143 * ASN.1 definition of a BLISS private key
1144 */
1145static const asn1Object_t privkeyObjects[] = {
443346f5
AS
1146 { 0, "BLISSPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
1147 { 1, "keyType", ASN1_OID, ASN1_BODY }, /* 1 */
1148 { 1, "public", ASN1_BIT_STRING, ASN1_BODY }, /* 2 */
1149 { 1, "secret1", ASN1_BIT_STRING, ASN1_BODY }, /* 3 */
1150 { 1, "secret2", ASN1_BIT_STRING, ASN1_BODY }, /* 4 */
1151 { 0, "exit", ASN1_EOC, ASN1_EXIT }
56009f20
AS
1152};
1153#define PRIV_KEY_TYPE 1
1154#define PRIV_KEY_PUBLIC 2
1155#define PRIV_KEY_SECRET1 3
1156#define PRIV_KEY_SECRET2 4
1157
9d5b91d1
AS
1158/**
1159 * See header.
1160 */
1161bliss_private_key_t *bliss_private_key_load(key_type_t type, va_list args)
1162{
1163 private_bliss_private_key_t *this;
56009f20 1164 chunk_t key = chunk_empty, object;
443346f5 1165 bliss_bitpacker_t *packer;
56009f20 1166 asn1_parser_t *parser;
443346f5 1167 size_t s_bits = 0;
c2aca9ee 1168 int8_t s, s_min, s_max;
9b4e411c 1169 uint32_t s_sign = 0x02, s_mask = 0xfffffffc, value;
56009f20 1170 bool success = FALSE;
443346f5 1171 int objectID, oid, i;
9d5b91d1
AS
1172
1173 while (TRUE)
1174 {
1175 switch (va_arg(args, builder_part_t))
1176 {
56009f20
AS
1177 case BUILD_BLOB_ASN1_DER:
1178 key = va_arg(args, chunk_t);
1179 continue;
1180 case BUILD_END:
1181 break;
9d5b91d1
AS
1182 default:
1183 return NULL;
1184 }
1185 break;
1186 }
1187
56009f20
AS
1188 if (key.len == 0)
1189 {
1190 return NULL;
1191 }
9d5b91d1
AS
1192 this = bliss_private_key_create_empty();
1193
56009f20
AS
1194 parser = asn1_parser_create(privkeyObjects, key);
1195 parser->set_flags(parser, FALSE, TRUE);
1196
1197 while (parser->iterate(parser, &objectID, &object))
1198 {
1199 switch (objectID)
1200 {
1201 case PRIV_KEY_TYPE:
1202 oid = asn1_known_oid(object);
1203 if (oid == OID_UNKNOWN)
1204 {
1205 goto end;
1206 }
1207 this->set = bliss_param_set_get_by_oid(oid);
1208 if (this->set == NULL)
1209 {
1210 goto end;
1211 }
c2aca9ee
AS
1212 if (lib->settings->get_bool(lib->settings,
1213 "%s.plugins.bliss.use_bliss_b",TRUE, lib->ns))
1214 {
1215 switch (this->set->id)
1216 {
1217 case BLISS_I:
1218 this->set = bliss_param_set_get_by_id(BLISS_B_I);
1219 break;
1220 case BLISS_III:
1221 this->set = bliss_param_set_get_by_id(BLISS_B_III);
1222 break;
1223 case BLISS_IV:
1224 this->set = bliss_param_set_get_by_id(BLISS_B_IV);
1225 break;
1226 default:
1227 break;
1228 }
1229 }
1230 if (this->set->non_zero2)
1231 {
1232 s_min = -2;
1233 s_max = 2;
1234 s_bits = 3;
1235 }
1236 else
1237 {
1238 s_min = -1;
1239 s_max = 1;
1240 s_bits = 2;
1241 }
443346f5
AS
1242 s_sign = 1 << (s_bits - 1);
1243 s_mask = ((1 << (32 - s_bits)) - 1) << s_bits;
56009f20
AS
1244 break;
1245 case PRIV_KEY_PUBLIC:
0d8a3f5d 1246 if (!bliss_public_key_from_asn1(object, this->set, &this->A))
56009f20
AS
1247 {
1248 goto end;
1249 }
56009f20
AS
1250 break;
1251 case PRIV_KEY_SECRET1:
443346f5 1252 if (object.len != 1 + (s_bits * this->set->n + 7)/8)
56009f20
AS
1253 {
1254 goto end;
1255 }
1256 this->s1 = malloc(this->set->n);
443346f5
AS
1257
1258 /* Skip unused bits octet */
1259 object = chunk_skip(object, 1);
1260 packer = bliss_bitpacker_create_from_data(object);
1261 for (i = 0; i < this->set->n; i++)
1262 {
1263 packer->read_bits(packer, &value, s_bits);
c2aca9ee
AS
1264 s = (value & s_sign) ? value | s_mask : value;
1265 if (s < s_min || s > s_max)
1266 {
1267 packer->destroy(packer);
1268 goto end;
1269 }
1270 this->s1[i] = s;
443346f5
AS
1271 }
1272 packer->destroy(packer);
56009f20
AS
1273 break;
1274 case PRIV_KEY_SECRET2:
443346f5 1275 if (object.len != 1 + (s_bits * this->set->n + 7)/8)
56009f20
AS
1276 {
1277 goto end;
1278 }
1279 this->s2 = malloc(this->set->n);
443346f5
AS
1280
1281 /* Skip unused bits octet */
1282 object = chunk_skip(object, 1);
1283 packer = bliss_bitpacker_create_from_data(object);
1284 for (i = 0; i < this->set->n; i++)
1285 {
1286 packer->read_bits(packer, &value, s_bits);
c2aca9ee
AS
1287 s = (value & s_sign) ? value | s_mask : value;
1288 if (s < s_min || s > s_max)
1289 {
1290 packer->destroy(packer);
1291 goto end;
1292 }
1293 this->s2[i] = 2 * s;
443346f5
AS
1294 if (i == 0)
1295 {
1296 this->s2[0] += 1;
1297 }
1298 }
1299 packer->destroy(packer);
56009f20
AS
1300 break;
1301 }
1302 }
1303 success = parser->success(parser);
1304
1305end:
1306 parser->destroy(parser);
1307 if (!success)
1308 {
1309 destroy(this);
1310 return NULL;
1311 }
1312
9d5b91d1
AS
1313 return &this->public;
1314}
1315