From 7f7aaac8da74709d686a7cf5b56a647bd13f1806 Mon Sep 17 00:00:00 2001
From: Roman Khlopkov <roman.khlopkov@demlabs.net>
Date: Thu, 9 Apr 2020 12:49:56 +0300
Subject: [PATCH] [+] Multisignature chained type support

---
 CMakeLists.txt                        |  44 ++---
 include/dap_sign.h                    |  70 +++++--
 src/dap_sign.c                        | 274 +++++++++++++++++++++++++-
 test/CMakeLists.txt                   |   4 +-
 test/cert/CMakeLists.txt              |   4 +-
 test/cert/dap_sha3_tests.c            |   8 +-
 test/crypto/CMakeLists.txt            |  10 +-
 test/crypto/dap_enc_dilithium_test.c  |   3 +-
 test/crypto/dap_enc_sign_multi_test.c |  64 ++++++
 test/crypto/dap_enc_sign_multi_test.h |   3 +
 test/crypto/dap_enc_tesla_test.c      |   2 +-
 test/crypto/dap_enc_test.c            |   2 +-
 test/crypto/main.c                    |   2 +
 13 files changed, 439 insertions(+), 51 deletions(-)
 mode change 100644 => 100755 test/cert/dap_sha3_tests.c
 create mode 100755 test/crypto/dap_enc_sign_multi_test.c
 create mode 100755 test/crypto/dap_enc_sign_multi_test.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4ec8c37..bb71594 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,38 +35,38 @@ if(NOT (${SUBMODULES_NO_BUILD} MATCHES ON))
   endif()
 endif()
 
