//
// Created by triton on 25.01.23.
//

#ifndef PKCS11KEYWRAPPING_PKCS11_HANDLER_H
#define PKCS11KEYWRAPPING_PKCS11_HANDLER_H

#include <string.h>
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <stdbool.h>
#include <openssl/hmac.h>

#include "shared.h"

#define MAX_OBJECT_COUNT 1

#define TLS_CRYPT_V2_KEY_LEN 32
#define TLS_CRYPT_V2_IV_LENGTH 16

#define SLOT_LIST_MAX_SIZE 10

#define AES_BLOCK_SIZE 16

// Helper Functions

void xor_byte_array(unsigned char *a_array, const unsigned char *b_array, int array_length);
void increment_byte_array(unsigned char *array, int array_length);
CK_MECHANISM get_aes_ecb_mechanism();
CK_MECHANISM get_aes_cbc_mechanism();

// Cipher Functions

int perform_aes_key_derivation(struct PKCS_Context *pkcs_ctx,
                               const unsigned char *data, unsigned long data_len,
                               unsigned char *out, unsigned long *out_len,
                               const unsigned char *iv);
int perform_aes(struct PKCS_Context *pkcs_ctx,
                const unsigned char *data, unsigned long data_len,
                unsigned char *out, unsigned long *out_len,
                const unsigned char *nonce);
int perform_aes_256_ctr(struct PKCS_Context *pkcs_ctx,
                        const unsigned char *data, unsigned long data_len,
                        unsigned char *out, unsigned long *out_len,
                        const unsigned char *nonce);
int encrypt_block(struct PKCS_Context *pkcs_ctx, const unsigned char *data, unsigned char *out, CK_OBJECT_HANDLE key_handle);

// Authentication Functions
int perform_hmac_key_derivation(struct PKCS_Context *ctx,
                            const unsigned char *data, unsigned long data_len,
                            unsigned char *out, unsigned long *out_len);

int perform_sha_256_hmac_keyfreedom(struct PKCS_Context *ctx,
                                    const unsigned char *data, unsigned long data_len,
                                    unsigned char *out, unsigned long *out_len,
                                    CK_OBJECT_HANDLE key_handle);

int perform_sha_256_hmac(struct PKCS_Context *ctx,
                         const unsigned char *data, unsigned long data_len,
                         unsigned char *out, unsigned long *out_len);

// Key Functions
int find_key(struct PKCS_Context *ctx, CK_OBJECT_HANDLE *key, CK_ATTRIBUTE attr_list[], ulong attr_list_len);
int find_key_by_label(struct PKCS_Context *pkcs_ctx, CK_OBJECT_HANDLE *key_handle, char *label);
int find_aes_key(struct PKCS_Context *ctx, CK_OBJECT_HANDLE *key);
int find_hmac_key(struct PKCS_Context *ctx, CK_OBJECT_HANDLE *key);
int find_keys(struct plugin_ctx *plugin_ctx);

int delete_aes_key(struct PKCS_Context *ctx);
int delete_hmac_key(struct PKCS_Context *ctx);

int create_hmac_key(struct PKCS_Context *ctx, char *label);
int create_aes_key(struct PKCS_Context *ctx, char *label);

// Token Functions

int load_pkcs11_functions(struct PKCS_Context *ctx, const char *lib_path);
int connect_to_pkcs11_token(struct plugin_ctx *ctx);
int determine_token_capabilities(struct plugin_ctx *ctx);
int pkcs11_startup(struct plugin_ctx *plugin_ctx, const char *lib_path);
int disconnect_from_pkcs11_token(struct PKCS_Context *pkcs_ctx);
int try_reconnect(struct plugin_ctx *plugin_ctx);

#endif //PKCS11KEYWRAPPING_PKCS11_HANDLER_H