1010//! Apache License (Version 2.0), and the BSD 1-Clause License;
1111//! users may pick which license to apply.
1212
13- // TODO(tarcieri): 32-bit backend?
14- #[ path = "field/p521_64.rs" ]
13+ # [ cfg_attr ( target_pointer_width = "32" , path = "field/p521_32.rs" ) ]
14+ #[ cfg_attr ( target_pointer_width = "64" , path = "field/p521_64.rs" ) ]
1515#[ allow( clippy:: needless_lifetimes, clippy:: unnecessary_cast) ]
1616#[ allow( dead_code) ] // TODO(tarcieri): remove this when we can use `const _` to silence warnings
17+ #[ rustfmt:: skip]
1718mod field_impl;
1819mod loose;
1920
2021pub ( crate ) use self :: loose:: LooseFieldElement ;
2122
2223use self :: field_impl:: * ;
23- use crate :: { FieldBytes , NistP521 , U576 } ;
24+ use crate :: { FieldBytes , NistP521 , Uint } ;
2425use core:: {
26+ cmp:: Ordering ,
2527 fmt:: { self , Debug } ,
2628 iter:: { Product , Sum } ,
2729 ops:: { Add , AddAssign , Mul , MulAssign , Neg , Sub , SubAssign } ,
2830} ;
29- use elliptic_curve:: ops:: Invert ;
3031use elliptic_curve:: {
3132 Error , FieldBytesEncoding ,
33+ bigint:: Word ,
3234 ff:: { self , Field , PrimeField } ,
35+ ops:: Invert ,
3336 rand_core:: TryRngCore ,
3437 subtle:: { Choice , ConditionallySelectable , ConstantTimeEq , ConstantTimeLess , CtOption } ,
3538 zeroize:: DefaultIsZeroes ,
3639} ;
37- use primefield:: bigint:: { Limb , Uint } ;
40+ use primefield:: bigint:: { self , Limb } ;
3841
42+ #[ cfg( target_pointer_width = "32" ) ]
43+ const MODULUS_HEX : & str = "000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ;
44+ #[ cfg( target_pointer_width = "64" ) ]
3945const MODULUS_HEX : & str = "00000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" ;
4046
4147/// Field modulus: p = 2^{521} − 1
42- pub ( crate ) const MODULUS : U576 = U576 :: from_be_hex ( MODULUS_HEX ) ;
48+ pub ( crate ) const MODULUS : Uint = Uint :: from_be_hex ( MODULUS_HEX ) ;
4349
4450/// Element of the secp521r1 base field used for curve coordinates.
4551#[ derive( Clone , Copy ) ]
@@ -52,9 +58,14 @@ impl FieldElement {
5258 /// Multiplicative identity.
5359 pub const ONE : Self = Self :: from_u64 ( 1 ) ;
5460
61+ #[ cfg( target_pointer_width = "32" ) ]
62+ const LIMBS : usize = 19 ;
63+ #[ cfg( target_pointer_width = "64" ) ]
64+ const LIMBS : usize = 9 ;
65+
5566 /// Create a [`FieldElement`] from a canonical big-endian representation.
5667 pub fn from_bytes ( repr : & FieldBytes ) -> CtOption < Self > {
57- let uint = <U576 as FieldBytesEncoding < NistP521 > >:: decode_field_bytes ( repr) ;
68+ let uint = <Uint as FieldBytesEncoding < NistP521 > >:: decode_field_bytes ( repr) ;
5869 Self :: from_uint ( uint)
5970 }
6071
@@ -64,33 +75,56 @@ impl FieldElement {
6475 Self :: from_bytes ( & field_bytes) . into_option ( ) . ok_or ( Error )
6576 }
6677
67- /// Decode [`FieldElement`] from [`U576 `].
68- pub fn from_uint ( uint : U576 ) -> CtOption < Self > {
78+ /// Decode [`FieldElement`] from [`Uint `].
79+ pub fn from_uint ( uint : Uint ) -> CtOption < Self > {
6980 let is_some = uint. ct_lt ( & MODULUS ) ;
7081 CtOption :: new ( Self :: from_uint_unchecked ( uint) , is_some)
7182 }
7283
7384 /// Parse a [`FieldElement`] from big endian hex-encoded bytes.
7485 ///
75- /// Does *not* perform a check that the field element does not overflow the order.
76- ///
7786 /// This method is primarily intended for defining internal constants.
78- pub ( crate ) const fn from_hex_unchecked ( hex : & str ) -> Self {
79- Self :: from_uint_unchecked ( U576 :: from_be_hex ( hex) )
87+ ///
88+ /// # Panics
89+ /// - if the input in hex is not the correct length
90+ /// - if the given value when decoded from hex overflows the modulus
91+ pub ( crate ) const fn from_hex ( hex : & str ) -> Self {
92+ assert ! (
93+ hex. len( ) == 521usize . div_ceil( 8 ) * 2 ,
94+ "hex is the wrong length (expected 132 hex chars)"
95+ ) ;
96+
97+ // Build a hex string of the expected size, regardless of the size of `Uint`
98+ let mut hex_bytes = [ b'0' ; { Uint :: BITS as usize / 4 } ] ;
99+
100+ let offset = hex_bytes. len ( ) - hex. len ( ) ;
101+ let mut i = 0 ;
102+ while i < hex. len ( ) {
103+ hex_bytes[ i + offset] = hex. as_bytes ( ) [ i] ;
104+ i += 1 ;
105+ }
106+
107+ let uint = match core:: str:: from_utf8 ( & hex_bytes) {
108+ Ok ( padded_hex) => Uint :: from_be_hex ( padded_hex) ,
109+ Err ( _) => panic ! ( "invalid hex string" ) ,
110+ } ;
111+
112+ assert ! ( matches!( uint. cmp_vartime( & MODULUS ) , Ordering :: Less ) ) ;
113+ Self :: from_uint_unchecked ( uint)
80114 }
81115
82116 /// Convert a `u64` into a [`FieldElement`].
83117 pub const fn from_u64 ( w : u64 ) -> Self {
84- Self :: from_uint_unchecked ( U576 :: from_u64 ( w) )
118+ Self :: from_uint_unchecked ( Uint :: from_u64 ( w) )
85119 }
86120
87- /// Decode [`FieldElement`] from [`U576 `].
121+ /// Decode [`FieldElement`] from [`Uint `].
88122 ///
89123 /// Does *not* perform a check that the field element does not overflow the order.
90124 ///
91125 /// Used incorrectly this can lead to invalid results!
92- pub ( crate ) const fn from_uint_unchecked ( w : U576 ) -> Self {
93- // Converts the saturated representation used by `U576 ` into a 66-byte array with a
126+ pub ( crate ) const fn from_uint_unchecked ( w : Uint ) -> Self {
127+ // Converts the saturated representation used by `Uint ` into a 66-byte array with a
94128 // little-endian byte ordering.
95129 // TODO(tarcieri): use `FieldBytesEncoding::encode_field_bytes` when `const impl` is stable
96130 let le_bytes_wide = w. to_le_bytes ( ) ;
@@ -106,7 +140,7 @@ impl FieldElement {
106140
107141 // Decode the little endian serialization into the unsaturated big integer form used by
108142 // the fiat-crypto synthesized code.
109- let mut out = fiat_p521_tight_field_element ( [ 0 ; 9 ] ) ;
143+ let mut out = fiat_p521_tight_field_element ( [ 0 ; Self :: LIMBS ] ) ;
110144 fiat_p521_from_bytes ( & mut out, & le_bytes) ;
111145 Self ( out)
112146 }
@@ -149,7 +183,7 @@ impl FieldElement {
149183 /// Add elements.
150184 #[ inline]
151185 pub const fn add_loose ( & self , rhs : & Self ) -> LooseFieldElement {
152- let mut out = fiat_p521_loose_field_element ( [ 0 ; 9 ] ) ;
186+ let mut out = fiat_p521_loose_field_element ( [ 0 ; Self :: LIMBS ] ) ;
153187 fiat_p521_add ( & mut out, & self . 0 , & rhs. 0 ) ;
154188 LooseFieldElement ( out)
155189 }
@@ -164,39 +198,39 @@ impl FieldElement {
164198 /// Subtract elements, returning a loose field element.
165199 #[ inline]
166200 pub const fn sub_loose ( & self , rhs : & Self ) -> LooseFieldElement {
167- let mut out = fiat_p521_loose_field_element ( [ 0 ; 9 ] ) ;
201+ let mut out = fiat_p521_loose_field_element ( [ 0 ; Self :: LIMBS ] ) ;
168202 fiat_p521_sub ( & mut out, & self . 0 , & rhs. 0 ) ;
169203 LooseFieldElement ( out)
170204 }
171205
172206 /// Negate element, returning a loose field element.
173207 #[ inline]
174208 pub const fn neg_loose ( & self ) -> LooseFieldElement {
175- let mut out = fiat_p521_loose_field_element ( [ 0 ; 9 ] ) ;
209+ let mut out = fiat_p521_loose_field_element ( [ 0 ; Self :: LIMBS ] ) ;
176210 fiat_p521_opp ( & mut out, & self . 0 ) ;
177211 LooseFieldElement ( out)
178212 }
179213
180214 /// Add two field elements.
181215 #[ inline]
182216 pub const fn add ( & self , rhs : & Self ) -> Self {
183- let mut out = fiat_p521_tight_field_element ( [ 0 ; 9 ] ) ;
217+ let mut out = fiat_p521_tight_field_element ( [ 0 ; Self :: LIMBS ] ) ;
184218 fiat_p521_carry_add ( & mut out, & self . 0 , & rhs. 0 ) ;
185219 Self ( out)
186220 }
187221
188222 /// Subtract field elements.
189223 #[ inline]
190224 pub const fn sub ( & self , rhs : & Self ) -> Self {
191- let mut out = fiat_p521_tight_field_element ( [ 0 ; 9 ] ) ;
225+ let mut out = fiat_p521_tight_field_element ( [ 0 ; Self :: LIMBS ] ) ;
192226 fiat_p521_carry_sub ( & mut out, & self . 0 , & rhs. 0 ) ;
193227 Self ( out)
194228 }
195229
196230 /// Negate element.
197231 #[ inline]
198232 pub const fn neg ( & self ) -> Self {
199- let mut out = fiat_p521_tight_field_element ( [ 0 ; 9 ] ) ;
233+ let mut out = fiat_p521_tight_field_element ( [ 0 ; Self :: LIMBS ] ) ;
200234 fiat_p521_carry_opp ( & mut out, & self . 0 ) ;
201235 Self ( out)
202236 }
@@ -236,7 +270,7 @@ impl FieldElement {
236270 /// **This operation is variable time with respect to the exponent `exp`.**
237271 ///
238272 /// If the exponent is fixed, this operation is constant time.
239- pub const fn pow_vartime < const RHS_LIMBS : usize > ( & self , exp : & Uint < RHS_LIMBS > ) -> Self {
273+ pub const fn pow_vartime < const RHS_LIMBS : usize > ( & self , exp : & bigint :: Uint < RHS_LIMBS > ) -> Self {
240274 let mut res = Self :: ONE ;
241275 let mut i = RHS_LIMBS ;
242276
@@ -329,7 +363,7 @@ impl FieldElement {
329363 /// Relax a tight field element into a loose one.
330364 #[ inline]
331365 pub const fn relax ( & self ) -> LooseFieldElement {
332- let mut out = fiat_p521_loose_field_element ( [ 0 ; 9 ] ) ;
366+ let mut out = fiat_p521_loose_field_element ( [ 0 ; Self :: LIMBS ] ) ;
333367 fiat_p521_relax ( & mut out, & self . 0 ) ;
334368 LooseFieldElement ( out)
335369 }
@@ -389,32 +423,25 @@ impl PartialEq for FieldElement {
389423
390424impl From < u32 > for FieldElement {
391425 fn from ( n : u32 ) -> FieldElement {
392- Self :: from_uint_unchecked ( U576 :: from ( n) )
426+ Self :: from_uint_unchecked ( Uint :: from ( n) )
393427 }
394428}
395429
396430impl From < u64 > for FieldElement {
397431 fn from ( n : u64 ) -> FieldElement {
398- Self :: from_uint_unchecked ( U576 :: from ( n) )
432+ Self :: from_uint_unchecked ( Uint :: from ( n) )
399433 }
400434}
401435
402436impl From < u128 > for FieldElement {
403437 fn from ( n : u128 ) -> FieldElement {
404- Self :: from_uint_unchecked ( U576 :: from ( n) )
438+ Self :: from_uint_unchecked ( Uint :: from ( n) )
405439 }
406440}
407441
408442impl ConditionallySelectable for FieldElement {
409443 fn conditional_select ( a : & Self , b : & Self , choice : Choice ) -> Self {
410- let mut out = [ 0 ; 9 ] ;
411- let a = & a. 0 ;
412- let b = & b. 0 ;
413-
414- for i in 0 ..out. len ( ) {
415- out[ i] = u64:: conditional_select ( & a[ i] , & b[ i] , choice) ;
416- }
417-
444+ let out = <[ Word ; Self :: LIMBS ] >:: conditional_select ( & a. 0 . 0 , & b. 0 . 0 , choice) ;
418445 Self ( fiat_p521_tight_field_element ( out) )
419446 }
420447}
@@ -479,8 +506,8 @@ impl PrimeField for FieldElement {
479506 const TWO_INV : Self = Self :: from_u64 ( 2 ) . invert_unchecked ( ) ;
480507 const MULTIPLICATIVE_GENERATOR : Self = Self :: from_u64 ( 3 ) ;
481508 const S : u32 = 1 ;
482- const ROOT_OF_UNITY : Self = Self :: from_hex_unchecked (
483- "00000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe " ,
509+ const ROOT_OF_UNITY : Self = Self :: from_hex (
510+ "01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe " ,
484511 ) ;
485512 const ROOT_OF_UNITY_INV : Self = Self :: ROOT_OF_UNITY . invert_unchecked ( ) ;
486513 const DELTA : Self = Self :: from_u64 ( 9 ) ;
@@ -675,10 +702,10 @@ impl Invert for FieldElement {
675702
676703#[ cfg( test) ]
677704mod tests {
678- use super :: { FieldElement , U576 } ;
705+ use super :: { FieldElement , Uint } ;
679706 use hex_literal:: hex;
680707
681- primefield:: test_primefield!( FieldElement , U576 ) ;
708+ primefield:: test_primefield!( FieldElement , Uint ) ;
682709
683710 /// Regression test for RustCrypto/elliptic-curves#965
684711 #[ test]
0 commit comments