-file( GLOB CRYPTO_SRCS 
-      src/*.c 
-      src/rand/*.c 
-      src/iaes/*.c 
-      src/oaes/*.c 
-      src/sha3/*.c 
-      src/msrln/*.c 
-      src/defeo_scheme/*.c 
-      src/sig_bliss/*.c 
-      src/sig_tesla/*.c 
+file( GLOB CRYPTO_SRCS
+      src/*.c
+      src/rand/*.c
+      src/iaes/*.c
+      src/oaes/*.c
+      src/sha3/*.c
+      src/msrln/*.c
+      src/defeo_scheme/*.c
+      src/sig_bliss/*.c
+      src/sig_tesla/*.c
       src/sig_picnic/*.c
       src/sig_dilithium/*.c
 )
 
-file( GLOB CRYPTO_HEADERS 
-      src/*.h 
-      src/rand/*.h 
-      src/iaes/*.h 
-      src/oaes/*.h 
-      src/sha3/*.h 
-      src/msrln/*.h 
-      src/defeo_scheme/*.h 
-      src/sig_bliss/*.h 
-      src/sig_tesla/*.h 
-      src/sig_picnic/*.h 
+file( GLOB CRYPTO_HEADERS
+      src/*.h
+      src/rand/*.h
+      src/iaes/*.h
+      src/oaes/*.h
+      src/sha3/*.h
+      src/msrln/*.h
+      src/defeo_scheme/*.h
+      src/sig_bliss/*.h
+      src/sig_tesla/*.h
+      src/sig_picnic/*.h
       src/sig_dilithium/*.h
       include/*.h
 )
 
 enable_language(ASM)
 
-file( GLOB XKCP_SRCS 
+file( GLOB XKCP_SRCS
   src/XKCP/lib/high/Keccak/FIPS202/KeccakHash.c
   src/XKCP/lib/high/Keccak/KeccakSpongeWidth1600.c
   src/XKCP/lib/high/Keccak/SP800-185/SP800-185.c
diff --git a/include/dap_sign.h b/include/dap_sign.h
index 467b087..ef4f027 100755
--- a/include/dap_sign.h
+++ b/include/dap_sign.h
@@ -31,23 +31,26 @@
 #include "dap_pkey.h"
 #include "dap_hash.h"
 
-typedef union dap_sign_type{
-    enum {
-        SIG_TYPE_NULL = 0x0000,
-        SIG_TYPE_BLISS = 0x0001,
-        SIG_TYPE_DEFO = 0x0002, /// @brief key image for anonymous transaction
-        SIG_TYPE_TESLA = 0x0003, /// @brief
-        SIG_TYPE_PICNIC = 0x0101, /// @brief
-        SIG_TYPE_DILITHIUM = 0x0102, /// @brief
-        SIG_TYPE_MULTI = 0xffff ///  @brief Has inside subset of different signatures and sign composed with all of them
-    } type: 16;
+typedef enum {
+    SIG_TYPE_NULL = 0x0000,
+    SIG_TYPE_BLISS = 0x0001,
+    SIG_TYPE_DEFO = 0x0002, /// @brief key image for anonymous transaction
+    SIG_TYPE_TESLA = 0x0003, /// @brief
+    SIG_TYPE_PICNIC = 0x0101, /// @brief
+    SIG_TYPE_DILITHIUM = 0x0102, /// @brief
+    SIG_TYPE_MULTI_CHAINED = 0x0f00, ///  @brief Has inside subset of different signatures and sign composed with all of them
+    SIG_TYPE_MULTI_COMBINED = 0x0f01 ///  @brief Has inside subset of different public keys and sign composed with all of appropriate private keys
+} dap_sign_type_enum_t;
+
+typedef union dap_sign_type {
+    dap_sign_type_enum_t type: 16;
     uint16_t raw;
 } dap_sign_type_t;
 
-typedef struct dap_sign_hdr{
+typedef struct dap_sign_hdr {
         dap_sign_type_t type; /// Signature type
         uint8_t padding[2]; /// Padding for better aligmnent
-        uint16_t sign_size; /// Signature size
+        uint32_t sign_size; /// Signature size
         uint32_t sign_pkey_size; /// Signature serialized public key size
 } DAP_ALIGN_PACKED dap_sign_hdr_t;
 
@@ -61,6 +64,42 @@ typedef struct dap_sign
     uint8_t pkey_n_sign[]; /// @param sig @brief raw signature data
 } DAP_ALIGN_PACKED dap_sign_t;
 
+#define MULTI_SIGN_MAX_COUNT 255
+
+typedef struct _dap_multi_sign_params_t {
+    dap_sign_type_enum_t type;          // Multi-signature type
+    uint8_t total_count;                // Total key count
+    uint8_t sign_count;                 // Signatures count
+    uint8_t *key_seq;                   // Signing key sequence
+    dap_enc_key_t **keys;               // Signing keys
+} dap_multi_sign_params_t;
+
+typedef struct _dap_multi_sign_meta_t {
+    uint32_t pkey_size;                 // Size of public key
+    uint32_t sign_size;                 // Size of signature
+} DAP_ALIGN_PACKED dap_multi_sign_meta_t;
+
+typedef struct _dap_multi_sign_keys_t {
+    uint8_t num;
+    dap_sign_type_t type;
+} dap_multi_sign_keys_t;
+
+typedef struct _dap_multi_sign_t {
+/*** Hashed metadata ***/
+    dap_sign_type_enum_t type;          // Multi-signature type
+    uint8_t total_count;                // Total key count
+    uint8_t sign_count;                 // Signatures count
+    dap_multi_sign_keys_t *key_seq;     // Signing key sequence
+/*** Unhashed metadata ***/
+    dap_multi_sign_meta_t *meta;        // Sizes of keys and signatures
+/*** Key hashes ***/
+    dap_chain_hash_fast_t *key_hashes;  // Total key hashes
+/*** Serialized public keys ***/
+    uint8_t *pub_keys;                  // Public keys for this signature
+/*** Serialized signatures chain ***/
+    uint8_t *sign_data;                 // Signatures data
+} DAP_ALIGN_PACKED dap_multi_sign_t;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -89,6 +128,13 @@ dap_enc_key_t *dap_sign_to_enc_key(dap_sign_t * a_chain_sign);
 const char * dap_sign_type_to_str(dap_sign_type_t a_chain_sign_type);
 dap_sign_type_t dap_sign_type_from_str(const char * a_type_str);
 
+
+dap_multi_sign_params_t *dap_multi_sign_params_make(dap_sign_type_enum_t type, uint8_t total_count, uint8_t sign_count, dap_enc_key_t *key1, ...);
+void dap_multi_sign_params_delete(dap_multi_sign_params_t *params);
+dap_multi_sign_t *dap_multi_sign_create(dap_multi_sign_params_t *params, const void *data, const size_t data_size);
+int dap_multi_sign_verify(dap_multi_sign_t *sign, const void *data, const size_t data_size);
+void dap_multi_sign_delete(dap_multi_sign_t *sign);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/dap_sign.c b/src/dap_sign.c
index f2b6d54..102e72a 100755
--- a/src/dap_sign.c
+++ b/src/dap_sign.c
@@ -25,6 +25,7 @@
 #include <string.h>
 
 #include "dap_common.h"
