in xmss_fast.c [970:1105]
int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params)
{
unsigned int n = params->n;
unsigned int tree_h = params->xmss_par.h;
unsigned int idx_len = params->index_len;
uint64_t idx_tree;
uint32_t idx_leaf;
unsigned long long i, m_len;
unsigned long long idx=0;
unsigned char wots_pk[params->xmss_par.wots_par.keysize];
unsigned char pkhash[n];
unsigned char root[n];
unsigned char msg_h[n];
unsigned char hash_key[3*n];
unsigned char pub_seed[n];
memcpy(pub_seed, pk+n, n);
// Init addresses
uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
// Extract index
for (i = 0; i < idx_len; i++) {
idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - i));
}
printf("verify:: idx = %llu\n", idx);
sig_msg += idx_len;
sig_msg_len -= idx_len;
// Generate hash key (R || root || idx)
memcpy(hash_key, sig_msg,n);
memcpy(hash_key+n, pk, n);
to_byte(hash_key+2*n, idx, n);
sig_msg += n;
sig_msg_len -= n;
// hash message (recall, R is now on pole position at sig_msg
unsigned long long tmp_sig_len = (params->d * params->xmss_par.wots_par.keysize) + (params->h * n);
m_len = sig_msg_len - tmp_sig_len;
h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n);
//-----------------------
// Verify signature
//-----------------------
// Prepare Address
idx_tree = idx >> tree_h;
idx_leaf = (idx & ((1 << tree_h)-1));
setLayerADRS(ots_addr, 0);
setTreeADRS(ots_addr, idx_tree);
setType(ots_addr, 0);
memcpy(ltree_addr, ots_addr, 12);
setType(ltree_addr, 1);
memcpy(node_addr, ltree_addr, 12);
setType(node_addr, 2);
setOTSADRS(ots_addr, idx_leaf);
// Check WOTS signature
wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->xmss_par.wots_par), pub_seed, ots_addr);
sig_msg += params->xmss_par.wots_par.keysize;
sig_msg_len -= params->xmss_par.wots_par.keysize;
// Compute Ltree
setLtreeADRS(ltree_addr, idx_leaf);
l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr);
// Compute root
validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr);
sig_msg += tree_h*n;
sig_msg_len -= tree_h*n;
for (i = 1; i < params->d; i++) {
// Prepare Address
idx_leaf = (idx_tree & ((1 << tree_h)-1));
idx_tree = idx_tree >> tree_h;
setLayerADRS(ots_addr, i);
setTreeADRS(ots_addr, idx_tree);
setType(ots_addr, 0);
memcpy(ltree_addr, ots_addr, 12);
setType(ltree_addr, 1);
memcpy(node_addr, ltree_addr, 12);
setType(node_addr, 2);
setOTSADRS(ots_addr, idx_leaf);
// Check WOTS signature
wots_pkFromSig(wots_pk, sig_msg, root, &(params->xmss_par.wots_par), pub_seed, ots_addr);
sig_msg += params->xmss_par.wots_par.keysize;
sig_msg_len -= params->xmss_par.wots_par.keysize;
// Compute Ltree
setLtreeADRS(ltree_addr, idx_leaf);
l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr);
// Compute root
validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr);
sig_msg += tree_h*n;
sig_msg_len -= tree_h*n;
}
for (i = 0; i < n; i++)
if (root[i] != pk[i])
goto fail;
*msglen = sig_msg_len;
for (i = 0; i < *msglen; i++)
msg[i] = sig_msg[i];
return 0;
fail:
*msglen = sig_msg_len;
for (i = 0; i < *msglen; i++)
msg[i] = 0;
*msglen = -1;
return -1;
}