2024-01-25 21:17:18 +00:00
|
|
|
//use alloc::vec::Vec;
|
2024-01-13 22:45:33 +00:00
|
|
|
use generic_array::{ArrayLength, GenericArray};
|
2024-01-12 23:22:21 +00:00
|
|
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
|
|
|
|
|
2024-01-13 22:45:33 +00:00
|
|
|
/// Fig 16 on page 34
|
2024-01-25 02:42:54 +00:00
|
|
|
#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
|
2024-01-16 02:08:41 +00:00
|
|
|
pub struct SlhDsaSig<
|
|
|
|
|
A: ArrayLength,
|
|
|
|
|
D: ArrayLength,
|
|
|
|
|
HP: ArrayLength,
|
|
|
|
|
K: ArrayLength,
|
|
|
|
|
LEN: ArrayLength,
|
|
|
|
|
N: ArrayLength,
|
|
|
|
|
> {
|
2024-01-17 01:00:05 +00:00
|
|
|
pub(crate) randomness: GenericArray<u8, N>,
|
|
|
|
|
pub(crate) fors_sig: ForsSig<A, K, N>,
|
|
|
|
|
pub(crate) ht_sig: HtSig<D, HP, LEN, N>,
|
2024-01-13 22:45:33 +00:00
|
|
|
}
|
|
|
|
|
|
2024-01-25 02:42:54 +00:00
|
|
|
impl<
|
2024-01-25 21:17:18 +00:00
|
|
|
A: ArrayLength,
|
|
|
|
|
D: ArrayLength,
|
|
|
|
|
HP: ArrayLength,
|
|
|
|
|
K: ArrayLength,
|
|
|
|
|
LEN: ArrayLength,
|
|
|
|
|
N: ArrayLength,
|
|
|
|
|
> SlhDsaSig<A, D, HP, K, LEN, N>
|
|
|
|
|
{
|
2024-01-26 02:55:05 +00:00
|
|
|
pub fn deserialize<const SIG_LEN: usize>(self) -> [u8; SIG_LEN] {
|
|
|
|
|
let mut out = [0u8; SIG_LEN];
|
|
|
|
|
debug_assert_eq!(
|
2024-01-25 21:17:18 +00:00
|
|
|
out.len(),
|
|
|
|
|
N::to_usize() + // randomness
|
2024-01-25 02:42:54 +00:00
|
|
|
N::to_usize() * K::to_usize() + K::to_usize() * A::to_usize() * N::to_usize() + // ForsSig
|
|
|
|
|
D::to_usize() * (HP::to_usize() * N::to_usize() + LEN::to_usize() * N::to_usize())
|
|
|
|
|
);
|
|
|
|
|
out[0..N::to_usize()].copy_from_slice(&self.randomness);
|
|
|
|
|
let mut start = N::to_usize();
|
|
|
|
|
for k in 0..K::to_usize() {
|
2024-01-25 21:17:18 +00:00
|
|
|
out[start..(start + N::to_usize())]
|
|
|
|
|
.copy_from_slice(&self.fors_sig.private_key_value[k]);
|
2024-01-25 02:42:54 +00:00
|
|
|
start += N::to_usize();
|
|
|
|
|
for a in 0..A::to_usize() {
|
2024-01-25 21:17:18 +00:00
|
|
|
out[start..(start + N::to_usize())].copy_from_slice(&self.fors_sig.auth[k].tree[a]);
|
2024-01-25 02:42:54 +00:00
|
|
|
start += N::to_usize();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for d in 0..D::to_usize() {
|
2024-01-25 21:17:18 +00:00
|
|
|
//println!("and we move to xmss {} starting at {}", d, start);
|
2024-01-25 02:42:54 +00:00
|
|
|
for len in 0..LEN::to_usize() {
|
2024-01-25 21:17:18 +00:00
|
|
|
out[start..(start + N::to_usize())]
|
|
|
|
|
.copy_from_slice(&self.ht_sig.xmss_sigs[d].sig_wots.data[len]);
|
2024-01-25 02:42:54 +00:00
|
|
|
start += N::to_usize();
|
|
|
|
|
}
|
|
|
|
|
for hp in 0..HP::to_usize() {
|
2024-01-25 21:17:18 +00:00
|
|
|
out[start..(start + N::to_usize())]
|
|
|
|
|
.copy_from_slice(&self.ht_sig.xmss_sigs[d].auth[hp]);
|
2024-01-25 02:42:54 +00:00
|
|
|
start += N::to_usize();
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-25 21:17:18 +00:00
|
|
|
debug_assert_eq!(start, out.len());
|
2024-01-26 02:55:05 +00:00
|
|
|
out
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn serialize(bytes: &[u8]) -> Self {
|
|
|
|
|
debug_assert_eq!(
|
|
|
|
|
bytes.len(),
|
|
|
|
|
N::to_usize() + // randomness
|
|
|
|
|
N::to_usize() * K::to_usize() + K::to_usize() * A::to_usize() * N::to_usize() + // ForsSig
|
|
|
|
|
D::to_usize() * (HP::to_usize() * N::to_usize() + LEN::to_usize() * N::to_usize())
|
|
|
|
|
);
|
|
|
|
|
let mut output = Self::default();
|
|
|
|
|
output.randomness.copy_from_slice(&bytes[0..N::to_usize()]);
|
|
|
|
|
let mut start = N::to_usize();
|
|
|
|
|
for k in 0..K::to_usize() {
|
|
|
|
|
output.fors_sig.private_key_value[k]
|
|
|
|
|
.copy_from_slice(&bytes[start..(start + N::to_usize())]);
|
|
|
|
|
start += N::to_usize();
|
|
|
|
|
for a in 0..A::to_usize() {
|
|
|
|
|
output.fors_sig.auth[k].tree[a]
|
|
|
|
|
.copy_from_slice(&bytes[start..(start + N::to_usize())]);
|
|
|
|
|
start += N::to_usize();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for d in 0..D::to_usize() {
|
|
|
|
|
for len in 0..LEN::to_usize() {
|
|
|
|
|
output.ht_sig.xmss_sigs[d].sig_wots.data[len]
|
|
|
|
|
.copy_from_slice(&bytes[start..(start + N::to_usize())]);
|
|
|
|
|
start += N::to_usize();
|
|
|
|
|
}
|
|
|
|
|
for hp in 0..HP::to_usize() {
|
|
|
|
|
output.ht_sig.xmss_sigs[d].auth[hp]
|
|
|
|
|
.copy_from_slice(&bytes[start..(start + N::to_usize())]);
|
|
|
|
|
start += N::to_usize();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
debug_assert_eq!(start, bytes.len());
|
|
|
|
|
output
|
2024-01-25 02:42:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-26 02:55:05 +00:00
|
|
|
|
2024-01-17 01:00:05 +00:00
|
|
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
|
|
|
|
pub struct SlhPublicKey<N: ArrayLength> {
|
|
|
|
|
pub(crate) pk_seed: GenericArray<u8, N>,
|
|
|
|
|
pub(crate) pk_root: GenericArray<u8, N>,
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-09 21:28:59 +00:00
|
|
|
#[allow(dead_code)]
|
|
|
|
|
impl<N: ArrayLength> SlhPublicKey<N> {
|
|
|
|
|
pub fn serialize<const PK_LEN: usize>(self) -> [u8; PK_LEN] {
|
|
|
|
|
let mut out = [0u8; PK_LEN];
|
|
|
|
|
debug_assert_eq!(out.len(), 2 * N::to_usize());
|
|
|
|
|
out[0..N::to_usize()].copy_from_slice(&self.pk_seed);
|
|
|
|
|
out[N::to_usize()..2 * N::to_usize()].copy_from_slice(&self.pk_root);
|
|
|
|
|
out
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn deserialize<const PK_LEN: usize>(bytes: [u8; PK_LEN]) -> Self {
|
|
|
|
|
let mut pub_key = Self::default();
|
|
|
|
|
pub_key.pk_seed.copy_from_slice(&bytes[0..N::to_usize()]);
|
|
|
|
|
pub_key
|
|
|
|
|
.pk_root
|
|
|
|
|
.copy_from_slice(&bytes[N::to_usize()..2 * N::to_usize()]);
|
|
|
|
|
pub_key
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
|
2024-01-17 01:00:05 +00:00
|
|
|
pub struct SlhPrivateKey<N: ArrayLength> {
|
|
|
|
|
pub(crate) sk_seed: GenericArray<u8, N>,
|
|
|
|
|
pub(crate) sk_prf: GenericArray<u8, N>,
|
|
|
|
|
pub(crate) pk_seed: GenericArray<u8, N>,
|
|
|
|
|
pub(crate) pk_root: GenericArray<u8, N>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-01-13 22:45:33 +00:00
|
|
|
/// Fig 13 on page 29
|
2024-01-25 02:42:54 +00:00
|
|
|
#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
|
2024-01-13 22:45:33 +00:00
|
|
|
pub(crate) struct ForsSig<A: ArrayLength, K: ArrayLength, N: ArrayLength> {
|
2024-01-17 01:00:05 +00:00
|
|
|
pub(crate) private_key_value: GenericArray<GenericArray<u8, N>, K>,
|
|
|
|
|
pub(crate) auth: GenericArray<Auth<A, N>, K>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
|
|
|
|
pub(crate) struct ForsPk<N: ArrayLength> {
|
|
|
|
|
pub(crate) key: GenericArray<u8, N>,
|
2024-01-13 22:45:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Fig 10?
|
2024-01-25 02:42:54 +00:00
|
|
|
#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
|
2024-01-13 22:45:33 +00:00
|
|
|
pub(crate) struct Auth<A: ArrayLength, N: ArrayLength> {
|
2024-01-17 01:00:05 +00:00
|
|
|
pub(crate) tree: GenericArray<GenericArray<u8, N>, A>,
|
2024-01-13 22:45:33 +00:00
|
|
|
}
|
|
|
|
|
|
2024-01-25 02:42:54 +00:00
|
|
|
#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
|
2024-01-16 02:08:41 +00:00
|
|
|
pub(crate) struct HtSig<D: ArrayLength, HP: ArrayLength, LEN: ArrayLength, N: ArrayLength> {
|
|
|
|
|
pub(crate) xmss_sigs: GenericArray<XmssSig<HP, LEN, N>, D>,
|
2024-01-13 22:45:33 +00:00
|
|
|
}
|
|
|
|
|
|
2024-01-25 02:42:54 +00:00
|
|
|
#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
|
2024-01-14 21:37:30 +00:00
|
|
|
pub struct WotsSig<LEN: ArrayLength, N: ArrayLength> {
|
2024-01-13 23:10:25 +00:00
|
|
|
pub(crate) data: GenericArray<GenericArray<u8, N>, LEN>,
|
2024-01-13 22:45:33 +00:00
|
|
|
}
|
|
|
|
|
|
2024-01-14 21:37:30 +00:00
|
|
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
|
|
|
|
pub struct WotsPk<N: ArrayLength>(pub(crate) GenericArray<u8, N>);
|
|
|
|
|
|
2024-01-13 22:45:33 +00:00
|
|
|
|
2024-01-25 02:42:54 +00:00
|
|
|
#[derive(Clone, Debug, Default, Zeroize, ZeroizeOnDrop)]
|
2024-01-16 02:08:41 +00:00
|
|
|
pub struct XmssSig<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength> {
|
|
|
|
|
pub(crate) sig_wots: WotsSig<LEN, N>,
|
|
|
|
|
pub(crate) auth: GenericArray<GenericArray<u8, N>, HP>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<HP: ArrayLength, LEN: ArrayLength, N: ArrayLength> XmssSig<HP, LEN, N> {
|
|
|
|
|
pub(crate) fn get_wots_sig(&self) -> &WotsSig<LEN, N> { &self.sig_wots }
|
|
|
|
|
|
|
|
|
|
pub(crate) fn get_xmss_auth(&self) -> &GenericArray<GenericArray<u8, N>, HP> { &self.auth }
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-14 21:37:30 +00:00
|
|
|
pub(crate) const WOTS_HASH: u32 = 0;
|
2024-01-12 23:22:21 +00:00
|
|
|
pub(crate) const WOTS_PK: u32 = 1;
|
2024-01-14 21:37:30 +00:00
|
|
|
pub(crate) const TREE: u32 = 2;
|
2024-01-17 01:00:05 +00:00
|
|
|
pub(crate) const FORS_TREE: u32 = 3;
|
|
|
|
|
pub(crate) const FORS_ROOTS: u32 = 4;
|
2024-01-12 23:22:21 +00:00
|
|
|
pub(crate) const WOTS_PRF: u32 = 5;
|
2024-01-17 01:00:05 +00:00
|
|
|
pub(crate) const FORS_PRF: u32 = 6;
|
2024-01-12 23:22:21 +00:00
|
|
|
|
|
|
|
|
/// Straddling the line between struct, enum and union...
|
|
|
|
|
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
|
|
|
|
|
#[repr(align(32))]
|
2024-01-13 23:10:25 +00:00
|
|
|
pub struct Adrs {
|
2024-01-12 23:22:21 +00:00
|
|
|
f0: [u8; 4], // layer address
|
|
|
|
|
f1: [u8; 4], // tree address (LSB?)
|
|
|
|
|
f2: [u8; 4], // tree address
|
|
|
|
|
f3: [u8; 4], // tree address (MSB)
|
|
|
|
|
f4: [u8; 4], // type
|
|
|
|
|
f5: [u8; 4], // key pair address OR padding
|
|
|
|
|
f6: [u8; 4], // chain address OR padding OR tree height
|
2024-01-14 21:37:30 +00:00
|
|
|
f7: [u8; 4], // hash address OR padding OR tree index OR hash address = 0
|
2024-01-12 23:22:21 +00:00
|
|
|
}
|
|
|
|
|
|
2024-01-13 23:10:25 +00:00
|
|
|
impl Adrs {
|
2024-01-16 02:08:41 +00:00
|
|
|
pub(crate) fn set_layer_address(&mut self, la: u32) { self.f0 = la.to_be_bytes() }
|
2024-01-12 23:22:21 +00:00
|
|
|
|
2024-01-16 02:08:41 +00:00
|
|
|
pub(crate) fn get_key_pair_address(&self) -> u32 { u32::from_be_bytes(self.f5) }
|
|
|
|
|
|
|
|
|
|
pub(crate) fn set_key_pair_address(&mut self, kp_addr: u32) { self.f5 = kp_addr.to_be_bytes(); }
|
2024-01-12 23:22:21 +00:00
|
|
|
|
2024-01-13 23:10:25 +00:00
|
|
|
#[allow(clippy::cast_possible_truncation)]
|
2024-01-16 02:08:41 +00:00
|
|
|
pub(crate) fn set_chain_address(&mut self, i: u32) { self.f6 = i.to_be_bytes(); }
|
2024-01-12 23:22:21 +00:00
|
|
|
|
|
|
|
|
pub(crate) fn set_type_and_clear(&mut self, type_t: u32) {
|
|
|
|
|
self.f4 = type_t.to_be_bytes();
|
|
|
|
|
self.f5 = 0u32.to_be_bytes();
|
|
|
|
|
self.f6 = 0u32.to_be_bytes();
|
|
|
|
|
self.f7 = 0u32.to_be_bytes();
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-25 21:17:18 +00:00
|
|
|
#[allow(clippy::cast_possible_truncation)]
|
|
|
|
|
pub(crate) fn set_tree_address(&mut self, t: u64) {
|
|
|
|
|
self.f2 = ((t >> 32) as u32).to_be_bytes();
|
|
|
|
|
self.f3 = (t as u32).to_be_bytes();
|
|
|
|
|
}
|
2024-01-16 02:08:41 +00:00
|
|
|
|
|
|
|
|
// TODO: revisit 16 bytes
|
|
|
|
|
|
2024-01-14 21:37:30 +00:00
|
|
|
pub(crate) fn set_hash_address(&mut self, addr: u32) { self.f7 = addr.to_be_bytes() }
|
2024-01-12 23:22:21 +00:00
|
|
|
|
2024-01-14 21:37:30 +00:00
|
|
|
pub(crate) fn set_tree_height(&mut self, z: u32) { self.f6 = z.to_be_bytes() }
|
|
|
|
|
|
2024-01-16 02:08:41 +00:00
|
|
|
pub(crate) fn get_tree_index(&mut self) -> u32 { u32::from_be_bytes(self.f7) }
|
|
|
|
|
|
2024-01-14 21:37:30 +00:00
|
|
|
pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() }
|
|
|
|
|
|
2024-01-25 21:17:18 +00:00
|
|
|
pub(crate) fn to_32_bytes(&self) -> [u8; 32] {
|
|
|
|
|
let mut ret = [0u8; 32];
|
|
|
|
|
let mut start = 0;
|
|
|
|
|
for sl in [
|
|
|
|
|
self.f0, self.f1, self.f2, self.f3, self.f4, self.f5, self.f6, self.f7,
|
|
|
|
|
] {
|
|
|
|
|
ret[start..start + 4].copy_from_slice(&sl);
|
|
|
|
|
start += 4;
|
|
|
|
|
}
|
|
|
|
|
ret
|
|
|
|
|
}
|
2024-02-03 16:17:59 +00:00
|
|
|
|
|
|
|
|
pub(crate) fn to_22_bytes(&self) -> [u8; 22] {
|
|
|
|
|
let mut ret = [0u8; 22];
|
|
|
|
|
ret[0] = self.f0[3];
|
|
|
|
|
ret[1..5].copy_from_slice(&self.f2);
|
|
|
|
|
ret[5..9].copy_from_slice(&self.f3);
|
|
|
|
|
ret[9] = self.f4[3];
|
|
|
|
|
ret[10..14].copy_from_slice(&self.f5);
|
|
|
|
|
ret[14..18].copy_from_slice(&self.f6);
|
|
|
|
|
ret[18..22].copy_from_slice(&self.f7);
|
|
|
|
|
ret
|
|
|
|
|
}
|
2024-01-12 23:22:21 +00:00
|
|
|
}
|