10#include "hashx_endian.h"
16#error HASHX_SIZE cannot be more than 32
19#ifndef HASHX_BLOCK_MODE
20#define HASHX_INPUT_ARGS input
22#define HASHX_INPUT_ARGS input, size
26 if (!hashx_program_generate(&keys[0], &ctx->program)) {
29#ifndef HASHX_BLOCK_MODE
30 memcpy(&ctx->keys, &keys[1], 32);
32 memcpy(&ctx->params.salt, &keys[1], 32);
37hashx_result hashx_make(
hashx_ctx* ctx,
const void* seed,
size_t size) {
39 assert(seed != NULL || size == 0);
43 hashx_blake2b_init_param(&hash_state, &hashx_blake2_params);
44 hashx_blake2b_update(&hash_state, seed, size);
45 hashx_blake2b_final(&hash_state, keys_bytes,
sizeof(keys_bytes));
48 keys[0].v0 = load64(keys_bytes + 0 *
sizeof(uint64_t));
49 keys[0].v1 = load64(keys_bytes + 1 *
sizeof(uint64_t));
50 keys[0].v2 = load64(keys_bytes + 2 *
sizeof(uint64_t));
51 keys[0].v3 = load64(keys_bytes + 3 *
sizeof(uint64_t));
52 keys[1].v0 = load64(keys_bytes + 4 *
sizeof(uint64_t));
53 keys[1].v1 = load64(keys_bytes + 5 *
sizeof(uint64_t));
54 keys[1].v2 = load64(keys_bytes + 6 *
sizeof(uint64_t));
55 keys[1].v3 = load64(keys_bytes + 7 *
sizeof(uint64_t));
57 ctx->func_type = (hashx_type)0;
58 if (!initialize_program(ctx, keys)) {
59 return HASHX_FAIL_SEED;
62 switch (ctx->ctx_type) {
63 case HASHX_TYPE_INTERPRETED:
64 ctx->func_type = HASHX_TYPE_INTERPRETED;
66 case HASHX_TYPE_COMPILED:
67 case HASHX_TRY_COMPILE:
68 if (ctx->compiler_mem != NULL &&
69 hashx_compile(&ctx->program, ctx->compiler_mem)) {
70 ctx->func_type = HASHX_TYPE_COMPILED;
73 if (ctx->ctx_type == HASHX_TRY_COMPILE) {
74 ctx->func_type = HASHX_TYPE_INTERPRETED;
77 return HASHX_FAIL_COMPILE;
80 return HASHX_FAIL_UNDEFINED;
84hashx_result hashx_query_type(
hashx_ctx* ctx, hashx_type *type_out) {
86 assert(type_out != NULL);
88 if (ctx->func_type == (hashx_type)0) {
89 return HASHX_FAIL_UNPREPARED;
91 *type_out = ctx->func_type;
95hashx_result hashx_exec(
const hashx_ctx* ctx, HASHX_INPUT,
void* output) {
97 assert(output != NULL);
100#ifndef HASHX_BLOCK_MODE
101 hashx_siphash24_ctr_state512(&ctx->keys, input, r);
103 hashx_blake2b_4r(&ctx->params, input, size, r);
106 if (ctx->func_type == HASHX_TYPE_COMPILED) {
107 typedef void program_func(uint64_t r[8]);
108 assert(ctx->compiler_mem != NULL);
109 ((program_func*)ctx->compiler_mem)(r);
110 }
else if (ctx->func_type == HASHX_TYPE_INTERPRETED) {
111 hashx_program_execute(&ctx->program, r);
113 return HASHX_FAIL_UNPREPARED;
117#ifndef HASHX_BLOCK_MODE
118 r[0] += ctx->keys.v0;
119 r[1] += ctx->keys.v1;
120 r[6] += ctx->keys.v2;
121 r[7] += ctx->keys.v3;
123 const uint8_t* p = (
const uint8_t*)&ctx->params;
124 r[0] ^= load64(&p[8 * 0]);
125 r[1] ^= load64(&p[8 * 1]);
126 r[2] ^= load64(&p[8 * 2]);
127 r[3] ^= load64(&p[8 * 3]);
128 r[4] ^= load64(&p[8 * 4]);
129 r[5] ^= load64(&p[8 * 5]);
130 r[6] ^= load64(&p[8 * 6]);
131 r[7] ^= load64(&p[8 * 7]);
134 SIPROUND(r[0], r[1], r[2], r[3]);
135 SIPROUND(r[4], r[5], r[6], r[7]);
140#if HASHX_SIZE % 8 == 0
141 uint8_t* temp_out = (uint8_t*)output;
143 store64(temp_out + 0, r[0] ^ r[4]);
146 store64(temp_out + 8, r[1] ^ r[5]);
149 store64(temp_out + 16, r[2] ^ r[6]);
152 store64(temp_out + 24, r[3] ^ r[7]);
155 uint8_t temp_out[32];
157 store64(temp_out + 0, r[0] ^ r[4]);
160 store64(temp_out + 8, r[1] ^ r[5]);
163 store64(temp_out + 16, r[2] ^ r[6]);
166 store64(temp_out + 24, r[3] ^ r[7]);
168 memcpy(output, temp_out, HASHX_SIZE);