]>
Commit | Line | Data |
---|---|---|
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 | |
33 | typedef 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 | */ | |
40 | struct 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 | ||
72 | METHOD(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 | */ | |
81 | static 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 | */ | |
108 | static 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 |
163 | static 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 |
494 | end: |
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 |
513 | METHOD(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 | ||
532 | METHOD(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 | ||
541 | METHOD(private_key_t, get_keysize, int, | |
542 | private_bliss_private_key_t *this) | |
543 | { | |
73a32740 | 544 | return this->set->strength; |
9d5b91d1 AS |
545 | } |
546 | ||
547 | METHOD(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 | ||
561 | METHOD(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 | ||
628 | METHOD(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 | ||
646 | METHOD(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 | ||
653 | METHOD(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 | */ | |
677 | static 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 | 706 | static 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 | */ | |
725 | static 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 |
742 | static 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 | 763 | static 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 | */ | |
797 | static 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 | */ | |
828 | static 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 | */ | |
896 | static 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 | */ | |
994 | bliss_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 | */ | |
1145 | static 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 | */ | |
1161 | bliss_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 | ||
1305 | end: | |
1306 | parser->destroy(parser); | |
1307 | if (!success) | |
1308 | { | |
1309 | destroy(this); | |
1310 | return NULL; | |
1311 | } | |
1312 | ||
9d5b91d1 AS |
1313 | return &this->public; |
1314 | } | |
1315 |