@@ -13,7 +13,6 @@ use crate::{private::Ed25519Keypair, public::Ed25519PublicKey};
1313use {
1414 crate :: { private:: DsaKeypair , public:: DsaPublicKey } ,
1515 bigint:: BigUint ,
16- core:: iter,
1716 sha1:: Sha1 ,
1817 signature:: { DigestSigner , DigestVerifier } ,
1918} ;
@@ -24,6 +23,9 @@ use crate::{
2423 public:: EcdsaPublicKey ,
2524} ;
2625
26+ #[ cfg( any( feature = "dsa" , feature = "p256" , feature = "p384" , feature = "p521" ) ) ]
27+ use core:: iter;
28+
2729#[ cfg( feature = "rsa" ) ]
2830use {
2931 crate :: { private:: RsaKeypair , public:: RsaPublicKey , HashAlg } ,
@@ -151,7 +153,7 @@ fn ecdsa_sig_size(data: &Vec<u8>, curve: EcdsaCurve, sk_trailer: bool) -> Result
151153 for _ in 0 ..2 {
152154 let component = Mpint :: decode ( reader) ?;
153155
154- if component. as_positive_bytes ( ) . ok_or ( Error :: Crypto ) ?. len ( ) != curve. field_size ( ) {
156+ if component. as_positive_bytes ( ) . ok_or ( Error :: Crypto ) ?. len ( ) > curve. field_size ( ) {
155157 return Err ( encoding:: Error :: Length . into ( ) ) ;
156158 }
157159 }
@@ -519,6 +521,17 @@ impl_signature_for_curve!(p256, "p256", NistP256, 32);
519521impl_signature_for_curve ! ( p384, "p384" , NistP384 , 48 ) ;
520522impl_signature_for_curve ! ( p521, "p521" , NistP521 , 66 ) ;
521523
524+ /// Build a generic sized object from a `u8` iterator, with leading zero padding
525+ #[ cfg( any( feature = "p256" , feature = "p384" , feature = "p521" ) ) ]
526+ fn zero_pad_field_bytes < B : FromIterator < u8 > + Copy > ( m : Mpint ) -> Option < B > {
527+ use core:: mem:: size_of;
528+
529+ let bytes = m. as_positive_bytes ( ) ?;
530+ size_of :: < B > ( )
531+ . checked_sub ( bytes. len ( ) )
532+ . map ( |i| B :: from_iter ( iter:: repeat ( 0u8 ) . take ( i) . chain ( bytes. iter ( ) . cloned ( ) ) ) )
533+ }
534+
522535#[ cfg( feature = "p256" ) ]
523536impl TryFrom < & Signature > for p256:: ecdsa:: Signature {
524537 type Error = Error ;
@@ -534,19 +547,15 @@ impl TryFrom<&Signature> for p256::ecdsa::Signature {
534547}
535548#[ cfg( feature = "p256" ) ]
536549fn p256_signature_from_openssh_bytes ( mut signature_bytes : & [ u8 ] ) -> Result < p256:: ecdsa:: Signature > {
537- const FIELD_SIZE : usize = 32 ;
538-
539550 let reader = & mut signature_bytes;
540551 let r = Mpint :: decode ( reader) ?;
541552 let s = Mpint :: decode ( reader) ?;
542553
543- match ( r. as_positive_bytes ( ) , s. as_positive_bytes ( ) ) {
544- ( Some ( r) , Some ( s) ) if r. len ( ) == FIELD_SIZE && s. len ( ) == FIELD_SIZE => {
545- Ok ( p256:: ecdsa:: Signature :: from_scalars (
546- * p256:: FieldBytes :: from_slice ( r) ,
547- * p256:: FieldBytes :: from_slice ( s) ,
548- ) ?)
549- }
554+ match (
555+ zero_pad_field_bytes :: < p256:: FieldBytes > ( r) ,
556+ zero_pad_field_bytes :: < p256:: FieldBytes > ( s) ,
557+ ) {
558+ ( Some ( r) , Some ( s) ) => Ok ( p256:: ecdsa:: Signature :: from_scalars ( r, s) ?) ,
550559 _ => Err ( Error :: Crypto ) ,
551560 }
552561}
@@ -556,8 +565,6 @@ impl TryFrom<&Signature> for p384::ecdsa::Signature {
556565 type Error = Error ;
557566
558567 fn try_from ( signature : & Signature ) -> Result < p384:: ecdsa:: Signature > {
559- const FIELD_SIZE : usize = 48 ;
560-
561568 match signature. algorithm {
562569 Algorithm :: Ecdsa {
563570 curve : EcdsaCurve :: NistP384 ,
@@ -566,13 +573,11 @@ impl TryFrom<&Signature> for p384::ecdsa::Signature {
566573 let r = Mpint :: decode ( reader) ?;
567574 let s = Mpint :: decode ( reader) ?;
568575
569- match ( r. as_positive_bytes ( ) , s. as_positive_bytes ( ) ) {
570- ( Some ( r) , Some ( s) ) if r. len ( ) == FIELD_SIZE && s. len ( ) == FIELD_SIZE => {
571- Ok ( p384:: ecdsa:: Signature :: from_scalars (
572- * p384:: FieldBytes :: from_slice ( r) ,
573- * p384:: FieldBytes :: from_slice ( s) ,
574- ) ?)
575- }
576+ match (
577+ zero_pad_field_bytes :: < p384:: FieldBytes > ( r) ,
578+ zero_pad_field_bytes :: < p384:: FieldBytes > ( s) ,
579+ ) {
580+ ( Some ( r) , Some ( s) ) => Ok ( p384:: ecdsa:: Signature :: from_scalars ( r, s) ?) ,
576581 _ => Err ( Error :: Crypto ) ,
577582 }
578583 }
@@ -586,8 +591,6 @@ impl TryFrom<&Signature> for p521::ecdsa::Signature {
586591 type Error = Error ;
587592
588593 fn try_from ( signature : & Signature ) -> Result < p521:: ecdsa:: Signature > {
589- const FIELD_SIZE : usize = 66 ;
590-
591594 match signature. algorithm {
592595 Algorithm :: Ecdsa {
593596 curve : EcdsaCurve :: NistP521 ,
@@ -596,13 +599,11 @@ impl TryFrom<&Signature> for p521::ecdsa::Signature {
596599 let r = Mpint :: decode ( reader) ?;
597600 let s = Mpint :: decode ( reader) ?;
598601
599- match ( r. as_positive_bytes ( ) , s. as_positive_bytes ( ) ) {
600- ( Some ( r) , Some ( s) ) if r. len ( ) == FIELD_SIZE && s. len ( ) == FIELD_SIZE => {
601- Ok ( p521:: ecdsa:: Signature :: from_scalars (
602- * p521:: FieldBytes :: from_slice ( r) ,
603- * p521:: FieldBytes :: from_slice ( s) ,
604- ) ?)
605- }
602+ match (
603+ zero_pad_field_bytes :: < p521:: FieldBytes > ( r) ,
604+ zero_pad_field_bytes :: < p521:: FieldBytes > ( s) ,
605+ ) {
606+ ( Some ( r) , Some ( s) ) => Ok ( p521:: ecdsa:: Signature :: from_scalars ( r, s) ?) ,
606607 _ => Err ( Error :: Crypto ) ,
607608 }
608609 }
@@ -712,6 +713,9 @@ mod tests {
712713 signature:: { Signer , Verifier } ,
713714 } ;
714715
716+ #[ cfg( feature = "p256" ) ]
717+ use super :: { zero_pad_field_bytes, Mpint } ;
718+
715719 const DSA_SIGNATURE : & [ u8 ] = & hex ! ( "000000077373682d6473730000002866725bf3c56100e975e21fff28a60f73717534d285ea3e1beefc2891f7189d00bd4d94627e84c55c" ) ;
716720 const ECDSA_SHA2_P256_SIGNATURE : & [ u8 ] = & hex ! ( "0000001365636473612d736861322d6e6973747032353600000048000000201298ab320720a32139cda8a40c97a13dc54ce032ea3c6f09ea9e87501e48fa1d0000002046e4ac697a6424a9870b9ef04ca1182cd741965f989bd1f1f4a26fd83cf70348" ) ;
717721 const ED25519_SIGNATURE : & [ u8 ] = & hex ! ( "0000000b7373682d65643235353139000000403d6b9906b76875aef1e7b2f1e02078a94f439aebb9a4734da1a851a81e22ce0199bbf820387a8de9c834c9c3cc778d9972dcbe70f68d53cc6bc9e26b02b46d04" ) ;
@@ -729,6 +733,35 @@ mod tests {
729733 let _ssh_signature = Signature :: try_from ( p256_signature) . unwrap ( ) ;
730734 }
731735
736+ #[ cfg( feature = "p256" ) ]
737+ #[ test]
738+ fn zero_pad_field_bytes_p256 ( ) {
739+ let i = Mpint :: from_bytes ( & hex ! (
740+ "1122334455667788112233445566778811223344556677881122334455667788"
741+ ) )
742+ . unwrap ( ) ;
743+ let fb = zero_pad_field_bytes :: < p256:: FieldBytes > ( i) ;
744+ assert ! ( fb. is_some( ) ) ;
745+
746+ // too long
747+ let i = Mpint :: from_bytes ( & hex ! (
748+ "991122334455667788112233445566778811223344556677881122334455667788"
749+ ) )
750+ . unwrap ( ) ;
751+ let fb = zero_pad_field_bytes :: < p256:: FieldBytes > ( i) ;
752+ assert ! ( fb. is_none( ) ) ;
753+
754+ // short is okay
755+ let i = Mpint :: from_bytes ( & hex ! (
756+ "22334455667788112233445566778811223344556677881122334455667788"
757+ ) )
758+ . unwrap ( ) ;
759+ let fb = zero_pad_field_bytes :: < p256:: FieldBytes > ( i)
760+ . expect ( "failed to build FieldBytes from short hex string" ) ;
761+ assert_eq ! ( fb[ 0 ] , 0x00 ) ;
762+ assert_eq ! ( fb[ 1 ] , 0x22 ) ;
763+ }
764+
732765 #[ test]
733766 fn decode_dsa ( ) {
734767 let signature = Signature :: try_from ( DSA_SIGNATURE ) . unwrap ( ) ;
0 commit comments