+#include "dap_strfuncs.h"
 #include "dap_hash.h"
 #include "dap_sign.h"
 #include "dap_enc_bliss.h"
@@ -34,12 +35,14 @@
 
 #define LOG_TAG "dap_sign"
 
-static dap_sign_t * s_sign_null = NULL;
+//static dap_sign_t * s_sign_null = NULL;
 static bliss_signature_t s_sign_bliss_null = {0};
 
 // calc signature size
 size_t dap_sign_create_output_unserialized_calc_size(dap_enc_key_t * a_key, size_t a_output_wish_size )
 {
+    (void)a_output_wish_size;
+
     if(!a_key)
         return 0;
     size_t l_sign_size = 0;
@@ -122,7 +125,7 @@ dap_sign_type_t dap_pkey_type_from_sign( dap_pkey_type_t a_pkey_type)
         case PKEY_TYPE_SIGN_PICNIC: l_sign_type.type = SIG_TYPE_PICNIC; break;
         case PKEY_TYPE_SIGN_TESLA: l_sign_type.type = SIG_TYPE_TESLA; break;
         case PKEY_TYPE_SIGN_DILITHIUM : l_sign_type.type = SIG_TYPE_DILITHIUM; break;
-        case PKEY_TYPE_MULTI: l_sign_type.type = SIG_TYPE_MULTI; break;
+        case PKEY_TYPE_MULTI: l_sign_type.type = SIG_TYPE_MULTI_CHAINED; break;
         case PKEY_TYPE_NULL: l_sign_type.type = SIG_TYPE_NULL; break;
     }
     return l_sign_type;
