@@ -12,7 +12,7 @@ use elliptic_curve::bigint::U448;
1212use elliptic_curve:: consts:: { U28 , U84 } ;
1313use hash2curve:: { ExpandMsg , ExpandMsgXof , Expander , FromOkm , MapToCurve } ;
1414use sha3:: Shake256 ;
15- use subtle:: { Choice , ConditionallyNegatable , ConditionallySelectable , ConstantTimeEq } ;
15+ use subtle:: { Choice , ConditionallyNegatable , ConditionallySelectable , ConstantTimeEq , CtOption } ;
1616
1717impl MontgomeryXpoint {
1818 /// First low order point on Curve448 and it's twist
@@ -112,19 +112,19 @@ impl MontgomeryXpoint {
112112 }
113113
114114 /// Compute the Y-coordinate
115- pub fn y ( & self , sign : Choice ) -> [ u8 ; 56 ] {
116- Self :: y_internal ( & FieldElement :: from_bytes ( & self . 0 ) , sign) . to_bytes ( )
115+ pub fn y ( & self , sign : Choice ) -> CtOption < [ u8 ; 56 ] > {
116+ Self :: y_internal ( & FieldElement :: from_bytes ( & self . 0 ) , sign) . map ( FieldElement :: to_bytes )
117117 }
118118
119119 // See https://www.rfc-editor.org/rfc/rfc7748#section-1.
120- pub ( super ) fn y_internal ( u : & FieldElement , sign : Choice ) -> FieldElement {
120+ pub ( super ) fn y_internal ( u : & FieldElement , sign : Choice ) -> CtOption < FieldElement > {
121121 // v^2 = u^3 + A*u^2 + u
122122 let uu = u. square ( ) ;
123123 let vv = uu * u + FieldElement :: J * uu + u;
124124
125125 let mut v = vv. sqrt ( ) ;
126126 v. conditional_negate ( v. is_negative ( ) ^ sign) ;
127- v
127+ CtOption :: new ( v , v . square ( ) . ct_eq ( & vv ) )
128128 }
129129
130130 pub ( super ) fn mul_internal (
@@ -160,21 +160,21 @@ impl MontgomeryXpoint {
160160 }
161161
162162 /// Convert the point to projective form including the y-coordinate
163- pub fn to_extended_projective ( & self , sign : Choice ) -> ProjectiveMontgomeryPoint {
163+ pub fn to_extended_projective ( & self , sign : Choice ) -> CtOption < ProjectiveMontgomeryPoint > {
164164 self . to_projective ( ) . to_extended ( sign)
165165 }
166166
167167 /// Convert the point to its form including the y-coordinate
168- pub fn to_extended ( & self , sign : Choice ) -> AffineMontgomeryPoint {
168+ pub fn to_extended ( & self , sign : Choice ) -> CtOption < AffineMontgomeryPoint > {
169169 let x = FieldElement :: from_bytes ( & self . 0 ) ;
170170 let y = Self :: y_internal ( & x, sign) ;
171171
172- AffineMontgomeryPoint :: new ( x, y)
172+ y . map ( |y| AffineMontgomeryPoint :: new ( x, y) )
173173 }
174174
175175 /// Convert this point to an [`AffinePoint`]
176- pub fn to_edwards ( & self , sign : Choice ) -> AffinePoint {
177- self . to_extended ( sign) . into ( )
176+ pub fn to_edwards ( & self , sign : Choice ) -> CtOption < AffinePoint > {
177+ self . to_extended ( sign) . map ( AffinePoint :: from )
178178 }
179179}
180180
@@ -273,14 +273,14 @@ impl ProjectiveMontgomeryXpoint {
273273 } ;
274274
275275 // See https://www.rfc-editor.org/rfc/rfc7748#section-1.
276- fn y ( & self , sign : Choice ) -> FieldElement {
276+ fn y ( & self , sign : Choice ) -> CtOption < FieldElement > {
277277 // v^2 = u^3 + A*u^2 + u
278278 let u_sq = self . U . square ( ) ;
279279 let v_sq = u_sq * self . U + FieldElement :: J * u_sq + self . U ;
280280
281281 let mut v = v_sq. sqrt ( ) ;
282282 v. conditional_negate ( v. is_negative ( ) ^ sign) ;
283- v
283+ CtOption :: new ( v , v . square ( ) . ct_eq ( & v_sq ) )
284284 }
285285
286286 /// Double this point
@@ -365,20 +365,30 @@ impl ProjectiveMontgomeryXpoint {
365365 }
366366
367367 /// Convert the point to affine form including the y-coordinate
368- pub fn to_extended_affine ( & self , sign : Choice ) -> AffineMontgomeryPoint {
368+ pub fn to_extended_affine ( & self , sign : Choice ) -> CtOption < AffineMontgomeryPoint > {
369369 let x = self . U * self . W . invert ( ) ;
370370 let y = self . y ( sign) ;
371371
372- AffineMontgomeryPoint :: new ( x, y)
372+ y . map ( |y| AffineMontgomeryPoint :: new ( x, y) )
373373 }
374374
375375 /// Convert the point to its form including the y-coordinate
376- pub fn to_extended ( & self , sign : Choice ) -> ProjectiveMontgomeryPoint {
377- ProjectiveMontgomeryPoint :: conditional_select (
378- & ProjectiveMontgomeryPoint :: new ( self . U , self . y ( sign) , self . W ) ,
379- & ProjectiveMontgomeryPoint :: IDENTITY ,
376+ pub fn to_extended ( & self , sign : Choice ) -> CtOption < ProjectiveMontgomeryPoint > {
377+ CtOption :: new (
378+ ProjectiveMontgomeryPoint :: IDENTITY ,
380379 self . ct_eq ( & Self :: IDENTITY ) ,
381380 )
381+ . or_else ( || {
382+ let y = self . y ( sign) ;
383+
384+ y. map ( |y| {
385+ ProjectiveMontgomeryPoint :: conditional_select (
386+ & ProjectiveMontgomeryPoint :: new ( self . U , y, self . W ) ,
387+ & ProjectiveMontgomeryPoint :: IDENTITY ,
388+ self . ct_eq ( & Self :: IDENTITY ) ,
389+ )
390+ } )
391+ } )
382392 }
383393}
384394
@@ -411,15 +421,15 @@ mod tests {
411421 let x_identity = ProjectiveMontgomeryXpoint :: IDENTITY ;
412422 let identity = ProjectiveMontgomeryPoint :: IDENTITY ;
413423
414- assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) , identity) ;
424+ assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) . unwrap ( ) , identity) ;
415425 }
416426
417427 #[ test]
418428 fn to_extended_affine ( ) {
419429 let x_identity = ProjectiveMontgomeryXpoint :: IDENTITY . to_affine ( ) ;
420430 let identity = ProjectiveMontgomeryPoint :: IDENTITY . to_affine ( ) ;
421431
422- assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) , identity) ;
432+ assert_eq ! ( x_identity. to_extended( Choice :: from( 1 ) ) . unwrap ( ) , identity) ;
423433 }
424434
425435 #[ test]
@@ -443,7 +453,7 @@ mod tests {
443453 yy. copy_from_slice ( & y[ ..] ) ;
444454 yy. reverse ( ) ;
445455 assert_eq ! ( p. 0 , xx) ;
446- assert ! ( p. y( Choice :: from( 0 ) ) == yy || p. y( Choice :: from( 1 ) ) == yy) ;
456+ assert ! ( p. y( Choice :: from( 0 ) ) . unwrap ( ) == yy || p. y( Choice :: from( 1 ) ) . unwrap ( ) == yy) ;
447457 }
448458 }
449459
@@ -468,7 +478,7 @@ mod tests {
468478 yy. copy_from_slice ( & y[ ..] ) ;
469479 yy. reverse ( ) ;
470480 assert_eq ! ( p. 0 , xx) ;
471- assert ! ( p. y( Choice :: from( 0 ) ) == yy || p. y( Choice :: from( 1 ) ) == yy) ;
481+ assert ! ( p. y( Choice :: from( 0 ) ) . unwrap ( ) == yy || p. y( Choice :: from( 1 ) ) . unwrap ( ) == yy) ;
472482 }
473483 }
474484}
0 commit comments