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);
}