Explicitly mention SHA2 algorithm in BLISS OIDs and signature schemes
[strongswan.git] / src / libstrongswan / plugins / bliss / bliss_public_key.c
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_public_key.h"
17 #include "bliss_signature.h"
18 #include "bliss_bitpacker.h"
19 #include "bliss_fft.h"
20 #include "bliss_utils.h"
21
22 #include <asn1/asn1.h>
23 #include <asn1/asn1_parser.h>
24 #include <asn1/oid.h>
25
26 typedef struct private_bliss_public_key_t private_bliss_public_key_t;
27
28 /**
29 * Private data structure with signing context.
30 */
31 struct private_bliss_public_key_t {
32 /**
33 * Public interface for this signer.
34 */
35 bliss_public_key_t public;
36
37 /**
38 * BLISS signature parameter set
39 */
40 bliss_param_set_t *set;
41
42 /**
43 * NTT of BLISS public key a (coefficients of polynomial (2g + 1)/f)
44 */
45 uint32_t *A;
46
47 /**
48 * reference counter
49 */
50 refcount_t ref;
51 };
52
53 METHOD(public_key_t, get_type, key_type_t,
54 private_bliss_public_key_t *this)
55 {
56 return KEY_BLISS;
57 }
58
59 /**
60 * Verify a BLISS signature based on a SHA-512 hash
61 */
62 static bool verify_bliss(private_bliss_public_key_t *this, hash_algorithm_t alg,
63 chunk_t data, chunk_t signature)
64 {
65 int i, n;
66 int32_t *z1, *u;
67 int16_t *ud, *z2d;
68 uint16_t q, q2, p, *c_indices, *indices;
69 uint32_t *az;
70 uint8_t data_hash_buf[HASH_SIZE_SHA512];
71 chunk_t data_hash;
72 hasher_t *hasher;
73 hash_algorithm_t oracle_alg;
74 bliss_fft_t *fft;
75 bliss_signature_t *sig;
76 bool success = FALSE;
77
78 /* Create data hash using configurable hash algorithm */
79 hasher = lib->crypto->create_hasher(lib->crypto, alg);
80 if (!hasher )
81 {
82 return FALSE;
83 }
84 data_hash = chunk_create(data_hash_buf, hasher->get_hash_size(hasher));
85
86 if (!hasher->get_hash(hasher, data, data_hash_buf))
87 {
88 hasher->destroy(hasher);
89 return FALSE;
90 }
91 hasher->destroy(hasher);
92
93 sig = bliss_signature_create_from_data(this->set, signature);
94 if (!sig)
95 {
96 return FALSE;
97 }
98 sig->get_parameters(sig, &z1, &z2d, &c_indices);
99
100 if (!bliss_utils_check_norms(this->set, z1, z2d))
101 {
102 sig->destroy(sig);
103 return FALSE;
104 }
105
106 /* MGF1 hash algorithm to be used for random oracle */
107 oracle_alg = HASH_SHA512;
108
109 /* Initialize a couple of needed variables */
110 n = this->set->n;
111 q = this->set->q;
112 p = this->set->p;
113 q2 = 2 * q;
114 az = malloc(n * sizeof(uint32_t));
115 u = malloc(n * sizeof(int32_t));
116 ud = malloc(n * sizeof(int16_t));
117 indices = malloc(this->set->kappa * sizeof(uint16_t));
118
119 for (i = 0; i < n; i++)
120 {
121 az[i] = z1[i] < 0 ? q + z1[i] : z1[i];
122 }
123 fft = bliss_fft_create(this->set->fft_params);
124 fft->transform(fft, az, az, FALSE);
125
126 for (i = 0; i < n; i++)
127 {
128 az[i] = (this->A[i] * az[i]) % q;
129 }
130 fft->transform(fft, az, az, TRUE);
131
132 for (i = 0; i < n; i++)
133 {
134 u[i] = (2 * this->set->q2_inv * az[i]) % q2;
135 }
136
137 for (i = 0; i < this->set->kappa; i++)
138 {
139 u[c_indices[i]] = (u[c_indices[i]] + q * this->set->q2_inv) % q2;
140 }
141 bliss_utils_round_and_drop(this->set, u, ud);
142
143 for (i = 0; i < n; i++)
144 {
145 ud[i] += z2d[i];
146 if (ud[i] < 0)
147 {
148 ud[i] += p;
149 }
150 else if (ud[i] >= p)
151 {
152 ud[i] -= p;
153 }
154 }
155
156 /* Detailed debugging information */
157 DBG3(DBG_LIB, " i u[i] ud[i] z2d[i]");
158 for (i = 0; i < n; i++)
159 {
160 DBG3(DBG_LIB, "%3d %6d %4d %4d", i, u[i], ud[i], z2d[i]);
161 }
162
163 if (!bliss_utils_generate_c(oracle_alg, data_hash, ud, this->set, indices))
164 {
165 goto end;
166 }
167
168 for (i = 0; i < this->set->kappa; i++)
169 {
170 if (indices[i] != c_indices[i])
171 {
172 DBG1(DBG_LIB, "signature verification failed");
173 goto end;
174 }
175 }
176 success = TRUE;
177
178 end:
179 /* cleanup */
180 sig->destroy(sig);
181 fft->destroy(fft);
182 free(az);
183 free(u);
184 free(ud);
185 free(indices);
186
187 return success;
188 }
189
190 METHOD(public_key_t, verify, bool,
191 private_bliss_public_key_t *this, signature_scheme_t scheme,
192 chunk_t data, chunk_t signature)
193 {
194 switch (scheme)
195 {
196 case SIGN_BLISS_WITH_SHA2_256:
197 return verify_bliss(this, HASH_SHA256, data, signature);
198 case SIGN_BLISS_WITH_SHA2_384:
199 return verify_bliss(this, HASH_SHA384, data, signature);
200 case SIGN_BLISS_WITH_SHA2_512:
201 return verify_bliss(this, HASH_SHA512, data, signature);
202 case SIGN_BLISS_WITH_SHA3_256:
203 return verify_bliss(this, HASH_SHA3_256, data, signature);
204 case SIGN_BLISS_WITH_SHA3_384:
205 return verify_bliss(this, HASH_SHA3_384, data, signature);
206 case SIGN_BLISS_WITH_SHA3_512:
207 return verify_bliss(this, HASH_SHA3_512, data, signature);
208 default:
209 DBG1(DBG_LIB, "signature scheme %N not supported by BLISS",
210 signature_scheme_names, scheme);
211 return FALSE;
212 }
213 }
214
215 METHOD(public_key_t, encrypt_, bool,
216 private_bliss_public_key_t *this, encryption_scheme_t scheme,
217 chunk_t plain, chunk_t *crypto)
218 {
219 DBG1(DBG_LIB, "encryption scheme %N not supported",
220 encryption_scheme_names, scheme);
221 return FALSE;
222 }
223
224 METHOD(public_key_t, get_keysize, int,
225 private_bliss_public_key_t *this)
226 {
227 return this->set->strength;
228 }
229
230 METHOD(public_key_t, get_encoding, bool,
231 private_bliss_public_key_t *this, cred_encoding_type_t type,
232 chunk_t *encoding)
233 {
234 bool success = TRUE;
235
236 *encoding = bliss_public_key_info_encode(this->set->oid, this->A, this->set);
237
238 if (type != PUBKEY_SPKI_ASN1_DER)
239 {
240 chunk_t asn1_encoding = *encoding;
241
242 success = lib->encoding->encode(lib->encoding, type,
243 NULL, encoding, CRED_PART_BLISS_PUB_ASN1_DER,
244 asn1_encoding, CRED_PART_END);
245 chunk_clear(&asn1_encoding);
246 }
247 return success;
248 }
249
250 METHOD(public_key_t, get_fingerprint, bool,
251 private_bliss_public_key_t *this, cred_encoding_type_t type, chunk_t *fp)
252 {
253 bool success;
254
255 if (lib->encoding->get_cache(lib->encoding, type, this, fp))
256 {
257 return TRUE;
258 }
259 success = bliss_public_key_fingerprint(this->set->oid, this->A,
260 this->set, type, fp);
261 if (success)
262 {
263 lib->encoding->cache(lib->encoding, type, this, *fp);
264 }
265 return success;
266 }
267
268 METHOD(public_key_t, get_ref, public_key_t*,
269 private_bliss_public_key_t *this)
270 {
271 ref_get(&this->ref);
272 return &this->public.key;
273 }
274
275 METHOD(public_key_t, destroy, void,
276 private_bliss_public_key_t *this)
277 {
278 if (ref_put(&this->ref))
279 {
280 lib->encoding->clear_cache(lib->encoding, this);
281 free(this->A);
282 free(this);
283 }
284 }
285
286 /**
287 * ASN.1 definition of a BLISS public key
288 */
289 static const asn1Object_t pubkeyObjects[] = {
290 { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
291 { 1, "algorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
292 { 1, "subjectPublicKey", ASN1_BIT_STRING, ASN1_BODY }, /* 2 */
293 { 0, "exit", ASN1_EOC, ASN1_EXIT }
294 };
295 #define BLISS_SUBJECT_PUBLIC_KEY_ALGORITHM 1
296 #define BLISS_SUBJECT_PUBLIC_KEY 2
297
298 /**
299 * See header.
300 */
301 bliss_public_key_t *bliss_public_key_load(key_type_t type, va_list args)
302 {
303 private_bliss_public_key_t *this;
304 chunk_t blob = chunk_empty, object, param;
305 asn1_parser_t *parser;
306 bool success = FALSE;
307 int objectID, oid;
308
309 while (TRUE)
310 {
311 switch (va_arg(args, builder_part_t))
312 {
313 case BUILD_BLOB_ASN1_DER:
314 blob = va_arg(args, chunk_t);
315 continue;
316 case BUILD_END:
317 break;
318 default:
319 return NULL;
320 }
321 break;
322 }
323
324 if (blob.len == 0)
325 {
326 return NULL;
327 }
328
329 INIT(this,
330 .public = {
331 .key = {
332 .get_type = _get_type,
333 .verify = _verify,
334 .encrypt = _encrypt_,
335 .equals = public_key_equals,
336 .get_keysize = _get_keysize,
337 .get_fingerprint = _get_fingerprint,
338 .has_fingerprint = public_key_has_fingerprint,
339 .get_encoding = _get_encoding,
340 .get_ref = _get_ref,
341 .destroy = _destroy,
342 },
343 },
344 .ref = 1,
345 );
346
347 parser = asn1_parser_create(pubkeyObjects, blob);
348
349 while (parser->iterate(parser, &objectID, &object))
350 {
351 switch (objectID)
352 {
353 case BLISS_SUBJECT_PUBLIC_KEY_ALGORITHM:
354 {
355 oid = asn1_parse_algorithmIdentifier(object,
356 parser->get_level(parser)+1, &param);
357 if (oid != OID_BLISS_PUBLICKEY)
358 {
359 goto end;
360 }
361 if (!asn1_parse_simple_object(&param, ASN1_OID,
362 parser->get_level(parser)+3, "blissKeyType"))
363 {
364 goto end;
365 }
366 oid = asn1_known_oid(param);
367 if (oid == OID_UNKNOWN)
368 {
369 goto end;
370 }
371 this->set = bliss_param_set_get_by_oid(oid);
372 if (this->set == NULL)
373 {
374 goto end;
375 }
376 break;
377 }
378 case BLISS_SUBJECT_PUBLIC_KEY:
379 if (!bliss_public_key_from_asn1(object, this->set, &this->A))
380 {
381 goto end;
382 }
383 break;
384 }
385 }
386 success = parser->success(parser);
387
388 end:
389 parser->destroy(parser);
390 if (!success)
391 {
392 destroy(this);
393 return NULL;
394 }
395
396 return &this->public;
397 }
398
399 /**
400 * See header.
401 */
402 bool bliss_public_key_from_asn1(chunk_t object, bliss_param_set_t *set,
403 uint32_t **pubkey)
404 {
405 bliss_bitpacker_t *packer;
406 uint32_t coefficient;
407 uint16_t needed_bits;
408 int i;
409
410 /* skip initial bit string octet defining unused bits */
411 object = chunk_skip(object, 1);
412
413 needed_bits = set->n * set->q_bits;
414
415 if (8 * object.len < needed_bits)
416 {
417 return FALSE;
418 }
419 *pubkey = malloc(set->n * sizeof(uint32_t));
420
421 packer = bliss_bitpacker_create_from_data(object);
422
423 for (i = 0; i < set->n; i++)
424 {
425 packer->read_bits(packer, &coefficient, set->q_bits);
426 if (coefficient >= set->q)
427 {
428 packer->destroy(packer);
429 return FALSE;
430 }
431 (*pubkey)[i] = coefficient;
432 }
433 packer->destroy(packer);
434
435 return TRUE;
436 }
437
438 /**
439 * See header.
440 */
441 chunk_t bliss_public_key_encode(uint32_t *pubkey, bliss_param_set_t *set)
442 {
443 bliss_bitpacker_t *packer;
444 chunk_t encoding;
445 int i;
446
447 packer = bliss_bitpacker_create(set->n * set->q_bits);
448
449 for (i = 0; i < set->n; i++)
450 {
451 packer->write_bits(packer, pubkey[i], set->q_bits);
452 }
453 encoding = packer->extract_buf(packer);
454 packer->destroy(packer);
455
456 return encoding;
457 }
458
459 /**
460 * See header.
461 */
462 chunk_t bliss_public_key_info_encode(int oid, uint32_t *pubkey,
463 bliss_param_set_t *set)
464 {
465 chunk_t encoding, pubkey_encoding;
466
467 pubkey_encoding = bliss_public_key_encode(pubkey, set);
468
469 encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
470 asn1_wrap(ASN1_SEQUENCE, "mm",
471 asn1_build_known_oid(OID_BLISS_PUBLICKEY),
472 asn1_build_known_oid(oid)),
473 asn1_bitstring("m", pubkey_encoding));
474
475 return encoding;
476 }
477
478 /**
479 * See header.
480 */
481 bool bliss_public_key_fingerprint(int oid, uint32_t *pubkey,
482 bliss_param_set_t *set,
483 cred_encoding_type_t type, chunk_t *fp)
484 {
485 hasher_t *hasher;
486 chunk_t key;
487
488 switch (type)
489 {
490 case KEYID_PUBKEY_SHA1:
491 key = bliss_public_key_encode(pubkey, set);
492 break;
493 case KEYID_PUBKEY_INFO_SHA1:
494 key = bliss_public_key_info_encode(oid, pubkey, set);
495 break;
496 default:
497 return FALSE;
498 }
499
500 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
501 if (!hasher || !hasher->allocate_hash(hasher, key, fp))
502 {
503 DBG1(DBG_LIB, "SHA1 hash algorithm not supported, fingerprinting failed");
504 DESTROY_IF(hasher);
505 free(key.ptr);
506
507 return FALSE;
508 }
509 hasher->destroy(hasher);
510 free(key.ptr);
511
512 return TRUE;
513 }
514