in xmss_fast.c [446:515]
static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, uint32_t addr[8])
{
unsigned int i;
unsigned int n = params->n;
unsigned int h = params->h;
unsigned int k = params->k;
unsigned int tau = h;
unsigned int startidx;
unsigned int offset, rowidx;
unsigned char buf[2 * n];
uint32_t ots_addr[8];
uint32_t ltree_addr[8];
uint32_t node_addr[8];
// only copy layer and tree address parts
memcpy(ots_addr, addr, 12);
// type = ots
setType(ots_addr, 0);
memcpy(ltree_addr, addr, 12);
setType(ltree_addr, 1);
memcpy(node_addr, addr, 12);
setType(node_addr, 2);
for (i = 0; i < h; i++) {
if (! ((leaf_idx >> i) & 1)) {
tau = i;
break;
}
}
if (tau > 0) {
memcpy(buf, state->auth + (tau-1) * n, n);
// we need to do this before refreshing state->keep to prevent overwriting
memcpy(buf + n, state->keep + ((tau-1) >> 1) * n, n);
}
if (!((leaf_idx >> (tau + 1)) & 1) && (tau < h - 1)) {
memcpy(state->keep + (tau >> 1)*n, state->auth + tau*n, n);
}
if (tau == 0) {
setLtreeADRS(ltree_addr, leaf_idx);
setOTSADRS(ots_addr, leaf_idx);
gen_leaf_wots(state->auth, sk_seed, params, pub_seed, ltree_addr, ots_addr);
}
else {
setTreeHeight(node_addr, (tau-1));
setTreeIndex(node_addr, leaf_idx >> tau);
hash_h(state->auth + tau * n, buf, pub_seed, node_addr, n);
for (i = 0; i < tau; i++) {
if (i < h - k) {
memcpy(state->auth + i * n, state->treehash[i].node, n);
}
else {
offset = (1 << (h - 1 - i)) + i - h;
rowidx = ((leaf_idx >> i) - 1) >> 1;
memcpy(state->auth + i * n, state->retain + (offset + rowidx) * n, n);
}
}
for (i = 0; i < ((tau < h - k) ? tau : (h - k)); i++) {
startidx = leaf_idx + 1 + 3 * (1 << i);
if (startidx < 1U << h) {
state->treehash[i].h = i;
state->treehash[i].next_idx = startidx;
state->treehash[i].completed = 0;
state->treehash[i].stackusage = 0;
}
}
}
}