#include <user_settings.h>
#include <openssl/evp.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/x509.h>

 
static EVP_PKEY *vio_keygen()
{
  EVP_PKEY_CTX *ctx;
  EVP_PKEY *pkey= NULL;

  if (!(ctx= EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)))
    return NULL;

  if (EVP_PKEY_keygen_init(ctx) <= 0)
    goto end;

  if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 4096) <= 0)
    goto end;

  if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
    pkey= NULL; /* just in case */

end:
  EVP_PKEY_CTX_free(ctx);
  return pkey;
}

static X509 *vio_gencert(EVP_PKEY *pkey)
{
  X509 *x;
  X509_NAME *name;

  if (!(x= X509_new()))
    goto err;

  if (!X509_set_version(x, 2))
    goto err;
  if (!(name= X509_get_subject_name(x)))
    goto err;
  if (!X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char *)"x",1,-1,0))
    goto err;
  if (!X509_set_issuer_name(x, name))
    goto err;
  if (!X509_gmtime_adj(X509_get_notBefore(x), 0))
    goto err;
  if (!X509_gmtime_adj(X509_get_notAfter(x), 60 * 60 * 24 * 365 * 10))
    goto err;
  if (!X509_set_pubkey(x, pkey))
    goto err;
  if (!X509_sign(x, pkey, EVP_sha256()))
    goto err;

  return x;

err:
  X509_free(x);
  return NULL;
}

int main()
{
  unsigned long long start,end,freq;
  QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
  QueryPerformanceCounter((LARGE_INTEGER*)&start);
  auto key= vio_keygen();
  if (!key)
  {
    printf("Failed to generate key\n");
    return 1;
  }
  QueryPerformanceCounter((LARGE_INTEGER*)&end);
  printf("Keygen took %f seconds\n", (end-start)/(double)freq);
  auto cert= vio_gencert(key);
  if (!cert)
  {
    printf("Failed to generate cert\n");
    return 1;
  }
  printf("Success\n");
  return 0;
}