#include "bee2/core/blob.h"
#include "bee2/core/err.h"
#include "bee2/core/mem.h"
#include "bee2/core/util.h"
#include "bee2/crypto/bash.h"
typedef struct {
octet s[192];
octet s1[192];
size_t buf_len;
size_t pos;
octet stack[];
} bash_hash_st;
size_t bashHash_keep()
{
return sizeof(bash_hash_st) + bashF_deep();
}
void bashHashStart(void* state, size_t l)
{
bash_hash_st* st = (bash_hash_st*)state;
ASSERT(l > 0 && l % 16 == 0 && l <= 256);
ASSERT(memIsValid(st, bashHash_keep()));
memSetZero(st->s, sizeof(st->s));
st->s[192 - 8] = (octet)(l / 4);
st->buf_len = 192 - l / 2;
st->pos = 0;
}
void bashHashStepH(const void* buf, size_t count, void* state)
{
bash_hash_st* st = (bash_hash_st*)state;
ASSERT(memIsDisjoint2(st, bashHash_keep(), buf, count));
if (count < st->buf_len - st->pos)
{
memCopy(st->s + st->pos, buf, count);
st->pos += count;
return;
}
memCopy(st->s + st->pos, buf, st->buf_len - st->pos);
buf = (const octet*)buf + st->buf_len - st->pos;
count -= st->buf_len - st->pos;
bashF(st->s, st->stack);
while (count >= st->buf_len)
{
memCopy(st->s, buf, st->buf_len);
buf = (const octet*)buf + st->buf_len;
count -= st->buf_len;
bashF(st->s, st->stack);
}
if (st->pos = count)
memCopy(st->s, buf, count);
}
static void bashHashStepG_internal(size_t hash_len, void* state)
{
bash_hash_st* st = (bash_hash_st*)state;
ASSERT(memIsValid(st, bashHash_keep()));
ASSERT(st->buf_len + hash_len * 2 <= 192);
memCopy(st->s1, st->s, sizeof(st->s));
if (st->pos)
{
memSetZero(st->s1 + st->pos, st->buf_len - st->pos);
st->s1[st->pos] = 0x40;
}
else
{
memSetZero(st->s1, st->buf_len);
st->s1[0] = 0x40;
}
bashF(st->s1, st->stack);
}
void bashHashStepG(octet hash[], size_t hash_len, void* state)
{
bash_hash_st* st = (bash_hash_st*)state;
bashHashStepG_internal(hash_len, state);
memMove(hash, st->s1, hash_len);
}
bool_t bashHashStepV(const octet hash[], size_t hash_len, void* state)
{
bash_hash_st* st = (bash_hash_st*)state;
bashHashStepG_internal(hash_len, state);
return memEq(hash, st->s1, hash_len);
}
err_t bashHash(octet hash[], size_t l, const void* src, size_t count)
{
void* state;
if (l == 0 || l % 16 != 0 || l > 256)
return ERR_BAD_PARAMS;
if (!memIsValid(src, count) || !memIsValid(hash, l / 4))
return ERR_BAD_INPUT;
state = blobCreate(bashHash_keep());
if (state == 0)
return ERR_OUTOFMEMORY;
bashHashStart(state, l);
bashHashStepH(src, count, state);
bashHashStepG(hash, l / 4, state);
blobClose(state);
return ERR_OK;
}