hash.c 2.67 KB
Newer Older
lwc-tester committed
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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
#include "crypto_hash.h"

#include "siv.h"
#include "rijndael256.h"

#define HASH_M_DOMAIN0  0
#define HASH_M_DOMAIN1  1

/* Declaration of basic internal functions */
static void Setup(const unsigned char *k);

static void XOR_State(
	uint8_t *state_inout,
	const uint8_t *data_in,
	const uint64_t dlen_inbytes);

static void Absorb(
	uint8_t *state_inout,
	const uint8_t *data_in,
	const uint64_t dlen_inbytes,
	const uint8_t domain);

static void Squzze(
	uint8_t *tag_out,
	uint8_t *state);

/* Definition of basic internal functions */
static void Setup(const unsigned char *k)
{
	rijndael256KeySched(k);
}

static void XOR_State(
	uint8_t *state_inout,
	const uint8_t *data_in,
	const uint64_t dlen_inbytes)
{
	size_t i;
	for (i = 0; i < dlen_inbytes; i++)
	{
		state_inout[i] ^= data_in[i];
	}
}

static void Absorb(
	uint8_t *state_inout,
	const uint8_t *data_in,
	const uint64_t dlen_inbytes,
	const uint8_t  domain)
{
	size_t i;
	i = dlen_inbytes;
	while (i > RATE_INBYTES)
	{
		XOR_State(state_inout, data_in, RATE_INBYTES);
		rijndael256Encrypt(state_inout, HASH_M_DOMAIN0);
		data_in += RATE_INBYTES;
		i -= RATE_INBYTES;
	}
	XOR_State(state_inout, data_in, i);
	rijndael256Encrypt(state_inout, domain);
	if (i < RATE_INBYTES) state_inout[i] ^= 0x80; // State ^ pad_32(M[m])
	rijndael256Encrypt(state_inout, domain);
}

static void Squzze(
	uint8_t *Tag_out,
	uint8_t *state)
{
	size_t i;
	i = TAG_INBYTES;
	while (i > SQUEEZE_RATE_INBYTES)
	{
		memcpy(Tag_out, state, SQUEEZE_RATE_INBYTES);
		rijndael256Encrypt(state, HASH_M_DOMAIN0);
		Tag_out += SQUEEZE_RATE_INBYTES;
		i -= SQUEEZE_RATE_INBYTES;
	}
	memcpy(Tag_out, state, i);
}

int crypto_hash(
	unsigned char *out,
	const unsigned char *in,
	unsigned long long inlen
)
{
	/*
	...
	... the code for the hash function implementation goes here
	... generating a hash value out[0],out[1],...,out[CRYPTO_BYTES-1]
	... from a message in[0],in[1],...,in[in-1] 
	...
	... return 0;
	*/
	uint8_t state[STATE_INBYTES] = { 0 };
	uint8_t domain;

	uint8_t k[16] = { 0 };
	Setup(k);

	if (inlen <= INITIAL_RATE_INBYTES)
	{
		memcpy(state, in, inlen);
		if (inlen < INITIAL_RATE_INBYTES)
		{
			state[inlen] ^= 0x80; // State ^ pad_128(M[m])
			domain = HASH_M_DOMAIN1;
		}
		else
		{
			domain = HASH_M_DOMAIN1 + 1;
		}
		rijndael256Encrypt(state, domain);
	}
	else
	{
		memcpy(state, in, INITIAL_RATE_INBYTES);
		rijndael256Encrypt(state, 0);

		inlen -= INITIAL_RATE_INBYTES;
		domain = (inlen % RATE_INBYTES == 0) ? (HASH_M_DOMAIN1 + 1) : HASH_M_DOMAIN1;
		Absorb(state, in + INITIAL_RATE_INBYTES, inlen, domain);
	}
	Squzze(out, state);

	return 0;
}