1414//
1515use std:: convert:: TryFrom ;
1616
17+ use block_padding:: generic_array:: GenericArray ;
1718use ed25519_dalek:: { Signer , Verifier } ;
1819#[ cfg( feature = "openssl" ) ]
1920use openssl:: pkey:: { Private , Public } ;
@@ -38,6 +39,8 @@ impl AsRef<str> for Name {
3839
3940/// The name of the ecdsa-sha2-nistp256 algorithm for SSH.
4041pub const ECDSA_SHA2_NISTP256 : Name = Name ( "ecdsa-sha2-nistp256" ) ;
42+ /// The name of the ecdsa-sha2-nistp521 algorithm for SSH.
43+ pub const ECDSA_SHA2_NISTP521 : Name = Name ( "ecdsa-sha2-nistp521" ) ;
4144/// The name of the Ed25519 algorithm for SSH.
4245pub const ED25519 : Name = Name ( "ssh-ed25519" ) ;
4346/// The name of the ssh-sha2-512 algorithm for SSH.
@@ -53,7 +56,7 @@ impl Name {
5356 /// Base name of the private key file for a key name.
5457 pub fn identity_file ( & self ) -> & ' static str {
5558 match * self {
56- ECDSA_SHA2_NISTP256 => "id_ecdsa" ,
59+ ECDSA_SHA2_NISTP256 | ECDSA_SHA2_NISTP521 => "id_ecdsa" ,
5760 ED25519 => "id_ed25519" ,
5861 RSA_SHA2_512 => "id_rsa" ,
5962 RSA_SHA2_256 => "id_rsa" ,
@@ -123,6 +126,8 @@ pub enum PublicKey {
123126 } ,
124127 #[ doc( hidden) ]
125128 P256 ( p256:: PublicKey ) ,
129+ #[ doc( hidden) ]
130+ P521 ( p521:: PublicKey ) ,
126131}
127132
128133impl PartialEq for PublicKey {
@@ -132,6 +137,7 @@ impl PartialEq for PublicKey {
132137 ( Self :: RSA { key : a, .. } , Self :: RSA { key : b, .. } ) => a == b,
133138 ( Self :: Ed25519 ( a) , Self :: Ed25519 ( b) ) => a == b,
134139 ( Self :: P256 ( a) , Self :: P256 ( b) ) => a == b,
140+ ( Self :: P521 ( a) , Self :: P521 ( b) ) => a == b,
135141 _ => false ,
136142 }
137143 }
@@ -223,6 +229,18 @@ impl PublicKey {
223229 . map_err ( |_| Error :: CouldNotReadKey ) ?;
224230 Ok ( PublicKey :: P256 ( key) )
225231 }
232+ b"ecdsa-sha2-nistp521" => {
233+ let mut p = pubkey. reader ( 0 ) ;
234+ let key_algo = p. read_string ( ) ?;
235+ let curve = p. read_string ( ) ?;
236+ if key_algo != b"ecdsa-sha2-nistp521" || curve != b"nistp521" {
237+ return Err ( Error :: CouldNotReadKey ) ;
238+ }
239+ let sec1_bytes = p. read_string ( ) ?;
240+ let key = p521:: PublicKey :: from_sec1_bytes ( sec1_bytes)
241+ . map_err ( |_| Error :: CouldNotReadKey ) ?;
242+ Ok ( PublicKey :: P521 ( key) )
243+ }
226244 _ => Err ( Error :: CouldNotReadKey ) ,
227245 }
228246 }
@@ -234,6 +252,7 @@ impl PublicKey {
234252 #[ cfg( feature = "openssl" ) ]
235253 PublicKey :: RSA { ref hash, .. } => hash. name ( ) . 0 ,
236254 PublicKey :: P256 ( _) => ECDSA_SHA2_NISTP256 . 0 ,
255+ PublicKey :: P521 ( _) => ECDSA_SHA2_NISTP521 . 0 ,
237256 }
238257 }
239258
@@ -282,6 +301,31 @@ impl PublicKey {
282301 . verify ( buffer, & signature)
283302 . is_ok ( )
284303 }
304+ PublicKey :: P521 ( ref public) => {
305+ const FIELD_LEN : usize =
306+ <p521:: NistP521 as p256:: elliptic_curve:: Curve >:: FieldBytesSize :: USIZE ;
307+ let mut reader = sig. reader ( 0 ) ;
308+ let mut read_field = || -> Option < p521:: FieldBytes > {
309+ let f = reader. read_mpint ( ) . ok ( ) ?;
310+ let f = f. strip_prefix ( & [ 0 ] ) . unwrap_or ( f) ;
311+ let mut result = [ 0 ; FIELD_LEN ] ;
312+ if f. len ( ) > FIELD_LEN {
313+ return None ;
314+ }
315+ #[ allow( clippy:: indexing_slicing) ] // length is known
316+ result[ FIELD_LEN - f. len ( ) ..] . copy_from_slice ( f) ;
317+ // Some(result.into())
318+ Some ( GenericArray :: clone_from_slice ( & result) ) // ew
319+ } ;
320+ let Some ( r) = read_field ( ) else { return false } ;
321+ let Some ( s) = read_field ( ) else { return false } ;
322+ let Ok ( signature) = p521:: ecdsa:: Signature :: from_scalars ( r, s) else {
323+ return false ;
324+ } ;
325+ p521:: ecdsa:: VerifyingKey :: from_sec1_bytes ( & public. to_sec1_bytes ( ) ) . unwrap ( ) // also ew
326+ . verify ( buffer, & signature)
327+ . is_ok ( )
328+ }
285329 }
286330 }
287331
@@ -560,5 +604,13 @@ pub fn parse_public_key(
560604 let key = p256:: PublicKey :: from_sec1_bytes ( sec1_bytes) ?;
561605 return Ok ( PublicKey :: P256 ( key) ) ;
562606 }
607+ if t == b"ecdsa-sha2-nistp521" {
608+ if pos. read_string ( ) ? != b"nistp521" {
609+ return Err ( Error :: CouldNotReadKey ) ;
610+ }
611+ let sec1_bytes = pos. read_string ( ) ?;
612+ let key = p521:: PublicKey :: from_sec1_bytes ( sec1_bytes) ?;
613+ return Ok ( PublicKey :: P521 ( key) ) ;
614+ }
563615 Err ( Error :: CouldNotReadKey )
564616}
0 commit comments