@@ -10,7 +10,7 @@ use elliptic_curve::consts::{U28, U84};
1010use elliptic_curve:: ops:: Reduce ;
1111use hash2curve:: { ExpandMsg , ExpandMsgXof , ExpandMsgXofError , Expander , MapToCurve } ;
1212use sha3:: Shake256 ;
13- use subtle:: { Choice , ConditionallyNegatable , ConditionallySelectable , ConstantTimeEq } ;
13+ use subtle:: { Choice , ConditionallyNegatable , ConditionallySelectable , ConstantTimeEq , CtOption } ;
1414
1515impl MontgomeryXpoint {
1616 /// First low order point on Curve448 and it's twist
@@ -110,19 +110,19 @@ impl MontgomeryXpoint {
110110 }
111111
112112 /// Compute the Y-coordinate
113- pub fn y ( & self , sign : Choice ) -> [ u8 ; 56 ] {
114- Self :: y_internal ( & FieldElement :: from_bytes ( & self . 0 ) , sign) . to_bytes ( )
113+ pub fn y ( & self , sign : Choice ) -> CtOption < [ u8 ; 56 ] > {
114+ Self :: y_internal ( & FieldElement :: from_bytes ( & self . 0 ) , sign) . map ( FieldElement :: to_bytes )
115115 }
116116
117117 // See https://www.rfc-editor.org/rfc/rfc7748#section-1.
118- pub ( super ) fn y_internal ( u : & FieldElement , sign : Choice ) -> FieldElement {
118+ pub ( super ) fn y_internal ( u : & FieldElement , sign : Choice ) -> CtOption < FieldElement > {
119119 // v^2 = u^3 + A*u^2 + u
120120 let uu = u. square ( ) ;
121121 let vv = uu * u + FieldElement :: J * uu + u;
122122
123123 let mut v = vv. sqrt ( ) ;
124124 v. conditional_negate ( v. is_negative ( ) ^ sign) ;
125- v
125+ CtOption :: new ( v , v . square ( ) . ct_eq ( & vv ) )
126126 }
127127
128128 pub ( super ) fn mul_internal (
@@ -158,21 +158,21 @@ impl MontgomeryXpoint {
158158 }
159159
160160 /// Convert the point to projective form including the y-coordinate
161- pub fn to_extended_projective ( & self , sign : Choice ) -> ProjectiveMontgomeryPoint {
161+ pub fn to_extended_projective ( & self , sign : Choice ) -> CtOption < ProjectiveMontgomeryPoint > {
162162 self . to_projective ( ) . to_extended ( sign)
163163 }
164164
165165 /// Convert the point to its form including the y-coordinate
166- pub fn to_extended ( & self , sign : Choice ) -> AffineMontgomeryPoint {
166+ pub fn to_extended ( & self , sign : Choice ) -> CtOption < AffineMontgomeryPoint > {
167167 let x = FieldElement :: from_bytes ( & self . 0 ) ;
168168 let y = Self :: y_internal ( & x, sign) ;
169169
170- AffineMontgomeryPoint :: new ( x, y)
170+ y . map ( |y| AffineMontgomeryPoint :: new ( x, y) )
171171 }
172172
173173 /// Convert this point to an [`AffinePoint`]
174- pub fn to_edwards ( & self , sign : Choice ) -> AffinePoint {
175- self . to_extended ( sign) . into ( )
174+ pub fn to_edwards ( & self , sign : Choice ) -> CtOption < AffinePoint > {
175+ self . to_extended ( sign) . map ( AffinePoint :: from )
176176 }
177177}
178178
@@ -271,14 +271,14 @@ impl ProjectiveMontgomeryXpoint {
271271 } ;
272272
273273 // See https://www.rfc-editor.org/rfc/rfc7748#section-1.
274- fn y ( & self , sign : Choice ) -> FieldElement {
274+ fn y ( & self , sign : Choice ) -> CtOption < FieldElement > {
275275 // v^2 = u^3 + A*u^2 + u
276276 let u_sq = self . U . square ( ) ;
277277 let v_sq = u_sq * self . U + FieldElement :: J * u_sq + self . U ;
278278
279279 let mut v = v_sq. sqrt ( ) ;
280280 v. conditional_negate ( v. is_negative ( ) ^ sign) ;
281- v
281+ CtOption :: new ( v , v . square ( ) . ct_eq ( & v_sq ) )
282282 }
283283
284284 /// Double this point
@@ -367,20 +367,30 @@ impl ProjectiveMontgomeryXpoint {
367367 }
368368
369369 /// Convert the point to affine form including the y-coordinate
370- pub fn to_extended_affine ( & self , sign : Choice ) -> AffineMontgomeryPoint {
370+ pub fn to_extended_affine ( & self , sign : Choice ) -> CtOption < AffineMontgomeryPoint > {
371371 let x = self . U * self . W . invert ( ) ;
372372 let y = self . y ( sign) ;
373373
374- AffineMontgomeryPoint :: new ( x, y)
374+ y . map ( |y| AffineMontgomeryPoint :: new ( x, y) )
375375 }
376376
377377 /// Convert the point to its form including the y-coordinate
378- pub fn to_extended ( & self , sign : Choice ) -> ProjectiveMontgomeryPoint {
379- ProjectiveMontgomeryPoint :: conditional_select (
380- & ProjectiveMontgomeryPoint :: new ( self . U , self . y ( sign) , self . W ) ,
381- & ProjectiveMontgomeryPoint :: IDENTITY ,
378+ pub fn to_extended ( & self , sign : Choice ) -> CtOption < ProjectiveMontgomeryPoint > {
379+ CtOption :: new (
380+ ProjectiveMontgomeryPoint :: IDENTITY ,
382381 self . ct_eq ( & Self :: IDENTITY ) ,
383382 )
383+ . or_else ( || {
384+ let y = self . y ( sign) ;
385+
386+ y. map ( |y| {
387+ ProjectiveMontgomeryPoint :: conditional_select (
388+ & ProjectiveMontgomeryPoint :: new ( self . U , y, self . W ) ,
389+ & ProjectiveMontgomeryPoint :: IDENTITY ,
390+ self . ct_eq ( & Self :: IDENTITY ) ,
391+ )
392+ } )
393+ } )
384394 }
385395}
386396
@@ -413,15 +423,15 @@ mod tests {
413423 let x_identity = ProjectiveMontgomeryXpoint :: IDENTITY ;
414424 let identity = ProjectiveMontgomeryPoint :: IDENTITY ;
415425
416- assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) , identity) ;
426+ assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) . unwrap ( ) , identity) ;
417427 }
418428
419429 #[ test]
420430 fn to_extended_affine ( ) {
421431 let x_identity = ProjectiveMontgomeryXpoint :: IDENTITY . to_affine ( ) ;
422432 let identity = ProjectiveMontgomeryPoint :: IDENTITY . to_affine ( ) ;
423433
424- assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) , identity) ;
434+ assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) . unwrap ( ) , identity) ;
425435 }
426436
427437 #[ test]
@@ -446,7 +456,7 @@ mod tests {
446456 yy. copy_from_slice ( & y[ ..] ) ;
447457 yy. reverse ( ) ;
448458 assert_eq ! ( p. 0 , xx) ;
449- assert ! ( p. y( Choice :: from( 0 ) ) == yy || p. y( Choice :: from( 1 ) ) == yy) ;
459+ assert ! ( p. y( Choice :: from( 0 ) ) . unwrap ( ) == yy || p. y( Choice :: from( 1 ) ) . unwrap ( ) == yy) ;
450460 }
451461 }
452462
@@ -472,7 +482,7 @@ mod tests {
472482 yy. copy_from_slice ( & y[ ..] ) ;
473483 yy. reverse ( ) ;
474484 assert_eq ! ( p. 0 , xx) ;
475- assert ! ( p. y( Choice :: from( 0 ) ) == yy || p. y( Choice :: from( 1 ) ) == yy) ;
485+ assert ! ( p. y( Choice :: from( 0 ) ) . unwrap ( ) == yy || p. y( Choice :: from( 1 ) ) . unwrap ( ) == yy) ;
476486 }
477487 }
478488}
0 commit comments