use crate::hashers::Hashers;
use crate::types::{Adrs, HtSig, WotsSig, XmssSig};
use crate::xmss;
#[allow(clippy::similar_names)] pub(crate) fn ht_sign<
const D: usize,
const H: usize,
const HP: usize,
const K: usize,
const LEN: usize,
const M: usize,
const N: usize,
>(
hashers: &Hashers<K, LEN, M, N>, m: &[u8], sk_seed: &[u8], pk_seed: &[u8], idx_tree: u64,
idx_leaf: u32,
) -> Result<HtSig<D, HP, LEN, N>, &'static str> {
let mut idx_tree = idx_tree;
let (d32, hp32) = (u32::try_from(D).unwrap(), u32::try_from(HP).unwrap());
let mut adrs = Adrs::default();
adrs.set_tree_address(idx_tree);
let mut sig_tmp =
xmss::xmss_sign::<H, HP, K, LEN, M, N>(hashers, m, sk_seed, idx_leaf, pk_seed, &adrs);
let mut sig_ht = HtSig {
xmss_sigs: core::array::from_fn(|_| XmssSig {
sig_wots: WotsSig { data: [[0u8; N]; LEN] },
auth: [[0u8; N]; HP],
}),
};
sig_ht.xmss_sigs[0] = sig_tmp.clone();
let mut root =
xmss::xmss_pk_from_sig::<HP, K, LEN, M, N>(hashers, idx_leaf, &sig_tmp, m, pk_seed, &adrs);
for j in 1..d32 {
let idx_leaf =
u32::try_from(idx_tree & ((1 << hp32) - 1)).map_err(|_| "Alg11: oversized idx leaf")?;
idx_tree >>= hp32;
adrs.set_layer_address(j);
adrs.set_tree_address(idx_tree);
sig_tmp = xmss::xmss_sign::<H, HP, K, LEN, M, N>(
hashers, &root, sk_seed, idx_leaf, pk_seed, &adrs,
);
sig_ht.xmss_sigs[j as usize] = sig_tmp.clone();
if j < (d32 - 1) {
root = xmss::xmss_pk_from_sig::<HP, K, LEN, M, N>(
hashers, idx_leaf, &sig_tmp, &root, pk_seed, &adrs,
);
}
}
Ok(sig_ht)
}
pub(crate) fn ht_verify<
const D: usize,
const HP: usize,
const K: usize,
const LEN: usize,
const M: usize,
const N: usize,
>(
hashers: &Hashers<K, LEN, M, N>, m: &[u8], sig_ht: &HtSig<D, HP, LEN, N>, pk_seed: &[u8],
idx_tree: u64, idx_leaf: u32, pk_root: &[u8; N],
) -> bool {
let mut idx_tree = idx_tree;
let (d32, hp32) = (u32::try_from(D).unwrap(), u32::try_from(HP).unwrap());
let mut adrs = Adrs::default();
adrs.set_tree_address(idx_tree);
let sig_tmp = sig_ht.xmss_sigs[0].clone();
let mut node = xmss::xmss_pk_from_sig(hashers, idx_leaf, &sig_tmp, m, pk_seed, &adrs);
for j in 1..d32 {
let idx_leaf = u32::try_from(idx_tree & ((1 << hp32) - 1));
if idx_leaf.is_err() {
return false;
};
let idx_leaf = idx_leaf.unwrap();
idx_tree >>= hp32;
adrs.set_layer_address(j);
adrs.set_tree_address(idx_tree);
let sig_tmp = sig_ht.xmss_sigs[j as usize].clone();
node = xmss::xmss_pk_from_sig(hashers, idx_leaf, &sig_tmp, &node, pk_seed, &adrs);
}
node == *pk_root }