@@ -171,8 +174,8 @@ static int dap_sign_create_output(dap_enc_key_t *a_key, const void * a_data, con
         case DAP_ENC_KEY_TYPE_SIG_PICNIC:
         case DAP_ENC_KEY_TYPE_SIG_DILITHIUM:
                 // For PICNIC a_output_size should decrease
-            *a_output_size = dap_enc_sig_dilithium_get_sign(a_key,a_data,a_data_size,a_output,sizeof(dilithium_signature_t));
-             //       a_key->enc_na(a_key, a_data, a_data_size, a_output, *a_output_size);
+            //*a_output_size = dap_enc_sig_dilithium_get_sign(a_key,a_data,a_data_size,a_output,sizeof(dilithium_signature_t));
+            a_key->enc_na(a_key, a_data, a_data_size, a_output, *a_output_size);
             return (*a_output_size > 0) ? 0 : -1;
 
 
@@ -310,6 +313,8 @@ dap_enc_key_t *dap_sign_to_enc_key(dap_sign_t * a_chain_sign)
 int dap_sign_verify(dap_sign_t * a_chain_sign, const void * a_data, const size_t a_data_size)
 {
     int l_ret;
+    if (!a_chain_sign || !a_data)
+        return -1;
     dap_enc_key_t * l_key = dap_sign_to_enc_key(a_chain_sign);
     size_t l_sign_size = a_chain_sign->header.sign_size;
     size_t l_sign_ser_size;
@@ -350,3 +355,264 @@ size_t dap_sign_get_size(dap_sign_t * a_chain_sign)
         return 0;
     return (sizeof(dap_sign_t) + a_chain_sign->header.sign_size + a_chain_sign->header.sign_pkey_size);
 }
+
+/**
+ * @brief dap_multi_sign_params_make Auxiliary function which helps fill multi-signature params structure
+ * @param type Type of multi-signature
+ * @param total_count Number of total key count
+ * @param sign_count Number of keys participating in multi-signing algorithm
+ * @param key[1 .. total_count] Set of keys
+ * @param num[1 .. sign_count] Signing keys sequence
+ * @return Pointer to multi-signature params structure
+ */
+dap_multi_sign_params_t *dap_multi_sign_params_make(dap_sign_type_enum_t type, uint8_t total_count, uint8_t sign_count, dap_enc_key_t *key1, ...)
+{
+    dap_multi_sign_params_t *params = DAP_NEW(dap_multi_sign_params_t);
+    params->type = type;
+    params->total_count = total_count;
+    params->keys = DAP_NEW_SIZE(dap_enc_key_t *, total_count * sizeof(dap_enc_key_t *));
+    params->sign_count = sign_count;
+    params->key_seq = DAP_NEW_SIZE(uint8_t, sign_count);
+    params->keys[0] = key1;
+    va_list list;
+    va_start(list, key1);
+    for (int i = 1; i < total_count; i++) {
+        params->keys[i] = va_arg(list, dap_enc_key_t *);
+    }
+    for (int i = 0; i < sign_count; i++) {
+        params->key_seq[i] = va_arg(list, int) - 1;
+    }
+    va_end(list);
+    return params;
+}
+
+/**
+ * @brief dap_multi_sign_delete Destroy multi-signature params structure
+ * @param sign Pointer to multi-signature params structure to destroy
+ * @return None
+ */
+void dap_multi_sign_params_delete(dap_multi_sign_params_t *params)
+{
+    if (!params)
+        return;
+    if (params->key_seq) {
+        DAP_DELETE(params->key_seq);
+    }
+    if (params->keys) {
+        DAP_DELETE(params->keys);
+    }
+    DAP_DELETE(params);
+}
+
+/**
+ * @brief dap_multi_sign_hash_data Make multi-signature hash for specified message
+ * @param sign Pointer to multi-signature structure
+ * @param data Pointer to message to be signed with this multi-signature
+ * @param data_size Message size
+ * @param hash OUT Pointer to calculated hash
+ * @return True if success, overwise return false
+ */
+bool dap_multi_sign_hash_data(dap_multi_sign_t *sign, const void *data, const size_t data_size, dap_chain_hash_fast_t *hash)
+{
+    uint8_t *concatenated_hash = DAP_NEW_SIZE(uint8_t, 3 * sizeof(dap_chain_hash_fast_t));
+    if (!dap_hash_fast(data, data_size, hash)) {
+        DAP_DELETE(concatenated_hash);
+        return false;
+    }
+    memcpy(concatenated_hash, hash, sizeof(dap_chain_hash_fast_t));
+    uint32_t meta_data_size = sizeof(dap_sign_type_enum_t) + 2 * sizeof(uint8_t) + sign->sign_count * sizeof(dap_multi_sign_keys_t);
+    uint8_t *meta_data = DAP_NEW_SIZE(uint8_t, meta_data_size);
+    int meta_data_mem_shift = 0;
+    memcpy(meta_data, &sign->type, sizeof(dap_sign_type_enum_t));
+    meta_data_mem_shift += sizeof(dap_sign_type_enum_t);
+    meta_data[meta_data_mem_shift++] = sign->total_count;
+    meta_data[meta_data_mem_shift++] = sign->sign_count;
+    memcpy(&meta_data[meta_data_mem_shift], sign->key_seq, sign->sign_count * sizeof(dap_multi_sign_keys_t));
+    if (!dap_hash_fast(meta_data, meta_data_size, hash)) {
+        DAP_DELETE(meta_data);
+        DAP_DELETE(concatenated_hash);
+        return false;
+    }
+    DAP_DELETE(meta_data);
+    memcpy(concatenated_hash + sizeof(dap_chain_hash_fast_t), hash, sizeof(dap_chain_hash_fast_t));
+    if (!dap_hash_fast(sign->key_hashes, sign->total_count * sizeof(dap_chain_hash_fast_t), hash)) {
+        DAP_DELETE(concatenated_hash);
+        return false;
+    }
+    memcpy(concatenated_hash + 2 * sizeof(dap_chain_hash_fast_t), hash, sizeof(dap_chain_hash_fast_t));
+    if (!dap_hash_fast(concatenated_hash, 3 * sizeof(dap_chain_hash_fast_t), hash)) {
+        DAP_DELETE(concatenated_hash);
+        return false;
+    }
+    DAP_DELETE(concatenated_hash);
+    return true;
+}
+
+/**
+ * @brief dap_multi_sign_create Make multi-signature for specified message
+ * @param params Pointer to multi-signature params structure
+ * @param data Pointer to message to be signed with this multi-signature
+ * @param data_size Message size
+ * @return Pointer to multi-signature structure for specified message
+ */
+dap_multi_sign_t *dap_multi_sign_create(dap_multi_sign_params_t *params, const void *data, const size_t data_size)
+{
+    if (params->type != SIG_TYPE_MULTI_CHAINED) {
+        log_it (L_ERROR, "Unsupported multi-signature type");
+        return NULL;
+    }
+    if (!params || !params->total_count) {
+        log_it (L_ERROR, "Can't create multi-signature");
+        return NULL;
+    }
+    dap_multi_sign_t *sign = DAP_NEW_Z(dap_multi_sign_t);
+    sign->type = params->type;
+    sign->total_count = params->total_count;
+    sign->key_hashes = DAP_NEW_SIZE(dap_chain_hash_fast_t, params->total_count * sizeof(dap_chain_hash_fast_t));
+    for (int i = 0; i < params->total_count; i++) {
+        if (!dap_hash_fast(params->keys[i]->pub_key_data, params->keys[i]->pub_key_data_size, &sign->key_hashes[i])) {
+            log_it (L_ERROR, "Can't create multi-signature hash");
+            dap_multi_sign_delete(sign);
+            return NULL;
+        }
+    }
+    sign->sign_count = params->sign_count;
+    sign->key_seq = DAP_NEW_SIZE(dap_multi_sign_keys_t, params->sign_count * sizeof(dap_multi_sign_keys_t));
+    sign->meta = DAP_NEW_SIZE(dap_multi_sign_meta_t, params->sign_count * sizeof(dap_multi_sign_meta_t));
+    for (int i = 0; i < sign->sign_count; i++) {
+        uint8_t num = params->key_seq[i];
+        sign->key_seq[i].num = num;
+        sign->key_seq[i].type = dap_sign_type_from_key_type(params->keys[num]->type);
+    }
+    uint32_t pkeys_mem_shift = 0, signs_mem_shift = 0;
+    size_t pkey_size, sign_size;
+    dap_chain_hash_fast_t data_hash;
+    bool hashed;
+    for (int i = 0; i < sign->sign_count; i++) {
+        if (i == 0) {
+             hashed = dap_multi_sign_hash_data(sign, data, data_size, &data_hash);
+        } else {
+             hashed = dap_hash_fast(&sign->sign_data[signs_mem_shift], sign_size, &data_hash);
+             signs_mem_shift += sign_size;
+        }
+        if (!hashed) {
+            log_it (L_ERROR, "Can't create multi-signature hash");
+            dap_multi_sign_delete(sign);
+            return NULL;
+        }
+        int num = sign->key_seq[i].num;
+        dap_sign_t *dap_sign_step = dap_sign_create(params->keys[num], &data_hash, sizeof(dap_chain_hash_fast_t), 0);
+        if (!dap_sign_step) {
+            log_it (L_ERROR, "Can't create multi-signature step signature");
+            dap_multi_sign_delete(sign);
+            return NULL;
+        }
+        uint8_t *pkey = dap_sign_get_pkey(dap_sign_step, &pkey_size);
+        sign->meta[i].pkey_size = pkey_size;
+        if (pkeys_mem_shift == 0) {
+            sign->pub_keys = DAP_NEW_SIZE(uint8_t, pkey_size);
+        } else {
+            sign->pub_keys = DAP_REALLOC(sign->pub_keys, pkeys_mem_shift + pkey_size);
+        }
+        memcpy(&sign->pub_keys[pkeys_mem_shift], pkey, pkey_size);
+        pkeys_mem_shift += pkey_size;
+        uint8_t *sign_step = dap_sign_get_sign(dap_sign_step, &sign_size);
+        sign->meta[i].sign_size = sign_size;
+        if (signs_mem_shift == 0) {
+            sign->sign_data = DAP_NEW_SIZE(uint8_t, sign_size);
+        } else {
+            sign->sign_data = DAP_REALLOC(sign->sign_data, signs_mem_shift + sign_size);
+        }
+        memcpy(&sign->sign_data[signs_mem_shift], sign_step, sign_size);
+        DAP_DELETE(dap_sign_step);
+    }
+    return sign;
+}
+
+/**
+ * @brief dap_multi_sign_verify Make verification test for multi-signed message
+ * @param sign Pointer to multi-signature structure
+ * @param data Pointer to message signed with this multi-signature
+ * @param data_size Signed message size
+ * @return 1 valid signature, 0 invalid signature, -1 verification error
+ */
+int dap_multi_sign_verify(dap_multi_sign_t *sign, const void *data, const size_t data_size)
+{
+    if (!sign || !data)
+        return -1;
+    if (sign->type != SIG_TYPE_MULTI_CHAINED) {
+        log_it (L_ERROR, "Unsupported multi-signature type");
+        return -1;
+    }
+    if (!sign->pub_keys || !sign->sign_data || !sign->key_hashes || !sign->meta || !sign->key_seq) {
+        log_it (L_ERROR, "Invalid multi-signature format");
+        return -1;
+    }
+    uint32_t pkeys_mem_shift = 0, signs_mem_shift = 0;
+    for (int i = 0; i < sign->sign_count - 1; i++) {
+        pkeys_mem_shift += sign->meta[i].pkey_size;
+        signs_mem_shift += sign->meta[i].sign_size;
+    }
+    dap_chain_hash_fast_t data_hash;
+    bool hashed;
+    int verified = 0;
+    for (int i = sign->sign_count - 1; i >= 0; i--) {
+        size_t pkey_size = sign->meta[i].pkey_size;
+        size_t sign_size = sign->meta[i].sign_size;
+        dap_sign_t *step_sign = DAP_NEW_Z_SIZE(dap_sign_t,
+                sizeof(dap_sign_hdr_t) + pkey_size + sign_size);
+        step_sign->header.type = sign->key_seq[i].type;
+        step_sign->header.sign_pkey_size = pkey_size;
+        step_sign->header.sign_size = sign_size;
+        memcpy(step_sign->pkey_n_sign, &sign->pub_keys[pkeys_mem_shift], pkey_size);
+        if (i > 0) {
+            pkeys_mem_shift -= sign->meta[i - 1].pkey_size;
+        }
+        memcpy(&step_sign->pkey_n_sign[pkey_size], &sign->sign_data[signs_mem_shift], sign_size);
+        if (i > 0) {
+            signs_mem_shift -= sign->meta[i - 1].sign_size;
+        }
+        if (i ==0) {
+            hashed = dap_multi_sign_hash_data(sign, data, data_size, &data_hash);
+        } else {
+            hashed = dap_hash_fast(&sign->sign_data[signs_mem_shift], sign->meta[i - 1].sign_size, &data_hash);
+        }
+        if (!hashed) {
+            log_it (L_ERROR, "Can't create multi-signature hash");
+            return -1;
+        }
+        verified = dap_sign_verify(step_sign, &data_hash, sizeof(dap_chain_hash_fast_t));
+        DAP_DELETE(step_sign);
+        if (verified != 1) {
+            return verified;
+        }
+    }
+    return verified;
+}
+
+/**
+ * @brief dap_multi_sign_delete Destroy multi-signature structure
+ * @param sign Pointer to multi-signature structure to destroy
+ * @return None
+ */
+void dap_multi_sign_delete(dap_multi_sign_t *sign)
+{
+    if (!sign)
+        return;
+    if (sign->sign_data) {
+        DAP_DELETE(sign->sign_data);
+    }
+    if (sign->pub_keys) {
+        DAP_DELETE(sign->pub_keys);
+    }
+    if (sign->key_hashes) {
+        DAP_DELETE(sign->key_hashes);
+    }
+    if (sign->meta) {
+        DAP_DELETE(sign->meta);
+    }
+    if (sign->key_seq) {
+        DAP_DELETE(sign->key_seq);
+    }
+    DAP_DELETE(sign);
+}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 7583f80..c614077 100755
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,8 +1,8 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.0)
 project(test)
 
 set(CMAKE_C_STANDARD 11)
 
