packages feed

hashes-0.2.1.0: cbits/keccak.c

#include <openssl/evp.h>
#include "keccak.h"

/* *************************************************************************** */
/* OpenSSL Master */

/*
int main()
{
    int ok = 1;
    unsigned int md_len = 0;
    MD_VALUE md_value;
    MD_VALUE_HEX result;
    EVP_MD *md;
    EVP_MD_CTX *ctx;

    CHECKED(md = EVP_get_digestbyname("KECCAK-256"));
    CHECKED(ctx = EVP_MD_CTX_new());
    CHECKED(EVP_DigestInit(ctx, md));
    CHECKED(EVP_DigestUpdate(ctx, msg, strlen(msg)));
    CHECKED(EVP_DigestFinal(ctx, md_value, &md_len));

    // Print Digest
    digestToHex(result, md_value);
    printf("Keccak-256 digest: %s\n", result);
    printf("expected         : %s\n", expected);

finally:
    if (ctx) keccak256_freectx(ctx);
    return ! ok;
}
*/

#if OPENSSL_VERSION_NUMBER >= 0x30000000L
/* *************************************************************************** */
/* KECCAK-256 for OpenSSL 3.0 */

extern const OSSL_DISPATCH ossl_sha3_256_functions[];
extern const OSSL_DISPATCH ossl_sha3_512_functions[];
extern int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen);

typedef void (*VoidFunPtr) (void);

VoidFunPtr dispatch(const OSSL_DISPATCH *fns, int fn_id) {
    for (; fns->function_id != 0; fns++) {
        if (fns->function_id == fn_id) {
            return fns->function;
        }
    }
    return NULL;
}

VoidFunPtr dispatch256(int fn_id) {
    return dispatch(ossl_sha3_256_functions, fn_id);
}

VoidFunPtr dispatch512(int fn_id) {
    return dispatch(ossl_sha3_512_functions, fn_id);
}

KECCAK256_CTX *keccak256_newctx()
{
    KECCAK256_CTX * ctx = ((OSSL_FUNC_digest_newctx_fn *) dispatch256(OSSL_FUNC_DIGEST_NEWCTX))(NULL);

    // this has already be called once by the dispatch function. Here we update the pad character
    if (ctx) ossl_sha3_init(ctx, '\x01', 256);
    return ctx;
}

KECCAK512_CTX *keccak512_newctx()
{
    KECCAK512_CTX * ctx = ((OSSL_FUNC_digest_newctx_fn *) dispatch512(OSSL_FUNC_DIGEST_NEWCTX))(NULL);

    // this has already be called once by the dispatch function. Here we update the pad character
    if (ctx) ossl_sha3_init(ctx, '\x01', 512);
    return ctx;
}

int keccak256_init(KECCAK256_CTX *ctx) {
    return ((OSSL_FUNC_digest_init_fn *) dispatch256(OSSL_FUNC_DIGEST_INIT))(ctx, NULL);
}

int keccak512_init(KECCAK256_CTX *ctx) {
    return ((OSSL_FUNC_digest_init_fn *) dispatch512(OSSL_FUNC_DIGEST_INIT))(ctx, NULL);
}

int keccak256_update(KECCAK256_CTX *ctx, const void *p, size_t l)
{
    return ((OSSL_FUNC_digest_update_fn *) dispatch256(OSSL_FUNC_DIGEST_UPDATE))(ctx, p, l);
}

int keccak512_update(KECCAK512_CTX *ctx, const void *p, size_t l)
{
    return ((OSSL_FUNC_digest_update_fn *) dispatch512(OSSL_FUNC_DIGEST_UPDATE))(ctx, p, l);
}

int keccak256_final(KECCAK256_CTX *ctx, unsigned char *md)
{
    size_t l;
    return ((OSSL_FUNC_digest_final_fn *) dispatch256(OSSL_FUNC_DIGEST_FINAL))(ctx, md, &l, 32);
}

int keccak512_final(KECCAK512_CTX *ctx, unsigned char *md)
{
    size_t l;
    return ((OSSL_FUNC_digest_final_fn *) dispatch512(OSSL_FUNC_DIGEST_FINAL))(ctx, md, &l, 64);
}

void keccak256_freectx(KECCAK256_CTX *ctx)
{
    return ((OSSL_FUNC_digest_freectx_fn *) dispatch256(OSSL_FUNC_DIGEST_FREECTX))(ctx);
}

void keccak512_freectx(KECCAK512_CTX *ctx)
{
    return ((OSSL_FUNC_digest_freectx_fn *) dispatch512(OSSL_FUNC_DIGEST_FREECTX))(ctx);
}

#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
/* *************************************************************************** */
/* OpenSSL 1.1 */

/* The computation of the magic offset is base on the keccak_st structure in
 * OpenSSL-1.1.
 *
 * Assuming conventional alignment, the bytes offset is
 *
 * sizeof(uint64_t) * 40 + size_of(size_t) * 3 + (1600 / 8 - 32)
 *
 * On a 64bit platform this number is 392
 */

// struct keccak_st {
//     uint64_t A[5][5];
//     size_t block_size;          /* cached ctx->digest->block_size */
//     size_t md_size;             /* output length, variable in XOF */
//     size_t bufsz;               /* used bytes in below buffer */
//     unsigned char buf[KECCAK1600_WIDTH / 8 - 32];
//     unsigned char pad;
// };

KECCAK256_CTX *keccak256_newctx()
{
    return EVP_MD_CTX_new();
}

KECCAK512_CTX *keccak512_newctx()
{
    return EVP_MD_CTX_new();
}

int keccak256_init(KECCAK256_CTX *ctx) {
    int ok = 1;
    const EVP_MD *md = NULL;
    int padByteOffset = 25 * sizeof(uint64_t) + 3 * sizeof(size_t) + 1600/8 - 32;
    CHECKED(md = EVP_sha3_256());
    CHECKED(EVP_DigestInit(ctx, md));

    // MAGIC (set padding char to 0x1)
    ((uint8_t *) EVP_MD_CTX_md_data(ctx))[padByteOffset] = 0x01;
finally:
    return ok;
}

int keccak512_init(KECCAK512_CTX *ctx) {
    int ok = 1;
    const EVP_MD *md = NULL;
    int padByteOffset = 25 * sizeof(uint64_t) + 3 * sizeof(size_t) + 1600/8 - 32;
    CHECKED(md = EVP_sha3_512());
    CHECKED(EVP_DigestInit(ctx, md));

    // MAGIC (set padding char to 0x1)
    ((uint8_t *) EVP_MD_CTX_md_data(ctx))[padByteOffset] = 0x01;
finally:
    return ok;
}

int keccak256_update(KECCAK256_CTX *ctx, const void *p, size_t l)
{
    return EVP_DigestUpdate(ctx, p, l);
}

int keccak512_update(KECCAK512_CTX *ctx, const void *p, size_t l)
{
    return EVP_DigestUpdate(ctx, p, l);
}

int keccak256_final(KECCAK256_CTX *ctx, unsigned char *md)
{
    unsigned int l;
    return EVP_DigestFinal(ctx, md, &l);
}

int keccak512_final(KECCAK512_CTX *ctx, unsigned char *md)
{
    unsigned int l;
    return EVP_DigestFinal(ctx, md, &l);
}

void keccak256_freectx(KECCAK256_CTX *ctx)
{
    return EVP_MD_CTX_free(ctx);
}

void keccak512_freectx(KECCAK512_CTX *ctx)
{
    return EVP_MD_CTX_free(ctx);
}

#endif