#ifndef PKCS11KEYWRAPPING_SHARED_H
#define PKCS11KEYWRAPPING_SHARED_H

#define CK_PTR *
#define CK_DECLARE_FUNCTION(returnType, name) \
    returnType name
#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
    returnType (* name)
#define CK_CALLBACK_FUNCTION(returnType, name) \
    returnType (* name)
#ifndef NULL_PTR
#define NULL_PTR 0
#endif

#include <stdbool.h>
#include "pkcs11.h"

#include "openvpn-plugin.h"

extern char *MODULE;

#define TLS_CRYPT_V2_MAX_WKC_LEN 1024
#define TLS_CRYPT_V2_TAG_LEN 32
#define TLS_CRYPT_V2_LEN_LEN 2

#define AES_KEY_LABEL "ServerAESKey"
#define HMAC_KEY_LABEL "ServerHMACKey"

/* Error handling */
#define CRYPTO_ECHECK(cond, text) do { if (cond) { plog(PLOG_ERR, text); goto error_exit; } } while(0)
#define ERROR_CHECK(cond, text) do { if (cond) { plog(PLOG_ERR, text); return false; } } while(0)

/* Exported plug-in v3 API functions */
extern plugin_vlog_t plugin_vlog_func;
extern plugin_base64_decode_t ovpn_base64_decode;
extern plugin_base64_encode_t ovpn_base64_encode;
extern plugin_secure_memzero_t ovpn_secure_memzero;

/* local wrapping of the log function, to add more details */
extern void plog(int flags, char *fmt, ...);

struct PKCS_Context
{
    CK_SESSION_HANDLE session;
    CK_FUNCTION_LIST_PTR p11_functions;
    CK_VOID_PTR lib_handle;
    CK_OBJECT_HANDLE aes_key;
    CK_OBJECT_HANDLE hmac_key;
    CK_MECHANISM aes_mechanism;
    CK_ULONG slot;
};

/*
 * Our context, where we keep our state.
 */
struct plugin_ctx {
    struct PKCS_Context *pkcs_ctx;
    int verb;
    const char *pin;
    int (*cipher_function)(struct PKCS_Context*,
                           const unsigned char*, unsigned long,
                           unsigned char*, unsigned long*,
                           const unsigned char*);
    int (*authentication_function)(struct PKCS_Context*,
                                   const unsigned char*, unsigned long,
                                   unsigned char*, unsigned long*);
    int (*cipher_key_generation)(struct PKCS_Context *, char *);
    int (*authentication_key_generation)(struct PKCS_Context *, char *);
};

#endif //PKCS11KEYWRAPPING_SHARED_H