1macro_rules! impl_struct {
4 ($name:ident, $doc:expr) => {
5 #[doc = $doc]
6 #[derive(Clone)]
7 pub struct $name<const SIZE: usize> {
8 pub(crate) value: [u8; SIZE],
9 }
10
11 impl<const SIZE: usize> $name<SIZE> {
12 pub const fn zero() -> Self {
14 Self { value: [0u8; SIZE] }
15 }
16
17 pub const fn new(value: [u8; SIZE]) -> Self {
19 Self { value }
20 }
21
22 pub const fn as_slice(&self) -> &[u8] {
24 &self.value
25 }
26
27 pub const fn as_ref(&self) -> &[u8; SIZE] {
29 &self.value
30 }
31
32 pub const fn len() -> usize {
34 SIZE
35 }
36 }
37 };
38}
39
40impl_struct!(MLDSASigningKey, "An ML-DSA signature key.");
41impl_struct!(MLDSAVerificationKey, "An ML-DSA verification key.");
42impl_struct!(MLDSASignature, "An ML-DSA signature.");
43
44macro_rules! impl_non_hax_types {
45 ($name:ident) => {
46 impl<const SIZE: usize> $name<SIZE> {
47 pub fn as_mut_slice(&mut self) -> &mut [u8] {
49 &mut self.value
50 }
51
52 pub fn as_ref_mut(&mut self) -> &mut [u8; SIZE] {
54 &mut self.value
55 }
56 }
57 };
58}
59
60mod non_hax_impls {
62 use super::*;
63 impl_non_hax_types!(MLDSASigningKey);
64 impl_non_hax_types!(MLDSAVerificationKey);
65 impl_non_hax_types!(MLDSASignature);
66}
67
68pub struct MLDSAKeyPair<const VERIFICATION_KEY_SIZE: usize, const SIGNING_KEY_SIZE: usize> {
70 pub signing_key: MLDSASigningKey<SIGNING_KEY_SIZE>,
71 pub verification_key: MLDSAVerificationKey<VERIFICATION_KEY_SIZE>,
72}
73
74#[cfg_attr(not(eurydice), derive(Debug))]
75pub enum VerificationError {
76 MalformedHintError,
77 SignerResponseExceedsBoundError,
78 CommitmentHashesDontMatchError,
79 VerificationContextTooLongError,
82}
83
84#[cfg_attr(not(eurydice), derive(Debug))]
85pub enum SigningError {
86 RejectionSamplingError,
87 ContextTooLongError,
88}
89
90#[cfg(feature = "codec")]
91mod codec {
92 use super::*;
93
94 macro_rules! impl_tls_codec_for_generic_struct {
95 ($name:ident) => {
96 impl<const SIZE: usize> tls_codec::DeserializeBytes for $name<SIZE> {
102 fn tls_deserialize_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), tls_codec::Error> {
103 let (bytes, remainder) = tls_codec::VLBytes::tls_deserialize_bytes(bytes)?;
104 Ok((
105 Self {
106 value: bytes
107 .as_ref()
108 .try_into()
109 .map_err(|_| tls_codec::Error::InvalidInput)?,
110 },
111 remainder,
112 ))
113 }
114 }
115
116 #[cfg(feature = "std")]
117 impl<const SIZE: usize> tls_codec::Serialize for $name<SIZE> {
118 fn tls_serialize<W: std::io::Write>(
119 &self,
120 writer: &mut W,
121 ) -> Result<usize, tls_codec::Error> {
122 let out = tls_codec::VLByteSlice(self.as_ref());
123 out.tls_serialize(writer)
124 }
125 }
126
127 #[cfg(feature = "std")]
128 impl<const SIZE: usize> tls_codec::Serialize for &$name<SIZE> {
129 fn tls_serialize<W: std::io::Write>(
130 &self,
131 writer: &mut W,
132 ) -> Result<usize, tls_codec::Error> {
133 (*self).tls_serialize(writer)
134 }
135 }
136
137 #[cfg(feature = "std")]
138 impl<const SIZE: usize> tls_codec::Deserialize for $name<SIZE> {
139 fn tls_deserialize<R: std::io::Read>(
140 bytes: &mut R,
141 ) -> Result<Self, tls_codec::Error> {
142 let bytes = tls_codec::VLBytes::tls_deserialize(bytes)?;
143 Ok(Self {
144 value: bytes
145 .as_ref()
146 .try_into()
147 .map_err(|_| tls_codec::Error::InvalidInput)?,
148 })
149 }
150 }
151
152 impl<const SIZE: usize> tls_codec::Size for $name<SIZE> {
153 fn tls_serialized_len(&self) -> usize {
154 tls_codec::VLByteSlice(self.as_ref()).tls_serialized_len()
155 }
156 }
157
158 impl<const SIZE: usize> tls_codec::Size for &$name<SIZE> {
159 fn tls_serialized_len(&self) -> usize {
160 (*self).tls_serialized_len()
161 }
162 }
163 };
164 }
165
166 impl_tls_codec_for_generic_struct!(MLDSAVerificationKey);
167 impl_tls_codec_for_generic_struct!(MLDSASignature);
168}