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();
 }