Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • car/libdap-crypto
1 result
Show changes
Commits on Source (2)
Showing
with 2095 additions and 2 deletions
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
......@@ -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)
......
File mode changed from 100644 to 100755
#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
......@@ -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;
......
Subproject commit 9915cf2b350ee58f6beab8a53eac5a3c6ab7d67d
Subproject commit 85933c820be2c81416848447b82bb8af15a34a5c
#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;
}
......@@ -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;
}
......
#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;
}
#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
#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;
}
}
#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
#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]);
}
}
#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
#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);
}
#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
#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;
}
#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
#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;
}