2 * Copyright (C) 2014 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
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"
22 #include <asn1/asn1.h>
23 #include <asn1/asn1_parser.h>
26 typedef struct private_bliss_public_key_t private_bliss_public_key_t
;
29 * Private data structure with signing context.
31 struct private_bliss_public_key_t
{
33 * Public interface for this signer.
35 bliss_public_key_t
public;
38 * BLISS signature parameter set
40 bliss_param_set_t
*set
;
43 * NTT of BLISS public key a (coefficients of polynomial (2g + 1)/f)
53 METHOD(public_key_t
, get_type
, key_type_t
,
54 private_bliss_public_key_t
*this)
60 * Verify a BLISS signature based on a SHA-512 hash
62 static bool verify_bliss(private_bliss_public_key_t
*this, hash_algorithm_t alg
,
63 chunk_t data
, chunk_t signature
)
68 uint16_t q
, q2
, p
, *c_indices
, *indices
;
70 uint8_t data_hash_buf
[HASH_SIZE_SHA512
];
73 hash_algorithm_t oracle_alg
;
75 bliss_signature_t
*sig
;
78 /* Create data hash using configurable hash algorithm */
79 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, alg
);
84 data_hash
= chunk_create(data_hash_buf
, hasher
->get_hash_size(hasher
));
86 if (!hasher
->get_hash(hasher
, data
, data_hash_buf
))
88 hasher
->destroy(hasher
);
91 hasher
->destroy(hasher
);
93 sig
= bliss_signature_create_from_data(this->set
, signature
);
98 sig
->get_parameters(sig
, &z1
, &z2d
, &c_indices
);
100 if (!bliss_utils_check_norms(this->set
, z1
, z2d
))
106 /* MGF1 hash algorithm to be used for random oracle */
107 oracle_alg
= HASH_SHA512
;
109 /* Initialize a couple of needed variables */
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));
119 for (i
= 0; i
< n
; i
++)
121 az
[i
] = z1
[i
] < 0 ? q
+ z1
[i
] : z1
[i
];
123 fft
= bliss_fft_create(this->set
->fft_params
);
124 fft
->transform(fft
, az
, az
, FALSE
);
126 for (i
= 0; i
< n
; i
++)
128 az
[i
] = (this->A
[i
] * az
[i
]) % q
;
130 fft
->transform(fft
, az
, az
, TRUE
);
132 for (i
= 0; i
< n
; i
++)
134 u
[i
] = (2 * this->set
->q2_inv
* az
[i
]) % q2
;
137 for (i
= 0; i
< this->set
->kappa
; i
++)
139 u
[c_indices
[i
]] = (u
[c_indices
[i
]] + q
* this->set
->q2_inv
) % q2
;
141 bliss_utils_round_and_drop(this->set
, u
, ud
);
143 for (i
= 0; i
< n
; i
++)
156 /* Detailed debugging information */
157 DBG3(DBG_LIB
, " i u[i] ud[i] z2d[i]");
158 for (i
= 0; i
< n
; i
++)
160 DBG3(DBG_LIB
, "%3d %6d %4d %4d", i
, u
[i
], ud
[i
], z2d
[i
]);
163 if (!bliss_utils_generate_c(oracle_alg
, data_hash
, ud
, this->set
, indices
))
168 for (i
= 0; i
< this->set
->kappa
; i
++)
170 if (indices
[i
] != c_indices
[i
])
172 DBG1(DBG_LIB
, "signature verification failed");
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
)
196 case SIGN_BLISS_WITH_SHA256
:
197 return verify_bliss(this, HASH_SHA256
, data
, signature
);
198 case SIGN_BLISS_WITH_SHA384
:
199 return verify_bliss(this, HASH_SHA384
, data
, signature
);
200 case SIGN_BLISS_WITH_SHA512
:
201 return verify_bliss(this, HASH_SHA512
, data
, signature
);
203 DBG1(DBG_LIB
, "signature scheme %N not supported by BLISS",
204 signature_scheme_names
, scheme
);
209 METHOD(public_key_t
, encrypt_
, bool,
210 private_bliss_public_key_t
*this, encryption_scheme_t scheme
,
211 chunk_t plain
, chunk_t
*crypto
)
213 DBG1(DBG_LIB
, "encryption scheme %N not supported",
214 encryption_scheme_names
, scheme
);
218 METHOD(public_key_t
, get_keysize
, int,
219 private_bliss_public_key_t
*this)
221 return this->set
->strength
;
224 METHOD(public_key_t
, get_encoding
, bool,
225 private_bliss_public_key_t
*this, cred_encoding_type_t type
,
230 *encoding
= bliss_public_key_info_encode(this->set
->oid
, this->A
, this->set
);
232 if (type
!= PUBKEY_SPKI_ASN1_DER
)
234 chunk_t asn1_encoding
= *encoding
;
236 success
= lib
->encoding
->encode(lib
->encoding
, type
,
237 NULL
, encoding
, CRED_PART_BLISS_PUB_ASN1_DER
,
238 asn1_encoding
, CRED_PART_END
);
239 chunk_clear(&asn1_encoding
);
244 METHOD(public_key_t
, get_fingerprint
, bool,
245 private_bliss_public_key_t
*this, cred_encoding_type_t type
, chunk_t
*fp
)
249 if (lib
->encoding
->get_cache(lib
->encoding
, type
, this, fp
))
253 success
= bliss_public_key_fingerprint(this->set
->oid
, this->A
,
254 this->set
, type
, fp
);
257 lib
->encoding
->cache(lib
->encoding
, type
, this, *fp
);
262 METHOD(public_key_t
, get_ref
, public_key_t
*,
263 private_bliss_public_key_t
*this)
266 return &this->public.key
;
269 METHOD(public_key_t
, destroy
, void,
270 private_bliss_public_key_t
*this)
272 if (ref_put(&this->ref
))
274 lib
->encoding
->clear_cache(lib
->encoding
, this);
281 * ASN.1 definition of a BLISS public key
283 static const asn1Object_t pubkeyObjects
[] = {
284 { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE
, ASN1_OBJ
}, /* 0 */
285 { 1, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 1 */
286 { 1, "subjectPublicKey", ASN1_BIT_STRING
, ASN1_BODY
}, /* 2 */
287 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
289 #define BLISS_SUBJECT_PUBLIC_KEY_ALGORITHM 1
290 #define BLISS_SUBJECT_PUBLIC_KEY 2
295 bliss_public_key_t
*bliss_public_key_load(key_type_t type
, va_list args
)
297 private_bliss_public_key_t
*this;
298 chunk_t blob
= chunk_empty
, object
, param
;
299 asn1_parser_t
*parser
;
300 bool success
= FALSE
;
305 switch (va_arg(args
, builder_part_t
))
307 case BUILD_BLOB_ASN1_DER
:
308 blob
= va_arg(args
, chunk_t
);
326 .get_type
= _get_type
,
328 .encrypt
= _encrypt_
,
329 .equals
= public_key_equals
,
330 .get_keysize
= _get_keysize
,
331 .get_fingerprint
= _get_fingerprint
,
332 .has_fingerprint
= public_key_has_fingerprint
,
333 .get_encoding
= _get_encoding
,
341 parser
= asn1_parser_create(pubkeyObjects
, blob
);
343 while (parser
->iterate(parser
, &objectID
, &object
))
347 case BLISS_SUBJECT_PUBLIC_KEY_ALGORITHM
:
349 oid
= asn1_parse_algorithmIdentifier(object
,
350 parser
->get_level(parser
)+1, ¶m
);
351 if (oid
!= OID_BLISS_PUBLICKEY
)
355 if (!asn1_parse_simple_object(¶m
, ASN1_OID
,
356 parser
->get_level(parser
)+3, "blissKeyType"))
360 oid
= asn1_known_oid(param
);
361 if (oid
== OID_UNKNOWN
)
365 this->set
= bliss_param_set_get_by_oid(oid
);
366 if (this->set
== NULL
)
372 case BLISS_SUBJECT_PUBLIC_KEY
:
373 if (!bliss_public_key_from_asn1(object
, this->set
, &this->A
))
380 success
= parser
->success(parser
);
383 parser
->destroy(parser
);
390 return &this->public;
396 bool bliss_public_key_from_asn1(chunk_t object
, bliss_param_set_t
*set
,
399 bliss_bitpacker_t
*packer
;
400 uint32_t coefficient
;
401 uint16_t needed_bits
;
404 /* skip initial bit string octet defining unused bits */
405 object
= chunk_skip(object
, 1);
407 needed_bits
= set
->n
* set
->q_bits
;
409 if (8 * object
.len
< needed_bits
)
413 *pubkey
= malloc(set
->n
* sizeof(uint32_t));
415 packer
= bliss_bitpacker_create_from_data(object
);
417 for (i
= 0; i
< set
->n
; i
++)
419 packer
->read_bits(packer
, &coefficient
, set
->q_bits
);
420 if (coefficient
>= set
->q
)
422 packer
->destroy(packer
);
425 (*pubkey
)[i
] = coefficient
;
427 packer
->destroy(packer
);
435 chunk_t
bliss_public_key_encode(uint32_t *pubkey
, bliss_param_set_t
*set
)
437 bliss_bitpacker_t
*packer
;
441 packer
= bliss_bitpacker_create(set
->n
* set
->q_bits
);
443 for (i
= 0; i
< set
->n
; i
++)
445 packer
->write_bits(packer
, pubkey
[i
], set
->q_bits
);
447 encoding
= packer
->extract_buf(packer
);
448 packer
->destroy(packer
);
456 chunk_t
bliss_public_key_info_encode(int oid
, uint32_t *pubkey
,
457 bliss_param_set_t
*set
)
459 chunk_t encoding
, pubkey_encoding
;
461 pubkey_encoding
= bliss_public_key_encode(pubkey
, set
);
463 encoding
= asn1_wrap(ASN1_SEQUENCE
, "mm",
464 asn1_wrap(ASN1_SEQUENCE
, "mm",
465 asn1_build_known_oid(OID_BLISS_PUBLICKEY
),
466 asn1_build_known_oid(oid
)),
467 asn1_bitstring("m", pubkey_encoding
));
475 bool bliss_public_key_fingerprint(int oid
, uint32_t *pubkey
,
476 bliss_param_set_t
*set
,
477 cred_encoding_type_t type
, chunk_t
*fp
)
484 case KEYID_PUBKEY_SHA1
:
485 key
= bliss_public_key_encode(pubkey
, set
);
487 case KEYID_PUBKEY_INFO_SHA1
:
488 key
= bliss_public_key_info_encode(oid
, pubkey
, set
);
494 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
495 if (!hasher
|| !hasher
->allocate_hash(hasher
, key
, fp
))
497 DBG1(DBG_LIB
, "SHA1 hash algorithm not supported, fingerprinting failed");
503 hasher
->destroy(hasher
);