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_with_sha512(private_bliss_public_key_t
*this,
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
];
71 chunk_t data_hash
= { data_hash_buf
, sizeof(data_hash_buf
) };
74 bliss_signature_t
*sig
;
77 /* Create data hash */
78 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA512
);
83 if (!hasher
->get_hash(hasher
, data
, data_hash_buf
))
85 hasher
->destroy(hasher
);
89 sig
= bliss_signature_create_from_data(this->set
, signature
);
92 hasher
->destroy(hasher
);
95 sig
->get_parameters(sig
, &z1
, &z2d
, &c_indices
);
97 if (!bliss_utils_check_norms(this->set
, z1
, z2d
))
99 hasher
->destroy(hasher
);
104 /* Initialize a couple of needed variables */
109 az
= malloc(n
* sizeof(uint32_t));
110 u
= malloc(n
* sizeof(int32_t));
111 ud
= malloc(n
* sizeof(int16_t));
112 indices
= malloc(this->set
->kappa
* sizeof(uint16_t));
114 for (i
= 0; i
< n
; i
++)
116 az
[i
] = z1
[i
] < 0 ? q
+ z1
[i
] : z1
[i
];
118 fft
= bliss_fft_create(this->set
->fft_params
);
119 fft
->transform(fft
, az
, az
, FALSE
);
121 for (i
= 0; i
< n
; i
++)
123 az
[i
] = (this->A
[i
] * az
[i
]) % q
;
125 fft
->transform(fft
, az
, az
, TRUE
);
127 for (i
= 0; i
< n
; i
++)
129 u
[i
] = (2 * this->set
->q2_inv
* az
[i
]) % q2
;
132 for (i
= 0; i
< this->set
->kappa
; i
++)
134 u
[c_indices
[i
]] = (u
[c_indices
[i
]] + q
* this->set
->q2_inv
) % q2
;
136 bliss_utils_round_and_drop(this->set
, u
, ud
);
138 for (i
= 0; i
< n
; i
++)
151 /* Detailed debugging information */
152 DBG3(DBG_LIB
, " i u[i] ud[i] z2d[i]");
153 for (i
= 0; i
< n
; i
++)
155 DBG3(DBG_LIB
, "%3d %6d %4d %4d", i
, u
[i
], ud
[i
], z2d
[i
]);
158 if (!bliss_utils_generate_c(hasher
, data_hash
, ud
, n
, this->set
->kappa
,
164 for (i
= 0; i
< this->set
->kappa
; i
++)
166 if (indices
[i
] != c_indices
[i
])
168 DBG1(DBG_LIB
, "signature verification failed");
176 hasher
->destroy(hasher
);
187 METHOD(public_key_t
, verify
, bool,
188 private_bliss_public_key_t
*this, signature_scheme_t scheme
,
189 chunk_t data
, chunk_t signature
)
193 case SIGN_BLISS_WITH_SHA512
:
194 return verify_bliss_with_sha512(this, data
, signature
);
196 DBG1(DBG_LIB
, "signature scheme %N not supported by BLISS",
197 signature_scheme_names
, scheme
);
202 METHOD(public_key_t
, encrypt_
, bool,
203 private_bliss_public_key_t
*this, encryption_scheme_t scheme
,
204 chunk_t plain
, chunk_t
*crypto
)
206 DBG1(DBG_LIB
, "encryption scheme %N not supported",
207 encryption_scheme_names
, scheme
);
211 METHOD(public_key_t
, get_keysize
, int,
212 private_bliss_public_key_t
*this)
214 return this->set
->strength
;
217 METHOD(public_key_t
, get_encoding
, bool,
218 private_bliss_public_key_t
*this, cred_encoding_type_t type
,
223 *encoding
= bliss_public_key_info_encode(this->set
->oid
, this->A
, this->set
);
225 if (type
!= PUBKEY_SPKI_ASN1_DER
)
227 chunk_t asn1_encoding
= *encoding
;
229 success
= lib
->encoding
->encode(lib
->encoding
, type
,
230 NULL
, encoding
, CRED_PART_BLISS_PUB_ASN1_DER
,
231 asn1_encoding
, CRED_PART_END
);
232 chunk_clear(&asn1_encoding
);
237 METHOD(public_key_t
, get_fingerprint
, bool,
238 private_bliss_public_key_t
*this, cred_encoding_type_t type
, chunk_t
*fp
)
242 if (lib
->encoding
->get_cache(lib
->encoding
, type
, this, fp
))
246 success
= bliss_public_key_fingerprint(this->set
->oid
, this->A
,
247 this->set
, type
, fp
);
250 lib
->encoding
->cache(lib
->encoding
, type
, this, *fp
);
255 METHOD(public_key_t
, get_ref
, public_key_t
*,
256 private_bliss_public_key_t
*this)
259 return &this->public.key
;
262 METHOD(public_key_t
, destroy
, void,
263 private_bliss_public_key_t
*this)
265 if (ref_put(&this->ref
))
267 lib
->encoding
->clear_cache(lib
->encoding
, this);
274 * ASN.1 definition of a BLISS public key
276 static const asn1Object_t pubkeyObjects
[] = {
277 { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE
, ASN1_OBJ
}, /* 0 */
278 { 1, "algorithm", ASN1_EOC
, ASN1_RAW
}, /* 1 */
279 { 1, "subjectPublicKey", ASN1_BIT_STRING
, ASN1_BODY
}, /* 2 */
280 { 0, "exit", ASN1_EOC
, ASN1_EXIT
}
282 #define BLISS_SUBJECT_PUBLIC_KEY_ALGORITHM 1
283 #define BLISS_SUBJECT_PUBLIC_KEY 2
288 bliss_public_key_t
*bliss_public_key_load(key_type_t type
, va_list args
)
290 private_bliss_public_key_t
*this;
291 chunk_t blob
= chunk_empty
, object
, param
;
292 asn1_parser_t
*parser
;
293 bool success
= FALSE
;
298 switch (va_arg(args
, builder_part_t
))
300 case BUILD_BLOB_ASN1_DER
:
301 blob
= va_arg(args
, chunk_t
);
319 .get_type
= _get_type
,
321 .encrypt
= _encrypt_
,
322 .equals
= public_key_equals
,
323 .get_keysize
= _get_keysize
,
324 .get_fingerprint
= _get_fingerprint
,
325 .has_fingerprint
= public_key_has_fingerprint
,
326 .get_encoding
= _get_encoding
,
334 parser
= asn1_parser_create(pubkeyObjects
, blob
);
336 while (parser
->iterate(parser
, &objectID
, &object
))
340 case BLISS_SUBJECT_PUBLIC_KEY_ALGORITHM
:
342 oid
= asn1_parse_algorithmIdentifier(object
,
343 parser
->get_level(parser
)+1, ¶m
);
344 if (oid
!= OID_BLISS_PUBLICKEY
)
348 if (!asn1_parse_simple_object(¶m
, ASN1_OID
,
349 parser
->get_level(parser
)+3, "blissKeyType"))
353 oid
= asn1_known_oid(param
);
354 if (oid
== OID_UNKNOWN
)
358 this->set
= bliss_param_set_get_by_oid(oid
);
359 if (this->set
== NULL
)
365 case BLISS_SUBJECT_PUBLIC_KEY
:
366 if (!bliss_public_key_from_asn1(object
, this->set
, &this->A
))
373 success
= parser
->success(parser
);
376 parser
->destroy(parser
);
383 return &this->public;
389 bool bliss_public_key_from_asn1(chunk_t object
, bliss_param_set_t
*set
,
392 bliss_bitpacker_t
*packer
;
393 uint32_t coefficient
;
394 uint16_t needed_bits
;
397 /* skip initial bit string octet defining unused bits */
398 object
= chunk_skip(object
, 1);
400 needed_bits
= set
->n
* set
->q_bits
;
402 if (8 * object
.len
< needed_bits
)
406 *pubkey
= malloc(set
->n
* sizeof(uint32_t));
408 packer
= bliss_bitpacker_create_from_data(object
);
410 for (i
= 0; i
< set
->n
; i
++)
412 packer
->read_bits(packer
, &coefficient
, set
->q_bits
);
413 if (coefficient
>= set
->q
)
415 packer
->destroy(packer
);
418 (*pubkey
)[i
] = coefficient
;
420 packer
->destroy(packer
);
428 chunk_t
bliss_public_key_encode(uint32_t *pubkey
, bliss_param_set_t
*set
)
430 bliss_bitpacker_t
*packer
;
434 packer
= bliss_bitpacker_create(set
->n
* set
->q_bits
);
436 for (i
= 0; i
< set
->n
; i
++)
438 packer
->write_bits(packer
, pubkey
[i
], set
->q_bits
);
440 encoding
= packer
->extract_buf(packer
);
441 packer
->destroy(packer
);
449 chunk_t
bliss_public_key_info_encode(int oid
, uint32_t *pubkey
,
450 bliss_param_set_t
*set
)
452 chunk_t encoding
, pubkey_encoding
;
454 pubkey_encoding
= bliss_public_key_encode(pubkey
, set
);
456 encoding
= asn1_wrap(ASN1_SEQUENCE
, "mm",
457 asn1_wrap(ASN1_SEQUENCE
, "mm",
458 asn1_build_known_oid(OID_BLISS_PUBLICKEY
),
459 asn1_build_known_oid(oid
)),
460 asn1_bitstring("m", pubkey_encoding
));
468 bool bliss_public_key_fingerprint(int oid
, uint32_t *pubkey
,
469 bliss_param_set_t
*set
,
470 cred_encoding_type_t type
, chunk_t
*fp
)
477 case KEYID_PUBKEY_SHA1
:
478 key
= bliss_public_key_encode(pubkey
, set
);
480 case KEYID_PUBKEY_INFO_SHA1
:
481 key
= bliss_public_key_info_encode(oid
, pubkey
, set
);
487 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
488 if (!hasher
|| !hasher
->allocate_hash(hasher
, key
, fp
))
490 DBG1(DBG_LIB
, "SHA1 hash algorithm not supported, fingerprinting failed");
496 hasher
->destroy(hasher
);