// Reproduced from "./deps/sqlcipher/src/sqlite.h"
// we can't include that directly because it requires "parse.h" which is a compile-time artifact.
// that does not exist in the source, and once compiled this definition ends up in the *.c file
// so we reproduce...
typedef struct sqlcipher_provider sqlcipher_provider;
struct sqlcipher_provider {
  int (*init)(void);
  void (*shutdown)(void);
  const char* (*get_provider_name)(void *ctx);
  int (*add_random)(void *ctx, const void *buffer, int length);
  int (*random)(void *ctx, void *buffer, int length);
  int (*hmac)(void *ctx, int algorithm,
              const unsigned char *hmac_key, int key_sz,
              const unsigned char *in, int in_sz,
              const unsigned char *in2, int in2_sz,
              unsigned char *out);
  int (*kdf)(void *ctx, int algorithm,
              const unsigned char *pass, int pass_sz,
              const unsigned char* salt, int salt_sz,
              int workfactor,
              int key_sz, unsigned char *key);
  int (*cipher)(void *ctx, int mode,
              const unsigned char *key, int key_sz,
              const unsigned char *iv,
              const unsigned char *in, int in_sz,
              unsigned char *out);
  const char* (*get_cipher)(void *ctx);
  int (*get_key_sz)(void *ctx);
  int (*get_iv_sz)(void *ctx);
  int (*get_block_sz)(void *ctx);
  int (*get_hmac_sz)(void *ctx, int algorithm);
  int (*ctx_init)(void **ctx);
  int (*ctx_free)(void **ctx);
  int (*fips_status)(void *ctx);
  const char* (*get_provider_version)(void *ctx);
  sqlcipher_provider *next;
};

 extern int gocrypto_add_random(void *ctx, const void *buffer, int length);
 extern int gocrypto_random(void *ctx, void *buffer, int length);
 extern int gocrypto_hmac(void *ctx, int algorithm, const unsigned char *hmac_key, int key_sz,const unsigned char *in, int in_sz,const unsigned char *in2, int in2_sz,unsigned char *out);
 extern int gocrypto_kdf(void *ctx, int algorithm,const unsigned char *pass, int pass_sz,const unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key);
 extern int gocrypto_cipher(void *ctx, int mode, const unsigned char *key, int key_sz, const unsigned char *iv,              const unsigned char *in, int in_sz,    unsigned char *out);
 extern const char * gocrypto_get_cipher(void *ctx);
 extern int gocrypto_get_key_sz(void *ctx);
extern int gocrypto_get_iv_sz(void *ctx);
 extern int gocrypto_get_block_sz(void *ctx);
 extern int gocrypto_get_hmac_sz(void *ctx, int algorithm);
 extern int gocrypto_ctx_init(void **ctx);
 extern int gocrypto_ctx_free(void **ctx);
 extern int gocrypto_fips_status(void *ctx);
 extern const char* gocrypto_get_provider_version(void *ctx);

 static const char* gocrypto_get_provider_name(void *ctx) {
	return "go_crypto";
} 

int gocrypto_setup(sqlcipher_provider *p) {
  p->init = 0;
  p->shutdown = 0;
  p->get_provider_name = gocrypto_get_provider_name;
  p->random = gocrypto_random;
  p->hmac = gocrypto_hmac;
  p->kdf = gocrypto_kdf;
  p->cipher = gocrypto_cipher;
  p->get_cipher = gocrypto_get_cipher;
  p->get_key_sz = gocrypto_get_key_sz;
  p->get_iv_sz = gocrypto_get_iv_sz;
  p->get_block_sz = gocrypto_get_block_sz;
  p->get_hmac_sz = gocrypto_get_hmac_sz;
  p->ctx_init = gocrypto_ctx_init;
  p->ctx_free = gocrypto_ctx_free;
  p->add_random = gocrypto_add_random;
  p->fips_status = gocrypto_fips_status;
  p->get_provider_version = gocrypto_get_provider_version;
  return 0;
}