1111 alloc:: vec:: Vec ,
1212} ;
1313
14+ #[ cfg( feature = "mldsa" ) ]
15+ use super :: MlDsaKeypair ;
16+
1417#[ cfg( feature = "ecdsa" ) ]
1518use super :: EcdsaKeypair ;
1619
@@ -44,6 +47,10 @@ pub enum KeypairData {
4447 #[ cfg( feature = "alloc" ) ]
4548 Rsa ( RsaKeypair ) ,
4649
50+ /// ML-DSA keypair
51+ #[ cfg( feature = "mldsa" ) ]
52+ MlDsa ( MlDsaKeypair ) ,
53+
4754 /// Security Key (FIDO/U2F) using ECDSA/NIST P-256 as specified in [PROTOCOL.u2f].
4855 ///
4956 /// [PROTOCOL.u2f]: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.u2f?annotate=HEAD
@@ -77,6 +84,8 @@ impl KeypairData {
7784 Self :: Encrypted ( _) => return Err ( Error :: Encrypted ) ,
7885 #[ cfg( feature = "alloc" ) ]
7986 Self :: Rsa ( _) => Algorithm :: Rsa { hash : None } ,
87+ #[ cfg( feature = "mldsa" ) ]
88+ Self :: MlDsa ( key) => key. algorithm ( ) ,
8089 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
8190 Self :: SkEcdsaSha2NistP256 ( _) => Algorithm :: SkEcdsaSha2NistP256 ,
8291 #[ cfg( feature = "alloc" ) ]
@@ -136,6 +145,16 @@ impl KeypairData {
136145 }
137146 }
138147
148+ /// Get ML-DSA keypair if this key is the correct type.
149+ #[ cfg( feature = "mldsa" ) ]
150+ #[ must_use]
151+ pub fn mldsa ( & self ) -> Option < & MlDsaKeypair > {
152+ match self {
153+ Self :: MlDsa ( key) => Some ( key) ,
154+ _ => None ,
155+ }
156+ }
157+
139158 /// Get FIDO/U2F ECDSA/NIST P-256 private key if this key is the correct type.
140159 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
141160 #[ must_use]
@@ -207,6 +226,13 @@ impl KeypairData {
207226 matches ! ( self , Self :: Rsa ( _) )
208227 }
209228
229+ /// Is this key an ML-DSA key?
230+ #[ cfg( feature = "mldsa" ) ]
231+ #[ must_use]
232+ pub fn is_mldsa ( & self ) -> bool {
233+ matches ! ( self , Self :: MlDsa ( _) )
234+ }
235+
210236 /// Is this key a FIDO/U2F ECDSA/NIST P-256 key?
211237 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
212238 #[ must_use]
@@ -243,6 +269,8 @@ impl KeypairData {
243269 Self :: Encrypted ( ciphertext) => ciphertext. as_ref ( ) ,
244270 #[ cfg( feature = "alloc" ) ]
245271 Self :: Rsa ( rsa) => rsa. private ( ) . d ( ) . as_bytes ( ) ,
272+ #[ cfg( feature = "mldsa" ) ]
273+ Self :: MlDsa ( mldsa) => mldsa. private . as_ref ( ) ,
246274 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
247275 Self :: SkEcdsaSha2NistP256 ( sk) => sk. key_handle ( ) ,
248276 #[ cfg( feature = "alloc" ) ]
@@ -278,6 +306,8 @@ impl KeypairData {
278306 Algorithm :: Ed25519 => Ed25519Keypair :: decode ( reader) . map ( Self :: Ed25519 ) ,
279307 #[ cfg( feature = "alloc" ) ]
280308 Algorithm :: Rsa { .. } => RsaKeypair :: decode ( reader) . map ( Self :: Rsa ) ,
309+ #[ cfg( feature = "mldsa" ) ]
310+ Algorithm :: MlDsa { params } => MlDsaKeypair :: decode_as ( reader, params) . map ( Self :: MlDsa ) ,
281311 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
282312 Algorithm :: SkEcdsaSha2NistP256 => {
283313 SkEcdsaSha2NistP256 :: decode ( reader) . map ( Self :: SkEcdsaSha2NistP256 )
@@ -307,6 +337,8 @@ impl CtEq for KeypairData {
307337 ( Self :: Encrypted ( a) , Self :: Encrypted ( b) ) => a. ct_eq ( b) ,
308338 #[ cfg( feature = "alloc" ) ]
309339 ( Self :: Rsa ( a) , Self :: Rsa ( b) ) => a. ct_eq ( b) ,
340+ #[ cfg( feature = "mldsa" ) ]
341+ ( Self :: MlDsa ( a) , Self :: MlDsa ( b) ) => a. ct_eq ( b) ,
310342 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
311343 ( Self :: SkEcdsaSha2NistP256 ( a) , Self :: SkEcdsaSha2NistP256 ( b) ) => {
312344 // Security Keys store the actual private key in hardware.
@@ -363,6 +395,8 @@ impl Encode for KeypairData {
363395 Self :: Encrypted ( ciphertext) => return Ok ( ciphertext. len ( ) ) ,
364396 #[ cfg( feature = "alloc" ) ]
365397 Self :: Rsa ( key) => key. encoded_len ( ) ?,
398+ #[ cfg( feature = "mldsa" ) ]
399+ Self :: MlDsa ( key) => key. encoded_len ( ) ?,
366400 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
367401 Self :: SkEcdsaSha2NistP256 ( sk) => sk. encoded_len ( ) ?,
368402 #[ cfg( feature = "alloc" ) ]
@@ -389,6 +423,8 @@ impl Encode for KeypairData {
389423 Self :: Encrypted ( ciphertext) => writer. write ( ciphertext) ?,
390424 #[ cfg( feature = "alloc" ) ]
391425 Self :: Rsa ( key) => key. encode ( writer) ?,
426+ #[ cfg( feature = "mldsa" ) ]
427+ Self :: MlDsa ( key) => key. encode ( writer) ?,
392428 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
393429 Self :: SkEcdsaSha2NistP256 ( sk) => sk. encode ( writer) ?,
394430 #[ cfg( feature = "alloc" ) ]
@@ -415,6 +451,8 @@ impl TryFrom<&KeypairData> for public::KeyData {
415451 KeypairData :: Encrypted ( _) => return Err ( Error :: Encrypted ) ,
416452 #[ cfg( feature = "alloc" ) ]
417453 KeypairData :: Rsa ( rsa) => public:: KeyData :: Rsa ( rsa. into ( ) ) ,
454+ #[ cfg( feature = "mldsa" ) ]
455+ KeypairData :: MlDsa ( mldsa) => public:: KeyData :: MlDsa ( mldsa. into ( ) ) ,
418456 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
419457 KeypairData :: SkEcdsaSha2NistP256 ( sk) => {
420458 public:: KeyData :: SkEcdsaSha2NistP256 ( sk. public ( ) . clone ( ) )
@@ -454,6 +492,13 @@ impl From<RsaKeypair> for KeypairData {
454492 }
455493}
456494
495+ #[ cfg( feature = "mldsa" ) ]
496+ impl From < MlDsaKeypair > for KeypairData {
497+ fn from ( keypair : MlDsaKeypair ) -> KeypairData {
498+ Self :: MlDsa ( keypair)
499+ }
500+ }
501+
457502#[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
458503impl From < SkEcdsaSha2NistP256 > for KeypairData {
459504 fn from ( keypair : SkEcdsaSha2NistP256 ) -> KeypairData {
0 commit comments