/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>                                */
/* This work has been released under the CC0 1.0 Universal license!           */
/******************************************************************************/

#ifndef INC_SLUNKCRYPT_H
#define INC_SLUNKCRYPT_H

/*
 * Compiler check
 */
#if defined(__cplusplus) && (__cplusplus < 201103L) && (!defined(_MSVC_LANG) || (_MSVC_LANG < 201103L))
#error This file requires compiler and library support for the ISO C++11 standard.
#elif !defined(__cplusplus) && (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)) && (!defined(_MSC_VER) || (_MSC_VER < 1600))
#error This file requires compiler and library support for the ISO C99 standard.
#endif

/*
 * Build options
 */
#ifndef SLUNKCRYPT_SHARED
#define SLUNKCRYPT_SHARED 0
#endif
#ifndef SLUNKCRYPT_EXPORT
#define SLUNKCRYPT_EXPORT 0
#endif

 /*
  * DLL support
  */
#if defined(_MSC_VER) && SLUNKCRYPT_SHARED
#if SLUNKCRYPT_EXPORT
#define SLUNKCRYPT_API __declspec(dllexport)
#else
#define SLUNKCRYPT_API __declspec(dllimport)
#endif
#else
#define SLUNKCRYPT_API
#endif

/*
 * C++ support
 */
#ifndef __cplusplus
#include <stdlib.h>
#include <stdint.h>
#else
#include <cstdlib>
#include <cstdint>
extern "C" {
#endif

/*
 * Opaque handle to internal state
 */
typedef uintptr_t slunkcrypt_t;
#define SLUNKCRYPT_NULL ((slunkcrypt_t)NULL)

/*
 * Boolean flags
 */
static const int SLUNKCRYPT_FALSE = 0;
static const int SLUNKCRYPT_TRUE  = 1;

/*
 * Mode of operation
 */
static const int SLUNKCRYPT_ENCRYPT = 0;
static const int SLUNKCRYPT_DECRYPT = 1;

/*
 * Error codes
 */
static const int SLUNKCRYPT_SUCCESS =  0;
static const int SLUNKCRYPT_FAILURE = -1;
static const int SLUNKCRYPT_ABORTED = -2;

/*
 * Limits
 */
static const size_t SLUNKCRYPT_PWDLEN_MIN =   8U;
static const size_t SLUNKCRYPT_PWDLEN_MAX = 256U;

/*
 * Optional parameters
 */
static const uint16_t SLUNKCRYPT_PARAM_VERSION = 2U;
typedef struct
{
	uint16_t version;    /* Must set to SLUNKCRYPT_PARAM_VERSION */
	size_t thread_count; /* Number of threads, set to 0 for auto-detection */
	int legacy_compat;   /* Compatibility with pre-1.3 versions */
	int debug_logging;   /* Enable debug logging (writes to the syslog) */
}
slunkparam_t;

/*
 * Version info
 */
SLUNKCRYPT_API extern const uint16_t SLUNKCRYPT_VERSION_MAJOR;
SLUNKCRYPT_API extern const uint16_t SLUNKCRYPT_VERSION_MINOR;
SLUNKCRYPT_API extern const uint16_t SLUNKCRYPT_VERSION_PATCH;

/*
 * Build date and time
 */
SLUNKCRYPT_API extern const char *const SLUNKCRYPT_BUILD;

/*
 * Configuration
 */
SLUNKCRYPT_API extern const int SLUNKCRYPT_HAVE_THREADS;

/*
 * Abort flag
 */
SLUNKCRYPT_API extern volatile int g_slunkcrypt_abort_flag;

/*
 * Nonce generator
 */
SLUNKCRYPT_API int slunkcrypt_generate_nonce(uint64_t *const nonce);

/*
 * Allocate, reset or free state
 */
SLUNKCRYPT_API slunkcrypt_t slunkcrypt_alloc(const uint64_t nonce, const uint8_t *const passwd, const size_t passwd_len, const int mode);
SLUNKCRYPT_API slunkcrypt_t slunkcrypt_alloc_ext(const uint64_t nonce, const uint8_t *const passwd, const size_t passwd_len, const int mode, const slunkparam_t *const param);
SLUNKCRYPT_API int slunkcrypt_reset(const slunkcrypt_t context, const uint64_t nonce, const uint8_t *const passwd, const size_t passwd_len, const int mode);
SLUNKCRYPT_API void slunkcrypt_free(const slunkcrypt_t context);

/*
 * Encryption routines
 */
SLUNKCRYPT_API int slunkcrypt_process(const slunkcrypt_t context, const uint8_t *const input, uint8_t *const output, size_t length);
SLUNKCRYPT_API int slunkcrypt_inplace(const slunkcrypt_t context, uint8_t *const buffer, size_t length);

/*
 * Auxiliary functions
 */
SLUNKCRYPT_API size_t slunkcrypt_random_bytes(uint8_t *const buffer, const size_t length);
SLUNKCRYPT_API void slunkcrypt_bzero(void *const buffer, const size_t length);

/*
 * Helper macros
 */
#define SLUNKCRYPT_SAFE_FREE(X) do { if((X) != SLUNKCRYPT_NULL) { slunkcrypt_free((X)); X = SLUNKCRYPT_NULL; } } while(0)

#ifdef __cplusplus
}
#endif
#endif
