@@ -41,7 +41,7 @@ fd_secp256r1_scalar_from_digest( fd_secp256r1_scalar_t * r,
4141}
4242
4343static inline fd_secp256r1_scalar_t *
44- fd_secp256r1_scalar_mul ( fd_secp256r1_scalar_t * r ,
44+ fd_secp256r1_scalar_mul ( fd_secp256r1_scalar_t * r ,
4545 fd_secp256r1_scalar_t const * a ,
4646 fd_secp256r1_scalar_t const * b ) {
4747 ulong t [ 8 ];
@@ -51,7 +51,7 @@ fd_secp256r1_scalar_mul( fd_secp256r1_scalar_t * r,
5151}
5252
5353static inline fd_secp256r1_scalar_t *
54- fd_secp256r1_scalar_inv ( fd_secp256r1_scalar_t * r ,
54+ fd_secp256r1_scalar_inv ( fd_secp256r1_scalar_t * r ,
5555 fd_secp256r1_scalar_t const * a ) {
5656 ulong t [ 12 ];
5757 bignum_modinv ( 4 , r -> limbs , (ulong * )a -> limbs , (ulong * )fd_secp256r1_const_n [0 ].limbs , t );
@@ -131,7 +131,7 @@ fd_secp256r1_point_frombytes( fd_secp256r1_point_t * r,
131131 }
132132
133133 bignum_tomont_p256 ( r -> x -> limbs , r -> x -> limbs );
134-
134+
135135 /* y^2 = x^3 + ax + b */
136136 bignum_montsqr_p256 ( y2 -> limbs , r -> x -> limbs );
137137 bignum_add_p256 ( y2 -> limbs , y2 -> limbs , (ulong * )fd_secp256r1_const_a_mont [0 ].limbs );
@@ -176,6 +176,41 @@ fd_secp256r1_point_eq_x( fd_secp256r1_point_t const * p,
176176 return FD_SECP256R1_FAILURE ;
177177}
178178
179+ /* Given the projective point `r` and the affine point `p`,
180+ returns 1 if they are equal and 0 otherwise.
181+ Assumes that `p` X and Y coordinates are in Montgomery domain. */
182+ static inline int
183+ fd_secp256r1_point_eq_mixed ( fd_secp256r1_point_t const * a ,
184+ ulong const b [ 8 ] ) {
185+ fd_secp256r1_fp_t x [1 ], y [1 ];
186+ fd_memcpy ( x -> limbs , b + 0 , sizeof (fd_secp256r1_fp_t ) );
187+ fd_memcpy ( y -> limbs , b + 4 , sizeof (fd_secp256r1_fp_t ) );
188+ /* Indicates if the affine point is zero. */
189+ int is_zero = fd_uint256_eq ( x , fd_secp256r1_const_zero ) & fd_uint256_eq ( y , fd_secp256r1_const_zero );
190+
191+ /* Easy cases */
192+ if ( FD_UNLIKELY ( fd_uint256_eq ( a -> z , fd_secp256r1_const_zero ) ) ) {
193+ return is_zero ;
194+ }
195+ if ( FD_UNLIKELY ( is_zero ) ) {
196+ return 0 ;
197+ }
198+
199+ fd_secp256r1_fp_t z1z1 [1 ];
200+ bignum_montsqr_p256 ( z1z1 -> limbs , (ulong * )a -> z -> limbs );
201+
202+ fd_secp256r1_fp_t temp [1 ];
203+ bignum_montmul_p256 ( temp -> limbs , (ulong * )x -> limbs , z1z1 -> limbs );
204+
205+ if ( FD_UNLIKELY ( fd_uint256_eq ( a -> x , temp ) ) ) {
206+ bignum_montmul_p256 ( temp -> limbs , z1z1 -> limbs , (ulong * )a -> z -> limbs );
207+ bignum_montmul_p256 ( temp -> limbs , temp -> limbs , (ulong * )y -> limbs );
208+ return fd_uint256_eq ( a -> y , temp );
209+ } else {
210+ return 0 ;
211+ }
212+ }
213+
179214static inline void
180215fd_secp256r1_double_scalar_mul_base ( fd_secp256r1_point_t * r ,
181216 fd_secp256r1_scalar_t const * u1 ,
@@ -189,5 +224,9 @@ fd_secp256r1_double_scalar_mul_base( fd_secp256r1_point_t * r,
189224
190225 p256_montjscalarmul ( (ulong * )r , (ulong * )u2 -> limbs , (ulong * )a );
191226
192- p256_montjmixadd ( (ulong * )r , (ulong * )r , rtmp );
227+ if ( FD_UNLIKELY ( fd_secp256r1_point_eq_mixed ( r , rtmp ) ) ) {
228+ p256_montjdouble ( (ulong * )r , (ulong * )r );
229+ } else {
230+ p256_montjmixadd ( (ulong * )r , (ulong * )r , rtmp );
231+ }
193232}
0 commit comments