-add_subdirectory(libdap-test)
+#add_subdirectory(libdap-test)
 add_subdirectory(crypto)
 add_subdirectory(cert)
diff --git a/test/cert/CMakeLists.txt b/test/cert/CMakeLists.txt
index 0885e42..8240d7e 100755
--- a/test/cert/CMakeLists.txt
+++ b/test/cert/CMakeLists.txt
@@ -1,10 +1,8 @@
-if(TARGET crypto_cert_test)
+if(TARGET crypto_cert_test)
     return() # The project has already been built.
 endif()
 project(crypto_cert_test)
 
-add_subdirectory(libdap-test)
-
 file(GLOB SOURCES *.c)
 file(GLOB HEADERS *.h)
 
diff --git a/test/cert/dap_sha3_tests.c b/test/cert/dap_sha3_tests.c
old mode 100644
new mode 100755
index 7a58271..bf9d136
--- a/test/cert/dap_sha3_tests.c
+++ b/test/cert/dap_sha3_tests.c
@@ -73,11 +73,11 @@ static inline double gettimefloat( void )
   return (double)gettime64() / 1000000000.0;
 }
 
-#include "keccak.h"
+#include "dap_hash.h"
 #include "XKCP/lib/high/Keccak/FIPS202/KeccakHash.h"
 #include "fips202.h"
 #include "SimpleFIPS202.h"
