hsmtool/util/key/
slhdsa.rs

1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5use anyhow::{Result, anyhow};
6use cryptoki::mechanism::dsa::{HashSignAdditionalContext, HedgeType, SignAdditionalContext};
7use cryptoki::mechanism::{Mechanism, MechanismType};
8use rsa::pkcs8;
9use rsa::pkcs8::spki;
10use rsa::pkcs8::{
11    DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey, Error, LineEnding,
12};
13use slh_dsa::{SigningKey, VerifyingKey};
14use sphincsplus::SpxDomain;
15use std::path::Path;
16
17use crate::error::HsmError;
18use crate::util::attribute::{AttrData, AttributeMap, AttributeType, KeyType, ObjectClass};
19use crate::util::key::KeyEncoding;
20
21fn _load_private_key(path: &Path) -> Result<SlhDsaPrivateKey> {
22    let data = std::fs::read_to_string(path)?;
23    if let Ok(sk) = SlhDsaPrivateKey::from_pkcs8_pem(&data) {
24        return Ok(sk);
25    }
26    if let Ok(sk) = SlhDsaPrivateKey::from_pkcs8_der(data.as_bytes()) {
27        return Ok(sk);
28    }
29    Err(anyhow!("Invalid Private Key PEM/DER"))
30}
31
32fn _load_public_key(path: &Path) -> Result<SlhDsaPublicKey> {
33    let data = std::fs::read_to_string(path)?;
34    if let Ok(sk) = SlhDsaPublicKey::from_public_key_pem(&data) {
35        return Ok(sk);
36    }
37    if let Ok(sk) = SlhDsaPublicKey::from_public_key_der(data.as_bytes()) {
38        return Ok(sk);
39    }
40    Err(anyhow!("Invalid Public Key PEM/DER"))
41}
42
43pub fn load_private_key<P: AsRef<Path>>(path: P) -> Result<SlhDsaPrivateKey> {
44    _load_private_key(path.as_ref())
45}
46
47pub fn load_public_key<P: AsRef<Path>>(path: P) -> Result<SlhDsaPublicKey> {
48    _load_public_key(path.as_ref())
49}
50
51fn _save_private_key(path: &Path, key: &SlhDsaPrivateKey, enc: KeyEncoding) -> Result<()> {
52    match enc {
53        KeyEncoding::Der | KeyEncoding::Pkcs8Der => key.write_pkcs8_der_file(path)?,
54        KeyEncoding::Pem | KeyEncoding::Pkcs8Pem | KeyEncoding::Pkcs8 => {
55            key.write_pkcs8_pem_file(path, LineEnding::LF)?
56        }
57        _ => Err(HsmError::Unsupported("Unsupported output format".into()))?,
58    };
59    Ok(())
60}
61
62fn _save_public_key(path: &Path, key: &SlhDsaPublicKey, enc: KeyEncoding) -> Result<()> {
63    match enc {
64        KeyEncoding::Der => key.write_public_key_der_file(path)?,
65        KeyEncoding::Pem => key.write_public_key_pem_file(path, LineEnding::LF)?,
66        _ => Err(HsmError::Unsupported("Unsupported output format".into()))?,
67    };
68    Ok(())
69}
70
71pub fn save_private_key<P: AsRef<Path>>(
72    path: P,
73    key: &SlhDsaPrivateKey,
74    enc: KeyEncoding,
75) -> Result<()> {
76    _save_private_key(path.as_ref(), key, enc)
77}
78
79pub fn save_public_key<P: AsRef<Path>>(
80    path: P,
81    key: &SlhDsaPublicKey,
82    enc: KeyEncoding,
83) -> Result<()> {
84    _save_public_key(path.as_ref(), key, enc)
85}
86
87pub enum SlhDsaPrivateKey {
88    Sha2_128s(SigningKey<slh_dsa::Sha2_128s>),
89    Sha2_128f(SigningKey<slh_dsa::Sha2_128f>),
90    Sha2_192s(SigningKey<slh_dsa::Sha2_192s>),
91    Sha2_192f(SigningKey<slh_dsa::Sha2_192f>),
92    Sha2_256s(SigningKey<slh_dsa::Sha2_256s>),
93    Sha2_256f(SigningKey<slh_dsa::Sha2_256f>),
94    Shake128s(SigningKey<slh_dsa::Shake128s>),
95    Shake128f(SigningKey<slh_dsa::Shake128f>),
96    Shake192s(SigningKey<slh_dsa::Shake192s>),
97    Shake192f(SigningKey<slh_dsa::Shake192f>),
98    Shake256s(SigningKey<slh_dsa::Shake256s>),
99    Shake256f(SigningKey<slh_dsa::Shake256f>),
100}
101
102pub enum SlhDsaPublicKey {
103    Sha2_128s(VerifyingKey<slh_dsa::Sha2_128s>),
104    Sha2_128f(VerifyingKey<slh_dsa::Sha2_128f>),
105    Sha2_192s(VerifyingKey<slh_dsa::Sha2_192s>),
106    Sha2_192f(VerifyingKey<slh_dsa::Sha2_192f>),
107    Sha2_256s(VerifyingKey<slh_dsa::Sha2_256s>),
108    Sha2_256f(VerifyingKey<slh_dsa::Sha2_256f>),
109    Shake128s(VerifyingKey<slh_dsa::Shake128s>),
110    Shake128f(VerifyingKey<slh_dsa::Shake128f>),
111    Shake192s(VerifyingKey<slh_dsa::Shake192s>),
112    Shake192f(VerifyingKey<slh_dsa::Shake192f>),
113    Shake256s(VerifyingKey<slh_dsa::Shake256s>),
114    Shake256f(VerifyingKey<slh_dsa::Shake256f>),
115}
116
117impl EncodePrivateKey for SlhDsaPrivateKey {
118    fn to_pkcs8_der(&self) -> pkcs8::Result<der::SecretDocument> {
119        match self {
120            Self::Sha2_128s(x) => x.to_pkcs8_der(),
121            Self::Sha2_128f(x) => x.to_pkcs8_der(),
122            Self::Sha2_192s(x) => x.to_pkcs8_der(),
123            Self::Sha2_192f(x) => x.to_pkcs8_der(),
124            Self::Sha2_256s(x) => x.to_pkcs8_der(),
125            Self::Sha2_256f(x) => x.to_pkcs8_der(),
126            Self::Shake128s(x) => x.to_pkcs8_der(),
127            Self::Shake128f(x) => x.to_pkcs8_der(),
128            Self::Shake192s(x) => x.to_pkcs8_der(),
129            Self::Shake192f(x) => x.to_pkcs8_der(),
130            Self::Shake256s(x) => x.to_pkcs8_der(),
131            Self::Shake256f(x) => x.to_pkcs8_der(),
132        }
133    }
134}
135
136impl EncodePublicKey for SlhDsaPublicKey {
137    fn to_public_key_der(&self) -> spki::Result<der::Document> {
138        match self {
139            Self::Sha2_128s(x) => x.to_public_key_der(),
140            Self::Sha2_128f(x) => x.to_public_key_der(),
141            Self::Sha2_192s(x) => x.to_public_key_der(),
142            Self::Sha2_192f(x) => x.to_public_key_der(),
143            Self::Sha2_256s(x) => x.to_public_key_der(),
144            Self::Sha2_256f(x) => x.to_public_key_der(),
145            Self::Shake128s(x) => x.to_public_key_der(),
146            Self::Shake128f(x) => x.to_public_key_der(),
147            Self::Shake192s(x) => x.to_public_key_der(),
148            Self::Shake192f(x) => x.to_public_key_der(),
149            Self::Shake256s(x) => x.to_public_key_der(),
150            Self::Shake256f(x) => x.to_public_key_der(),
151        }
152    }
153}
154
155impl DecodePrivateKey for SlhDsaPrivateKey {
156    fn from_pkcs8_der(bytes: &[u8]) -> pkcs8::Result<Self> {
157        if let Ok(sk) = SigningKey::<slh_dsa::Sha2_128s>::from_pkcs8_der(bytes) {
158            return Ok(Self::Sha2_128s(sk));
159        }
160        if let Ok(sk) = SigningKey::<slh_dsa::Sha2_128f>::from_pkcs8_der(bytes) {
161            return Ok(Self::Sha2_128f(sk));
162        }
163        if let Ok(sk) = SigningKey::<slh_dsa::Sha2_192s>::from_pkcs8_der(bytes) {
164            return Ok(Self::Sha2_192s(sk));
165        }
166        if let Ok(sk) = SigningKey::<slh_dsa::Sha2_192f>::from_pkcs8_der(bytes) {
167            return Ok(Self::Sha2_192f(sk));
168        }
169        if let Ok(sk) = SigningKey::<slh_dsa::Sha2_256s>::from_pkcs8_der(bytes) {
170            return Ok(Self::Sha2_256s(sk));
171        }
172        if let Ok(sk) = SigningKey::<slh_dsa::Sha2_256f>::from_pkcs8_der(bytes) {
173            return Ok(Self::Sha2_256f(sk));
174        }
175        if let Ok(sk) = SigningKey::<slh_dsa::Shake128s>::from_pkcs8_der(bytes) {
176            return Ok(Self::Shake128s(sk));
177        }
178        if let Ok(sk) = SigningKey::<slh_dsa::Shake128f>::from_pkcs8_der(bytes) {
179            return Ok(Self::Shake128f(sk));
180        }
181        if let Ok(sk) = SigningKey::<slh_dsa::Shake192s>::from_pkcs8_der(bytes) {
182            return Ok(Self::Shake192s(sk));
183        }
184        if let Ok(sk) = SigningKey::<slh_dsa::Shake192f>::from_pkcs8_der(bytes) {
185            return Ok(Self::Shake192f(sk));
186        }
187        if let Ok(sk) = SigningKey::<slh_dsa::Shake256s>::from_pkcs8_der(bytes) {
188            return Ok(Self::Shake256s(sk));
189        }
190        if let Ok(sk) = SigningKey::<slh_dsa::Shake256f>::from_pkcs8_der(bytes) {
191            return Ok(Self::Shake256f(sk));
192        }
193        Err(Error::KeyMalformed)
194    }
195}
196
197impl DecodePublicKey for SlhDsaPublicKey {
198    fn from_public_key_der(bytes: &[u8]) -> spki::Result<Self> {
199        if let Ok(sk) = VerifyingKey::<slh_dsa::Sha2_128s>::from_public_key_der(bytes) {
200            return Ok(Self::Sha2_128s(sk));
201        }
202        if let Ok(sk) = VerifyingKey::<slh_dsa::Sha2_128f>::from_public_key_der(bytes) {
203            return Ok(Self::Sha2_128f(sk));
204        }
205        if let Ok(sk) = VerifyingKey::<slh_dsa::Sha2_192s>::from_public_key_der(bytes) {
206            return Ok(Self::Sha2_192s(sk));
207        }
208        if let Ok(sk) = VerifyingKey::<slh_dsa::Sha2_192f>::from_public_key_der(bytes) {
209            return Ok(Self::Sha2_192f(sk));
210        }
211        if let Ok(sk) = VerifyingKey::<slh_dsa::Sha2_256s>::from_public_key_der(bytes) {
212            return Ok(Self::Sha2_256s(sk));
213        }
214        if let Ok(sk) = VerifyingKey::<slh_dsa::Sha2_256f>::from_public_key_der(bytes) {
215            return Ok(Self::Sha2_256f(sk));
216        }
217        if let Ok(sk) = VerifyingKey::<slh_dsa::Shake128s>::from_public_key_der(bytes) {
218            return Ok(Self::Shake128s(sk));
219        }
220        if let Ok(sk) = VerifyingKey::<slh_dsa::Shake128f>::from_public_key_der(bytes) {
221            return Ok(Self::Shake128f(sk));
222        }
223        if let Ok(sk) = VerifyingKey::<slh_dsa::Shake192s>::from_public_key_der(bytes) {
224            return Ok(Self::Shake192s(sk));
225        }
226        if let Ok(sk) = VerifyingKey::<slh_dsa::Shake192f>::from_public_key_der(bytes) {
227            return Ok(Self::Shake192f(sk));
228        }
229        if let Ok(sk) = VerifyingKey::<slh_dsa::Shake256s>::from_public_key_der(bytes) {
230            return Ok(Self::Shake256s(sk));
231        }
232        if let Ok(sk) = VerifyingKey::<slh_dsa::Shake256f>::from_public_key_der(bytes) {
233            return Ok(Self::Shake256f(sk));
234        }
235        Err(Error::KeyMalformed.into())
236    }
237}
238
239impl SlhDsaPrivateKey {
240    pub fn to_vec(&self) -> Vec<u8> {
241        match self {
242            Self::Sha2_128s(x) => x.to_vec(),
243            Self::Sha2_128f(x) => x.to_vec(),
244            Self::Sha2_192s(x) => x.to_vec(),
245            Self::Sha2_192f(x) => x.to_vec(),
246            Self::Sha2_256s(x) => x.to_vec(),
247            Self::Sha2_256f(x) => x.to_vec(),
248            Self::Shake128s(x) => x.to_vec(),
249            Self::Shake128f(x) => x.to_vec(),
250            Self::Shake192s(x) => x.to_vec(),
251            Self::Shake192f(x) => x.to_vec(),
252            Self::Shake256s(x) => x.to_vec(),
253            Self::Shake256f(x) => x.to_vec(),
254        }
255    }
256}
257
258impl SlhDsaPublicKey {
259    pub fn to_vec(&self) -> Vec<u8> {
260        match self {
261            Self::Sha2_128s(x) => x.to_vec(),
262            Self::Sha2_128f(x) => x.to_vec(),
263            Self::Sha2_192s(x) => x.to_vec(),
264            Self::Sha2_192f(x) => x.to_vec(),
265            Self::Sha2_256s(x) => x.to_vec(),
266            Self::Sha2_256f(x) => x.to_vec(),
267            Self::Shake128s(x) => x.to_vec(),
268            Self::Shake128f(x) => x.to_vec(),
269            Self::Shake192s(x) => x.to_vec(),
270            Self::Shake192f(x) => x.to_vec(),
271            Self::Shake256s(x) => x.to_vec(),
272            Self::Shake256f(x) => x.to_vec(),
273        }
274    }
275}
276
277impl TryFrom<&AttributeMap> for SlhDsaPrivateKey {
278    type Error = HsmError;
279
280    fn try_from(map: &AttributeMap) -> Result<Self, Self::Error> {
281        let class: ObjectClass = map
282            .get(&AttributeType::Class)
283            .ok_or_else(|| HsmError::KeyError("Missing key class".into()))?
284            .try_into()
285            .map_err(HsmError::AttributeError)?;
286        let key_type: KeyType = map
287            .get(&AttributeType::KeyType)
288            .ok_or_else(|| HsmError::KeyError("Missing key type".into()))?
289            .try_into()
290            .map_err(HsmError::AttributeError)?;
291        if class != ObjectClass::PrivateKey || key_type != KeyType::SlhDsa {
292            return Err(HsmError::KeyError(
293                " Key is not an SLH-DSA Private Key".into(),
294            ));
295        }
296
297        let parameter_set = map
298            .get(&AttributeType::ParameterSet)
299            .ok_or_else(|| HsmError::KeyError("Missing key parameter set".into()))?
300            .try_into()
301            .map_err(HsmError::AttributeError)?;
302        let value: Vec<u8> = map
303            .get(&AttributeType::Value)
304            .ok_or_else(|| HsmError::KeyError("Missing key value".into()))?
305            .try_into()
306            .map_err(HsmError::AttributeError)?;
307        let value = value.as_slice();
308
309        let key = match parameter_set {
310            cryptoki_sys::CKP_SLH_DSA_SHA2_128S => {
311                let key = SigningKey::<slh_dsa::Sha2_128s>::try_from(value)
312                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
313                SlhDsaPrivateKey::Sha2_128s(key)
314            }
315            cryptoki_sys::CKP_SLH_DSA_SHA2_128F => {
316                let key = SigningKey::<slh_dsa::Sha2_128f>::try_from(value)
317                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
318                SlhDsaPrivateKey::Sha2_128f(key)
319            }
320            cryptoki_sys::CKP_SLH_DSA_SHA2_192S => {
321                let key = SigningKey::<slh_dsa::Sha2_192s>::try_from(value)
322                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
323                SlhDsaPrivateKey::Sha2_192s(key)
324            }
325            cryptoki_sys::CKP_SLH_DSA_SHA2_192F => {
326                let key = SigningKey::<slh_dsa::Sha2_192f>::try_from(value)
327                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
328                SlhDsaPrivateKey::Sha2_192f(key)
329            }
330            cryptoki_sys::CKP_SLH_DSA_SHA2_256S => {
331                let key = SigningKey::<slh_dsa::Sha2_256s>::try_from(value)
332                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
333                SlhDsaPrivateKey::Sha2_256s(key)
334            }
335            cryptoki_sys::CKP_SLH_DSA_SHA2_256F => {
336                let key = SigningKey::<slh_dsa::Sha2_256f>::try_from(value)
337                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
338                SlhDsaPrivateKey::Sha2_256f(key)
339            }
340            cryptoki_sys::CKP_SLH_DSA_SHAKE_128S => {
341                let key = SigningKey::<slh_dsa::Shake128s>::try_from(value)
342                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
343                SlhDsaPrivateKey::Shake128s(key)
344            }
345            cryptoki_sys::CKP_SLH_DSA_SHAKE_128F => {
346                let key = SigningKey::<slh_dsa::Shake128f>::try_from(value)
347                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
348                SlhDsaPrivateKey::Shake128f(key)
349            }
350            cryptoki_sys::CKP_SLH_DSA_SHAKE_192S => {
351                let key = SigningKey::<slh_dsa::Shake192s>::try_from(value)
352                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
353                SlhDsaPrivateKey::Shake192s(key)
354            }
355            cryptoki_sys::CKP_SLH_DSA_SHAKE_192F => {
356                let key = SigningKey::<slh_dsa::Shake192f>::try_from(value)
357                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
358                SlhDsaPrivateKey::Shake192f(key)
359            }
360            cryptoki_sys::CKP_SLH_DSA_SHAKE_256S => {
361                let key = SigningKey::<slh_dsa::Shake256s>::try_from(value)
362                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
363                SlhDsaPrivateKey::Shake256s(key)
364            }
365            cryptoki_sys::CKP_SLH_DSA_SHAKE_256F => {
366                let key = SigningKey::<slh_dsa::Shake256f>::try_from(value)
367                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
368                SlhDsaPrivateKey::Shake256f(key)
369            }
370            _ => Err(HsmError::KeyError("Invalid parameter set for key".into()))?,
371        };
372
373        Ok(key)
374    }
375}
376
377impl TryFrom<&AttributeMap> for SlhDsaPublicKey {
378    type Error = HsmError;
379
380    fn try_from(map: &AttributeMap) -> Result<Self, Self::Error> {
381        let class: ObjectClass = map
382            .get(&AttributeType::Class)
383            .ok_or_else(|| HsmError::KeyError("Missing key class".into()))?
384            .try_into()
385            .map_err(HsmError::AttributeError)?;
386        let key_type: KeyType = map
387            .get(&AttributeType::KeyType)
388            .ok_or_else(|| HsmError::KeyError("Missing key type".into()))?
389            .try_into()
390            .map_err(HsmError::AttributeError)?;
391        if class != ObjectClass::PublicKey || key_type != KeyType::SlhDsa {
392            return Err(HsmError::KeyError(
393                " Key is not an SLH-DSA Public Key".into(),
394            ));
395        }
396
397        let parameter_set = map
398            .get(&AttributeType::ParameterSet)
399            .ok_or_else(|| HsmError::KeyError("Missing key parameter set".into()))?
400            .try_into()
401            .map_err(HsmError::AttributeError)?;
402        let value: Vec<u8> = map
403            .get(&AttributeType::Value)
404            .ok_or_else(|| HsmError::KeyError("Missing key value".into()))?
405            .try_into()
406            .map_err(HsmError::AttributeError)?;
407        let value = value.as_slice();
408
409        let key = match parameter_set {
410            cryptoki_sys::CKP_SLH_DSA_SHA2_128S => {
411                let key = VerifyingKey::<slh_dsa::Sha2_128s>::try_from(value)
412                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
413                SlhDsaPublicKey::Sha2_128s(key)
414            }
415            cryptoki_sys::CKP_SLH_DSA_SHA2_128F => {
416                let key = VerifyingKey::<slh_dsa::Sha2_128f>::try_from(value)
417                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
418                SlhDsaPublicKey::Sha2_128f(key)
419            }
420            cryptoki_sys::CKP_SLH_DSA_SHA2_192S => {
421                let key = VerifyingKey::<slh_dsa::Sha2_192s>::try_from(value)
422                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
423                SlhDsaPublicKey::Sha2_192s(key)
424            }
425            cryptoki_sys::CKP_SLH_DSA_SHA2_192F => {
426                let key = VerifyingKey::<slh_dsa::Sha2_192f>::try_from(value)
427                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
428                SlhDsaPublicKey::Sha2_192f(key)
429            }
430            cryptoki_sys::CKP_SLH_DSA_SHA2_256S => {
431                let key = VerifyingKey::<slh_dsa::Sha2_256s>::try_from(value)
432                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
433                SlhDsaPublicKey::Sha2_256s(key)
434            }
435            cryptoki_sys::CKP_SLH_DSA_SHA2_256F => {
436                let key = VerifyingKey::<slh_dsa::Sha2_256f>::try_from(value)
437                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
438                SlhDsaPublicKey::Sha2_256f(key)
439            }
440            cryptoki_sys::CKP_SLH_DSA_SHAKE_128S => {
441                let key = VerifyingKey::<slh_dsa::Shake128s>::try_from(value)
442                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
443                SlhDsaPublicKey::Shake128s(key)
444            }
445            cryptoki_sys::CKP_SLH_DSA_SHAKE_128F => {
446                let key = VerifyingKey::<slh_dsa::Shake128f>::try_from(value)
447                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
448                SlhDsaPublicKey::Shake128f(key)
449            }
450            cryptoki_sys::CKP_SLH_DSA_SHAKE_192S => {
451                let key = VerifyingKey::<slh_dsa::Shake192s>::try_from(value)
452                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
453                SlhDsaPublicKey::Shake192s(key)
454            }
455            cryptoki_sys::CKP_SLH_DSA_SHAKE_192F => {
456                let key = VerifyingKey::<slh_dsa::Shake192f>::try_from(value)
457                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
458                SlhDsaPublicKey::Shake192f(key)
459            }
460            cryptoki_sys::CKP_SLH_DSA_SHAKE_256S => {
461                let key = VerifyingKey::<slh_dsa::Shake256s>::try_from(value)
462                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
463                SlhDsaPublicKey::Shake256s(key)
464            }
465            cryptoki_sys::CKP_SLH_DSA_SHAKE_256F => {
466                let key = VerifyingKey::<slh_dsa::Shake256f>::try_from(value)
467                    .map_err(|_| HsmError::KeyError("Invalid key".into()))?;
468                SlhDsaPublicKey::Shake256f(key)
469            }
470            _ => Err(HsmError::KeyError("Invalid parameter set for key".into()))?,
471        };
472
473        Ok(key)
474    }
475}
476
477impl From<&SlhDsaPrivateKey> for SlhDsaPublicKey {
478    fn from(sk: &SlhDsaPrivateKey) -> Self {
479        match sk {
480            SlhDsaPrivateKey::Sha2_128s(x) => SlhDsaPublicKey::Sha2_128s(x.as_ref().clone()),
481            SlhDsaPrivateKey::Sha2_128f(x) => SlhDsaPublicKey::Sha2_128f(x.as_ref().clone()),
482            SlhDsaPrivateKey::Sha2_192s(x) => SlhDsaPublicKey::Sha2_192s(x.as_ref().clone()),
483            SlhDsaPrivateKey::Sha2_192f(x) => SlhDsaPublicKey::Sha2_192f(x.as_ref().clone()),
484            SlhDsaPrivateKey::Sha2_256s(x) => SlhDsaPublicKey::Sha2_256s(x.as_ref().clone()),
485            SlhDsaPrivateKey::Sha2_256f(x) => SlhDsaPublicKey::Sha2_256f(x.as_ref().clone()),
486            SlhDsaPrivateKey::Shake128s(x) => SlhDsaPublicKey::Shake128s(x.as_ref().clone()),
487            SlhDsaPrivateKey::Shake128f(x) => SlhDsaPublicKey::Shake128f(x.as_ref().clone()),
488            SlhDsaPrivateKey::Shake192s(x) => SlhDsaPublicKey::Shake192s(x.as_ref().clone()),
489            SlhDsaPrivateKey::Shake192f(x) => SlhDsaPublicKey::Shake192f(x.as_ref().clone()),
490            SlhDsaPrivateKey::Shake256s(x) => SlhDsaPublicKey::Shake256s(x.as_ref().clone()),
491            SlhDsaPrivateKey::Shake256f(x) => SlhDsaPublicKey::Shake256f(x.as_ref().clone()),
492        }
493    }
494}
495
496impl From<SlhDsaPrivateKey> for AttributeMap {
497    fn from(sk: SlhDsaPrivateKey) -> Self {
498        let (parameter_set, value) = match sk {
499            SlhDsaPrivateKey::Sha2_128s(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_128S, x.to_vec()),
500            SlhDsaPrivateKey::Sha2_128f(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_128F, x.to_vec()),
501            SlhDsaPrivateKey::Sha2_192s(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_192S, x.to_vec()),
502            SlhDsaPrivateKey::Sha2_192f(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_192F, x.to_vec()),
503            SlhDsaPrivateKey::Sha2_256s(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_256S, x.to_vec()),
504            SlhDsaPrivateKey::Sha2_256f(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_256F, x.to_vec()),
505            SlhDsaPrivateKey::Shake128s(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_128S, x.to_vec()),
506            SlhDsaPrivateKey::Shake128f(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_128F, x.to_vec()),
507            SlhDsaPrivateKey::Shake192s(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_192S, x.to_vec()),
508            SlhDsaPrivateKey::Shake192f(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_192F, x.to_vec()),
509            SlhDsaPrivateKey::Shake256s(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_256S, x.to_vec()),
510            SlhDsaPrivateKey::Shake256f(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_256F, x.to_vec()),
511        };
512        let mut map = AttributeMap::default();
513        map.insert(
514            AttributeType::Class,
515            AttrData::ObjectClass(ObjectClass::PrivateKey),
516        );
517        map.insert(AttributeType::KeyType, AttrData::KeyType(KeyType::SlhDsa));
518        map.insert(AttributeType::ParameterSet, parameter_set.into());
519        map.insert(AttributeType::Value, value.as_slice().into());
520        map
521    }
522}
523
524impl From<SlhDsaPublicKey> for AttributeMap {
525    fn from(sk: SlhDsaPublicKey) -> Self {
526        let (parameter_set, value) = match &sk {
527            SlhDsaPublicKey::Sha2_128s(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_128S, x.to_vec()),
528            SlhDsaPublicKey::Sha2_128f(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_128F, x.to_vec()),
529            SlhDsaPublicKey::Sha2_192s(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_192S, x.to_vec()),
530            SlhDsaPublicKey::Sha2_192f(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_192F, x.to_vec()),
531            SlhDsaPublicKey::Sha2_256s(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_256S, x.to_vec()),
532            SlhDsaPublicKey::Sha2_256f(x) => (cryptoki_sys::CKP_SLH_DSA_SHA2_256F, x.to_vec()),
533            SlhDsaPublicKey::Shake128s(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_128S, x.to_vec()),
534            SlhDsaPublicKey::Shake128f(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_128F, x.to_vec()),
535            SlhDsaPublicKey::Shake192s(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_192S, x.to_vec()),
536            SlhDsaPublicKey::Shake192f(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_192F, x.to_vec()),
537            SlhDsaPublicKey::Shake256s(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_256S, x.to_vec()),
538            SlhDsaPublicKey::Shake256f(x) => (cryptoki_sys::CKP_SLH_DSA_SHAKE_256F, x.to_vec()),
539        };
540        let mut map = AttributeMap::default();
541        map.insert(
542            AttributeType::Class,
543            AttrData::ObjectClass(ObjectClass::PublicKey),
544        );
545        map.insert(AttributeType::KeyType, AttrData::KeyType(KeyType::SlhDsa));
546        map.insert(AttributeType::ParameterSet, parameter_set.into());
547        map.insert(AttributeType::Value, value.as_slice().into());
548        map
549    }
550}
551
552pub trait SlhDsaMechanism {
553    fn slh_dsa_mechanism(&self) -> Mechanism<'_>;
554}
555
556impl SlhDsaMechanism for SpxDomain {
557    fn slh_dsa_mechanism(&self) -> Mechanism<'_> {
558        match self {
559            SpxDomain::None | SpxDomain::Pure => {
560                Mechanism::SlhDsa(SignAdditionalContext::new(HedgeType::Preferred, None))
561            }
562            // In PKCS#11, there are separate CKM_HASH_SLH_DSA and CKM_HASH_SLH_DSA_*
563            // mechanisms, where the latter expect the full message and perform the hashing
564            // on token. Since our data is pre-hashed for this domain, use the former
565            // and specify SHA-256 as the hash already used.
566            SpxDomain::PreHashedSha256 => Mechanism::HashSlhDsa(HashSignAdditionalContext::new(
567                HedgeType::Preferred,
568                None,
569                MechanismType::SHA256,
570            )),
571        }
572    }
573}