#include "bee2/core/blob.h"
#include "bee2/core/err.h"
#include "bee2/core/mem.h"
#include "bee2/core/u32.h"
#include "bee2/core/util.h"
#include "bee2/crypto/belt.h"
#include "belt_lcl.h"
typedef struct {
u32 key[8];
size_t len;
u32 block[8];
u32 key_new[8];
octet stack[];
} belt_krp_st;
size_t beltKRP_keep()
{
return sizeof(belt_krp_st) + beltCompr_deep();
}
void beltKRPStart(void* state, const octet key[], size_t len,
const octet level[12])
{
belt_krp_st* st = (belt_krp_st*)state;
ASSERT(memIsDisjoint2(level, 12, state, beltKRP_keep()));
u32From(st->block + 1, level, 12);
beltKeyExpand2(st->key, key, st->len = len);
}
void beltKRPStepG(octet key_[], size_t key_len, const octet header[16],
void* state)
{
belt_krp_st* st = (belt_krp_st*)state;
ASSERT(memIsValid(state, beltKRP_keep()));
ASSERT(key_len == 16 || key_len == 24 || key_len == 32);
ASSERT(key_len <= st->len);
ASSERT(memIsDisjoint2(key_, key_len, state, beltKRP_keep()));
ASSERT(memIsDisjoint2(header, 16, state, beltKRP_keep()));
u32From(st->block, beltH() + 4 * (st->len - 16) + 2 * (key_len - 16), 4);
u32From(st->block + 4, header, 16);
beltBlockCopy(st->key_new, st->key);
beltBlockCopy(st->key_new + 4, st->key + 4);
beltCompr(st->key_new, st->block, st->stack);
u32To(key_, key_len, st->key_new);
}
err_t beltKRP(octet dest[], size_t m, const octet src[], size_t n,
const octet level[12], const octet header[16])
{
void* state;
if (m > n ||
m != 16 && m != 24 && m != 32 ||
n != 16 && n != 24 && n != 32 ||
!memIsValid(src, n) ||
!memIsValid(level, 12) ||
!memIsValid(header, 16) ||
!memIsValid(dest, m))
return ERR_BAD_INPUT;
state = blobCreate(beltKRP_keep());
if (state == 0)
return ERR_OUTOFMEMORY;
beltKRPStart(state, src, n, level);
beltKRPStepG(dest, m, header, state);
blobClose(state);
return ERR_OK;
}