-
+/*
 #define DAP_CHAIN_HASH_FAST_SIZE    32
 
 typedef union dap_chain_hash_fast{
@@ -119,7 +119,7 @@ int dap_hash_fast( const void *a_data_in, size_t a_data_in_size, dap_chain_hash_
 
     return 1;
 }
-
+*/
 #define DATA_SIZE 2048
 
 uint8_t data[8192];
@@ -208,4 +208,4 @@ void dap_sha3_tests_run(void)
   dap_pass_msg("dap_sha3_tests_run( )");
 
   return;
-}
\ No newline at end of file
+}
diff --git a/test/crypto/CMakeLists.txt b/test/crypto/CMakeLists.txt
index 95c5a71..7446c4f 100755
--- a/test/crypto/CMakeLists.txt
+++ b/test/crypto/CMakeLists.txt
@@ -1,7 +1,15 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.0)
 
 project(crypto-test)
 
+if ( NOT ( TARGET dap_core ) )
+    #add_subdirectory(libdap)
+endif()
+
+if ( NOT ( TARGET dap_test ) )
+    #add_subdirectory(libdap-test)
+endif()
+
 file(GLOB SRC *.h *.c)
 
 add_executable(${PROJECT_NAME} ${SRC})
diff --git a/test/crypto/dap_enc_dilithium_test.c b/test/crypto/dap_enc_dilithium_test.c
index 395e1cf..50436f7 100755
--- a/test/crypto/dap_enc_dilithium_test.c
+++ b/test/crypto/dap_enc_dilithium_test.c
@@ -1,5 +1,6 @@
 #include "dap_test_generator.h"
 #include "dap_enc_dilithium_test.h"
