diff --git a/src/algs.rs b/src/algs.rs
index 9ae4826..3ae77c9 100644
--- a/src/algs.rs
+++ b/src/algs.rs
@@ -7,10 +7,11 @@ use sha3::{
Shake256,
};
-use crate::types::{Adrs, WotsPk, WotsSig};
+use crate::types::{Adrs, HtSig, WotsPk, WotsSig, XmssSig};
use crate::types::{TREE, WOTS_HASH, WOTS_PK, WOTS_PRF};
use crate::Context;
+
/// Algorithm 1: `toInt(X, n)` on page 14.
/// Convert a byte string to an integer.
///
@@ -43,7 +44,7 @@ pub(crate) fn to_int(x: &[u8], n: usize) -> u64 {
/// Input: Integer `x`, string length `n`.
/// Output: Byte string of length `n` containing binary representation of `x` in big-endian byte-order.
pub(crate) fn to_byte(x: u64, n: usize) -> Vec {
- let mut s = vec![0u8; n]; // TODO revisit generic array
+ let mut s = vec![0u8; n]; // TODO revisit generic array
// 1: total ← x
let mut total = x;
@@ -73,7 +74,7 @@ pub(crate) fn to_byte(x: u64, n: usize) -> Vec {
/// Output: Array of `out_len` integers in the range `[0, . . . , 2^b − 1]`.
pub(crate) fn base_2b(x: &[u8], b: u32, out_len: usize) -> Vec {
assert!(x.len() >= out_len * b as usize / 8);
- let mut baseb = vec![0u64; out_len]; // TODO revisit GenericArray
+ let mut baseb = vec![0u64; out_len]; // TODO revisit GenericArray
// 1: in ← 0
let mut inn = 0;
@@ -228,6 +229,7 @@ pub(crate) fn wots_pkgen(
sk_adrs.set_key_pair_address(adrs.get_key_pair_address());
// 4: for i from 0 to len − 1 do
+ //#[allow(clippy::cast_possible_truncation)] // steps 5 and 7
for i in 0..context.len1 {
//
// 5: skADRS.setChainAddress(i)
@@ -240,7 +242,8 @@ pub(crate) fn wots_pkgen(
adrs.set_chain_address(i);
// 8: tmp[i] ← chain(sk, 0, w − 1, PK.seed, ADRS) ▷ Compute public value for chain i
- tmp[i] = chain(context, sk, 0, context.w - 1, pk_seed, &adrs).expect("chain broek!");
+ tmp[i as usize] =
+ chain(context, sk, 0, context.w - 1, pk_seed, &adrs).expect("chain broek!");
// 9: end for
}
@@ -269,9 +272,9 @@ pub(crate) fn wots_pkgen(
/// Output: WOTS+ signature sig.
#[allow(clippy::similar_names)]
pub(crate) fn wots_sign(
- context: &Context, m: &[u8], sk_seed: &[u8], pk_seed: &[u8], adrs: Adrs,
+ context: &Context, m: &[u8], sk_seed: &[u8], pk_seed: &[u8], adrs: &Adrs,
) -> WotsSig {
- let mut adrs = adrs;
+ let mut adrs = adrs.clone();
let mut sig: WotsSig = WotsSig::default();
// 1: csum ← 0
@@ -279,11 +282,11 @@ pub(crate) fn wots_sign(
// 2:
// 3: msg ← base_2b(M, lgw, len1) ▷ Convert message to base w
- let mut msg = base_2b(m, context.lgw, context.len1);
+ let mut msg = base_2b(m, context.lgw, context.len1 as usize);
// 4:
// 5: for i from 0 to len1 − 1 do ▷ Compute checksum
- for item in msg.iter().take(context.len1) {
+ for item in msg.iter().take(context.len1 as usize) {
//
// 6: csum ← csum + w − 1 − msg[i]
csum += context.w as u64 - 1 - item;
@@ -313,17 +316,17 @@ pub(crate) fn wots_sign(
sk_addrs.set_key_pair_address(adrs.get_key_pair_address());
// 15: for i from 0 to len − 1 do
- #[allow(clippy::cast_possible_truncation)] // step 19
+ #[allow(clippy::cast_possible_truncation)] // step 18/19
for (i, item) in msg.iter().enumerate().take(context.len) {
//
// 16: skADRS.setChainAddress(i)
- sk_addrs.set_chain_address(i);
+ sk_addrs.set_chain_address(i as u32);
// 17: sk ← PRF(PK.seed, SK.seed, skADRS) ▷ Compute secret value for chain i
let sk = prf(pk_seed, sk_seed, &sk_addrs);
// 18: ADRS.setChainAddress(i)
- adrs.set_chain_address(i);
+ adrs.set_chain_address(i as u32);
// 19: sig[i] ← chain(sk, 0, msg[i], PK.seed, ADRS) ▷ Compute signature value for chain i
sig.data[i] = chain(context, sk, 0, *item as usize, pk_seed, &adrs).unwrap();
@@ -352,11 +355,11 @@ pub(crate) fn wots_pk_from_sig(
// 2:
// 3: msg ← base_2b (M, lgw , len1 ) ▷ Convert message to base w
- let mut msg = base_2b(m, context.lgw, context.len1);
+ let mut msg = base_2b(m, context.lgw, context.len1 as usize);
// 4:
// 5: for i from 0 to len1 − 1 do ▷ Compute checksum
- for item in msg.iter().take(context.len1) {
+ for item in msg.iter().take(context.len1 as usize) {
//
// 6: csum ← csum + w − 1 − msg[i]
csum += context.w as u64 - 1 - item;
@@ -376,17 +379,18 @@ pub(crate) fn wots_pk_from_sig(
));
// 11: for i from 0 to len − 1 do
+ #[allow(clippy::cast_possible_truncation)] // steps 12 and 13
for i in 0..context.len {
//
// 12: ADRS.setChainAddress(i)
- adrs.set_chain_address(i);
+ adrs.set_chain_address(i as u32);
// 13: tmp[i] ← chain(sig[i], msg[i], w − 1 − msg[i], PK.seed, ADRS)
tmp[i] = chain(
context,
sig.data[i].clone(),
usize::try_from(msg[i]).unwrap(),
- context.w - 1 - usize::try_from(msg[i]).unwrap(),
+ context.w - 1 - msg[i] as usize,
pk_seed,
&adrs,
)
@@ -411,6 +415,7 @@ pub(crate) fn wots_pk_from_sig(
WotsPk(pk)
}
+
#[allow(clippy::similar_names)] // lnode and rnode
pub(crate) fn h(
pk_seed: &[u8], adrs: &Adrs, lnode: &[u8], rnode: &[u8],
@@ -435,14 +440,14 @@ pub(crate) fn h(
#[allow(clippy::similar_names)] // sk_seed and pk_seed
pub(crate) fn xmss_node(
context: &Context, sk_seed: &[u8], i: u32, z: u32, pk_seed: &[u8], adrs: &Adrs,
-) -> Option> {
+) -> Result, &'static str> {
let mut adrs = adrs.clone();
// 1: if z > h′ or i ≥ 2^{h −z} then
if (z > context.h_prime) | (i >= 2u32.pow(context.h - z)) {
//
// 2: return NULL
- return None;
+ return Err("Alg8: fail");
// 3: end if
}
@@ -454,7 +459,7 @@ pub(crate) fn xmss_node(
adrs.set_type_and_clear(WOTS_HASH);
// 6: ADRS.setKeyPairAddress(i)
- adrs.set_key_pair_address(i.to_be_bytes());
+ adrs.set_key_pair_address(i);
// 7: node ← wots_PKgen(SK.seed, PK.seed, ADRS)
wots_pkgen::(context, sk_seed, pk_seed, &adrs)
@@ -486,7 +491,7 @@ pub(crate) fn xmss_node(
};
// 16: return node
- Some(node)
+ Ok(node)
}
@@ -495,18 +500,41 @@ pub(crate) fn xmss_node(
///
/// Input: n-byte message `M`, secret seed `SK.seed`, index `idx`, public seed `PK.seed`, address `ADRS`.
/// Output: XMSS signature SIGXMSS = (sig ∥ AUTH).
-const _A9: u32 = 0;
-//
-// 1: for j from 0 to h′-1 do ▷ Build authentication path
-// 2: k ← idx/2 xor 1
-// 3: AUTH[j] ← xmss_node(SK.seed, k, j, PK.seed, ADRS)
-// 4: end for
-// 5:
-// 6: ADRS.setTypeAndClear(WOTS_HASH)
-// 7: ADRS.setKeyPairAddress(idx)
-// 8: sig ← wots_sign(M, SK.seed, PK.seed, ADRS)
-// 9: SIG_XMSS ← sig ∥ AUTH
-// 10: return SIG_XMSS
+#[allow(clippy::similar_names)] // sk_seed and pk_seed
+pub(crate) fn xmss_sign(
+ context: &Context, m: &[u8], sk_seed: &[u8], idx: u32, pk_seed: &[u8], adrs: &Adrs,
+) -> Result, &'static str> {
+ let mut adrs = adrs.clone();
+ let mut sig_xmss = XmssSig::default();
+
+ // 1: for j from 0 to h′-1 do ▷ Build authentication path
+ for j in 0..HP::to_u32() {
+ //
+ // 2: k ← idx/2 xor 1
+ let k = (idx / 2) ^ 1;
+
+ // 3: AUTH[j] ← xmss_node(SK.seed, k, j, PK.seed, ADRS)
+ sig_xmss.auth[j as usize] = xmss_node::(context, sk_seed, k, j, pk_seed, &adrs)?;
+
+ // 4: end for
+ }
+
+ // 5:
+ // 6: ADRS.setTypeAndClear(WOTS_HASH)
+ adrs.set_type_and_clear(WOTS_HASH);
+
+ // 7: ADRS.setKeyPairAddress(idx)
+ adrs.set_key_pair_address(idx);
+
+ // 8: sig ← wots_sign(M, SK.seed, PK.seed, ADRS)
+ sig_xmss.sig_wots = wots_sign(context, m, sk_seed, pk_seed, &adrs);
+
+ // 9: SIG_XMSS ← sig ∥ AUTH
+ // struct constructed above
+
+ // 10: return SIG_XMSS
+ Ok(sig_xmss)
+}
/// Algorithm 10: `xmss_PKFromSig(idx, SIG_XMSS, M, PK.seed, ADRS)`
@@ -515,27 +543,74 @@ const _A9: u32 = 0;
/// Input: Index `idx`, XMSS signature `SIG_XMSS = (sig ∥ AUTH)`, n-byte message `M`, public seed `PK.seed`,
/// address `ADRS`.
/// Output: n-byte root value `node[0]`.
-const _A10: u32 = 0;
-// 1: ADRS.setTypeAndClear(WOTS_HASH) ▷ Compute WOTS+ pk from WOTS+ sig
-// 2: ADRS.setKeyPairAddress(idx)
-// 3: sig ← SIG_XMSS .getWOTSSig() ▷ SIG_XMSS [0 : len · n]
-// 4: AUTH ← SIG_XMSS .getXMSSAUTH() ▷ SIG_XMSS [len · n : (len + h′) · n]
-// 5: node[0] ← wots_PKFromSig(sig, M, PK.seed, ADRS)
-// 6:
-// 7: ADRS.setTypeAndClear(TREE) ▷ Compute root from WOTS+ pk and AUTH
-// 8: ADRS.setTreeIndex(idx)
-// 9: for k from 0 to h′ − 1 do
-// 10: ADRS.setTreeHeight(k + 1)
-// 11: if idx/2^k is even then
-// 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2)
-// 13: node[1] ← H(PK.seed, ADRS, node[0] ∥ AUTH[k])
-// 14: else
-// 15: ADRS.setTreeIndex((ADRS.getTreeIndex() − 1)/2)
-// 16: node[1] ← H(PK.seed, ADRS, AUTH[k] ∥ node[0])
-// 17: end if
-// 18: node[0] ← node[1]
-// 19: end for
-// 20: return node[0]
+pub(crate) fn xmss_pk_from_sig(
+ context: &Context, idx: u32, sig_xmss: &XmssSig, m: &[u8], pk_seed: &[u8],
+ adrs: &Adrs,
+) -> GenericArray {
+ let mut adrs = adrs.clone();
+
+ // 1: ADRS.setTypeAndClear(WOTS_HASH) ▷ Compute WOTS+ pk from WOTS+ sig
+ adrs.set_type_and_clear(WOTS_HASH);
+
+ // 2: ADRS.setKeyPairAddress(idx)
+ adrs.set_chain_address(idx);
+
+ // 3: sig ← SIG_XMSS.getWOTSSig() ▷ SIG_XMSS [0 : len · n]
+ let sig = sig_xmss.get_wots_sig();
+
+ // 4: AUTH ← SIG_XMSS.getXMSSAUTH() ▷ SIG_XMSS [len · n : (len + h′) · n]
+ let auth = sig_xmss.get_xmss_auth();
+
+ // 5: node[0] ← wots_PKFromSig(sig, M, PK.seed, ADRS)
+ let mut node_0 = wots_pk_from_sig::(context, sig, m, pk_seed, &adrs)
+ .0
+ .clone();
+
+ // 6:
+ // 7: ADRS.setTypeAndClear(TREE) ▷ Compute root from WOTS+ pk and AUTH
+ adrs.set_type_and_clear(TREE);
+
+ // 8: ADRS.setTreeIndex(idx)
+ adrs.set_tree_index(idx);
+
+ // 9: for k from 0 to h′ − 1 do
+ for k in 0..HP::to_u32() {
+ //
+ // 10: ADRS.setTreeHeight(k + 1)
+ adrs.set_tree_height(k + 1);
+
+ // 11: if idx/2^k is even then
+ #[allow(clippy::if_not_else)] // Follows the algorithm as written
+ let node_1 = if (idx & 2_u32.pow(k)) != 0 {
+ // 12: ADRS.setTreeIndex(ADRS.getTreeIndex()/2)
+ let tmp = adrs.get_tree_index() / 2;
+ adrs.set_tree_index(tmp);
+
+ // 13: node[1] ← H(PK.seed, ADRS, node[0] ∥ AUTH[k])
+ h(pk_seed, &adrs, &node_0, &auth[k as usize])
+
+ // 14: else
+ } else {
+ //
+ // 15: ADRS.setTreeIndex((ADRS.getTreeIndex() − 1)/2)
+ let tmp = (adrs.get_tree_index() - 1) / 2;
+ adrs.set_tree_index(tmp);
+
+ // 16: node[1] ← H(PK.seed, ADRS, AUTH[k] ∥ node[0])
+ h(pk_seed, &adrs, &auth[k as usize], &node_0)
+
+ // 17: end if
+ };
+
+ // 18: node[0] ← node[1]
+ node_0 = node_1;
+
+ // 19: end for
+ }
+
+ // 20: return node[0]
+ node_0
+}
/// Algorithm 11: `ht_sign(M, SK.seed, PK.seed, idx_tree, idx_leaf)` on page 27.
@@ -544,26 +619,65 @@ const _A10: u32 = 0;
/// Input: Message `M`, private seed `SK.seed`, public seed `PK.seed`, tree index `idx_tree`, leaf
/// index `idx_leaf`.
/// Output: HT signature `SIG_HT`.
-const _A11: u32 = 0;
-// 1: ADRS ← toByte(0, 32)
-// 2:
-// 3: ADRS.setTreeAddress(idxtree)
-// 4: SIG_tmp ← xmss_sign(M, SK.seed, idxleaf, PK.seed, ADRS)
-// 5: SIG_HT ← SIG_tmp
-// 6: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, M, PK.seed, ADRS)
-// 7: for j from 1 to d − 1 do
-// 8: idx_leaf ← idx_tree mod 2^{h′} ▷ h′ least significant bits of idx_tree
-// 9: idx_tree ← idx_tree ≫ h′ ▷ Remove least significant h′ bits from idx_tree
-// 10: ADRS.setLayerAddress(j)
-// 11: ADRS.setTreeAddress(idx_tree)
-// 12: SIG_tmp ← xmss_sign(root, SK.seed, idx_leaf, PK.seed, ADRS)
-// 13: SIG_HT ← SIG_HT ∥ SIG_tmp
-// 14: if j < d − 1 then
-// 15: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, root, PK.seed, ADRS)
-// 16: end if
-// 17: end for
-// 18: return SIGHT
+#[allow(clippy::similar_names)] // sk_seed and pk_seed
+pub(crate) fn ht_sign(
+ context: &Context, m: &[u8], sk_seed: &[u8], pk_seed: &[u8], idx_tree: u32, idx_leaf: u32,
+) -> Result, &'static str> {
+ //
+ // 1: ADRS ← toByte(0, 32)
+ let mut adrs = Adrs::default();
+ // 2:
+ // 3: ADRS.setTreeAddress(idxtree)
+ adrs.set_tree_address(idx_tree);
+
+ // 4: SIG_tmp ← xmss_sign(M, SK.seed, idxleaf, PK.seed, ADRS)
+ let mut sig_tmp = xmss_sign::(context, m, sk_seed, idx_leaf, pk_seed, &adrs)?;
+
+ // 5: SIG_HT ← SIG_tmp
+ let mut sig_ht = HtSig::default();
+ sig_ht.xmss_sigs[0] = sig_tmp.clone();
+
+ // 6: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, M, PK.seed, ADRS)
+ let mut root = xmss_pk_from_sig::(context, idx_leaf, &sig_tmp, m, pk_seed, &adrs);
+
+ // 7: for j from 1 to d − 1 do
+ for j in 1..context.d {
+ //
+ // 8: idx_leaf ← idx_tree mod 2^{h′} ▷ h′ least significant bits of idx_tree
+ let idx_leaf = idx_tree % 2u32.pow(HP::to_u32());
+
+ // 9: idx_tree ← idx_tree ≫ h′ ▷ Remove least significant h′ bits from idx_tree
+ let idx_tree = idx_tree >> HP::to_u32();
+
+ // 10: ADRS.setLayerAddress(j)
+ adrs.set_layer_address(j);
+
+ // 11: ADRS.setTreeAddress(idx_tree)
+ adrs.set_tree_address(idx_tree);
+
+ // 12: SIG_tmp ← xmss_sign(root, SK.seed, idx_leaf, PK.seed, ADRS)
+ sig_tmp = xmss_sign::(context, &root, sk_seed, idx_leaf, pk_seed, &adrs)?;
+
+ // 13: SIG_HT ← SIG_HT ∥ SIG_tmp
+ sig_ht.xmss_sigs[j as usize] = sig_tmp.clone();
+
+ // 14: if j < d − 1 then
+ if j < (context.d - 1) {
+ //
+ // 15: root ← xmss_PKFromSig(idx_leaf, SIG_tmp, root, PK.seed, ADRS)
+ root =
+ xmss_pk_from_sig::(context, idx_leaf, &sig_tmp, &root, pk_seed, &adrs);
+
+ // 16: end if
+ }
+
+ // 17: end for
+ }
+
+ // 18: return SIGHT
+ Ok(sig_ht)
+}
/// Algorithm 12: `ht_verify(M, SIG_HT, PK.seed, idx_tree, idx_leaf, PK.root)` on page 28.
/// Verify a hypertree signature.
@@ -571,25 +685,55 @@ const _A11: u32 = 0;
/// Input: Message `M`, signature `SIG_HT`, public seed `PK.seed`, tree index `idx_tree`, leaf index `idx_leaf`,
/// HT public key `PK.root`.
/// Output: Boolean.
-const _A12: u32 = 0;
-// 1: ADRS ← toByte(0, 32)
-// 2:
-// 3: ADRS.setTreeAddress(idx_tree)
-// 4: SIG_tmp ← SIG_HT.getXMSSSignature(0) ▷ SIG_HT [0 : (h′ + len) · n]
-// 5: node ← xmss_PKFromSig(idx_leaf, SIG_tmp, M, PK.seed, ADRS)
-// 6: for j from 1 to d − 1 do
-// 7: idx_leaf ← idx_tree mod 2^{h′} ▷ h′ least significant bits of idx_tree
-// 8: idx_tree ← idx_tree ≫ h′ ▷ Remove least significant h′ bits from idx_tree
-// 9: ADRS.setLayerAddress(j)
-// 10: ADRS.setTreeAddress(idx_tree)
-// 11: SIG_tmp ← SIG_HT.getXMSSSignature(j) ▷ SIGHT [ j · (h′ + len) · n : ( j + 1)(h′ + len) · n]
-// 12: node ← xmss_PKFromSig(idx_leaf, SIG_tmp, node, PK.seed, ADRS)
-// 13: end for
-// 14: if node = PK.root then
-// 15: return true
-// 16: else
-// 17: return false
-// 18: end if
+pub(crate) fn ht_verify(
+ context: &Context, m: &[u8], sig_ht: &HtSig, pk_seed: &[u8], idx_tree: u32,
+ idx_leaf: u32, pk_root: &GenericArray,
+) -> bool {
+ //
+ // 1: ADRS ← toByte(0, 32)
+ let mut adrs = Adrs::default();
+
+ // 2:
+ // 3: ADRS.setTreeAddress(idx_tree)
+ adrs.set_tree_address(idx_tree);
+
+ // 4: SIG_tmp ← SIG_HT.getXMSSSignature(0) ▷ SIG_HT [0 : (h′ + len) · n]
+ let sig_tmp = sig_ht.xmss_sigs[0].clone();
+
+ // 5: node ← xmss_PKFromSig(idx_leaf, SIG_tmp, M, PK.seed, ADRS)
+ let mut node = xmss_pk_from_sig(context, idx_leaf, &sig_tmp, m, pk_seed, &adrs);
+
+ // 6: for j from 1 to d − 1 do
+ for j in 1..(context.d) {
+ //
+ // 7: idx_leaf ← idx_tree mod 2^{h′} ▷ h′ least significant bits of idx_tree
+ let idx_leaf = idx_tree % 2u32.pow(HP::to_u32());
+
+ // 8: idx_tree ← idx_tree ≫ h′ ▷ Remove least significant h′ bits from idx_tree
+ let idx_tree = idx_tree >> HP::to_u32();
+
+ // 9: ADRS.setLayerAddress(j)
+ adrs.set_layer_address(j);
+
+ // 10: ADRS.setTreeAddress(idx_tree)
+ adrs.set_tree_address(idx_tree);
+
+ // 11: SIG_tmp ← SIG_HT.getXMSSSignature(j) ▷ SIGHT [ j · (h′ + len) · n : ( j + 1)(h′ + len) · n]
+ let sig_tmp = sig_ht.xmss_sigs[j as usize].clone();
+
+ // 12: node ← xmss_PKFromSig(idx_leaf, SIG_tmp, node, PK.seed, ADRS)
+ node = xmss_pk_from_sig(context, idx_leaf, &sig_tmp, &node, pk_seed, &adrs);
+
+ // 13: end for
+ }
+
+ // 14: if node = PK.root then
+ // 15: return true
+ // 16: else
+ // 17: return false
+ // 18: end if
+ node == *pk_root
+}
/// Algorithm 13: `fors_SKgen(SK.seed, PK.seed, ADRS, idx)` on page 29.
diff --git a/src/lib.rs b/src/lib.rs
index fecfd84..a6e09c8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -8,7 +8,6 @@
extern crate alloc;
-
mod algs;
mod traits;
mod types;
@@ -20,14 +19,14 @@ pub fn add(left: usize, right: usize) -> usize { left + right }
struct Context {
lgw: u32,
w: usize,
- len1: usize,
+ len1: u32,
len2: usize,
len: usize,
h: u32,
h_prime: u32,
+ d: u32,
}
-
macro_rules! functionality {
() => {
use crate::traits::PK;
@@ -45,15 +44,18 @@ macro_rules! functionality {
static CONTEXT: Context = Context {
lgw: LGW,
w: W,
- len1: LEN1,
+ len1: LEN1 as u32,
len2: LEN2,
len: LEN,
h: H,
h_prime: H_PRIME,
+ d: D,
};
-
- fn sign() -> SlhDsaSig { SlhDsaSig::::default() }
+ // Dummy placeholder TODO: fix
+ fn sign() -> SlhDsaSig {
+ SlhDsaSig::::default()
+ }
/// Correctly sized private key specific to the target security parameter set.
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
@@ -90,7 +92,6 @@ pub mod slh_dsa_sha2_128s {
functionality!();
}
-
/// TKTK
#[cfg(feature = "slh_dsa_shake_128s")]
pub mod slh_dsa_shake_128s {
@@ -145,7 +146,6 @@ pub mod slh_dsa_shake_128f {
functionality!();
}
-
/// TKTK
#[cfg(feature = "slh_dsa_sha2_192s")]
pub mod slh_dsa_sha2_192s {
@@ -164,7 +164,6 @@ pub mod slh_dsa_sha2_192s {
functionality!();
}
-
/// TKTK
#[cfg(feature = "slh_dsa_shake_192s")]
pub mod slh_dsa_shake_192s {
@@ -219,7 +218,6 @@ pub mod slh_dsa_shake_192f {
functionality!();
}
-
/// TKTK
#[cfg(feature = "slh_dsa_sha2_256s")]
pub mod slh_dsa_sha2_256s {
@@ -238,7 +236,6 @@ pub mod slh_dsa_sha2_256s {
functionality!();
}
-
/// TKTK
#[cfg(feature = "slh_dsa_shake_256s")]
pub mod slh_dsa_shake_256s {
@@ -293,7 +290,6 @@ pub mod slh_dsa_shake_256f {
functionality!();
}
-
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/types.rs b/src/types.rs
index 867376b..b433859 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -2,16 +2,21 @@ use alloc::vec::Vec;
use generic_array::{ArrayLength, GenericArray};
use zeroize::{Zeroize, ZeroizeOnDrop};
-
/// Fig 16 on page 34
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
-pub struct SlhDsaSig {
+pub struct SlhDsaSig<
+ A: ArrayLength,
+ D: ArrayLength,
+ HP: ArrayLength,
+ K: ArrayLength,
+ LEN: ArrayLength,
+ N: ArrayLength,
+> {
randomness: GenericArray,
fors_sig: ForsSig,
- ht_sig: HtSig,
+ ht_sig: HtSig,
}
-
/// Fig 13 on page 29
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
pub(crate) struct ForsSig {
@@ -19,20 +24,17 @@ pub(crate) struct ForsSig {
auth: GenericArray, K>,
}
-
/// Fig 10?
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
pub(crate) struct Auth {
tree: GenericArray, A>,
}
-
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
-pub(crate) struct HtSig {
- x: GenericArray,
+pub(crate) struct HtSig {
+ pub(crate) xmss_sigs: GenericArray, D>,
}
-
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
pub struct WotsSig {
pub(crate) data: GenericArray, LEN>,
@@ -42,6 +44,18 @@ pub struct WotsSig {
pub struct WotsPk(pub(crate) GenericArray);
+#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
+pub struct XmssSig {
+ pub(crate) sig_wots: WotsSig,
+ pub(crate) auth: GenericArray, HP>,
+}
+
+impl XmssSig {
+ pub(crate) fn get_wots_sig(&self) -> &WotsSig { &self.sig_wots }
+
+ pub(crate) fn get_xmss_auth(&self) -> &GenericArray, HP> { &self.auth }
+}
+
pub(crate) const WOTS_HASH: u32 = 0;
pub(crate) const WOTS_PK: u32 = 1;
pub(crate) const TREE: u32 = 2;
@@ -50,7 +64,6 @@ const FORS_ROOTS: u32 = 4;
pub(crate) const WOTS_PRF: u32 = 5;
const FORS_PRF: u32 = 6;
-
/// Straddling the line between struct, enum and union...
#[derive(Clone, Default, Zeroize, ZeroizeOnDrop)]
#[repr(align(32))]
@@ -65,14 +78,15 @@ pub struct Adrs {
f7: [u8; 4], // hash address OR padding OR tree index OR hash address = 0
}
-
impl Adrs {
- pub(crate) fn get_key_pair_address(&self) -> [u8; 4] { self.f5 }
+ pub(crate) fn set_layer_address(&mut self, la: u32) { self.f0 = la.to_be_bytes() }
- pub(crate) fn set_key_pair_address(&mut self, kp_addr: [u8; 4]) { self.f5 = kp_addr; }
+ 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(); }
#[allow(clippy::cast_possible_truncation)]
- pub(crate) fn set_chain_address(&mut self, i: usize) { self.f6 = (i as u32).to_be_bytes(); }
+ pub(crate) fn set_chain_address(&mut self, i: u32) { self.f6 = i.to_be_bytes(); }
pub(crate) fn set_type_and_clear(&mut self, type_t: u32) {
self.f4 = type_t.to_be_bytes();
@@ -81,10 +95,16 @@ impl Adrs {
self.f7 = 0u32.to_be_bytes();
}
+ pub(crate) fn set_tree_address(&mut self, t: u32) { self.f1 = t.to_be_bytes() }
+
+ // TODO: revisit 16 bytes
+
pub(crate) fn set_hash_address(&mut self, addr: u32) { self.f7 = addr.to_be_bytes() }
pub(crate) fn set_tree_height(&mut self, z: u32) { self.f6 = z.to_be_bytes() }
+ pub(crate) fn get_tree_index(&mut self) -> u32 { u32::from_be_bytes(self.f7) }
+
pub(crate) fn set_tree_index(&mut self, i: u32) { self.f7 = i.to_be_bytes() }
pub(crate) fn to_bytes(&self) -> Vec { [self.f0, self.f1, self.f2, self.f3].concat() }