//
// Created by Fear1ess on 2021/4/27.
//

#include "data_handler.h"
#include <malloc.h>
#include <rsaencode.h>
#include <aesencode.h>
#include <zlib.h>
#include <fake_dlfcn.h>
#include <wd_syscall.h>
#include <openssl/md5.h>
#include <syscall.h>

IMPORTWDSYSCALL

int pack_data(unsigned char *raw, int len, unsigned char **packed_data, int *packed_len) {
    void* z_lib = fake_dlopen("libz.so", 0);
    int res = 0;
    if(z_lib) {
        u_long (*compressBound_func) (u_long) = fake_dlsym(z_lib, "compressBound");
        int (*compress_func) (unsigned char* dest, u_long* p_dest_len, const unsigned char* src, u_long src_len) =
        fake_dlsym(z_lib, "compress");
        if(compress && compressBound_func) {
            u_long bound = compressBound_func(len);
            unsigned char *compressed_data = malloc(bound);
            int res = compress_func(compressed_data, &bound, raw, len);
            if (res == Z_OK) {
                //加密
                char aes_key[17] = {0}, aes_iv[17] = {0};
                char *encoded_data;
                size_t encoded_len = 0;
                aes_Encoder_Base64(compressed_data, bound, &encoded_data, &encoded_len, aes_key,
                                   aes_iv);
                free(compressed_data);

                // 进行加密 key, iv, ts, data_md5, data_len
                int data_len = encoded_len + 128 + 128 + 4 + 16 + 4;
                unsigned char *data_buf = (unsigned char *) calloc(1, data_len);
                char encoded_key[128] = {0};
                char encoded_iv[128] = {0};
                int enckey_len, enciv_len;
                rsa_Encoder_Base64(aes_key, 16, encoded_key, &enckey_len);
                rsa_Encoder_Base64(aes_iv, 16, encoded_iv, &enciv_len);
                memcpy(data_buf, encoded_key, 128);
                memcpy(data_buf + 128, encoded_iv, 128);
                struct timespec ts;
                if (WDSYSCALL(SYS_clock_gettime, CLOCK_REALTIME, &ts) == 0) {
                    memcpy(data_buf + 256, &ts.tv_sec, 4);
                } else {
                    memset(data_buf + 256, 0, 4);
                }
                char md5[16];
                MD5(encoded_data, encoded_len, md5);
                memcpy(data_buf + 260, md5, 16);
                memcpy(data_buf + 276, &encoded_len, 4);
                memcpy(data_buf + 280, encoded_data, encoded_len);
                free(encoded_data);
                *packed_data = data_buf;
                *packed_len = data_len;
                return 0;
            }
            free(compressed_data);
            return -1;
        }
        return -1;
        }
    return -1;
}