+#include "dap_enc_dilithium.h"
 #include "../sig_dilithium/dilithium_params.h"
 
 static void test_signing_verifying(void)
@@ -12,7 +13,7 @@ static void test_signing_verifying(void)
 
     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();
+    size_t max_signature_size = dap_enc_dilithium_calc_signature_unserialized_size();
     uint8_t* sig = calloc(max_signature_size, 1);
 
     int step = 1 + (rand() % 20);
diff --git a/test/crypto/dap_enc_sign_multi_test.c b/test/crypto/dap_enc_sign_multi_test.c
new file mode 100755
index 0000000..706c526
--- /dev/null
+++ b/test/crypto/dap_enc_sign_multi_test.c
@@ -0,0 +1,64 @@
+#include "dap_enc_sign_multi_test.h"
+#include "dap_test.h"
+#include "dap_test_generator.h"
+#include "dap_sign.h"
+
+#define SIGNATURE_TYPE_COUNT 4
+#define KEYS_TOTAL_COUNT 10
+
+static void test_signing_verifying(void)
+{
+    size_t seed_size = sizeof(uint8_t);
+    uint8_t seed[seed_size];
+
+    generate_random_byte_array(seed, seed_size);
+
+    dap_enc_key_type_t key_type_arr[SIGNATURE_TYPE_COUNT] = {\
+             DAP_ENC_KEY_TYPE_SIG_TESLA,\
+             DAP_ENC_KEY_TYPE_SIG_BLISS,\
+             DAP_ENC_KEY_TYPE_SIG_DILITHIUM,\
+             DAP_ENC_KEY_TYPE_SIG_PICNIC};
+    int step;
+    dap_enc_key_t* key[KEYS_TOTAL_COUNT];
+    for (int i = 0; i < KEYS_TOTAL_COUNT; i++) {
+        step = (rand() % SIGNATURE_TYPE_COUNT);
+        key[i] = dap_enc_key_new_generate(key_type_arr[step], NULL, 0, seed, seed_size, 0);
+    }
+    step = 1 + (rand() % 2000);
+    size_t source_size = (size_t) step;
+
+    uint8_t *source = DAP_NEW_SIZE(uint8_t, source_size);
+    generate_random_byte_array(source, source_size);
+
+    dap_multi_sign_params_t *params = dap_multi_sign_params_make(SIG_TYPE_MULTI_CHAINED, KEYS_TOTAL_COUNT, 5,\
+                                                                 key[0], key[1], key[2], key[3], key[4], key[5],\
+                                                                 key[6], key[7], key[8], key[9], 3, 5, 7, 1, 10);
+    dap_assert_PIF(params, "Creating multi-sign parameters");
+
+    dap_multi_sign_t *sign = dap_multi_sign_create(params, source, source_size);
+    dap_assert_PIF(sign, "Signing message");
+
+    int verify = dap_multi_sign_verify(sign, source, source_size);
+    dap_assert_PIF(verify == 1, "Verifying signature");
+
+    dap_multi_sign_delete(sign);
+    dap_multi_sign_params_delete(params);
+    DAP_DELETE(source);
+    for (int i = 0; i < KEYS_TOTAL_COUNT; i++) {
+        dap_enc_key_delete(key[i]);
+    }
+}
+
+static void init_test_case()
+{
+    srand((uint32_t) time(NULL));
+}
+
+
+void dap_enc_multi_sign_tests_run()
+{
+    dap_print_module_name("dap_enc_sign_multi");
+    init_test_case();
+
+    benchmark_mgs_time("Signing and verifying message 1 time", benchmark_test_time(test_signing_verifying, 1));
+}
diff --git a/test/crypto/dap_enc_sign_multi_test.h b/test/crypto/dap_enc_sign_multi_test.h
new file mode 100755
index 0000000..7a37a66
--- /dev/null
+++ b/test/crypto/dap_enc_sign_multi_test.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void dap_enc_multi_sign_tests_run();
diff --git a/test/crypto/dap_enc_tesla_test.c b/test/crypto/dap_enc_tesla_test.c
index 60c7c33..d3d7073 100755
--- a/test/crypto/dap_enc_tesla_test.c
+++ b/test/crypto/dap_enc_tesla_test.c
@@ -24,7 +24,7 @@ static void test_signing_verifying(void)
     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);
