
#include <stdio.h>
#include <stdint.h>
#include "tool-sha1sum.h"

#ifdef OPENSSL

#include <openssl/evp.h>
#include <openssl/sha.h>

int done = 0;
EVP_MD_CTX *c;
const EVP_MD *md;

// See example at:
// https://www.openssl.org/docs/man1.1.1/man3/EVP_DigestInit.html

void CFC_API cubetools_sha1sum_first()
{
    if (done) {
      return;
    }
    c = EVP_MD_CTX_create();
    OpenSSL_add_all_algorithms();
    md = EVP_get_digestbyname("sha1");
    done = 1;
}

int32_t CFC_API cubetools_sha1sum_init()
{
    int ier;

    cubetools_sha1sum_first();

    // ZZZ Add sanity to forbid double initialization (means incorrect calls)?
    ier = EVP_DigestInit_ex(c, md, NULL);

    if (ier == 1) {
      return 0;  /* Success */
    } else {
      return 1;
    }
}

int32_t CFC_API cubetools_sha1sum_update( unsigned char *data, int64_t *ldata)
{
    int ier;

    // ZZZ Add sanity to forbid non initialized context (means incorrect calls)
    ier = EVP_DigestUpdate(c,data,*ldata);

    if (ier == 1) {
      return 0;  /* Success */
    } else {
      return 1;
    }
}

void CFC_API cubetools_sha1sum_final( void *outbytes)
{
    unsigned int mdlen = SHA_DIGEST_LENGTH;
    unsigned char md[mdlen];

    // ZZZ Add sanity to forbid non initialized context (means incorrect calls)
    EVP_DigestFinal_ex(c,md,&mdlen);

    // int i;
    // printf("Digest is: ");
    // for (i = 0; i < mdlen; i++)
    //   printf("%02x", md[i]);
    // printf("\n");

    memcpy(outbytes, md, mdlen);
}

#else /* OPENSSL */

int32_t CFC_API cubetools_sha1sum_init()
{
    printf("E-SHA1SUM>INIT, OpenSSL not available on this system\n");
    return 1;
}

int32_t CFC_API cubetools_sha1sum_update( unsigned char *data, int64_t *ldata)
{
    printf("E-SHA1SUM>UPDATE, OpenSSL not available on this system\n");
    return 1;
}

void CFC_API cubetools_sha1sum_final( void *outbytes)
{
    printf("E-SHA1SUM>FINAL, OpenSSL not available on this system\n");
}

#endif /* OPENSSL */
