aboutsummaryrefslogtreecommitdiff
path: root/pqcrypto_hash_shake256.c
blob: 6be917fce5725f1b06726b30ca12ca7ce5887c72 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
 * 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,
	}
};