#include "bee2/core/mem.h"
#include "bee2/core/util.h"
#include "bee2/crypto/belt.h"
#include "belt_lcl.h"
size_t beltWBL_keep()
{
return sizeof(belt_wbl_st);
}
void beltWBLStart(void* state, const octet key[], size_t len)
{
belt_wbl_st* st = (belt_wbl_st*)state;
ASSERT(memIsValid(state, beltWBL_keep()));
beltKeyExpand2(st->key, key, len);
st->round = 0;
}
static void beltWBLStepEBase(void* buf, size_t count, void* state)
{
belt_wbl_st* st = (belt_wbl_st*)state;
word n = ((word)count + 15) / 16;
ASSERT(count >= 32);
ASSERT(memIsDisjoint2(buf, count, state, beltWBL_keep()));
ASSERT(st->round % (2 * n) == 0);
do
{
size_t i;
beltBlockCopy(st->block, buf);
for (i = 16; i + 16 < count; i += 16)
beltBlockXor2(st->block, (octet*)buf + i);
memMove(buf, (octet*)buf + 16, count - 16);
beltBlockCopy((octet*)buf + count - 16, st->block);
beltBlockEncr(st->block, st->key);
st->round++;
#if (OCTET_ORDER == LITTLE_ENDIAN)
memXor2(st->block, &st->round, O_PER_W);
#else
st->round = wordRev(st->round);
memXor2(st->block, &st->round, O_PER_W);
st->round = wordRev(st->round);
#endif beltBlockXor2((octet*)buf + count - 32, st->block);
}
while (st->round % (2 * n));
}
static void beltWBLStepEOpt(void* buf, size_t count, void* state)
{
belt_wbl_st* st = (belt_wbl_st*)state;
word n = ((word)count + 15) / 16;
size_t i;
ASSERT(count >= 32 && count % 16 == 0);
ASSERT(memIsDisjoint2(buf, count, state, beltWBL_keep()));
beltBlockCopy(st->sum, buf);
for (i = 16; i + 16 < count; i += 16)
beltBlockXor2(st->sum, (octet*)buf + i);
ASSERT(st->round % (2 * n) == 0);
i = 0;
do
{
beltBlockCopy(st->block, st->sum);
beltBlockEncr(st->block, st->key);
st->round++;
#if (OCTET_ORDER == LITTLE_ENDIAN)
memXor2(st->block, &st->round, O_PER_W);
#else
st->round = wordRev(st->round);
memXor2(st->block, &st->round, O_PER_W);
st->round = wordRev(st->round);
#endif beltBlockXor2((octet*)buf + (i + count - 16) % count, st->block);
beltBlockCopy(st->block, st->sum);
beltBlockXor2(st->sum, (octet*)buf + (i + count - 16) % count);
beltBlockXor2(st->sum, (octet*)buf + i);
beltBlockCopy((octet*)buf + i, st->block);
i = (i + 16) % count;
}
while (st->round % (2 * n));
}
static void beltWBLStepDBase(void* buf, size_t count, void* state)
{
belt_wbl_st* st = (belt_wbl_st*)state;
word n = ((word)count + 15) / 16;
ASSERT(count >= 32);
ASSERT(memIsDisjoint2(buf, count, state, beltWBL_keep()));
for (st->round = 2 * n; st->round; --st->round)
{
size_t i;
beltBlockCopy(st->block, (octet*)buf + count - 16);
memMove((octet*)buf + 16, buf, count - 16);
beltBlockCopy(buf, st->block);
beltBlockEncr(st->block, st->key);
#if (OCTET_ORDER == LITTLE_ENDIAN)
memXor2(st->block, &st->round, O_PER_W);
#else
st->round = wordRev(st->round);
memXor2(st->block, &st->round, O_PER_W);
st->round = wordRev(st->round);
#endif beltBlockXor2((octet*)buf + count - 16, st->block);
for (i = 16; i + 16 < count; i += 16)
beltBlockXor2(buf, (octet*)buf + i);
}
}
static void beltWBLStepDOpt(void* buf, size_t count, void* state)
{
belt_wbl_st* st = (belt_wbl_st*)state;
word n = ((word)count + 15) / 16;
size_t i;
ASSERT(count >= 32 && count % 16 == 0);
ASSERT(memIsDisjoint2(buf, count, state, beltWBL_keep()));
beltBlockCopy(st->sum, (octet*)buf);
for (i = 16; i + 32 < count; i += 16)
beltBlockXor2(st->sum, (octet*)buf + i);
for (st->round = 2 * n, i = count - 16; st->round; --st->round)
{
beltBlockCopy(st->block, (octet*)buf + i);
beltBlockEncr(st->block, st->key);
#if (OCTET_ORDER == LITTLE_ENDIAN)
memXor2(st->block, &st->round, O_PER_W);
#else
st->round = wordRev(st->round);
memXor2(st->block, &st->round, O_PER_W);
st->round = wordRev(st->round);
#endif beltBlockXor2((octet*)buf + (i + count - 16) % count, st->block);
beltBlockXor2((octet*)buf + i, st->sum);
beltBlockXor2(st->sum, (octet*)buf + (i + count - 32) % count);
beltBlockXor2(st->sum, (octet*)buf + i);
i = (i + count - 16) % count;
}
}
void beltWBLStepE(void* buf, size_t count, void* state)
{
belt_wbl_st* st = (belt_wbl_st*)state;
ASSERT(memIsValid(state, beltWBL_keep()));
st->round = 0;
(count % 16 || count < 64) ?
beltWBLStepEBase(buf, count, state) :
beltWBLStepEOpt(buf, count, state);
}
void beltWBLStepD(void* buf, size_t count, void* state)
{
(count % 16 || count < 80) ?
beltWBLStepDBase(buf, count, state) :
beltWBLStepDOpt(buf, count, state);
}
void beltWBLStepD2(void* buf1, void* buf2, size_t count, void* state)
{
belt_wbl_st* st = (belt_wbl_st*)state;
word n = ((word)count + 15) / 16;
ASSERT(count >= 32);
ASSERT(memIsDisjoint3(buf1, count - 16, buf2, 16, state, beltWBL_keep()));
for (st->round = 2 * n; st->round; --st->round)
{
size_t i;
beltBlockCopy(st->block, buf2);
memCopy(buf2, (octet*)buf1 + count - 32, 16);
memMove((octet*)buf1 + 16, buf1, count - 32);
beltBlockCopy(buf1, st->block);
beltBlockEncr(st->block, st->key);
#if (OCTET_ORDER == LITTLE_ENDIAN)
memXor2(st->block, &st->round, O_PER_W);
#else
st->round = wordRev(st->round);
memXor2(st->block, &st->round, O_PER_W);
st->round = wordRev(st->round);
#endif beltBlockXor2(buf2, st->block);
for (i = 16; i + 32 < count; i += 16)
beltBlockXor2(buf1, (octet*)buf1 + i);
ASSERT(i + 16 <= count && i + 32 >= count);
if (i + 16 < count)
{
memXor2(buf1, (octet*)buf1 + i, count - 16 - i);
memXor2((octet*)buf1 + count - 16 - i, buf2, 32 + i - count);
}
}
}
void beltWBLStepR(void* buf, size_t count, void* state)
{
(count % 16 || count < 64) ?
beltWBLStepEBase(buf, count, state) :
beltWBLStepEOpt(buf, count, state);
}