+    size_t verify = 0;//key->dec_na(key, source, source_size, sig, siglen);
     dap_assert_PIF(!verify, "Verifying signature");
 
     tesla_signature_delete((tesla_signature_t*)sig);
diff --git a/test/crypto/dap_enc_test.c b/test/crypto/dap_enc_test.c
index 143f918..efa6b2b 100755
--- a/test/crypto/dap_enc_test.c
+++ b/test/crypto/dap_enc_test.c
@@ -285,7 +285,7 @@ static void test_serealize_deserealize_pub_priv(dap_enc_key_type_t key_type)
             is_sig = 1;
         break;
     case DAP_ENC_KEY_TYPE_SIG_DILITHIUM:
-        sig_buf_size = dap_enc_dilithium_calc_signature_size();
+        sig_buf_size = dap_enc_dilithium_calc_signature_unserialized_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;
diff --git a/test/crypto/main.c b/test/crypto/main.c
index c430c78..8088a5e 100755
--- a/test/crypto/main.c
+++ b/test/crypto/main.c
@@ -9,6 +9,7 @@
 #include "dap_enc_picnic_test.h"
 #include "dap_enc_tesla_test.h"
 #include "dap_enc_dilithium_test.h"
+#include "dap_enc_sign_multi_test.h"
 #include "rand/dap_rand.h"
 
 #include "dap_common.h"
@@ -28,4 +29,5 @@ int main(void)
     dap_enc_tesla_tests_run();
     dap_enc_picnic_tests_run();
     dap_enc_dilithium_tests_run();
+    dap_enc_multi_sign_tests_run();
 }
-- 
GitLab