@@ -7,7 +7,7 @@ use encoding::{CheckedSum, Decode, Encode, Reader, Writer};
77
88#[ cfg( feature = "alloc" ) ]
99use {
10- super :: { DsaKeypair , OpaqueKeypair , RsaKeypair , SkEd25519 } ,
10+ super :: { DsaKeypair , MlDsaKeypair , OpaqueKeypair , RsaKeypair , SkEd25519 } ,
1111 alloc:: vec:: Vec ,
1212} ;
1313
@@ -44,6 +44,10 @@ pub enum KeypairData {
4444 #[ cfg( feature = "alloc" ) ]
4545 Rsa ( RsaKeypair ) ,
4646
47+ /// ML-DSA keypair
48+ #[ cfg( feature = "alloc" ) ]
49+ MlDsa ( MlDsaKeypair ) ,
50+
4751 /// Security Key (FIDO/U2F) using ECDSA/NIST P-256 as specified in [PROTOCOL.u2f].
4852 ///
4953 /// [PROTOCOL.u2f]: https://cvsweb.openbsd.org/src/usr.bin/ssh/PROTOCOL.u2f?annotate=HEAD
@@ -77,6 +81,8 @@ impl KeypairData {
7781 Self :: Encrypted ( _) => return Err ( Error :: Encrypted ) ,
7882 #[ cfg( feature = "alloc" ) ]
7983 Self :: Rsa ( _) => Algorithm :: Rsa { hash : None } ,
84+ #[ cfg( feature = "alloc" ) ]
85+ Self :: MlDsa ( key) => key. algorithm ( ) ,
8086 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
8187 Self :: SkEcdsaSha2NistP256 ( _) => Algorithm :: SkEcdsaSha2NistP256 ,
8288 #[ cfg( feature = "alloc" ) ]
@@ -136,6 +142,16 @@ impl KeypairData {
136142 }
137143 }
138144
145+ /// Get ML-DSA keypair if this key is the correct type.
146+ #[ cfg( feature = "alloc" ) ]
147+ #[ must_use]
148+ pub fn mldsa ( & self ) -> Option < & MlDsaKeypair > {
149+ match self {
150+ Self :: MlDsa ( key) => Some ( key) ,
151+ _ => None ,
152+ }
153+ }
154+
139155 /// Get FIDO/U2F ECDSA/NIST P-256 private key if this key is the correct type.
140156 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
141157 #[ must_use]
@@ -207,6 +223,13 @@ impl KeypairData {
207223 matches ! ( self , Self :: Rsa ( _) )
208224 }
209225
226+ /// Is this key an ML-DSA key?
227+ #[ cfg( feature = "alloc" ) ]
228+ #[ must_use]
229+ pub fn is_mldsa ( & self ) -> bool {
230+ matches ! ( self , Self :: MlDsa ( _) )
231+ }
232+
210233 /// Is this key a FIDO/U2F ECDSA/NIST P-256 key?
211234 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
212235 #[ must_use]
@@ -243,6 +266,8 @@ impl KeypairData {
243266 Self :: Encrypted ( ciphertext) => ciphertext. as_ref ( ) ,
244267 #[ cfg( feature = "alloc" ) ]
245268 Self :: Rsa ( rsa) => rsa. private ( ) . d ( ) . as_bytes ( ) ,
269+ #[ cfg( feature = "alloc" ) ]
270+ Self :: MlDsa ( mldsa) => mldsa. private . as_ref ( ) ,
246271 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
247272 Self :: SkEcdsaSha2NistP256 ( sk) => sk. key_handle ( ) ,
248273 #[ cfg( feature = "alloc" ) ]
@@ -278,6 +303,8 @@ impl KeypairData {
278303 Algorithm :: Ed25519 => Ed25519Keypair :: decode ( reader) . map ( Self :: Ed25519 ) ,
279304 #[ cfg( feature = "alloc" ) ]
280305 Algorithm :: Rsa { .. } => RsaKeypair :: decode ( reader) . map ( Self :: Rsa ) ,
306+ #[ cfg( feature = "alloc" ) ]
307+ Algorithm :: MlDsa { params } => MlDsaKeypair :: decode_as ( reader, params) . map ( Self :: MlDsa ) ,
281308 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
282309 Algorithm :: SkEcdsaSha2NistP256 => {
283310 SkEcdsaSha2NistP256 :: decode ( reader) . map ( Self :: SkEcdsaSha2NistP256 )
@@ -307,6 +334,8 @@ impl CtEq for KeypairData {
307334 ( Self :: Encrypted ( a) , Self :: Encrypted ( b) ) => a. ct_eq ( b) ,
308335 #[ cfg( feature = "alloc" ) ]
309336 ( Self :: Rsa ( a) , Self :: Rsa ( b) ) => a. ct_eq ( b) ,
337+ #[ cfg( feature = "alloc" ) ]
338+ ( Self :: MlDsa ( a) , Self :: MlDsa ( b) ) => a. ct_eq ( b) ,
310339 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
311340 ( Self :: SkEcdsaSha2NistP256 ( a) , Self :: SkEcdsaSha2NistP256 ( b) ) => {
312341 // Security Keys store the actual private key in hardware.
@@ -363,6 +392,8 @@ impl Encode for KeypairData {
363392 Self :: Encrypted ( ciphertext) => return Ok ( ciphertext. len ( ) ) ,
364393 #[ cfg( feature = "alloc" ) ]
365394 Self :: Rsa ( key) => key. encoded_len ( ) ?,
395+ #[ cfg( feature = "alloc" ) ]
396+ Self :: MlDsa ( key) => key. encoded_len ( ) ?,
366397 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
367398 Self :: SkEcdsaSha2NistP256 ( sk) => sk. encoded_len ( ) ?,
368399 #[ cfg( feature = "alloc" ) ]
@@ -389,6 +420,8 @@ impl Encode for KeypairData {
389420 Self :: Encrypted ( ciphertext) => writer. write ( ciphertext) ?,
390421 #[ cfg( feature = "alloc" ) ]
391422 Self :: Rsa ( key) => key. encode ( writer) ?,
423+ #[ cfg( feature = "alloc" ) ]
424+ Self :: MlDsa ( key) => key. encode ( writer) ?,
392425 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
393426 Self :: SkEcdsaSha2NistP256 ( sk) => sk. encode ( writer) ?,
394427 #[ cfg( feature = "alloc" ) ]
@@ -415,6 +448,8 @@ impl TryFrom<&KeypairData> for public::KeyData {
415448 KeypairData :: Encrypted ( _) => return Err ( Error :: Encrypted ) ,
416449 #[ cfg( feature = "alloc" ) ]
417450 KeypairData :: Rsa ( rsa) => public:: KeyData :: Rsa ( rsa. into ( ) ) ,
451+ #[ cfg( feature = "alloc" ) ]
452+ KeypairData :: MlDsa ( mldsa) => public:: KeyData :: MlDsa ( mldsa. into ( ) ) ,
418453 #[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
419454 KeypairData :: SkEcdsaSha2NistP256 ( sk) => {
420455 public:: KeyData :: SkEcdsaSha2NistP256 ( sk. public ( ) . clone ( ) )
@@ -454,6 +489,13 @@ impl From<RsaKeypair> for KeypairData {
454489 }
455490}
456491
492+ #[ cfg( feature = "alloc" ) ]
493+ impl From < MlDsaKeypair > for KeypairData {
494+ fn from ( keypair : MlDsaKeypair ) -> KeypairData {
495+ Self :: MlDsa ( keypair)
496+ }
497+ }
498+
457499#[ cfg( all( feature = "alloc" , feature = "ecdsa" ) ) ]
458500impl From < SkEcdsaSha2NistP256 > for KeypairData {
459501 fn from ( keypair : SkEcdsaSha2NistP256 ) -> KeypairData {
0 commit comments