diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.gitmodules b/.gitmodules old mode 100644 new mode 100755 diff --git a/CMakeLists.txt b/CMakeLists.txt index 6803182408eda0f902ab14285e1cdde30e746f52..a0fb81f915c3795ad8d9576e6e45a6aa44d7a0fa 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ file( GLOB CRYPTO_SRCS src/sig_bliss/*.c src/sig_tesla/*.c src/sig_picnic/*.c + src/sig_dilithium/*.c ) file( GLOB CRYPTO_HEADERS @@ -55,6 +56,7 @@ file( GLOB CRYPTO_HEADERS src/sig_bliss/*.h src/sig_tesla/*.h src/sig_picnic/*.h + src/sig_dilithium/*.h include/*.h ) @@ -84,7 +86,7 @@ endif() add_library(${PROJECT_NAME} STATIC ${CRYPTO_SRCS} ${XKCP_SRCS} ${XKCP_SRCS2} ${CRYPTO_HEADERS} ) -target_include_directories(dap_crypto PRIVATE src/rand src/iaes src/oaes sha3 src/msrln src/defeo_scheme src/sig_bliss src/sig_tesla src/sig_picnic src include) +target_include_directories(dap_crypto PRIVATE src/rand src/iaes src/oaes sha3 src/msrln src/defeo_scheme src/sig_bliss src/sig_tesla src/sig_picnic src/sig_dilithium src include) target_include_directories(dap_crypto INTERFACE src/ src/sha3 include/) target_include_directories(dap_crypto INTERFACE src/XKCP/lib/common) diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/include/dap_enc_dilithium.h b/include/dap_enc_dilithium.h new file mode 100755 index 0000000000000000000000000000000000000000..9c6a0db94d6135146c9ea48fc45c6170b4f28ce5 --- /dev/null +++ b/include/dap_enc_dilithium.h @@ -0,0 +1,37 @@ +#ifndef _DAP_ENC_DILITHIUM_H_ +#define _DAP_ENC_DILITHIUM_H_ + +#include "sig_dilithium/dilithium_params.h" +#include "dap_enc_key.h" + + +enum DAP_DILITHIUM_SIGN_SECURITY { + DILITHIUM_TOY = 0, DILITHIUM_MAX_SPEED, DILITHIUM_MIN_SIZE, DILITHIUM_MAX_SECURITY +}; + +void dap_enc_sig_dilithium_set_type(enum DAP_DILITHIUM_SIGN_SECURITY type); + +void dap_enc_sig_dilithium_key_new(struct dap_enc_key *key); + +void dap_enc_sig_dilithium_key_new_generate(struct dap_enc_key * key, const void *kex_buf, + size_t kex_size, const void * seed, size_t seed_size, + size_t key_size); + +size_t dap_enc_sig_dilithium_get_sign(struct dap_enc_key * key,const void * msg, + const size_t msg_size, void * signature, const size_t signature_size); + +size_t dap_enc_sig_dilithium_verify_sign(struct dap_enc_key * key,const void * msg, + const size_t msg_size, void * signature, const size_t signature_size); + +void dap_enc_sig_dilithium_key_delete(struct dap_enc_key * key); + +size_t dap_enc_dilithium_calc_signature_size(void); + +uint8_t* dap_enc_dilithium_write_signature(dilithium_signature_t* a_sign, size_t *a_sign_out); +dilithium_signature_t* dap_enc_dilithium_read_signature(uint8_t *a_buf, size_t a_buflen); +uint8_t* dap_enc_dilithium_write_private_key(const dilithium_private_key_t* a_private_key, size_t *a_buflen_out); +uint8_t* dap_enc_dilithium_write_public_key(const dilithium_public_key_t* a_public_key, size_t *a_buflen_out); +dilithium_private_key_t* dap_enc_dilithium_read_private_key(const uint8_t *a_buf, size_t a_buflen); +dilithium_public_key_t* dap_enc_dilithium_read_public_key(const uint8_t *a_buf, size_t a_buflen); + +#endif diff --git a/include/dap_enc_key.h b/include/dap_enc_key.h index ad912cf6be81f37cc549635f38209472c9e04922..98b0cc244a813a7cc0a323885eb9bd7b69a618e5 100755 --- a/include/dap_enc_key.h +++ b/include/dap_enc_key.h @@ -110,6 +110,8 @@ typedef enum dap_enc_key_type{ DAP_ENC_KEY_TYPE_IAES, // Symmetric AES DAP_ENC_KEY_TYPE_SIG_TESLA, // signature based on Ring_LWE problem with zero-knowledge proof as specified in // Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives + DAP_ENC_KEY_TYPE_SIG_DILITHIUM, + DAP_ENC_KEY_TYPE_NULL = 0 } dap_enc_key_type_t; diff --git a/libdap b/libdap index 9915cf2b350ee58f6beab8a53eac5a3c6ab7d67d..85933c820be2c81416848447b82bb8af15a34a5c 160000 --- a/libdap +++ b/libdap @@ -1 +1 @@ -Subproject commit 9915cf2b350ee58f6beab8a53eac5a3c6ab7d67d +Subproject commit 85933c820be2c81416848447b82bb8af15a34a5c diff --git a/src/dap_enc_dilithium.c b/src/dap_enc_dilithium.c new file mode 100755 index 0000000000000000000000000000000000000000..b51112fbfe81bc7719d00580d8cef7fb985b67cc --- /dev/null +++ b/src/dap_enc_dilithium.c @@ -0,0 +1,226 @@ +#include <assert.h> +#include <inttypes.h> +#include <string.h> + +#include "dap_enc_dilithium.h" +#include "dap_common.h" +#include "dap_rand.h" + +#define LOG_TAG "dap_enc_sig_dilithium" + +static enum DAP_DILITHIUM_SIGN_SECURITY _dilithium_type = DILITHIUM_MIN_SIZE; // by default + +void dap_enc_sig_dilithium_set_type(enum DAP_DILITHIUM_SIGN_SECURITY type) +{ + _dilithium_type = type; +} + +void dap_enc_sig_dilithium_key_new(struct dap_enc_key *key) { + + key->type = DAP_ENC_KEY_TYPE_SIG_DILITHIUM; + key->enc = NULL; + key->enc_na = (dap_enc_callback_dataop_na_t) dap_enc_sig_dilithium_get_sign; + key->dec_na = (dap_enc_callback_dataop_na_t) dap_enc_sig_dilithium_verify_sign; +// key->gen_bob_shared_key = (dap_enc_gen_bob_shared_key) dap_enc_sig_dilithium_get_sign; +// key->gen_alice_shared_key = (dap_enc_gen_alice_shared_key) dap_enc_sig_dilithium_verify_sign; +} + +// generation key pair for sign Alice +// OUTPUT: +// a_key->data --- Alice's public key +// alice_priv --- Alice's private key +// alice_msg_len --- Alice's private key length +void dap_enc_sig_dilithium_key_new_generate(struct dap_enc_key * key, const void *kex_buf, + size_t kex_size, const void * seed, size_t seed_size, + size_t key_size) +{ + (void) kex_buf; + (void) kex_size; + (void) key_size; + + int32_t retcode; + + int dilithium_type = (seed && seed_size >= sizeof(uint8_t)) ? ((uint8_t*)seed)[0] % (DILITHIUM_MAX_SECURITY + 1) : + DILITHIUM_MIN_SIZE; + dap_enc_sig_dilithium_set_type(dilithium_type); + + + //int32_t type = 2; + key->priv_key_data_size = sizeof(dilithium_private_key_t); + key->pub_key_data_size = sizeof(dilithium_public_key_t); + key->priv_key_data = malloc(key->priv_key_data_size); + key->pub_key_data = malloc(key->pub_key_data_size); + + retcode = dilithium_crypto_sign_keypair((dilithium_public_key_t *) key->pub_key_data, + (dilithium_private_key_t *) key->priv_key_data, _dilithium_type); + if(retcode != 0) { + dilithium_private_and_public_keys_delete((dilithium_private_key_t *) key->pub_key_data, + (dilithium_public_key_t *) key->pub_key_data); + log_it(L_CRITICAL, "Error"); + return; + } +} + +size_t dap_enc_sig_dilithium_get_sign(struct dap_enc_key * key, const void * msg, + const size_t msg_size, void * signature, const size_t signature_size) +{ + if(signature_size < sizeof(dilithium_signature_t)) { + log_it(L_ERROR, "bad signature size"); + return 0; + } + + if(!dilithium_crypto_sign((dilithium_signature_t *) signature, (const unsigned char *) msg, msg_size, key->priv_key_data)) + return signature_size; + else + return 0; +} + +size_t dap_enc_sig_dilithium_verify_sign(struct dap_enc_key * key, const void * msg, + const size_t msg_size, void * signature, const size_t signature_size) +{ + if(signature_size < sizeof(dilithium_signature_t)) { + log_it(L_ERROR, "bad signature size"); + return 0; + } + + return (dilithium_crypto_sign_open( (unsigned char *) msg, msg_size, (dilithium_signature_t *) signature, key->pub_key_data)); +} + +void dap_enc_sig_dilithium_key_delete(struct dap_enc_key * key) +{ + dilithium_private_and_public_keys_delete((dilithium_private_key_t *) key->priv_key_data, + (dilithium_public_key_t *) key->pub_key_data); +} + +size_t dap_enc_dilithium_calc_signature_size(void) +{ + return sizeof(dilithium_signature_t); +} + +/* Serialize a signature */ +uint8_t* dap_enc_dilithium_write_signature(dilithium_signature_t* a_sign, size_t *a_sign_out) +{ + if(!a_sign || *a_sign_out!=sizeof(dilithium_signature_t)) { + return NULL ; + } + size_t l_shift_mem = 0; + size_t l_buflen = sizeof(size_t) + sizeof(dilithium_kind_t) + a_sign->sig_len + sizeof(unsigned long long); + + uint8_t *l_buf = DAP_NEW_SIZE(uint8_t, l_buflen); + memcpy(l_buf, &l_buflen, sizeof(size_t)); + l_shift_mem += sizeof(size_t); + memcpy(l_buf + l_shift_mem, &a_sign->kind, sizeof(dilithium_kind_t)); + l_shift_mem += sizeof(dilithium_kind_t); + memcpy(l_buf + l_shift_mem, &a_sign->sig_len, sizeof(unsigned long long)); + l_shift_mem += sizeof(unsigned long long); + memcpy(l_buf + l_shift_mem, a_sign->sig_data, a_sign->sig_len ); + l_shift_mem += a_sign->sig_len ; + + if(a_sign_out) + *a_sign_out = l_buflen; + return l_buf; +} + +/* Deserialize a signature */ +dilithium_signature_t* dap_enc_dilithium_read_signature(uint8_t *a_buf, size_t a_buflen) +{ + if(!a_buf || a_buflen < (sizeof(size_t) + sizeof(dilithium_kind_t))) + return NULL ; + dilithium_kind_t kind; + size_t l_buflen = 0; + memcpy(&l_buflen, a_buf, sizeof(size_t)); + memcpy(&kind, a_buf + sizeof(size_t), sizeof(dilithium_kind_t)); + if(l_buflen != a_buflen) + return NULL ; + dilithium_param_t p; + if(!dilithium_params_init(&p, kind)) + return NULL ; + + dilithium_signature_t* l_sign = DAP_NEW(dilithium_signature_t); + l_sign->kind = kind; + size_t l_shift_mem = sizeof(size_t) + sizeof(dilithium_kind_t); + memcpy(&l_sign->sig_len, a_buf + l_shift_mem, sizeof(unsigned long long)); + l_shift_mem += sizeof(unsigned long long); + l_sign->sig_data = DAP_NEW_SIZE(unsigned char, l_sign->sig_len); + memcpy(l_sign->sig_data, a_buf + l_shift_mem, l_sign->sig_len); + l_shift_mem += l_sign->sig_len; + return l_sign; +} + +/* Serialize a private key. */ +uint8_t* dap_enc_dilithium_write_private_key(const dilithium_private_key_t* a_private_key, size_t *a_buflen_out) +{ + dilithium_param_t p;// = malloc(sizeof(dilithium_param_t)); + if(!dilithium_params_init(&p, a_private_key->kind)) + return NULL; + + size_t l_buflen = sizeof(size_t) + sizeof(dilithium_kind_t) + p.CRYPTO_SECRETKEYBYTES; //CRYPTO_PUBLICKEYBYTES; + uint8_t *l_buf = DAP_NEW_SIZE(uint8_t, l_buflen); + memcpy(l_buf, &l_buflen, sizeof(size_t)); + memcpy(l_buf + sizeof(size_t), &a_private_key->kind, sizeof(dilithium_kind_t)); + memcpy(l_buf + sizeof(size_t) + sizeof(dilithium_kind_t), a_private_key->data, p.CRYPTO_SECRETKEYBYTES); + if(a_buflen_out) + *a_buflen_out = l_buflen; + return l_buf; +} + +/* Serialize a public key. */ +uint8_t* dap_enc_dilithium_write_public_key(const dilithium_public_key_t* a_public_key, size_t *a_buflen_out) +{ + dilithium_param_t p; + if(!dilithium_params_init(&p, a_public_key->kind)) + return NULL; + + size_t l_buflen = sizeof(size_t) + sizeof(dilithium_kind_t) + p.CRYPTO_PUBLICKEYBYTES; + uint8_t *l_buf = DAP_NEW_SIZE(uint8_t, l_buflen); + memcpy(l_buf, &l_buflen, sizeof(size_t)); + memcpy(l_buf + sizeof(size_t), &a_public_key->kind, sizeof(dilithium_kind_t)); + memcpy(l_buf + sizeof(size_t) + sizeof(dilithium_kind_t), a_public_key->data, p.CRYPTO_PUBLICKEYBYTES); + if(a_buflen_out) + *a_buflen_out = l_buflen; + return l_buf; +} + +/* Deserialize a private key. */ +dilithium_private_key_t* dap_enc_dilithium_read_private_key(const uint8_t *a_buf, size_t a_buflen) +{ + if(!a_buf || a_buflen < (sizeof(size_t) + sizeof(dilithium_kind_t))) + return NULL; + dilithium_kind_t kind; + size_t l_buflen = 0; + memcpy(&l_buflen, a_buf, sizeof(size_t)); + memcpy(&kind, a_buf + sizeof(size_t), sizeof(dilithium_kind_t)); + if(l_buflen != a_buflen) + return NULL; + dilithium_param_t p; + if(!dilithium_params_init(&p, kind)) + return NULL; + dilithium_private_key_t* l_private_key = DAP_NEW(dilithium_private_key_t); + l_private_key->kind = kind; + + l_private_key->data = DAP_NEW_SIZE(unsigned char, p.CRYPTO_SECRETKEYBYTES); + memcpy(l_private_key->data, a_buf + sizeof(size_t) + sizeof(dilithium_kind_t), p.CRYPTO_SECRETKEYBYTES); + return l_private_key; +} + +/* Deserialize a public key. */ +dilithium_public_key_t* dap_enc_dilithium_read_public_key(const uint8_t *a_buf, size_t a_buflen) +{ + if(!a_buf || a_buflen < (sizeof(size_t) + sizeof(dilithium_kind_t))) + return NULL; + dilithium_kind_t kind; + size_t l_buflen = 0; + memcpy(&l_buflen, a_buf, sizeof(size_t)); + memcpy(&kind, a_buf + sizeof(size_t), sizeof(dilithium_kind_t)); + if(l_buflen != a_buflen) + return NULL; + dilithium_param_t p; + if(!dilithium_params_init(&p, kind)) + return NULL; + dilithium_public_key_t* l_public_key = DAP_NEW(dilithium_public_key_t); + l_public_key->kind = kind; + + l_public_key->data = DAP_NEW_SIZE(unsigned char, p.CRYPTO_PUBLICKEYBYTES); + memcpy(l_public_key->data, a_buf + sizeof(size_t) + sizeof(dilithium_kind_t), p.CRYPTO_PUBLICKEYBYTES); + return l_public_key; +} diff --git a/src/dap_enc_key.c b/src/dap_enc_key.c index 5fe39c731d44b586c90ecaa3a2307bba3bccbd50..1b0d467c398d8eb5a359a1a4040a9f2c86cf7ff7 100755 --- a/src/dap_enc_key.c +++ b/src/dap_enc_key.c @@ -30,6 +30,7 @@ #include "dap_enc_picnic.h" #include "dap_enc_bliss.h" #include "dap_enc_tesla.h" +#include "dap_enc_dilithium.h" #include "dap_enc_key.h" @@ -182,6 +183,24 @@ struct dap_enc_key_callbacks{ .dec_out_size = NULL, .sign_get = NULL, .sign_verify = NULL + }, + [DAP_ENC_KEY_TYPE_SIG_DILITHIUM]={ + .name = "SIG_DILITHIUM", + .enc = NULL, + .dec = NULL, + .enc_na = dap_enc_sig_dilithium_get_sign, + .dec_na = dap_enc_sig_dilithium_verify_sign, + .gen_key_public = NULL, + .gen_key_public_size = NULL, + .gen_bob_shared_key = NULL, + .gen_alice_shared_key = NULL, + .new_callback = dap_enc_sig_dilithium_key_new, + .delete_callback = dap_enc_sig_dilithium_key_delete, + .new_generate_callback = dap_enc_sig_dilithium_key_new_generate, + .enc_out_size = NULL, + .dec_out_size = NULL, + .sign_get = NULL, + .sign_verify = NULL } }; @@ -222,6 +241,9 @@ uint8_t* dap_enc_key_serealize_sign(dap_enc_key_type_t a_key_type, uint8_t *a_si case DAP_ENC_KEY_TYPE_SIG_TESLA: data = dap_enc_tesla_write_signature((tesla_signature_t*)a_sign, a_sign_len); break; + case DAP_ENC_KEY_TYPE_SIG_DILITHIUM: + data = dap_enc_dilithium_write_signature((dilithium_signature_t*)a_sign, a_sign_len); + break; default: data = DAP_NEW_Z_SIZE(uint8_t, *a_sign_len); memcpy(data, a_sign, *a_sign_len); @@ -249,6 +271,10 @@ uint8_t* dap_enc_key_deserealize_sign(dap_enc_key_type_t a_key_type, uint8_t *a_ data = (uint8_t*)dap_enc_tesla_read_signature(a_sign, *a_sign_len); *a_sign_len = sizeof(tesla_signature_t); break; + case DAP_ENC_KEY_TYPE_SIG_DILITHIUM: + data = (uint8_t*)dap_enc_dilithium_read_signature(a_sign, *a_sign_len); + *a_sign_len = sizeof(dilithium_signature_t); + break; default: data = DAP_NEW_Z_SIZE(uint8_t, *a_sign_len); memcpy(data, a_sign, *a_sign_len); @@ -274,6 +300,9 @@ uint8_t* dap_enc_key_serealize_priv_key(dap_enc_key_t *a_key, size_t *a_buflen_o case DAP_ENC_KEY_TYPE_SIG_TESLA: data = dap_enc_tesla_write_private_key(a_key->priv_key_data, a_buflen_out); break; + case DAP_ENC_KEY_TYPE_SIG_DILITHIUM: + data = dap_enc_dilithium_write_private_key(a_key->priv_key_data, a_buflen_out); + break; default: data = DAP_NEW_Z_SIZE(uint8_t, a_key->priv_key_data_size); memcpy(data, a_key->priv_key_data, a_key->priv_key_data_size); @@ -300,6 +329,9 @@ uint8_t* dap_enc_key_serealize_pub_key(dap_enc_key_t *a_key, size_t *a_buflen_ou case DAP_ENC_KEY_TYPE_SIG_TESLA: data = dap_enc_tesla_write_public_key(a_key->pub_key_data, a_buflen_out); break; + case DAP_ENC_KEY_TYPE_SIG_DILITHIUM: + data = dap_enc_dilithium_write_public_key(a_key->pub_key_data, a_buflen_out); + break; default: data = DAP_NEW_Z_SIZE(uint8_t, a_key->pub_key_data_size); memcpy(data, a_key->pub_key_data, a_key->pub_key_data_size); @@ -351,6 +383,16 @@ int dap_enc_key_deserealize_priv_key(dap_enc_key_t *a_key, uint8_t *a_buf, size_ memcpy(a_key->priv_key_data, a_buf, a_key->priv_key_data_size); dap_enc_sig_picnic_update(a_key); break; + case DAP_ENC_KEY_TYPE_SIG_DILITHIUM: + dilithium_private_key_delete((dilithium_private_key_t *) a_key->priv_key_data); + a_key->priv_key_data = (uint8_t*) dap_enc_dilithium_read_private_key(a_buf, a_buflen); + if(!a_key->priv_key_data) + { + a_key->priv_key_data_size = 0; + return -1; + } + a_key->priv_key_data_size = sizeof(dilithium_private_key_t); + break; default: DAP_DELETE(a_key->priv_key_data); a_key->priv_key_data_size = a_buflen; @@ -403,6 +445,16 @@ int dap_enc_key_deserealize_pub_key(dap_enc_key_t *a_key,const uint8_t *a_buf, s memcpy(a_key->pub_key_data, a_buf, a_key->pub_key_data_size); dap_enc_sig_picnic_update(a_key); break; + case DAP_ENC_KEY_TYPE_SIG_DILITHIUM: + dilithium_public_key_delete((dilithium_public_key_t *) a_key->pub_key_data); + a_key->pub_key_data = (uint8_t*) dap_enc_dilithium_read_public_key(a_buf, a_buflen); + if(!a_key->pub_key_data) + { + a_key->pub_key_data_size = 0; + return -1; + } + a_key->pub_key_data_size = sizeof(dilithium_public_key_t); + break; default: DAP_DELETE(a_key->pub_key_data); a_key->pub_key_data_size = a_buflen; @@ -518,6 +570,8 @@ void dap_enc_key_update(dap_enc_key_t *a_key) break; case DAP_ENC_KEY_TYPE_SIG_BLISS: break; + case DAP_ENC_KEY_TYPE_SIG_DILITHIUM: + break; default: break; } @@ -556,6 +610,9 @@ void dap_enc_key_signature_delete(dap_enc_key_type_t a_key_type, uint8_t *a_sig_ case DAP_ENC_KEY_TYPE_SIG_TESLA: tesla_signature_delete((tesla_signature_t*)a_sig_buf); break; + case DAP_ENC_KEY_TYPE_SIG_DILITHIUM: + dilithium_signature_delete((dilithium_signature_t*)a_sig_buf); + break; default: break; } diff --git a/src/sig_dilithium/dilithium_packing.c b/src/sig_dilithium/dilithium_packing.c new file mode 100755 index 0000000000000000000000000000000000000000..f6ec1a02a0e8e9fcb1fd486b40b444f7789fffe2 --- /dev/null +++ b/src/sig_dilithium/dilithium_packing.c @@ -0,0 +1,198 @@ +#include "dilithium_packing.h" + +/*************************************************/ +void dilithium_pack_pk(unsigned char pk[], const unsigned char rho[], + const polyveck *t1, dilithium_param_t *p) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + pk[i] = rho[i]; + pk += SEEDBYTES; + + for(i = 0; i < p->PARAM_K; ++i) + polyt1_pack(pk + i * p->PARAM_POLT1_SIZE_PACKED, t1->vec + i); +} + +/*************************************************/ +void dilithium_unpack_pk(unsigned char rho[], polyveck *t1, + const unsigned char pk[], dilithium_param_t *p) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + rho[i] = pk[i]; + pk += SEEDBYTES; + + for(i = 0; i < p->PARAM_K; ++i) + polyt1_unpack(t1->vec + i, pk + i * p->PARAM_POLT1_SIZE_PACKED); +} + +/*************************************************/ +void dilithium_pack_sk(unsigned char sk[], const unsigned char rho[], + const unsigned char key[], const unsigned char tr[], + const polyvecl *s1, const polyveck *s2, + const polyveck *t0, dilithium_param_t *p) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + sk[i] = rho[i]; + sk += SEEDBYTES; + + for(i = 0; i < SEEDBYTES; ++i) + sk[i] = key[i]; + sk += SEEDBYTES; + + for(i = 0; i < CRHBYTES; ++i) + sk[i] = tr[i]; + sk += CRHBYTES; + + for(i = 0; i < p->PARAM_L; ++i) + polyeta_pack(sk + i * p->PARAM_POLETA_SIZE_PACKED, s1->vec + i, p); + sk += p->PARAM_L * p->PARAM_POLETA_SIZE_PACKED; + + for(i = 0; i < p->PARAM_K; ++i) + polyeta_pack(sk + i * p->PARAM_POLETA_SIZE_PACKED, s2->vec + i, p); + sk += p->PARAM_K * p->PARAM_POLETA_SIZE_PACKED; + + for(i = 0; i < p->PARAM_K; ++i) + polyt0_pack(sk + i * p->PARAM_POLT0_SIZE_PACKED, t0->vec + i); +} + +/*************************************************/ +void dilithium_unpack_sk(unsigned char rho[], unsigned char key[], + unsigned char tr[], polyvecl *s1, + polyveck *s2, polyveck *t0, + const unsigned char sk[], dilithium_param_t *p) +{ + unsigned int i; + + for(i = 0; i < SEEDBYTES; ++i) + rho[i] = sk[i]; + sk += SEEDBYTES; + + for(i = 0; i < SEEDBYTES; ++i) + key[i] = sk[i]; + sk += SEEDBYTES; + + for(i = 0; i < CRHBYTES; ++i) + tr[i] = sk[i]; + sk += CRHBYTES; + + for( i =0; i < p->PARAM_L; ++i) + polyeta_unpack(s1->vec + i, sk + i * p->PARAM_POLETA_SIZE_PACKED, p); + sk += p->PARAM_L * p->PARAM_POLETA_SIZE_PACKED; + + for(i = 0; i < p->PARAM_K; ++i) + polyeta_unpack(s2->vec+i, sk + i * p->PARAM_POLETA_SIZE_PACKED, p); + sk += p->PARAM_K * p->PARAM_POLETA_SIZE_PACKED; + + for(i=0; i < p->PARAM_K; ++i) + polyt0_unpack(t0->vec+i, sk + i * p->PARAM_POLT0_SIZE_PACKED); +} + +/*************************************************/ +void dilithium_pack_sig(unsigned char sig[], const polyvecl *z, const polyveck *h, + const poly *c, dilithium_param_t *p) +{ + unsigned int i, j, k; + uint64_t signs, mask; + + for(i = 0; i < p->PARAM_L; ++i) + polyz_pack(sig + i * p->PARAM_POLZ_SIZE_PACKED, z->vec + i); + sig += p->PARAM_L * p->PARAM_POLZ_SIZE_PACKED; + + /* Encode h */ + k = 0; + for(i = 0; i < p->PARAM_K; ++i) + { + for(j = 0; j < N; ++j) + if(h->vec[i].coeffs[j] != 0) + sig[k++] = j; + + sig[p->PARAM_OMEGA + i] = k; + } + while(k < p->PARAM_OMEGA) sig[k++] = 0; + sig += p->PARAM_OMEGA + p->PARAM_K; + + /* Encode c */ + signs = 0; + mask = 1; + for(i = 0; i < N/8; ++i) + { + sig[i] = 0; + for(j = 0; j < 8; ++j) + { + if(c->coeffs[8*i+j] != 0) + { + sig[i] |= (1U << j); + if(c->coeffs[8*i+j] == (Q - 1)) signs |= mask; + mask <<= 1; + } + } + } + sig += N/8; + for(i = 0; i < 8; ++i) + sig[i] = signs >> 8*i; +} + +/*************************************************/ +int dilithium_unpack_sig(polyvecl *z, polyveck *h, poly *c, + const unsigned char sig[], dilithium_param_t *p) +{ + unsigned int i, j, k; + uint64_t signs, mask; + + for(i = 0; i < p->PARAM_L; ++i) + polyz_unpack(z->vec + i, sig + i * p->PARAM_POLZ_SIZE_PACKED); + sig += p->PARAM_L * p->PARAM_POLZ_SIZE_PACKED; + + /* Decode h */ + k = 0; + for(i = 0; i < p->PARAM_K; ++i) + { + for(j = 0; j < N; ++j) + h->vec[i].coeffs[j] = 0; + + if(sig[p->PARAM_OMEGA + i] < k || sig[p->PARAM_OMEGA + i] > p->PARAM_OMEGA) + return 1; + + for(j = k; j < sig[p->PARAM_OMEGA + i]; ++j) + { + if(j > k && sig[j] <= sig[j-1]) + return 1; + h->vec[i].coeffs[sig[j]] = 1; + } + + k = sig[p->PARAM_OMEGA + i]; + } + + for(j = k; j < p->PARAM_OMEGA; ++j) + if(sig[j]) + return 1; + + sig += p->PARAM_OMEGA + p->PARAM_K; + + for(i = 0; i < N; ++i) + c->coeffs[i] = 0; + + signs = 0; + for(i = 0; i < 8; ++i) + signs |= (uint64_t)sig[N/8+i] << 8*i; + + if(signs >> 60) + return 1; + + mask = 1; + for(i = 0; i < N/8; ++i) { + for(j = 0; j < 8; ++j) { + if((sig[i] >> j) & 0x01) { + c->coeffs[8*i+j] = (signs & mask) ? Q - 1 : 1; + mask <<= 1; + } + } + } + + return 0; +} diff --git a/src/sig_dilithium/dilithium_packing.h b/src/sig_dilithium/dilithium_packing.h new file mode 100755 index 0000000000000000000000000000000000000000..c9e3a2a6489f40a9d918f4b2eb40a014d97a1c74 --- /dev/null +++ b/src/sig_dilithium/dilithium_packing.h @@ -0,0 +1,19 @@ +#ifndef PACKING_H +#define PACKING_H + +#include "dilithium_polyvec.h" + +void dilithium_pack_pk(unsigned char [], const unsigned char [], const polyveck *, dilithium_param_t *); +void dilithium_pack_sk(unsigned char [], const unsigned char [], const unsigned char [], const unsigned char [], + const polyvecl *, const polyveck *, const polyveck *, dilithium_param_t *); + +void dilithium_pack_sig(unsigned char [], const polyvecl *, const polyveck *, const poly *, dilithium_param_t *); + +void dilithium_unpack_pk(unsigned char [], polyveck *, const unsigned char [], dilithium_param_t *); + +void dilithium_unpack_sk(unsigned char [], unsigned char [], unsigned char [], + polyvecl *, polyveck *, polyveck *, const unsigned char [], dilithium_param_t *); + +int dilithium_unpack_sig(polyvecl *, polyveck *, poly *, const unsigned char [], dilithium_param_t *); + +#endif diff --git a/src/sig_dilithium/dilithium_params.c b/src/sig_dilithium/dilithium_params.c new file mode 100755 index 0000000000000000000000000000000000000000..ba5391535cc10e1de813a6a348ffb83b0f9fe330 --- /dev/null +++ b/src/sig_dilithium/dilithium_params.c @@ -0,0 +1,105 @@ +#include <assert.h> +#include <string.h> +#include "dilithium_params.h" + + +static const dilithium_param_t dilithium_params[] = { + + { MODE_0, /* kind */ + 3, + 2, + 7, + 4, + 375, + 64, + 736, + 288, + 448, + 128, + 640, + 128, + 2208, + 1472, + + 896, + 2096, + 1387 + }, + + { MODE_1, /* kind */ + 4, + 3, + 6, + 4, + 325, + 80, + 736, + 288, + 448, + 128, + 640, + 128, + 2944, + 2208, + + 1184, + 2800, + 2044 + + }, + + { MODE_2, /* kind */ + 5, + 4, + 5, + 4, + 275, + 96, + 736, + 288, + 448, + 128, + 640, + 128, + 3680, + 2944, + + 1472, + 3504, + 2701 + }, + + { MODE_3, /* kind */ + 6, + 5, + 3, + 3, + 175, + 120, + 736, + 288, + 448, + 96, + 640, + 128, + 4416, + 3680, + + 1760, + 3856, + 3366 + }, +}; + +bool dilithium_params_init(dilithium_param_t *params, dilithium_kind_t kind){ + assert(params != NULL); + + memset(params, 0, sizeof(dilithium_param_t)); + + if (MODE_0 <= kind && kind <= MODE_3 && params != NULL) { + *params = dilithium_params[kind]; + return true; + } else { + return false; + } +} diff --git a/src/sig_dilithium/dilithium_params.h b/src/sig_dilithium/dilithium_params.h new file mode 100755 index 0000000000000000000000000000000000000000..8362f50d4d5a8e973650ec425820cd7c79d8e4d7 --- /dev/null +++ b/src/sig_dilithium/dilithium_params.h @@ -0,0 +1,86 @@ +#ifndef __DILITHIUM_PARAMS__ +#define __DILITHIUM_PARAMS__ + +#include <assert.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include "dap_crypto_common.h" + +#define SEEDBYTES 32U +#define CRHBYTES 48U +#define N 256U +#define Q 8380417U +#define QBITS 23U +#define ROOT_OF_UNITY 1753U +#define D 14U +#define GAMMA1 ((Q - 1U)/16U) +#define GAMMA2 (GAMMA1/2U) +#define ALPHA (2U*GAMMA2) + +///======================================================================== +/* Names for the four varieties of Dilithium */ +typedef enum { MODE_0, MODE_1, MODE_2, MODE_3 } dilithium_kind_t; + +typedef struct { + dilithium_kind_t kind; /* the kind of Dilithium (i.e. *this* choice of parameters) */ + uint32_t PARAM_K; + uint32_t PARAM_L; + uint32_t PARAM_ETA; + uint32_t PARAM_SETABITS; + uint32_t PARAM_BETA; + uint32_t PARAM_OMEGA; + + uint32_t PARAM_POL_SIZE_PACKED; + uint32_t PARAM_POLT1_SIZE_PACKED; + uint32_t PARAM_POLT0_SIZE_PACKED; + uint32_t PARAM_POLETA_SIZE_PACKED; + uint32_t PARAM_POLZ_SIZE_PACKED; + uint32_t PARAM_POLW1_SIZE_PACKED; + uint32_t PARAM_POLVECK_SIZE_PACKED; + uint32_t PARAM_POLVECL_SIZE_PACKED; + + uint32_t CRYPTO_PUBLICKEYBYTES; + uint32_t CRYPTO_SECRETKEYBYTES; + uint32_t CRYPTO_BYTES; + +} dilithium_param_t; + +///========================================================================================== +typedef struct { + dilithium_kind_t kind; /* the kind of dilithium */ + unsigned char *data; +} dilithium_private_key_t; + +typedef struct { + dilithium_kind_t kind; /* the kind of dilithium */ + unsigned char *data; +} dilithium_public_key_t; + +typedef struct { + dilithium_kind_t kind; /* the kind of dilithium */ + unsigned char *sig_data; + unsigned long long sig_len; +} dilithium_signature_t; + + +///========================================================================================== +bool dilithium_params_init(dilithium_param_t *, dilithium_kind_t ); + +int dilithium_crypto_sign_keypair(dilithium_public_key_t *, dilithium_private_key_t *, dilithium_kind_t ); + +int dilithium_crypto_sign(dilithium_signature_t *, const unsigned char *, unsigned long long, const dilithium_private_key_t *); + +int dilithium_crypto_sign_open( unsigned char *, unsigned long long, dilithium_signature_t *, const dilithium_public_key_t *); + +void dilithium_private_key_delete(dilithium_private_key_t *private_key); +void dilithium_public_key_delete(dilithium_public_key_t *public_key); +void dilithium_private_and_public_keys_delete(dilithium_private_key_t *private_key, dilithium_public_key_t *public_key); + +void dilithium_signature_delete(dilithium_signature_t *sig); + +///========================================================================================== + +#endif + + diff --git a/src/sig_dilithium/dilithium_poly.c b/src/sig_dilithium/dilithium_poly.c new file mode 100755 index 0000000000000000000000000000000000000000..00c0a16b561265d1c99c10bb5e37d94d85b52416 --- /dev/null +++ b/src/sig_dilithium/dilithium_poly.c @@ -0,0 +1,597 @@ +#include <stdint.h> +#include "dilithium_poly.h" + +/*************************************************/ +void poly_reduce(poly *a) { + unsigned int i; + + for(i = 0; i < N; ++i) + a->coeffs[i] = reduce32(a->coeffs[i]); +} + +/*************************************************/ +void poly_csubq(poly *a) { + unsigned int i; + + for(i = 0; i < N; ++i) + a->coeffs[i] = csubq(a->coeffs[i]); +} + +/*************************************************/ +void poly_freeze(poly *a) { + unsigned int i; + + for(i = 0; i < N; ++i) + a->coeffs[i] = freeze(a->coeffs[i]); +} + +/*************************************************/ +void dilithium_poly_add(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for(i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] + b->coeffs[i]; +} + +/*************************************************/ +void dilithium_poly_sub(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for(i = 0; i < N; ++i) + c->coeffs[i] = a->coeffs[i] + 2*Q - b->coeffs[i]; +} + +/*************************************************/ +void poly_neg(poly *a) { + unsigned int i; + + for(i = 0; i < N; ++i) + a->coeffs[i] = Q - a->coeffs[i]; +} + +/*************************************************/ +void poly_shiftl(poly *a, unsigned int k) { + unsigned int i; + + for(i = 0; i < N; ++i) + a->coeffs[i] <<= k; +} + +/*************************************************/ +void dilithium_poly_ntt(poly *a) { + + dilithium_ntt(a->coeffs); +} + +/*************************************************/ +void poly_invntt_montgomery(poly *a) { + + invntt_frominvmont(a->coeffs); +} + +/*************************************************/ +void poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b) { + unsigned int i; + + for(i = 0; i < N; ++i) + c->coeffs[i] = montgomery_reduce((uint64_t)a->coeffs[i] * b->coeffs[i]); +} + +/*************************************************/ +void poly_power2round(poly *a1, poly *a0, const poly *a) { + unsigned int i; + + for(i = 0; i < N; ++i) + a1->coeffs[i] = power2round(a->coeffs[i], a0->coeffs+i); +} + +/*************************************************/ +void poly_decompose(poly *a1, poly *a0, const poly *a) { + unsigned int i; + + for(i = 0; i < N; ++i) + a1->coeffs[i] = decompose(a->coeffs[i], a0->coeffs+i); +} + +/*************************************************/ +unsigned int poly_make_hint(poly *h, const poly *a, const poly *b) { + unsigned int i, s = 0; + + for(i = 0; i < N; ++i) { + h->coeffs[i] = make_hint(a->coeffs[i], b->coeffs[i]); + s += h->coeffs[i]; + } + return s; +} + +/*************************************************/ +void poly_use_hint(poly *a, const poly *b, const poly *h) { + unsigned int i; + + for(i = 0; i < N; ++i) + a->coeffs[i] = use_hint(b->coeffs[i], h->coeffs[i]); +} + +/*************************************************/ +int poly_chknorm(const poly *a, uint32_t B) { + unsigned int i; + int32_t t; + + for(i = 0; i < N; ++i) { + t = (Q-1)/2 - a->coeffs[i]; + t ^= (t >> 31); + t = (Q-1)/2 - t; + + if((uint32_t)t >= B) { + return 1; + } + } + return 0; +} + +/*************************************************/ +void dilithium_poly_uniform(poly *a, const unsigned char *buf) { + unsigned int ctr, pos; + uint32_t t; + + ctr = pos = 0; + while(ctr < N) { + t = buf[pos++]; + t |= (uint32_t)buf[pos++] << 8; + t |= (uint32_t)buf[pos++] << 16; + t &= 0x7FFFFF; + + if(t < Q) + a->coeffs[ctr++] = t; + } +} + +/*************************************************/ +static unsigned int rej_eta(uint32_t *a, unsigned int len, const unsigned char *buf, + unsigned int buflen, dilithium_param_t *p) +{ +#if ETA > 7 +#error "rej_eta() assumes ETA <= 7" +#endif + unsigned int ctr, pos; + unsigned char t0, t1; + + ctr = pos = 0; + while(ctr < len && pos < buflen) { +#if ETA <= 3 + t0 = buf[pos] & 0x07; + t1 = buf[pos++] >> 5; +#else + t0 = buf[pos] & 0x0F; + t1 = buf[pos++] >> 4; +#endif + + if(t0 <= 2 * p->PARAM_ETA) + a[ctr++] = Q + p->PARAM_ETA - t0; + if(t1 <= 2 * p->PARAM_ETA && ctr < len) + a[ctr++] = Q + p->PARAM_ETA - t1; + } + return ctr; +} + +/*************************************************/ +void poly_uniform_eta(poly *a, const unsigned char seed[SEEDBYTES], unsigned char nonce, dilithium_param_t *p) +{ + unsigned int i, ctr; + unsigned char inbuf[SEEDBYTES + 1]; + + unsigned char outbuf[2*SHAKE256_RATE]; + uint64_t state[25] = {0}; + + for(i= 0; i < SEEDBYTES; ++i) + inbuf[i] = seed[i]; + inbuf[SEEDBYTES] = nonce; + + shake256_absorb(state, inbuf, SEEDBYTES + 1); + shake256_squeezeblocks(outbuf, 2, state); + + ctr = rej_eta(a->coeffs, N, outbuf, 2*SHAKE256_RATE, p); + if(ctr < N) { + shake256_squeezeblocks(outbuf, 1, state); + rej_eta(a->coeffs + ctr, N - ctr, outbuf, SHAKE256_RATE, p); + } +} + +/*************************************************/ +static unsigned int rej_gamma1m1(uint32_t *a, unsigned int len, const unsigned char *buf, unsigned int buflen) +{ +#if GAMMA1 > (1 << 19) +#error "rej_gamma1m1() assumes GAMMA1 - 1 fits in 19 bits" +#endif + unsigned int ctr, pos; + uint32_t t0, t1; + + ctr = pos = 0; + while(ctr < len && pos + 5 <= buflen) { + t0 = buf[pos]; + t0 |= (uint32_t)buf[pos + 1] << 8; + t0 |= (uint32_t)buf[pos + 2] << 16; + t0 &= 0xFFFFF; + + t1 = buf[pos + 2] >> 4; + t1 |= (uint32_t)buf[pos + 3] << 4; + t1 |= (uint32_t)buf[pos + 4] << 12; + + pos += 5; + + if(t0 <= 2*GAMMA1 - 2) + a[ctr++] = Q + GAMMA1 - 1 - t0; + if(t1 <= 2*GAMMA1 - 2 && ctr < len) + a[ctr++] = Q + GAMMA1 - 1 - t1; + } + return ctr; +} + +/*************************************************/ +void poly_uniform_gamma1m1(poly *a, const unsigned char seed[SEEDBYTES + CRHBYTES], uint16_t nonce) +{ + unsigned int i, ctr; + unsigned char inbuf[SEEDBYTES + CRHBYTES + 2]; + + unsigned char outbuf[5*SHAKE256_RATE]; + uint64_t state[25] = {0}; + + for(i = 0; i < SEEDBYTES + CRHBYTES; ++i) + inbuf[i] = seed[i]; + inbuf[SEEDBYTES + CRHBYTES] = nonce & 0xFF; + inbuf[SEEDBYTES + CRHBYTES + 1] = nonce >> 8; + + shake256_absorb(state, inbuf, SEEDBYTES + CRHBYTES + 2); + shake256_squeezeblocks(outbuf, 5, state); + + ctr = rej_gamma1m1(a->coeffs, N, outbuf, 5*SHAKE256_RATE); + if(ctr < N) { + + shake256_squeezeblocks(outbuf, 1, state); + rej_gamma1m1(a->coeffs + ctr, N - ctr, outbuf, SHAKE256_RATE); + } +} + +/*************************************************/ +void polyeta_pack(unsigned char *r, const poly *a, dilithium_param_t *p) +{ + if (p->PARAM_ETA > 7) + { + printf("polyeta_pack() assumes ETA <= 7"); + return; + } + + unsigned int i; + unsigned char t[8]; + + if (p->PARAM_ETA <= 3) + { + for(i = 0; i < N/8; ++i) + { + t[0] = Q + p->PARAM_ETA - a->coeffs[8*i+0]; + t[1] = Q + p->PARAM_ETA - a->coeffs[8*i+1]; + t[2] = Q + p->PARAM_ETA - a->coeffs[8*i+2]; + t[3] = Q + p->PARAM_ETA - a->coeffs[8*i+3]; + t[4] = Q + p->PARAM_ETA - a->coeffs[8*i+4]; + t[5] = Q + p->PARAM_ETA - a->coeffs[8*i+5]; + t[6] = Q + p->PARAM_ETA - a->coeffs[8*i+6]; + t[7] = Q + p->PARAM_ETA - a->coeffs[8*i+7]; + + r[3*i+0] = t[0]; + r[3*i+0] |= t[1] << 3; + r[3*i+0] |= t[2] << 6; + r[3*i+1] = t[2] >> 2; + r[3*i+1] |= t[3] << 1; + r[3*i+1] |= t[4] << 4; + r[3*i+1] |= t[5] << 7; + r[3*i+2] = t[5] >> 1; + r[3*i+2] |= t[6] << 2; + r[3*i+2] |= t[7] << 5; + } + } + else + { + for(i = 0; i < N/2; ++i) + { + t[0] = Q + p->PARAM_ETA - a->coeffs[2*i+0]; + t[1] = Q + p->PARAM_ETA - a->coeffs[2*i+1]; + r[i] = t[0] | (t[1] << 4); + } + } +} + +/*************************************************/ +void polyeta_unpack(poly *r, const unsigned char *a, dilithium_param_t *p) +{ + unsigned int i; + + if (p->PARAM_ETA <= 3) + { + for(i = 0; i < N/8; ++i) + { + r->coeffs[8*i+0] = a[3*i+0] & 0x07; + r->coeffs[8*i+1] = (a[3*i+0] >> 3) & 0x07; + r->coeffs[8*i+2] = (a[3*i+0] >> 6) | ((a[3*i+1] & 0x01) << 2); + r->coeffs[8*i+3] = (a[3*i+1] >> 1) & 0x07; + r->coeffs[8*i+4] = (a[3*i+1] >> 4) & 0x07; + r->coeffs[8*i+5] = (a[3*i+1] >> 7) | ((a[3*i+2] & 0x03) << 1); + r->coeffs[8*i+6] = (a[3*i+2] >> 2) & 0x07; + r->coeffs[8*i+7] = (a[3*i+2] >> 5); + + r->coeffs[8*i+0] = Q + p->PARAM_ETA - r->coeffs[8*i+0]; + r->coeffs[8*i+1] = Q + p->PARAM_ETA - r->coeffs[8*i+1]; + r->coeffs[8*i+2] = Q + p->PARAM_ETA - r->coeffs[8*i+2]; + r->coeffs[8*i+3] = Q + p->PARAM_ETA - r->coeffs[8*i+3]; + r->coeffs[8*i+4] = Q + p->PARAM_ETA - r->coeffs[8*i+4]; + r->coeffs[8*i+5] = Q + p->PARAM_ETA - r->coeffs[8*i+5]; + r->coeffs[8*i+6] = Q + p->PARAM_ETA - r->coeffs[8*i+6]; + r->coeffs[8*i+7] = Q + p->PARAM_ETA - r->coeffs[8*i+7]; + } + } + else + { + for(i = 0; i < N/2; ++i) + { + r->coeffs[2*i+0] = a[i] & 0x0F; + r->coeffs[2*i+1] = a[i] >> 4; + r->coeffs[2*i+0] = Q + p->PARAM_ETA - r->coeffs[2*i+0]; + r->coeffs[2*i+1] = Q + p->PARAM_ETA - r->coeffs[2*i+1]; + } + } +} + +/*************************************************/ +void polyt1_pack(unsigned char *r, const poly *a) { +#if D != 14 +#error "polyt1_pack() assumes D == 14" +#endif + unsigned int i; + + for(i = 0; i < N/8; ++i) { + r[9*i+0] = a->coeffs[8*i+0] & 0xFF; + r[9*i+1] = (a->coeffs[8*i+0] >> 8) | ((a->coeffs[8*i+1] & 0x7F) << 1); + r[9*i+2] = (a->coeffs[8*i+1] >> 7) | ((a->coeffs[8*i+2] & 0x3F) << 2); + r[9*i+3] = (a->coeffs[8*i+2] >> 6) | ((a->coeffs[8*i+3] & 0x1F) << 3); + r[9*i+4] = (a->coeffs[8*i+3] >> 5) | ((a->coeffs[8*i+4] & 0x0F) << 4); + r[9*i+5] = (a->coeffs[8*i+4] >> 4) | ((a->coeffs[8*i+5] & 0x07) << 5); + r[9*i+6] = (a->coeffs[8*i+5] >> 3) | ((a->coeffs[8*i+6] & 0x03) << 6); + r[9*i+7] = (a->coeffs[8*i+6] >> 2) | ((a->coeffs[8*i+7] & 0x01) << 7); + r[9*i+8] = a->coeffs[8*i+7] >> 1; + } +} + +/*************************************************/ +void polyt1_unpack(poly *r, const unsigned char *a) { + unsigned int i; + + for(i = 0; i < N/8; ++i) { + r->coeffs[8*i+0] = a[9*i+0] | ((uint32_t)(a[9*i+1] & 0x01) << 8); + r->coeffs[8*i+1] = (a[9*i+1] >> 1) | ((uint32_t)(a[9*i+2] & 0x03) << 7); + r->coeffs[8*i+2] = (a[9*i+2] >> 2) | ((uint32_t)(a[9*i+3] & 0x07) << 6); + r->coeffs[8*i+3] = (a[9*i+3] >> 3) | ((uint32_t)(a[9*i+4] & 0x0F) << 5); + r->coeffs[8*i+4] = (a[9*i+4] >> 4) | ((uint32_t)(a[9*i+5] & 0x1F) << 4); + r->coeffs[8*i+5] = (a[9*i+5] >> 5) | ((uint32_t)(a[9*i+6] & 0x3F) << 3); + r->coeffs[8*i+6] = (a[9*i+6] >> 6) | ((uint32_t)(a[9*i+7] & 0x7F) << 2); + r->coeffs[8*i+7] = (a[9*i+7] >> 7) | ((uint32_t)(a[9*i+8] & 0xFF) << 1); + } +} + +/*************************************************/ +void polyt0_pack(unsigned char *r, const poly *a) { + unsigned int i; + uint32_t t[4]; + + for(i = 0; i < N/4; ++i) { + t[0] = Q + (1 << (D-1)) - a->coeffs[4*i+0]; + t[1] = Q + (1 << (D-1)) - a->coeffs[4*i+1]; + t[2] = Q + (1 << (D-1)) - a->coeffs[4*i+2]; + t[3] = Q + (1 << (D-1)) - a->coeffs[4*i+3]; + + r[7*i+0] = t[0]; + r[7*i+1] = t[0] >> 8; + r[7*i+1] |= t[1] << 6; + r[7*i+2] = t[1] >> 2; + r[7*i+3] = t[1] >> 10; + r[7*i+3] |= t[2] << 4; + r[7*i+4] = t[2] >> 4; + r[7*i+5] = t[2] >> 12; + r[7*i+5] |= t[3] << 2; + r[7*i+6] = t[3] >> 6; + } +} + +/*************************************************/ +void polyt0_unpack(poly *r, const unsigned char *a) { + unsigned int i; + + for(i = 0; i < N/4; ++i) { + r->coeffs[4*i+0] = a[7*i+0]; + r->coeffs[4*i+0] |= (uint32_t)(a[7*i+1] & 0x3F) << 8; + + r->coeffs[4*i+1] = a[7*i+1] >> 6; + r->coeffs[4*i+1] |= (uint32_t)a[7*i+2] << 2; + r->coeffs[4*i+1] |= (uint32_t)(a[7*i+3] & 0x0F) << 10; + + r->coeffs[4*i+2] = a[7*i+3] >> 4; + r->coeffs[4*i+2] |= (uint32_t)a[7*i+4] << 4; + r->coeffs[4*i+2] |= (uint32_t)(a[7*i+5] & 0x03) << 12; + + r->coeffs[4*i+3] = a[7*i+5] >> 2; + r->coeffs[4*i+3] |= (uint32_t)a[7*i+6] << 6; + + r->coeffs[4*i+0] = Q + (1 << (D-1)) - r->coeffs[4*i+0]; + r->coeffs[4*i+1] = Q + (1 << (D-1)) - r->coeffs[4*i+1]; + r->coeffs[4*i+2] = Q + (1 << (D-1)) - r->coeffs[4*i+2]; + r->coeffs[4*i+3] = Q + (1 << (D-1)) - r->coeffs[4*i+3]; + } +} + +/*************************************************/ +void polyz_pack(unsigned char *r, const poly *a) { +#if GAMMA1 > (1 << 19) +#error "polyz_pack() assumes GAMMA1 <= 2^{19}" +#endif + unsigned int i; + uint32_t t[2]; + + for(i = 0; i < N/2; ++i) { + t[0] = GAMMA1 - 1 - a->coeffs[2*i+0]; + t[0] += ((int32_t)t[0] >> 31) & Q; + t[1] = GAMMA1 - 1 - a->coeffs[2*i+1]; + t[1] += ((int32_t)t[1] >> 31) & Q; + + r[5*i+0] = t[0]; + r[5*i+1] = t[0] >> 8; + r[5*i+2] = t[0] >> 16; + r[5*i+2] |= t[1] << 4; + r[5*i+3] = t[1] >> 4; + r[5*i+4] = t[1] >> 12; + } +} + +/*************************************************/ +void polyz_unpack(poly *r, const unsigned char *a) { + unsigned int i; + + for(i = 0; i < N/2; ++i) { + r->coeffs[2*i+0] = a[5*i+0]; + r->coeffs[2*i+0] |= (uint32_t)a[5*i+1] << 8; + r->coeffs[2*i+0] |= (uint32_t)(a[5*i+2] & 0x0F) << 16; + + r->coeffs[2*i+1] = a[5*i+2] >> 4; + r->coeffs[2*i+1] |= (uint32_t)a[5*i+3] << 4; + r->coeffs[2*i+1] |= (uint32_t)a[5*i+4] << 12; + + r->coeffs[2*i+0] = GAMMA1 - 1 - r->coeffs[2*i+0]; + r->coeffs[2*i+0] += ((int32_t)r->coeffs[2*i+0] >> 31) & Q; + r->coeffs[2*i+1] = GAMMA1 - 1 - r->coeffs[2*i+1]; + r->coeffs[2*i+1] += ((int32_t)r->coeffs[2*i+1] >> 31) & Q; + } +} + +/*************************************************/ +void polyw1_pack(unsigned char *r, const poly *a) { + unsigned int i; + + for(i = 0; i < N/2; ++i) + r[i] = a->coeffs[2*i+0] | (a->coeffs[2*i+1] << 4); +} + +/**************************************************/ +static const uint32_t zetas[N] = {0, 25847, 5771523, 7861508, 237124, 7602457, 7504169, 466468, + 1826347, 2353451, 8021166, 6288512, 3119733, 5495562, 3111497, 2680103, + 2725464, 1024112, 7300517, 3585928, 7830929, 7260833, 2619752, 6271868, + 6262231, 4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005, + 2706023, 95776, 3077325, 3530437, 6718724, 4788269, 5842901, 3915439, + 4519302, 5336701, 3574422, 5512770, 3539968, 8079950, 2348700, 7841118, + 6681150, 6736599, 3505694, 4558682, 3507263, 6239768, 6779997, 3699596, + 811944, 531354, 954230, 3881043, 3900724, 5823537, 2071892, 5582638, + 4450022, 6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196, + 7122806, 1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922, + 3412210, 7396998, 2147896, 2715295, 5412772, 4686924, 7969390, 5903370, + 7709315, 7151892, 8357436, 7072248, 7998430, 1349076, 1852771, 6949987, + 5037034, 264944, 508951, 3097992, 44288, 7280319, 904516, 3958618, + 4656075, 8371839, 1653064, 5130689, 2389356, 8169440, 759969, 7063561, + 189548, 4827145, 3159746, 6529015, 5971092, 8202977, 1315589, 1341330, + 1285669, 6795489, 7567685, 6940675, 5361315, 4499357, 4751448, 3839961, + 2091667, 3407706, 2316500, 3817976, 5037939, 2244091, 5933984, 4817955, + 266997, 2434439, 7144689, 3513181, 4860065, 4621053, 7183191, 5187039, + 900702, 1859098, 909542, 819034, 495491, 6767243, 8337157, 7857917, + 7725090, 5257975, 2031748, 3207046, 4823422, 7855319, 7611795, 4784579, + 342297, 286988, 5942594, 4108315, 3437287, 5038140, 1735879, 203044, + 2842341, 2691481, 5790267, 1265009, 4055324, 1247620, 2486353, 1595974, + 4613401, 1250494, 2635921, 4832145, 5386378, 1869119, 1903435, 7329447, + 7047359, 1237275, 5062207, 6950192, 7929317, 1312455, 3306115, 6417775, + 7100756, 1917081, 5834105, 7005614, 1500165, 777191, 2235880, 3406031, + 7838005, 5548557, 6709241, 6533464, 5796124, 4656147, 594136, 4603424, + 6366809, 2432395, 2454455, 8215696, 1957272, 3369112, 185531, 7173032, + 5196991, 162844, 1616392, 3014001, 810149, 1652634, 4686184, 6581310, + 5341501, 3523897, 3866901, 269760, 2213111, 7404533, 1717735, 472078, + 7953734, 1723600, 6577327, 1910376, 6712985, 7276084, 8119771, 4546524, + 5441381, 6144432, 7959518, 6094090, 183443, 7403526, 1612842, 4834730, + 7826001, 3919660, 8332111, 7018208, 3937738, 1400424, 7534263, 1976782}; + +static const uint32_t zetas_inv[N] = + {6403635, 846154, 6979993, 4442679, 1362209, 48306, 4460757, 554416, + 3545687, 6767575, 976891, 8196974, 2286327, 420899, 2235985, 2939036, + 3833893, 260646, 1104333, 1667432, 6470041, 1803090, 6656817, 426683, + 7908339, 6662682, 975884, 6167306, 8110657, 4513516, 4856520, 3038916, + 1799107, 3694233, 6727783, 7570268, 5366416, 6764025, 8217573, 3183426, + 1207385, 8194886, 5011305, 6423145, 164721, 5925962, 5948022, 2013608, + 3776993, 7786281, 3724270, 2584293, 1846953, 1671176, 2831860, 542412, + 4974386, 6144537, 7603226, 6880252, 1374803, 2546312, 6463336, 1279661, + 1962642, 5074302, 7067962, 451100, 1430225, 3318210, 7143142, 1333058, + 1050970, 6476982, 6511298, 2994039, 3548272, 5744496, 7129923, 3767016, + 6784443, 5894064, 7132797, 4325093, 7115408, 2590150, 5688936, 5538076, + 8177373, 6644538, 3342277, 4943130, 4272102, 2437823, 8093429, 8038120, + 3595838, 768622, 525098, 3556995, 5173371, 6348669, 3122442, 655327, + 522500, 43260, 1613174, 7884926, 7561383, 7470875, 6521319, 7479715, + 3193378, 1197226, 3759364, 3520352, 4867236, 1235728, 5945978, 8113420, + 3562462, 2446433, 6136326, 3342478, 4562441, 6063917, 4972711, 6288750, + 4540456, 3628969, 3881060, 3019102, 1439742, 812732, 1584928, 7094748, + 7039087, 7064828, 177440, 2409325, 1851402, 5220671, 3553272, 8190869, + 1316856, 7620448, 210977, 5991061, 3249728, 6727353, 8578, 3724342, + 4421799, 7475901, 1100098, 8336129, 5282425, 7871466, 8115473, 3343383, + 1430430, 6527646, 7031341, 381987, 1308169, 22981, 1228525, 671102, + 2477047, 411027, 3693493, 2967645, 5665122, 6232521, 983419, 4968207, + 8253495, 3632928, 3157330, 3190144, 1000202, 4083598, 6441103, 1257611, + 1585221, 6203962, 4904467, 1452451, 3041255, 3677745, 1528703, 3930395, + 2797779, 6308525, 2556880, 4479693, 4499374, 7426187, 7849063, 7568473, + 4680821, 1600420, 2140649, 4873154, 3821735, 4874723, 1643818, 1699267, + 539299, 6031717, 300467, 4840449, 2867647, 4805995, 3043716, 3861115, + 4464978, 2537516, 3592148, 1661693, 4849980, 5303092, 8284641, 5674394, + 8100412, 4369920, 19422, 6623180, 3277672, 1399561, 3859737, 2118186, + 2108549, 5760665, 1119584, 549488, 4794489, 1079900, 7356305, 5654953, + 5700314, 5268920, 2884855, 5260684, 2091905, 359251, 6026966, 6554070, + 7913949, 876248, 777960, 8143293, 518909, 2608894, 8354570}; + +/*************************************************/ +void dilithium_ntt(uint32_t pp[N]) +{ + unsigned int len, start, j, k; + uint32_t zeta, t; + + k = 1; + for(len = 128; len > 0; len >>= 1) + { + for(start = 0; start < N; start = j + len) + { + zeta = zetas[k++]; + for(j = start; j < start + len; ++j) + { + t = montgomery_reduce((uint64_t)zeta * pp[j + len]); + pp[j + len] = pp[j] + 2*Q - t; + pp[j] = pp[j] + t; + } + } + } +} + +/*************************************************/ +void invntt_frominvmont(uint32_t pp[N]) +{ + unsigned int start, len, j, k; + uint32_t t, zeta; + const uint32_t f = (((uint64_t)MONT*MONT % Q) * (Q-1) % Q) * ((Q-1) >> 8) % Q; + + k = 0; + for(len = 1; len < N; len <<= 1) + { + for(start = 0; start < N; start = j + len) + { + zeta = zetas_inv[k++]; + for(j = start; j < start + len; ++j) + { + t = pp[j]; + pp[j] = t + pp[j + len]; + pp[j + len] = t + 256*Q - pp[j + len]; + pp[j + len] = montgomery_reduce((uint64_t)zeta * pp[j + len]); + } + } + } + + for(j = 0; j < N; ++j) + { + pp[j] = montgomery_reduce((uint64_t)f * pp[j]); + } +} diff --git a/src/sig_dilithium/dilithium_poly.h b/src/sig_dilithium/dilithium_poly.h new file mode 100755 index 0000000000000000000000000000000000000000..f219ed0efc3cf3e023f81b88f16a5b51e8394794 --- /dev/null +++ b/src/sig_dilithium/dilithium_poly.h @@ -0,0 +1,52 @@ +#ifndef POLY_H +#define POLY_H + +#include <stdint.h> +#include "dilithium_params.h" +#include "dilithium_rounding_reduce.h" + +typedef struct { + uint32_t coeffs[N]; +} poly __attribute__((aligned(32))); + +void poly_reduce(poly *a); +void poly_csubq(poly *a); +void poly_freeze(poly *a); + +void dilithium_poly_add(poly *c, const poly *a, const poly *b); +void dilithium_poly_sub(poly *c, const poly *a, const poly *b); +void poly_neg(poly *a); +void poly_shiftl(poly *a, unsigned int k); + +void dilithium_poly_ntt(poly *a); +void poly_invntt_montgomery(poly *a); +void poly_pointwise_invmontgomery(poly *c, const poly *a, const poly *b); + +void poly_power2round(poly *a1, poly *a0, const poly *a); +void poly_decompose(poly *a1, poly *a0, const poly *a); +unsigned int poly_make_hint(poly *h, const poly *a, const poly *b); +void poly_use_hint(poly *a, const poly *b, const poly *h); + +int poly_chknorm(const poly *a, uint32_t B); +void dilithium_poly_uniform(poly *a, const unsigned char *buf); +void poly_uniform_eta(poly *a, const unsigned char seed[SEEDBYTES], unsigned char nonce, dilithium_param_t *p); +void poly_uniform_gamma1m1(poly *a, const unsigned char seed[SEEDBYTES + CRHBYTES], uint16_t nonce); + +void polyeta_pack(unsigned char *r, const poly *a, dilithium_param_t *p); +void polyeta_unpack(poly *r, const unsigned char *a, dilithium_param_t *p); + +void polyt1_pack(unsigned char *r, const poly *a); +void polyt1_unpack(poly *r, const unsigned char *a); + +void polyt0_pack(unsigned char *r, const poly *a); +void polyt0_unpack(poly *r, const unsigned char *a); + +void polyz_pack(unsigned char *r, const poly *a); +void polyz_unpack(poly *r, const unsigned char *a); + +void polyw1_pack(unsigned char *r, const poly *a); + +void dilithium_ntt(uint32_t pp[N]); +void invntt_frominvmont(uint32_t pp[N]); + +#endif diff --git a/src/sig_dilithium/dilithium_polyvec.c b/src/sig_dilithium/dilithium_polyvec.c new file mode 100755 index 0000000000000000000000000000000000000000..a0bb9c0341d87318feeceaa5501e88d5fa4d82c7 --- /dev/null +++ b/src/sig_dilithium/dilithium_polyvec.c @@ -0,0 +1,163 @@ +#include <stdint.h> + +#include "dilithium_poly.h" +#include "dilithium_polyvec.h" + +/*************************************************/ +void polyvecl_freeze(polyvecl *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_L; ++i) + poly_freeze(v->vec + i); +} + +/*************************************************/ +void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_L; ++i) + dilithium_poly_add(w->vec+i, u->vec+i, v->vec+i); +} + +/*************************************************/ +void polyvecl_ntt(polyvecl *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_L; ++i) + dilithium_poly_ntt(v->vec+i); +} + +/*************************************************/ +void polyvecl_pointwise_acc_invmontgomery(poly *w, const polyvecl *u, const polyvecl *v, dilithium_param_t *p) +{ + unsigned int i; + poly t; + + poly_pointwise_invmontgomery(w, u->vec+0, v->vec+0); + + for(i = 1; i < p->PARAM_L; ++i) { + poly_pointwise_invmontgomery(&t, u->vec+i, v->vec+i); + dilithium_poly_add(w, w, &t); + } +} + +/*************************************************/ +int polyvecl_chknorm(const polyvecl *v, uint32_t bound, dilithium_param_t *p) { + unsigned int i; + int ret = 0; + + for(i = 0; i < p->PARAM_L; ++i) + ret |= poly_chknorm(v->vec+i, bound); + + return ret; +} + +/*************************************************/ +void polyveck_reduce(polyveck *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + poly_reduce(v->vec+i); +} + +/*************************************************/ +void polyveck_csubq(polyveck *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + poly_csubq(v->vec+i); +} + +/*************************************************/ +void polyveck_freeze(polyveck *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + poly_freeze(v->vec+i); +} + +/*************************************************/ +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + dilithium_poly_add(w->vec+i, u->vec+i, v->vec+i); +} + +/*************************************************/ +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + dilithium_poly_sub(w->vec+i, u->vec+i, v->vec+i); +} + +/*************************************************/ +void polyveck_shiftl(polyveck *v, unsigned int k, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + poly_shiftl(v->vec + i, k); +} + +/*************************************************/ +void polyveck_ntt(polyveck *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + dilithium_poly_ntt(v->vec + i); +} + +/*************************************************/ +void polyveck_invntt_montgomery(polyveck *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + poly_invntt_montgomery(v->vec + i); +} + +/*************************************************/ +int polyveck_chknorm(const polyveck *v, uint32_t bound, dilithium_param_t *p) { + unsigned int i; + int ret = 0; + + for(i = 0; i < p->PARAM_K; ++i) + ret |= poly_chknorm(v->vec+i, bound); + + return ret; +} + +/*************************************************/ +void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + poly_power2round(v1->vec+i, v0->vec+i, v->vec+i); +} + +/*************************************************/ +void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + poly_decompose(v1->vec+i, v0->vec+i, v->vec+i); +} + +/*************************************************/ +unsigned int polyveck_make_hint(polyveck *h, const polyveck *u, const polyveck *v, dilithium_param_t *p) +{ + unsigned int i, s = 0; + + for(i = 0; i < p->PARAM_K; ++i) + s += poly_make_hint(h->vec+i, u->vec+i, v->vec+i); + + return s; +} + +/*************************************************/ +void polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h, dilithium_param_t *p) { + unsigned int i; + + for(i = 0; i < p->PARAM_K; ++i) + poly_use_hint(w->vec+i, u->vec+i, h->vec+i); +} diff --git a/src/sig_dilithium/dilithium_polyvec.h b/src/sig_dilithium/dilithium_polyvec.h new file mode 100755 index 0000000000000000000000000000000000000000..b9e1f985d622e48698c8a9faa63e8093457b370f --- /dev/null +++ b/src/sig_dilithium/dilithium_polyvec.h @@ -0,0 +1,43 @@ +#ifndef POLYVEC_H +#define POLYVEC_H + +#include <stdint.h> +#include "dilithium_poly.h" + +typedef struct { + poly vec[5]; +} polyvecl; + +void polyvecl_freeze(polyvecl *v, dilithium_param_t *p); + +void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v, dilithium_param_t *p); + +void polyvecl_ntt(polyvecl *v, dilithium_param_t *p); +void polyvecl_pointwise_acc_invmontgomery(poly *w, const polyvecl *u, const polyvecl *v, dilithium_param_t *p); + +int polyvecl_chknorm(const polyvecl *v, uint32_t B, dilithium_param_t *p); + + +typedef struct { + poly vec[6]; +} polyveck; + +void polyveck_reduce(polyveck *v, dilithium_param_t *p); +void polyveck_csubq(polyveck *v, dilithium_param_t *p); +void polyveck_freeze(polyveck *v, dilithium_param_t *p); + +void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v, dilithium_param_t *p); +void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v, dilithium_param_t *p); +void polyveck_shiftl(polyveck *v, unsigned int k, dilithium_param_t *p); + +void polyveck_ntt(polyveck *v, dilithium_param_t *p); +void polyveck_invntt_montgomery(polyveck *v, dilithium_param_t *p); + +int polyveck_chknorm(const polyveck *v, uint32_t B, dilithium_param_t *p); + +void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v, dilithium_param_t *p); +void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v, dilithium_param_t *p); +unsigned int polyveck_make_hint(polyveck *h, const polyveck *u, const polyveck *v, dilithium_param_t *p); +void polyveck_use_hint(polyveck *w, const polyveck *v, const polyveck *h, dilithium_param_t *p); + +#endif diff --git a/src/sig_dilithium/dilithium_rounding_reduce.c b/src/sig_dilithium/dilithium_rounding_reduce.c new file mode 100755 index 0000000000000000000000000000000000000000..9e061b0987fbe9416ca3f101b1d428610f7c5478 --- /dev/null +++ b/src/sig_dilithium/dilithium_rounding_reduce.c @@ -0,0 +1,105 @@ +#include <stdint.h> +#include "dilithium_rounding_reduce.h" + +/*************************************************/ +uint32_t montgomery_reduce(uint64_t a) +{ + uint64_t t; + + t = a * QINV; + t &= (1ULL << 32) - 1; + t *= Q; + t = a + t; + t >>= 32; + return t; +} + +/*************************************************/ +uint32_t reduce32(uint32_t a) +{ + uint32_t t; + + t = a & 0x7FFFFF; + a >>= 23; + t += (a << 13) - a; + return t; +} + +/*************************************************/ +uint32_t csubq(uint32_t a) +{ + a -= Q; + a += ((int32_t)a >> 31) & Q; + return a; +} + +/*************************************************/ +uint32_t freeze(uint32_t a) +{ + a = reduce32(a); + a = csubq(a); + return a; +} + +/*************************************************/ +uint32_t power2round(uint32_t a, uint32_t *a0) +{ + int32_t t; + + /* Centralized remainder mod 2^D */ + t = a & ((1 << D) - 1); + t -= (1 << (D-1)) + 1; + t += (t >> 31) & (1 << D); + t -= (1 << (D-1)) - 1; + *a0 = Q + t; + a = (a - t) >> D; + return a; +} + +/*************************************************/ +uint32_t decompose(uint32_t a, uint32_t *a0) +{ +#if ALPHA != (Q-1)/16 +#error "decompose assumes ALPHA == (Q-1)/16" +#endif + int32_t t, u; + + t = a & 0x7FFFF; + t += (a >> 19) << 9; + t -= ALPHA/2 + 1; + t += (t >> 31) & ALPHA; + t -= ALPHA/2 - 1; + a -= t; + + u = a - 1; + u >>= 31; + a = (a >> 19) + 1; + a -= u & 1; + + *a0 = Q + t - (a >> 4); + a &= 0xF; + return a; +} + +/*************************************************/ +unsigned int make_hint(const uint32_t a, const uint32_t b) +{ + uint32_t t; + + return decompose(a, &t) != decompose(b, &t); +} + +/*************************************************/ +uint32_t use_hint(const uint32_t a, const unsigned int hint) +{ + uint32_t a0, a1; + + a1 = decompose(a, &a0); + if(hint == 0) + return a1; + else if(a0 > Q) + return (a1 + 1) & 0xF; + else + return (a1 - 1) & 0xF; +} + diff --git a/src/sig_dilithium/dilithium_rounding_reduce.h b/src/sig_dilithium/dilithium_rounding_reduce.h new file mode 100755 index 0000000000000000000000000000000000000000..65cdf003ee3c57bf0a5ab17f195fe5005e8dbf82 --- /dev/null +++ b/src/sig_dilithium/dilithium_rounding_reduce.h @@ -0,0 +1,23 @@ +#ifndef REDUCE_H +#define REDUCE_H + +#include <stdint.h> +#include "dilithium_params.h" + +#define MONT 4193792U +#define QINV 4236238847U + +uint32_t montgomery_reduce(uint64_t a); + +uint32_t reduce32(uint32_t a); + +uint32_t csubq(uint32_t a); + +uint32_t freeze(uint32_t a); + +uint32_t power2round(const uint32_t a, uint32_t *a0); +uint32_t decompose(uint32_t a, uint32_t *a0); +unsigned int make_hint(const uint32_t a, const uint32_t b); +uint32_t use_hint(const uint32_t a, const unsigned int hint); + +#endif diff --git a/src/sig_dilithium/dilithium_sign.c b/src/sig_dilithium/dilithium_sign.c new file mode 100755 index 0000000000000000000000000000000000000000..04cbed881c83c39951a8a824ce5cec3ed2da5a82 --- /dev/null +++ b/src/sig_dilithium/dilithium_sign.c @@ -0,0 +1,378 @@ +#include <stdint.h> +#include "dilithium_sign.h" + +/********************************************************************************************/ +void expand_mat(polyvecl mat[], const unsigned char rho[SEEDBYTES], dilithium_param_t *p) +{ + unsigned int i, j; + unsigned char inbuf[SEEDBYTES + 1]; + + unsigned char outbuf[5*SHAKE128_RATE]; + + for(i = 0; i < SEEDBYTES; ++i) + inbuf[i] = rho[i]; + + for(i = 0; i < p->PARAM_K; ++i) { + for(j = 0; j < p->PARAM_L; ++j) { + inbuf[SEEDBYTES] = i + (j << 4); + shake128(outbuf, sizeof(outbuf), inbuf, SEEDBYTES + 1); + dilithium_poly_uniform(mat[i].vec + j, outbuf); + } + } +} + +/********************************************************************************************/ +void challenge(poly *c, const unsigned char mu[CRHBYTES], const polyveck *w1, dilithium_param_t *p) +{ + unsigned int i, b, pos; + unsigned char inbuf[CRHBYTES + p->PARAM_K * p->PARAM_POLW1_SIZE_PACKED]; + unsigned char outbuf[SHAKE256_RATE]; + uint64_t state[25] = {0}, signs, mask; + + for(i = 0; i < CRHBYTES; ++i) + inbuf[i] = mu[i]; + for(i = 0; i < p->PARAM_K; ++i) + polyw1_pack(inbuf + CRHBYTES + i * p->PARAM_POLW1_SIZE_PACKED, w1->vec + i); + + shake256_absorb(state, inbuf, sizeof(inbuf)); + shake256_squeezeblocks(outbuf, 1, state); + + signs = 0; + for(i = 0; i < 8; ++i) + signs |= (uint64_t)outbuf[i] << 8*i; + + pos = 8; + mask = 1; + + for(i = 0; i < N; ++i) + c->coeffs[i] = 0; + + for(i = 196; i < 256; ++i) { + do { + if(pos >= SHAKE256_RATE) { + shake256_squeezeblocks(outbuf, 1, state); + pos = 0; + } + + b = outbuf[pos++]; + } while(b > i); + + c->coeffs[i] = c->coeffs[b]; + c->coeffs[b] = (signs & mask) ? Q - 1 : 1; + mask <<= 1; + } +} + +/********************************************************************************************/ +void dilithium_private_key_delete(dilithium_private_key_t *private_key) +{ + + if(private_key) { + free(private_key->data); + private_key->data = NULL; + free(private_key); + } +} + +void dilithium_public_key_delete(dilithium_public_key_t *public_key) +{ + if(public_key) { + free(public_key->data); + public_key->data = NULL; + free(public_key); + } +} + +void dilithium_private_and_public_keys_delete(dilithium_private_key_t *private_key, dilithium_public_key_t *public_key){ + + free(private_key->data); + private_key->data = NULL; + free(public_key->data); + public_key->data = NULL; +} + +/********************************************************************************************/ + +static int32_t dilithium_private_and_public_keys_init(dilithium_private_key_t *private_key, dilithium_public_key_t *public_key, dilithium_param_t *p){ + + unsigned char *f = NULL, *g = NULL; + + f = calloc(p->CRYPTO_PUBLICKEYBYTES, sizeof(char)); + if (f == NULL) { + free(f); + free(g); + return -1; + } + public_key->kind = p->kind; + public_key->data = f; + + g = calloc(p->CRYPTO_SECRETKEYBYTES, sizeof(char)); + if (g == NULL) { + free(f); + free(g); + return -1; + } + + private_key->kind = p->kind; + private_key->data = g; + + return 0; +} + +/*************************************************/ +int dilithium_crypto_sign_keypair(dilithium_public_key_t *public_key, dilithium_private_key_t *private_key, dilithium_kind_t kind) { + + dilithium_param_t *p = malloc(sizeof(dilithium_param_t)); + if (! dilithium_params_init( p, kind)) return -1; + + assert(private_key != NULL); + + if(dilithium_private_and_public_keys_init( private_key, public_key, p) != 0) { + free(p); + return -1; + } + + unsigned int i; + unsigned char seedbuf[3*SEEDBYTES]; + unsigned char tr[CRHBYTES]; + unsigned char *rho, *rhoprime, *key; + uint16_t nonce = 0; + polyvecl mat[p->PARAM_K]; + polyvecl s1, s1hat; + polyveck s2, t, t1, t0; + + randombytes(seedbuf, SEEDBYTES); + + shake256(seedbuf, 3*SEEDBYTES, seedbuf, SEEDBYTES); + rho = seedbuf; + rhoprime = rho + SEEDBYTES; + key = rho + 2*SEEDBYTES; + + expand_mat(mat, rho, p); + + for(i = 0; i < p->PARAM_L; ++i) + poly_uniform_eta(s1.vec + i, rhoprime, nonce++, p); + for(i = 0; i < p->PARAM_K; ++i) + poly_uniform_eta(s2.vec + i, rhoprime, nonce++, p); + + s1hat = s1; + polyvecl_ntt(&s1hat, p); + for(i = 0; i < p->PARAM_K; ++i) { + polyvecl_pointwise_acc_invmontgomery(t.vec+i, mat+i, &s1hat, p); + poly_reduce(t.vec+i); + poly_invntt_montgomery(t.vec+i); + } + + polyveck_add(&t, &t, &s2, p); + + polyveck_freeze(&t, p); + polyveck_power2round(&t1, &t0, &t, p); + dilithium_pack_pk(public_key->data, rho, &t1, p); + + shake256(tr, CRHBYTES, public_key->data, p->CRYPTO_PUBLICKEYBYTES); + dilithium_pack_sk(private_key->data, rho, key, tr, &s1, &s2, &t0, p); + + free(p); + p = NULL; + + return 0; +} + +/*************************************************/ +int dilithium_crypto_sign( dilithium_signature_t *sig, const unsigned char *m, unsigned long long mlen, const dilithium_private_key_t *private_key) +{ + dilithium_param_t *p = malloc(sizeof(dilithium_param_t)); + if (! dilithium_params_init( p, private_key->kind)) { + free(p); + return 1; + } + + unsigned long long i, j; + unsigned int n; + unsigned char seedbuf[2*SEEDBYTES + CRHBYTES]; + unsigned char tr[CRHBYTES]; + unsigned char *rho, *key, *mu; + uint16_t nonce = 0; + poly c, chat; + polyvecl mat[p->PARAM_K], s1, y, yhat, z; + polyveck s2, t0, w, w1; + polyveck h, wcs2, wcs20, ct0, tmp; + + rho = seedbuf; + key = seedbuf + SEEDBYTES; + mu = seedbuf + 2*SEEDBYTES; + dilithium_unpack_sk(rho, key, tr, &s1, &s2, &t0, private_key->data, p); + + sig->sig_len = mlen + p->CRYPTO_BYTES; + sig->sig_data = malloc( sig->sig_len); + + for(i = 1; i <= mlen; ++i) + sig->sig_data[p->CRYPTO_BYTES + mlen - i] = m[mlen - i]; + for(i = 0; i < CRHBYTES; ++i) + sig->sig_data[p->CRYPTO_BYTES - CRHBYTES + i] = tr[i]; + + shake256(mu, CRHBYTES, sig->sig_data + p->CRYPTO_BYTES - CRHBYTES, CRHBYTES + mlen); + + expand_mat(mat, rho, p); + polyvecl_ntt(&s1, p); + polyveck_ntt(&s2, p); + polyveck_ntt(&t0, p); + + while(1){ + for(i = 0; i < p->PARAM_L; ++i) + poly_uniform_gamma1m1(y.vec+i, key, nonce++); + + yhat = y; + polyvecl_ntt(&yhat, p); + for(i = 0; i < p->PARAM_K; ++i) { + polyvecl_pointwise_acc_invmontgomery(w.vec+i, mat + i, &yhat, p); + poly_reduce(w.vec + i); + poly_invntt_montgomery(w.vec + i); + } + + polyveck_csubq(&w, p); + polyveck_decompose(&w1, &tmp, &w, p); + challenge(&c, mu, &w1, p); + + chat = c; + dilithium_poly_ntt(&chat); + for(i = 0; i < p->PARAM_L; ++i) { + poly_pointwise_invmontgomery(z.vec + i, &chat, s1.vec + i); + poly_invntt_montgomery(z.vec + i); + } + polyvecl_add(&z, &z, &y, p); + polyvecl_freeze(&z, p); + if(!polyvecl_chknorm(&z, GAMMA1 - p->PARAM_BETA, p)){ + + for(i = 0; i < p->PARAM_K; ++i) { + poly_pointwise_invmontgomery(wcs2.vec + i, &chat, s2.vec + i); + poly_invntt_montgomery(wcs2.vec + i); + } + polyveck_sub(&wcs2, &w, &wcs2, p); + polyveck_freeze(&wcs2, p); + polyveck_decompose(&tmp, &wcs20, &wcs2, p); + polyveck_csubq(&wcs20, p); + if(!polyveck_chknorm(&wcs20, GAMMA2 - p->PARAM_BETA, p)){ + + unsigned int S = 0; + for(i = 0; i < p->PARAM_K; ++i) + for(j = 0; j < N; ++j) + if(tmp.vec[i].coeffs[j] == w1.vec[i].coeffs[j]) + S++; + if(S == p->PARAM_K * N){ + + for(i = 0; i < p->PARAM_K; ++i) { + poly_pointwise_invmontgomery(ct0.vec + i, &chat, t0.vec + i); + poly_invntt_montgomery(ct0.vec + i); + } + + polyveck_csubq(&ct0, p); + if(!polyveck_chknorm(&ct0, GAMMA2, p)){ + + polyveck_add(&tmp, &wcs2, &ct0, p); + polyveck_csubq(&tmp, p); + n = polyveck_make_hint(&h, &wcs2, &tmp, p); + if(n <= p->PARAM_OMEGA){ + + dilithium_pack_sig(sig->sig_data, &z, &h, &c, p); + + sig->kind = p->kind; + + break; + } + } + } + } + } + } + + free(p); + p = NULL; + + return 0; +} + +/*************************************************/ +int dilithium_crypto_sign_open( unsigned char *m, unsigned long long mlen, dilithium_signature_t *sig, const dilithium_public_key_t * public_key) +{ + assert(public_key->kind == sig->kind); + + dilithium_param_t *p = malloc(sizeof(dilithium_param_t)); + if (! dilithium_params_init( p, public_key->kind)) { + free(p); + return -1; + } + + if (sig->sig_len < p->CRYPTO_BYTES ) { + free(p); + return -1; + } + + unsigned long long i; + unsigned char rho[SEEDBYTES]; + unsigned char mu[CRHBYTES]; + poly c, chat, cp; + polyvecl mat[p->PARAM_K], z; + polyveck t1, w1, h, tmp1, tmp2; + + if((sig->sig_len - p->CRYPTO_BYTES) != mlen) { + free(p); + return -1; + } + + dilithium_unpack_pk(rho, &t1, public_key->data, p); + if(dilithium_unpack_sig(&z, &h, &c, sig->sig_data, p)) { + free(p); + return -1; + } + + if(polyvecl_chknorm(&z, GAMMA1 - p->PARAM_BETA, p)) { + free(p); + return -1; + } + + unsigned char *tmp_m = malloc(CRHBYTES + mlen); + if(sig->sig_data != m) + for(i = 0; i < mlen; ++i) + tmp_m[CRHBYTES + i] = m[i]; + + shake256(tmp_m, CRHBYTES, public_key->data, p->CRYPTO_PUBLICKEYBYTES); + shake256(mu, CRHBYTES, tmp_m, CRHBYTES + mlen); + free(tmp_m); + + expand_mat(mat, rho, p); + polyvecl_ntt(&z, p); + for(i = 0; i < p->PARAM_K ; ++i) + polyvecl_pointwise_acc_invmontgomery(tmp1.vec + i, mat+i, &z, p); + + chat = c; + dilithium_poly_ntt(&chat); + polyveck_shiftl(&t1, D, p); + polyveck_ntt(&t1, p); + for(i = 0; i < p->PARAM_K; ++i) + poly_pointwise_invmontgomery(tmp2.vec + i, &chat, t1.vec + i); + + polyveck_sub(&tmp1, &tmp1, &tmp2, p); + polyveck_reduce(&tmp1, p); + polyveck_invntt_montgomery(&tmp1, p); + + polyveck_csubq(&tmp1, p); + polyveck_use_hint(&w1, &tmp1, &h, p); + + challenge(&cp, mu, &w1, p); + for(i = 0; i < N; ++i) + if(c.coeffs[i] != cp.coeffs[i]) { + free(p); + return -1; + } + + return 0; +} + +/*************************************************/ +void dilithium_signature_delete(dilithium_signature_t *sig){ + assert(sig != NULL); + + free(sig->sig_data); + sig->sig_data = NULL; +} diff --git a/src/sig_dilithium/dilithium_sign.h b/src/sig_dilithium/dilithium_sign.h new file mode 100755 index 0000000000000000000000000000000000000000..e6b29d3e84fdb42fc641bd0be19b97a2ec8bb0f5 --- /dev/null +++ b/src/sig_dilithium/dilithium_sign.h @@ -0,0 +1,9 @@ +#ifndef SIGN_H +#define SIGN_H + +#include "dilithium_packing.h" + +void expand_mat(polyvecl [], const unsigned char rho[SEEDBYTES], dilithium_param_t *); +void challenge(poly *, const unsigned char mu[CRHBYTES], const polyveck *, dilithium_param_t *p); + +#endif diff --git a/test/crypto/dap_enc_dilithium_test.c b/test/crypto/dap_enc_dilithium_test.c new file mode 100755 index 0000000000000000000000000000000000000000..395e1cff11ae67dc1ffe9b08057921f25f013448 --- /dev/null +++ b/test/crypto/dap_enc_dilithium_test.c @@ -0,0 +1,55 @@ +#include "dap_test_generator.h" +#include "dap_enc_dilithium_test.h" +#include "../sig_dilithium/dilithium_params.h" + +static void test_signing_verifying(void) +{ + static size_t source_size = 0; + size_t seed_size = sizeof(uint8_t); + uint8_t seed[seed_size]; + + generate_random_byte_array(seed, seed_size); + + dap_enc_key_t* key = dap_enc_key_new_generate(DAP_ENC_KEY_TYPE_SIG_DILITHIUM, NULL, 0, seed, seed_size, 0); + + size_t max_signature_size = dap_enc_dilithium_calc_signature_size(); + uint8_t* sig = calloc(max_signature_size, 1); + + int step = 1 + (rand() % 20); + source_size += (size_t) step; + + uint8_t source[source_size]; + generate_random_byte_array(source, source_size); + + size_t siglen = key->enc_na(key, source, source_size, sig, max_signature_size); + dap_assert_PIF(siglen > 0, "Signing message"); + + size_t verify = key->dec_na(key, source, source_size, sig, siglen); + dap_assert_PIF(!verify, "Verifying signature"); + + dilithium_signature_delete((dilithium_signature_t*)sig); + free(sig); + dap_enc_key_delete(key); +} + +static void init_test_case() +{ + srand((uint32_t) time(NULL)); + dap_enc_key_init(); +} + +static void cleanup_test_case() +{ + dap_enc_key_deinit(); +} + +void dap_enc_dilithium_tests_run() +{ + dap_print_module_name("dap_enc_dilithium"); + init_test_case(); + + benchmark_mgs_time("Signing and verifying message 1 time", benchmark_test_time(test_signing_verifying, 1)); + + cleanup_test_case(); +} + diff --git a/test/crypto/dap_enc_dilithium_test.h b/test/crypto/dap_enc_dilithium_test.h new file mode 100755 index 0000000000000000000000000000000000000000..76bf4ab2d708d36b83bcd713060e60687033a4f2 --- /dev/null +++ b/test/crypto/dap_enc_dilithium_test.h @@ -0,0 +1,6 @@ +#pragma once +#include "dap_enc_dilithium.h" +#include "dap_enc_key.h" +#include "dap_test.h" + +void dap_enc_dilithium_tests_run(void); diff --git a/test/crypto/dap_enc_test.c b/test/crypto/dap_enc_test.c index 8811b9db96abacb3699e04be37d146ab8edb34cf..143f9187052558c55b26f4a122875598f5dca189 100755 --- a/test/crypto/dap_enc_test.c +++ b/test/crypto/dap_enc_test.c @@ -8,6 +8,7 @@ #include "dap_enc_bliss.h" #include "dap_enc_picnic.h" #include "dap_enc_tesla.h" +#include "dap_enc_dilithium.h" #include "dap_enc.h" #define TEST_SER_FILE_NAME "keystorage.txt" @@ -283,6 +284,12 @@ static void test_serealize_deserealize_pub_priv(dap_enc_key_type_t key_type) if(key->enc_na(key, source_buf, source_size, sig_buf, sig_buf_size) > 0) is_sig = 1; break; + case DAP_ENC_KEY_TYPE_SIG_DILITHIUM: + sig_buf_size = dap_enc_dilithium_calc_signature_size(); + sig_buf = calloc(sig_buf_size, 1); + if(key->enc_na(key, source_buf, source_size, sig_buf, sig_buf_size) > 0) + is_sig = 1; + break; default: sig_buf_size = 0; } @@ -313,6 +320,10 @@ static void test_serealize_deserealize_pub_priv(dap_enc_key_type_t key_type) if(key2->dec_na(key2, source_buf, source_size, sig_buf, sig_buf_size) == 0) is_vefify = 1; break; + case DAP_ENC_KEY_TYPE_SIG_DILITHIUM: + if(key2->dec_na(key2, source_buf, source_size, sig_buf, sig_buf_size) == 0) + is_vefify = 1; + break; default: is_vefify = 0; } @@ -345,5 +356,7 @@ void dap_enc_tests_run() { test_serealize_deserealize_pub_priv(DAP_ENC_KEY_TYPE_SIG_PICNIC); dap_print_module_name("dap_enc_sig serealize->deserealize TESLA"); test_serealize_deserealize_pub_priv(DAP_ENC_KEY_TYPE_SIG_TESLA); + dap_print_module_name("dap_enc_sig serealize->deserealize DILITHIUM"); + test_serealize_deserealize_pub_priv(DAP_ENC_KEY_TYPE_SIG_DILITHIUM); cleanup_test_case(); } diff --git a/test/crypto/main.c b/test/crypto/main.c index bfaca6a6a7f40dc18b543447988beb5529360aa8..c430c7851d982c5b2e6f5c9f70accca8b6d03293 100755 --- a/test/crypto/main.c +++ b/test/crypto/main.c @@ -8,6 +8,7 @@ #include "dap_enc_sig_bliss_test.h" #include "dap_enc_picnic_test.h" #include "dap_enc_tesla_test.h" +#include "dap_enc_dilithium_test.h" #include "rand/dap_rand.h" #include "dap_common.h" @@ -26,4 +27,5 @@ int main(void) dap_enc_defeo_tests_run(); dap_enc_tesla_tests_run(); dap_enc_picnic_tests_run(); + dap_enc_dilithium_tests_run(); }