aboutsummaryrefslogtreecommitdiff
/*
 * SPDX-License-Identifier: CC0-1.0
 *
 * Copyright (C) 2025 W. Kosior <koszko@koszko.org>
 */

#include <stdbool.h>

#include <flint/fmpz.h>
#include <gcrypt.h>

#define PQCRYPTO_HASH_SHAKE256_C
#include "pqcrypto_hash_shake256.h"

struct hash_shake256_state {
	bool finished;
	gcry_md_hd_t hd;
};

static void * hash_shake256_make(void) {
	struct hash_shake256_state * state =
		malloc(sizeof(struct hash_shake256_state));

	if (!state)
		abort();

	if (gcry_md_open(&state->hd, GCRY_MD_SHAKE256, GCRY_MD_FLAG_SECURE) !=
	    GPG_ERR_NO_ERROR)
		abort();

	state->finished = false;

	return state;
}

static void hash_shake256_free(void * state) {
	struct hash_shake256_state * state_ = state;

	gcry_md_close(state_->hd);

	free(state_);
}

static void hash_shake256_feed(void * state, void const * data,
			       size_t data_bytes) {
	struct hash_shake256_state * state_ = state;

	if (state_->finished)
		abort();

	gcry_md_write(state_->hd, data, data_bytes);
}

static int hash_shake256_getc(void * state) {
	struct hash_shake256_state * state_ = state;
	unsigned char extracted;

	state_->finished = true;

	gcry_md_extract(state_->hd, 0, &extracted, 1);

	return extracted;
}

hash_function_t hash_function_shake256 = {
	{
		.make = hash_shake256_make,
		.free = hash_shake256_free,
		.feed = hash_shake256_feed,
		.getc = hash_shake256_getc,
	}
};