From 4ca515d13c16e84c37290d389f395fa6d97b0faf Mon Sep 17 00:00:00 2001 From: TechnoPorg Date: Mon, 5 Oct 2026 12:14:13 -0400 Subject: [PATCH 1/4] lms: make no_std --- lms/src/lib.rs | 7 +++++-- lms/src/lms/error.rs | 4 ++-- lms/src/lms/modes.rs | 8 ++++---- lms/src/lms/private.rs | 6 +++--- lms/src/lms/public.rs | 10 +++++----- lms/src/lms/signature.rs | 5 +++-- lms/src/ots/error.rs | 4 ++-- lms/src/ots/mod.rs | 2 +- lms/src/ots/modes.rs | 2 +- lms/src/ots/private.rs | 2 +- lms/src/ots/public.rs | 6 +++--- lms/src/ots/signature.rs | 6 +++--- lms/src/ots/util.rs | 2 +- 13 files changed, 34 insertions(+), 30 deletions(-) diff --git a/lms/src/lib.rs b/lms/src/lib.rs index ca7314cd..1cebeeaf 100644 --- a/lms/src/lib.rs +++ b/lms/src/lib.rs @@ -1,5 +1,3 @@ -#![warn(unreachable_pub)] - //! LMS in Rust //! //! This is a strongly typed implementation of Leighton-Micali signatures. You @@ -7,6 +5,11 @@ //! their respective crates. See [lms] for anything LMS related and [ots] for //! anything LM-OTS related. +#![warn(unreachable_pub)] +#![cfg_attr(not(test), no_std)] + +extern crate alloc; + pub mod error; pub mod lms; pub mod ots; diff --git a/lms/src/lms/error.rs b/lms/src/lms/error.rs index 0367de01..055623fc 100644 --- a/lms/src/lms/error.rs +++ b/lms/src/lms/error.rs @@ -1,7 +1,7 @@ //! LMS Signing error -use std::error::Error; -use std::fmt::{Display, Formatter, Result}; +use core::error::Error; +use core::fmt::{Display, Formatter, Result}; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct LmsOutOfPrivateKeys {} diff --git a/lms/src/lms/modes.rs b/lms/src/lms/modes.rs index e869c024..8d13d784 100644 --- a/lms/src/lms/modes.rs +++ b/lms/src/lms/modes.rs @@ -1,13 +1,13 @@ //! LMS modes use crate::ots::modes::LmsOtsMode; use crate::types::Typecode; -use digest::Digest; -use hybrid_array::ArraySize; -use std::ops::Add; -use std::{ +use core::ops::Add; +use core::{ marker::PhantomData, ops::{Shl, Sub}, }; +use digest::Digest; +use hybrid_array::ArraySize; use typenum::{Add1, Shleft, Sub1, U1, U5, U10, U15, U20, U25, bit::B1}; /// The basic trait that must be implemented for any valid LMS mode diff --git a/lms/src/lms/private.rs b/lms/src/lms/private.rs index 59da5050..37d55e76 100644 --- a/lms/src/lms/private.rs +++ b/lms/src/lms/private.rs @@ -11,8 +11,8 @@ use rand_core::{CryptoRng, TryCryptoRng}; use signature::{Error, RandomizedMultipartSignerMut, RandomizedSignerMut}; use core::array::TryFromSliceError; -use std::cmp::Ordering; -use std::ops::Add; +use core::cmp::Ordering; +use core::ops::Add; use typenum::{Sum, U28}; /// Opaque struct representing a LMS private key @@ -154,7 +154,7 @@ where fn from(pk: SigningKey) -> Self { // Return u32(type) || u32(otstype) || u32(q) || id || seed Array::try_from_iter( - std::iter::empty() + core::iter::empty() .chain(Mode::TYPECODE.to_be_bytes()) .chain(Mode::OtsMode::TYPECODE.to_be_bytes()) .chain(pk.q.to_be_bytes()) diff --git a/lms/src/lms/public.rs b/lms/src/lms/public.rs index 6c366d2f..9c9f4446 100644 --- a/lms/src/lms/public.rs +++ b/lms/src/lms/public.rs @@ -1,5 +1,5 @@ -use std::cmp::Ordering; -use std::ops::Add; +use core::cmp::Ordering; +use core::ops::Add; use crate::constants::{D_LEAF, ID_LEN}; @@ -113,7 +113,7 @@ where fn from(pk: VerifyingKey) -> Self { // Return u32(type) || u32(otstype) || id || k Array::try_from_iter( - std::iter::empty() + core::iter::empty() .chain(Mode::TYPECODE.to_be_bytes()) .chain(Mode::OtsMode::TYPECODE.to_be_bytes()) .chain(pk.id) @@ -162,7 +162,7 @@ impl<'a, Mode: LmsMode> TryFrom<&'a [u8]> for VerifyingKey { #[cfg(test)] mod tests { - use std::ops::Add; + use core::ops::Add; use crate::{ lms::SigningKey, @@ -261,7 +261,7 @@ mod tests { fn test_serialize_deserialize_random() where - VerifyingKey: std::fmt::Debug, + VerifyingKey: core::fmt::Debug, ::OutputSize: Add, Sum<::OutputSize, U24>: ArraySize, { diff --git a/lms/src/lms/signature.rs b/lms/src/lms/signature.rs index 4ee43715..5278a897 100644 --- a/lms/src/lms/signature.rs +++ b/lms/src/lms/signature.rs @@ -7,7 +7,8 @@ use crate::ots::modes::LmsOtsMode; use hybrid_array::{Array, ArraySize}; use signature::SignatureEncoding; -use std::{ +use alloc::vec::Vec; +use core::{ cmp::Ordering, ops::{Add, Mul}, }; @@ -138,11 +139,11 @@ mod tests { lms::{Signature, SigningKey, VerifyingKey, modes::*}, ots::modes::*, }; + use core::ops::{Add, Mul}; use getrandom::SysRng; use hex_literal::hex; use hybrid_array::ArraySize; use signature::{RandomizedSignerMut, Verifier}; - use std::ops::{Add, Mul}; use typenum::{Prod, Sum, U1, U4}; #[test] diff --git a/lms/src/ots/error.rs b/lms/src/ots/error.rs index 54cba2ea..3d281d99 100644 --- a/lms/src/ots/error.rs +++ b/lms/src/ots/error.rs @@ -1,7 +1,7 @@ //! LM-OTS Signing error -use std::error::Error; -use std::fmt::{Display, Formatter, Result}; +use core::error::Error; +use core::fmt::{Display, Formatter, Result}; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct LmsOtsInvalidPrivateKey {} diff --git a/lms/src/ots/mod.rs b/lms/src/ots/mod.rs index e243bca8..c6644f27 100644 --- a/lms/src/ots/mod.rs +++ b/lms/src/ots/mod.rs @@ -34,7 +34,7 @@ pub mod tests { use hybrid_array::{Array, ArraySize}; use rand_core::{TryCryptoRng, TryRng, UnwrapErr}; use signature::{RandomizedSignerMut, Verifier}; - use std::{matches, ops::Add}; + use core::{matches, ops::Add}; use typenum::{Sum, U2}; // tests that a signature signed with a private key verifies under diff --git a/lms/src/ots/modes.rs b/lms/src/ots/modes.rs index 97dcfcba..6282509f 100644 --- a/lms/src/ots/modes.rs +++ b/lms/src/ots/modes.rs @@ -4,7 +4,7 @@ use digest::{Digest, Output}; use hybrid_array::{Array, ArraySize}; use sha2::Sha256; use static_assertions::const_assert_eq; -use std::marker::PhantomData; +use core::marker::PhantomData; use typenum::Unsigned; use typenum::consts::{U34, U67, U133, U265}; diff --git a/lms/src/ots/private.rs b/lms/src/ots/private.rs index fdc22de2..b44a2c9f 100644 --- a/lms/src/ots/private.rs +++ b/lms/src/ots/private.rs @@ -10,7 +10,7 @@ use hybrid_array::Array; use rand_core::{CryptoRng, TryCryptoRng}; use signature::{Error, RandomizedMultipartSignerMut, RandomizedSignerMut}; use zeroize::Zeroize; -//use std::mem::MaybeUninit; +//use core::mem::MaybeUninit; #[derive(Debug)] /// Opaque struct representing an LM-OTS private key. Does not implement diff --git a/lms/src/ots/public.rs b/lms/src/ots/public.rs index 4f6eff55..fe157374 100644 --- a/lms/src/ots/public.rs +++ b/lms/src/ots/public.rs @@ -10,8 +10,8 @@ use digest::{Output, OutputSizeUser}; use hybrid_array::{Array, ArraySize}; use signature::{Error, MultipartVerifier, Verifier}; -use std::cmp::Ordering; -use std::ops::Add; +use core::cmp::Ordering; +use core::ops::Add; use typenum::{Sum, U2, U24}; #[derive(Debug)] @@ -82,7 +82,7 @@ where fn from(pk: VerifyingKey) -> Self { // Return u32str(type) || I || u32str(q) || K Array::try_from_iter( - std::iter::empty() + core::iter::empty() .chain(Mode::TYPECODE.to_be_bytes()) .chain(pk.id) .chain(pk.q.to_be_bytes()) diff --git a/lms/src/ots/signature.rs b/lms/src/ots/signature.rs index 68dd295a..7e0b9503 100644 --- a/lms/src/ots/signature.rs +++ b/lms/src/ots/signature.rs @@ -7,8 +7,8 @@ use crate::types::Identifier; use digest::Digest; use hybrid_array::{Array, ArraySize}; use signature::SignatureEncoding; -use std::cmp::Ordering; -use std::ops::{Add, Mul}; +use core::cmp::Ordering; +use core::ops::{Add, Mul}; use typenum::{Prod, Sum, U1, U4}; use super::VerifyingKey; @@ -52,7 +52,7 @@ where { fn from(sig: Signature) -> Self { Array::try_from_iter( - std::iter::empty() + core::iter::empty() .chain(Mode::TYPECODE.to_be_bytes()) .chain(sig.c.clone()) .chain(sig.y.iter().flatten().cloned()), diff --git a/lms/src/ots/util.rs b/lms/src/ots/util.rs index b508849f..33d37e52 100644 --- a/lms/src/ots/util.rs +++ b/lms/src/ots/util.rs @@ -1,4 +1,4 @@ -use std::iter::IntoIterator; +use core::iter::IntoIterator; /// Returns an iterator over the w-bit Winternitz coefficients of the inout bytes /// Implements the Coef function from section 3.1.3 of RFC8554 From 69cd36ec22e1c5492e6a2faae741ac9944c73bcb Mon Sep 17 00:00:00 2001 From: TechnoPorg Date: Mon, 5 Oct 2026 12:26:49 -0400 Subject: [PATCH 2/4] ci: add clippy step to lms --- .github/workflows/lms.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/lms.yml b/.github/workflows/lms.yml index 7eb56bb1..f8b77944 100644 --- a/.github/workflows/lms.yml +++ b/.github/workflows/lms.yml @@ -38,3 +38,4 @@ jobs: - run: cargo test --no-default-features - run: cargo test - run: cargo test --all-features + - run: cargo clippy --all-features --all-targets From 5dc13ccb28428b24fce00b2ff0cbb12009259da8 Mon Sep 17 00:00:00 2001 From: TechnoPorg Date: Mon, 5 Oct 2026 12:28:02 -0400 Subject: [PATCH 3/4] lms: use Array instead of Vec --- lms/src/lib.rs | 2 -- lms/src/lms/modes.rs | 11 ++++-- lms/src/lms/signature.rs | 78 ++++++++++++++-------------------------- lms/src/ots/mod.rs | 2 +- lms/src/ots/modes.rs | 29 +++++++++++++-- lms/src/ots/public.rs | 4 +-- lms/src/ots/signature.rs | 27 +++----------- 7 files changed, 70 insertions(+), 83 deletions(-) diff --git a/lms/src/lib.rs b/lms/src/lib.rs index 1cebeeaf..2ace939b 100644 --- a/lms/src/lib.rs +++ b/lms/src/lib.rs @@ -8,8 +8,6 @@ #![warn(unreachable_pub)] #![cfg_attr(not(test), no_std)] -extern crate alloc; - pub mod error; pub mod lms; pub mod ots; diff --git a/lms/src/lms/modes.rs b/lms/src/lms/modes.rs index 8d13d784..00821343 100644 --- a/lms/src/lms/modes.rs +++ b/lms/src/lms/modes.rs @@ -1,14 +1,14 @@ //! LMS modes use crate::ots::modes::LmsOtsMode; use crate::types::Typecode; -use core::ops::Add; +use core::ops::{Add, Mul}; use core::{ marker::PhantomData, ops::{Shl, Sub}, }; use digest::Digest; use hybrid_array::ArraySize; -use typenum::{Add1, Shleft, Sub1, U1, U5, U10, U15, U20, U25, bit::B1}; +use typenum::{Add1, Prod, Shleft, Sub1, Sum, U1, U5, U8, U10, U15, U20, U25, bit::B1}; /// The basic trait that must be implemented for any valid LMS mode pub trait LmsMode: Typecode + Clone { @@ -20,6 +20,8 @@ pub trait LmsMode: Typecode + Clone { type TreeLen: ArraySize; /// `h` as a type type HLen: ArraySize; + /// Length of an encoded signature, computed as `4 + ots_sig_len + 4 + m*h` + type SigLen: ArraySize; /// The length of the hash function output as a type const M: usize; /// `h` as a [usize] @@ -82,11 +84,16 @@ where U1: Shl<>::Output>, Shleft>::Output>: Sub, Sub1>::Output>>: ArraySize, + Hasher::OutputSize: Mul, + OtsMode::SigLen: Add>, + U8: Add>>, + Sum>>: ArraySize, { type OtsMode = OtsMode; type Hasher = Hasher; type TreeLen = Sub1>>; type HLen = HLen; + type SigLen = Sum>>; const M: usize = M; const H: usize = H; const LEAVES: u32 = 1 << H; // precomputed as 2 to the H power diff --git a/lms/src/lms/signature.rs b/lms/src/lms/signature.rs index 5278a897..0814114f 100644 --- a/lms/src/lms/signature.rs +++ b/lms/src/lms/signature.rs @@ -4,16 +4,13 @@ use crate::error::LmsDeserializeError; use crate::lms::LmsMode; use crate::ots::Signature as OtsSignature; use crate::ots::modes::LmsOtsMode; -use hybrid_array::{Array, ArraySize}; +use hybrid_array::Array; use signature::SignatureEncoding; -use alloc::vec::Vec; -use core::{ - cmp::Ordering, - ops::{Add, Mul}, -}; +use core::cmp::Ordering; -use typenum::{Prod, Sum, U1, U4}; +/// Byte representation of a [`Signature`] +pub type SignatureBytes = Array::SigLen>; /// Opaque struct representing a LMS signature pub struct Signature { @@ -40,40 +37,29 @@ impl PartialEq for Signature { } } -impl SignatureEncoding for Signature -where - ::PLen: Add, - ::NLen: Mul::PLen, U1>>, - Prod<::NLen, Sum<::PLen, U1>>: - Add, - Sum< - Prod<::NLen, Sum<::PLen, U1>>, - U4, - >: ArraySize, -{ - type Repr = Vec; // TODO: Array +impl SignatureEncoding for Signature { + type Repr = SignatureBytes; } -impl From> for Vec -where - ::PLen: Add, - ::NLen: Mul::PLen, U1>>, - Prod<::NLen, Sum<::PLen, U1>>: - Add, - Sum< - Prod<::NLen, Sum<::PLen, U1>>, - U4, - >: ArraySize, -{ +impl From> for SignatureBytes { fn from(val: Signature) -> Self { - let mut sig = Vec::new(); - sig.extend_from_slice(&val.q.to_be_bytes()); - let lms_sig: Array = val.lmots_sig.into(); - sig.extend_from_slice(&lms_sig); - sig.extend_from_slice(&Mode::TYPECODE.to_be_bytes()); - for node in val.path { - sig.extend_from_slice(&node); + let mut sig = SignatureBytes::::default(); + let (q, rest) = sig.split_at_mut(size_of::()); + q.copy_from_slice(&val.q.to_be_bytes()); + + let (lms_sig, rest) = rest.split_at_mut(Mode::OtsMode::SIG_LEN); + lms_sig.copy_from_slice(&Array::::from(val.lmots_sig)); + + let (typecode, path) = rest.split_at_mut(size_of::()); + typecode.copy_from_slice(&Mode::TYPECODE.to_be_bytes()); + + let mut path_chunks = path.chunks_exact_mut(Mode::M); + assert_eq!(path_chunks.len(), val.path.len()); + for (buf, node) in (&mut path_chunks).zip(val.path.iter()) { + buf.copy_from_slice(node); } + assert_eq!(path_chunks.into_remainder().len(), 0); + sig } } @@ -139,12 +125,10 @@ mod tests { lms::{Signature, SigningKey, VerifyingKey, modes::*}, ots::modes::*, }; - use core::ops::{Add, Mul}; use getrandom::SysRng; use hex_literal::hex; - use hybrid_array::ArraySize; + use hybrid_array::Array; use signature::{RandomizedSignerMut, Verifier}; - use typenum::{Prod, Sum, U1, U4}; #[test] fn test_deserialize_kat1() { @@ -258,23 +242,13 @@ mod tests { assert!(pk.verify(&msg[..], &sig).is_ok()); } - fn test_serialize_deserialize_random() - where - ::PLen: Add, - ::NLen: Mul::PLen, U1>>, - Prod<::NLen, Sum<::PLen, U1>>: - Add, - Sum< - Prod<::NLen, Sum<::PLen, U1>>, - U4, - >: ArraySize, - { + fn test_serialize_deserialize_random() { let mut rng = rand_core::UnwrapErr(SysRng); let mut sk = SigningKey::::new(&mut rng); let pk = sk.public(); let msg = b"Hello, world!"; let sig = sk.sign_with_rng(&mut rng, msg); - let sig_bytes: Vec<_> = sig.clone().into(); + let sig_bytes: Array<_, _> = sig.clone().into(); let sig2 = Signature::::try_from(&sig_bytes[..]).unwrap(); assert!(pk.verify(msg, &sig2).is_ok()); } diff --git a/lms/src/ots/mod.rs b/lms/src/ots/mod.rs index c6644f27..94c8c8e9 100644 --- a/lms/src/ots/mod.rs +++ b/lms/src/ots/mod.rs @@ -28,13 +28,13 @@ pub mod tests { }, }; use core::convert::Infallible; + use core::{matches, ops::Add}; use digest::{Digest, OutputSizeUser}; use getrandom::SysRng; use hex_literal::hex; use hybrid_array::{Array, ArraySize}; use rand_core::{TryCryptoRng, TryRng, UnwrapErr}; use signature::{RandomizedSignerMut, Verifier}; - use core::{matches, ops::Add}; use typenum::{Sum, U2}; // tests that a signature signed with a private key verifies under diff --git a/lms/src/ots/modes.rs b/lms/src/ots/modes.rs index 6282509f..a965179b 100644 --- a/lms/src/ots/modes.rs +++ b/lms/src/ots/modes.rs @@ -1,12 +1,13 @@ use crate::ots::util::coefs; use crate::types::Typecode; +use core::marker::PhantomData; +use core::ops::{Add, Mul}; use digest::{Digest, Output}; use hybrid_array::{Array, ArraySize}; use sha2::Sha256; use static_assertions::const_assert_eq; -use core::marker::PhantomData; -use typenum::Unsigned; use typenum::consts::{U34, U67, U133, U265}; +use typenum::{Prod, Sum, U1, U4, Unsigned}; /// The basic trait that must be implemented by any OTS mode. pub trait LmsOtsMode: Typecode { @@ -16,6 +17,8 @@ pub trait LmsOtsMode: Typecode { type NLen: ArraySize; /// The value of P as a type type PLen: ArraySize; + /// Length of an encoded signature, computed as `4 + n*(p+1)` + type SigLen: ArraySize; /// The length of the hash function output as a [usize] const N: usize; /// The Winternitz window, which should be a value that divides 8 @@ -87,10 +90,16 @@ impl Typecode /// https://datatracker.ietf.org/doc/html/rfc8554#section-4.1 impl LmsOtsMode for LmsOtsModeInternal +where + PP: Add, + Hasher::OutputSize: Mul>, + Prod>: Add, + Sum>, U4>: ArraySize, { type Hasher = Hasher; type NLen = Hasher::OutputSize; type PLen = PP; + type SigLen = Sum>, U4>; const N: usize = Hasher::OutputSize::USIZE; const W: usize = W; const U: usize = (8 * Self::N).div_ceil(W); @@ -118,6 +127,10 @@ const_assert_eq!( ::PLen::USIZE, LmsOtsSha256N32W1::P ); +const_assert_eq!( + ::SigLen::USIZE, + LmsOtsSha256N32W1::SIG_LEN +); const_assert_eq!(LmsOtsSha256N32W1::N, 32); const_assert_eq!(LmsOtsSha256N32W1::P, 265); const_assert_eq!(LmsOtsSha256N32W1::LS, 7); @@ -131,6 +144,10 @@ const_assert_eq!( ::PLen::USIZE, LmsOtsSha256N32W2::P ); +const_assert_eq!( + ::SigLen::USIZE, + LmsOtsSha256N32W2::SIG_LEN +); const_assert_eq!(LmsOtsSha256N32W2::N, 32); const_assert_eq!(LmsOtsSha256N32W2::P, 133); const_assert_eq!(LmsOtsSha256N32W2::LS, 6); @@ -144,6 +161,10 @@ const_assert_eq!( ::PLen::USIZE, LmsOtsSha256N32W4::P ); +const_assert_eq!( + ::SigLen::USIZE, + LmsOtsSha256N32W4::SIG_LEN +); const_assert_eq!(LmsOtsSha256N32W4::N, 32); const_assert_eq!(LmsOtsSha256N32W4::P, 67); const_assert_eq!(LmsOtsSha256N32W4::LS, 4); @@ -157,6 +178,10 @@ const_assert_eq!( ::PLen::USIZE, LmsOtsSha256N32W8::P ); +const_assert_eq!( + ::SigLen::USIZE, + LmsOtsSha256N32W8::SIG_LEN +); const_assert_eq!(LmsOtsSha256N32W8::N, 32); const_assert_eq!(LmsOtsSha256N32W8::P, 34); const_assert_eq!(LmsOtsSha256N32W8::LS, 0); diff --git a/lms/src/ots/public.rs b/lms/src/ots/public.rs index fe157374..6d0a7beb 100644 --- a/lms/src/ots/public.rs +++ b/lms/src/ots/public.rs @@ -8,10 +8,10 @@ use crate::ots::signature::Signature; use crate::types::Identifier; use digest::{Output, OutputSizeUser}; -use hybrid_array::{Array, ArraySize}; -use signature::{Error, MultipartVerifier, Verifier}; use core::cmp::Ordering; use core::ops::Add; +use hybrid_array::{Array, ArraySize}; +use signature::{Error, MultipartVerifier, Verifier}; use typenum::{Sum, U2, U24}; #[derive(Debug)] diff --git a/lms/src/ots/signature.rs b/lms/src/ots/signature.rs index 7e0b9503..fbf771fa 100644 --- a/lms/src/ots/signature.rs +++ b/lms/src/ots/signature.rs @@ -4,12 +4,10 @@ use crate::constants::{D_MESG, D_PBLC}; use crate::error::LmsDeserializeError; use crate::ots::modes::LmsOtsMode; use crate::types::Identifier; +use core::cmp::Ordering; use digest::Digest; -use hybrid_array::{Array, ArraySize}; +use hybrid_array::Array; use signature::SignatureEncoding; -use core::cmp::Ordering; -use core::ops::{Add, Mul}; -use typenum::{Prod, Sum, U1, U4}; use super::VerifyingKey; @@ -38,18 +36,10 @@ impl PartialEq for Signature { } /// Useful type alias to get the [`Array`] representation -pub type Output = - Array::NLen, Sum<::PLen, U1>>, U4>>; +pub type Output = Array::SigLen>; /// Converts a [`Signature`] into its byte representation -impl From> for Output -where - // required for Output - Mode::PLen: Add, - Mode::NLen: Mul>, - Prod>: Add, - Sum>, U4>: ArraySize, -{ +impl From> for Output { fn from(sig: Signature) -> Self { Array::try_from_iter( core::iter::empty() @@ -161,14 +151,7 @@ impl Signature { } } -impl SignatureEncoding for Signature -where - // required for Output - Mode::PLen: Add, - Mode::NLen: Mul>, - Prod>: Add, - Sum>, U4>: ArraySize, -{ +impl SignatureEncoding for Signature { type Repr = Output; } From d9af8bdb39e0226ee963d85c3c0398dcc1851cb6 Mon Sep 17 00:00:00 2001 From: TechnoPorg Date: Mon, 5 Oct 2026 14:58:01 -0400 Subject: [PATCH 4/4] deps: remove alloc features from lms dependencies --- lms/Cargo.toml | 10 +++++++--- lms/src/lms/private.rs | 8 ++++++-- lms/src/ots/private.rs | 8 ++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/lms/Cargo.toml b/lms/Cargo.toml index c906b19a..83b74e81 100644 --- a/lms/Cargo.toml +++ b/lms/Cargo.toml @@ -14,12 +14,16 @@ keywords = ["crypto", "signature"] [dependencies] digest = "0.11" hybrid-array = { version = "0.4", features = ["extra-sizes", "zeroize"] } -sha2 = "0.11" +sha2 = { version = "0.11", default-features = false } static_assertions = "1.1" rand_core = "0.10" -signature = { version = "3", features = ["alloc", "digest", "rand_core"] } +signature = { version = "3", features = ["digest", "rand_core"] } typenum = { version = "1.20", features = ["const-generics"] } -zeroize = "1.8" +zeroize = { version = "1.8", default-features = false } + +[features] +default = ["alloc"] +alloc = ["signature/alloc"] [dev-dependencies] hex = "0.4" diff --git a/lms/src/lms/private.rs b/lms/src/lms/private.rs index 37d55e76..869845a9 100644 --- a/lms/src/lms/private.rs +++ b/lms/src/lms/private.rs @@ -1,6 +1,5 @@ use crate::constants::{D_INTR, D_LEAF, ID_LEN}; use crate::error::LmsDeserializeError; -use crate::lms::error::LmsOutOfPrivateKeys; use crate::lms::{LmsMode, Signature, VerifyingKey}; use crate::ots::SigningKey as OtsPrivateKey; use crate::types::{Identifier, Typecode}; @@ -122,7 +121,12 @@ impl RandomizedMultipartSignerMut> for SigningKey msg: &[&[u8]], ) -> Result, Error> { if self.q >= Mode::LEAVES { - return Err(Error::from_source(LmsOutOfPrivateKeys {})); + #[cfg(feature = "alloc")] + return Err(Error::from_source( + crate::lms::error::LmsOutOfPrivateKeys {}, + )); + #[cfg(not(feature = "alloc"))] + return Err(Error::new()); } let mut ots_priv_key = diff --git a/lms/src/ots/private.rs b/lms/src/ots/private.rs index b44a2c9f..b2c52c65 100644 --- a/lms/src/ots/private.rs +++ b/lms/src/ots/private.rs @@ -1,5 +1,4 @@ use crate::constants::{D_MESG, D_PBLC}; -use crate::ots::error::LmsOtsInvalidPrivateKey; use crate::ots::modes::LmsOtsMode; use crate::ots::public::VerifyingKey; use crate::ots::signature::Signature; @@ -112,7 +111,12 @@ impl RandomizedMultipartSignerMut> for Signing msg: &[&[u8]], ) -> Result, Error> { if !self.valid { - return Err(Error::from_source(LmsOtsInvalidPrivateKey {})); + #[cfg(feature = "alloc")] + return Err(Error::from_source( + crate::ots::error::LmsOtsInvalidPrivateKey {}, + )); + #[cfg(not(feature = "alloc"))] + return Err(Error::new()); } // Generate the message randomizer C