packages feed

hashes-0.2.3: 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) EVP_MD_CTX_free(ctx);
    return ! ok;
}
*/

/* *************************************************************************** */
/* OpenSSL 1.1 and OpenSSL 3.0 */

/* The computation of the magic offset is based on the keccak_st structure in
 * OpenSSL-1.1 and OpenSSL-3.0
 *
 * Assuming conventional alignment, the bytes offset is
 *
 * sizeof(uint64_t) * 25 + 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;
 * //     size_t md_size;
 * //     size_t bufsz;
 * //     unsigned char buf[KECCAK1600_WIDTH / 8 - 32];
 * //     unsigned char pad;
 * // };
 *
 * For OpenSSL 1.1 this context is stored in EVP_MD_CTX as data and is accessed
 * via EVP_CTX_MD_md_data().
 *
 * For OpenSSL 3.0 it is stored in EVP_MD_CTX in the algctx field. The structure
 * is a field of pointers and algctx is the 8th pointer.
 *
 * // struct evp_md_ctx_st {
 * //   const EVP_MD *reqdigest;
 * //   const EVP_MD *digest;
 * //   ENGINE *engine;
 * //   unsigned long flags;
 * //   void *md_data;
 * //   EVP_PKEY_CTX *pctx;
 * //   int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
 * //
 * //   // Opaque ctx returned from a providers digest algorithm implementation
 * //   // OSSL_FUNC_digest_newctx()
 * //   //
 * //   void *algctx;
 * //   EVP_MD *fetched_digest;
 * // }
 */

#define PAD_BYTE_OFFSET (25 * sizeof(uint64_t) + 3 * sizeof(size_t) + 1600/8 - 32)

/* OPENSSL 3.1 */
#if OPENSSL_VERSION_NUMBER >= 0x31000000L
#define SET_PAD_BYTE

/* OPENSSL 3.0 */
#elif OPENSSL_VERSION_NUMBER >= 0x30000000L
#define GET_CTX(ctx) (*(((uint8_t **) ctx) + 7))
#define SET_PAD_BYTE (((uint8_t *) GET_CTX(ctx))[PAD_BYTE_OFFSET] = 0x01)

/* OPENSSL 1.1 */
#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
#define GET_CTX(ctx) ((uint8_t *) EVP_MD_CTX_md_data(ctx))
#define SET_PAD_BYTE (GET_CTX(ctx)[PAD_BYTE_OFFSET] = 0x01)

#endif

/* *************************************************************************** */
/* Implementation */


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;
    CHECKED(md = EVP_get_digestbyname("SHA3-256"));
    CHECKED(EVP_DigestInit_ex(ctx, md, NULL));
    SET_PAD_BYTE;
finally:
    return ok;
}

int keccak512_init(KECCAK512_CTX *ctx) {
    int ok = 1;
    const EVP_MD *md = NULL;
    CHECKED(md = EVP_get_digestbyname("SHA3-512"));
    CHECKED(EVP_DigestInit_ex(ctx, md, NULL));
    SET_PAD_BYTE;
finally:
    return ok;
}

int keccak256_reset(KECCAK512_CTX *ctx) {
    int ok = 1;
    CHECKED(EVP_DigestInit_ex(ctx, NULL, NULL));
    SET_PAD_BYTE;
finally:
    return ok;
}

int keccak512_reset(KECCAK512_CTX *ctx) {
    int ok = 1;
    CHECKED(EVP_DigestInit_ex(ctx, NULL, NULL));
    SET_PAD_BYTE;
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_ex(ctx, md, &l);
}

int keccak512_final(KECCAK512_CTX *ctx, unsigned char *md)
{
    unsigned int l;
    return EVP_DigestFinal_ex(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);
}