@@ -232,6 +232,21 @@ static int32_t secp256k1_modinv32_divsteps_30(int32_t zeta, uint32_t f0, uint32_
232232 return zeta ;
233233}
234234
235+ /* inv256[i] = -(2*i+1)^-1 (mod 256) */
236+ static const uint8_t secp256k1_modinv32_inv256 [128 ] = {
237+ 0xFF , 0x55 , 0x33 , 0x49 , 0xC7 , 0x5D , 0x3B , 0x11 , 0x0F , 0xE5 , 0xC3 , 0x59 ,
238+ 0xD7 , 0xED , 0xCB , 0x21 , 0x1F , 0x75 , 0x53 , 0x69 , 0xE7 , 0x7D , 0x5B , 0x31 ,
239+ 0x2F , 0x05 , 0xE3 , 0x79 , 0xF7 , 0x0D , 0xEB , 0x41 , 0x3F , 0x95 , 0x73 , 0x89 ,
240+ 0x07 , 0x9D , 0x7B , 0x51 , 0x4F , 0x25 , 0x03 , 0x99 , 0x17 , 0x2D , 0x0B , 0x61 ,
241+ 0x5F , 0xB5 , 0x93 , 0xA9 , 0x27 , 0xBD , 0x9B , 0x71 , 0x6F , 0x45 , 0x23 , 0xB9 ,
242+ 0x37 , 0x4D , 0x2B , 0x81 , 0x7F , 0xD5 , 0xB3 , 0xC9 , 0x47 , 0xDD , 0xBB , 0x91 ,
243+ 0x8F , 0x65 , 0x43 , 0xD9 , 0x57 , 0x6D , 0x4B , 0xA1 , 0x9F , 0xF5 , 0xD3 , 0xE9 ,
244+ 0x67 , 0xFD , 0xDB , 0xB1 , 0xAF , 0x85 , 0x63 , 0xF9 , 0x77 , 0x8D , 0x6B , 0xC1 ,
245+ 0xBF , 0x15 , 0xF3 , 0x09 , 0x87 , 0x1D , 0xFB , 0xD1 , 0xCF , 0xA5 , 0x83 , 0x19 ,
246+ 0x97 , 0xAD , 0x8B , 0xE1 , 0xDF , 0x35 , 0x13 , 0x29 , 0xA7 , 0x3D , 0x1B , 0xF1 ,
247+ 0xEF , 0xC5 , 0xA3 , 0x39 , 0xB7 , 0xCD , 0xAB , 0x01
248+ };
249+
235250/* Compute the transition matrix and eta for 30 divsteps (variable time).
236251 *
237252 * Input: eta: initial eta
@@ -243,21 +258,6 @@ static int32_t secp256k1_modinv32_divsteps_30(int32_t zeta, uint32_t f0, uint32_
243258 * Implements the divsteps_n_matrix_var function from the explanation.
244259 */
245260static int32_t secp256k1_modinv32_divsteps_30_var (int32_t eta , uint32_t f0 , uint32_t g0 , secp256k1_modinv32_trans2x2 * t ) {
246- /* inv256[i] = -(2*i+1)^-1 (mod 256) */
247- static const uint8_t inv256 [128 ] = {
248- 0xFF , 0x55 , 0x33 , 0x49 , 0xC7 , 0x5D , 0x3B , 0x11 , 0x0F , 0xE5 , 0xC3 , 0x59 ,
249- 0xD7 , 0xED , 0xCB , 0x21 , 0x1F , 0x75 , 0x53 , 0x69 , 0xE7 , 0x7D , 0x5B , 0x31 ,
250- 0x2F , 0x05 , 0xE3 , 0x79 , 0xF7 , 0x0D , 0xEB , 0x41 , 0x3F , 0x95 , 0x73 , 0x89 ,
251- 0x07 , 0x9D , 0x7B , 0x51 , 0x4F , 0x25 , 0x03 , 0x99 , 0x17 , 0x2D , 0x0B , 0x61 ,
252- 0x5F , 0xB5 , 0x93 , 0xA9 , 0x27 , 0xBD , 0x9B , 0x71 , 0x6F , 0x45 , 0x23 , 0xB9 ,
253- 0x37 , 0x4D , 0x2B , 0x81 , 0x7F , 0xD5 , 0xB3 , 0xC9 , 0x47 , 0xDD , 0xBB , 0x91 ,
254- 0x8F , 0x65 , 0x43 , 0xD9 , 0x57 , 0x6D , 0x4B , 0xA1 , 0x9F , 0xF5 , 0xD3 , 0xE9 ,
255- 0x67 , 0xFD , 0xDB , 0xB1 , 0xAF , 0x85 , 0x63 , 0xF9 , 0x77 , 0x8D , 0x6B , 0xC1 ,
256- 0xBF , 0x15 , 0xF3 , 0x09 , 0x87 , 0x1D , 0xFB , 0xD1 , 0xCF , 0xA5 , 0x83 , 0x19 ,
257- 0x97 , 0xAD , 0x8B , 0xE1 , 0xDF , 0x35 , 0x13 , 0x29 , 0xA7 , 0x3D , 0x1B , 0xF1 ,
258- 0xEF , 0xC5 , 0xA3 , 0x39 , 0xB7 , 0xCD , 0xAB , 0x01
259- };
260-
261261 /* Transformation matrix; see comments in secp256k1_modinv32_divsteps_30. */
262262 uint32_t u = 1 , v = 0 , q = 0 , r = 1 ;
263263 uint32_t f = f0 , g = g0 , m ;
@@ -297,7 +297,7 @@ static int32_t secp256k1_modinv32_divsteps_30_var(int32_t eta, uint32_t f0, uint
297297 VERIFY_CHECK (limit > 0 && limit <= 30 );
298298 m = (UINT32_MAX >> (32 - limit )) & 255U ;
299299 /* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */
300- w = (g * inv256 [(f >> 1 ) & 127 ]) & m ;
300+ w = (g * secp256k1_modinv32_inv256 [(f >> 1 ) & 127 ]) & m ;
301301 /* Do so. */
302302 g += f * w ;
303303 q += u * w ;
@@ -317,6 +317,83 @@ static int32_t secp256k1_modinv32_divsteps_30_var(int32_t eta, uint32_t f0, uint
317317 return eta ;
318318}
319319
320+ /* Compute the transition matrix and eta for 30 posdivsteps (variable time, eta=-delta), and keeps track
321+ * of the Jacobi symbol along the way. f0 and g0 must be f and g mod 2^32 rather than 2^30, because
322+ * Jacobi tracking requires knowing (f mod 8) rather than just (f mod 2).
323+ *
324+ * Input: eta: initial eta
325+ * f0: bottom limb of initial f
326+ * g0: bottom limb of initial g
327+ * Output: t: transition matrix
328+ * Return: final eta
329+ */
330+ static int32_t secp256k1_modinv32_posdivsteps_30_var (int32_t eta , uint32_t f0 , uint32_t g0 , secp256k1_modinv32_trans2x2 * t , int * jacp ) {
331+ /* Transformation matrix. */
332+ uint32_t u = 1 , v = 0 , q = 0 , r = 1 ;
333+ uint32_t f = f0 , g = g0 , m ;
334+ uint16_t w ;
335+ int i = 30 , limit , zeros ;
336+ int jac = * jacp ;
337+
338+ for (;;) {
339+ /* Use a sentinel bit to count zeros only up to i. */
340+ zeros = secp256k1_ctz32_var (g | (UINT32_MAX << i ));
341+ /* Perform zeros divsteps at once; they all just divide g by two. */
342+ g >>= zeros ;
343+ u <<= zeros ;
344+ v <<= zeros ;
345+ eta -= zeros ;
346+ i -= zeros ;
347+ /* Update the bottom bit of jac: when dividing g by an odd power of 2,
348+ * if (f mod 8) is 3 or 5, the Jacobi symbol changes sign. */
349+ jac ^= (zeros & ((f >> 1 ) ^ (f >> 2 )));
350+ /* We're done once we've done 60 posdivsteps. */
351+ if (i == 0 ) break ;
352+ VERIFY_CHECK ((f & 1 ) == 1 );
353+ VERIFY_CHECK ((g & 1 ) == 1 );
354+ VERIFY_CHECK ((u * f0 + v * g0 ) == f << (30 - i ));
355+ VERIFY_CHECK ((q * f0 + r * g0 ) == g << (30 - i ));
356+ /* If eta is negative, negate it and replace f,g with g,-f. */
357+ if (eta < 0 ) {
358+ uint32_t tmp ;
359+ eta = - eta ;
360+ /* Update bottom bit of jac: when swapping f and g, the Jacobi symbol changes sign
361+ * if both f and g are 3 mod 4. */
362+ jac ^= ((f & g ) >> 1 );
363+ tmp = f ; f = g ; g = tmp ;
364+ tmp = u ; u = q ; q = tmp ;
365+ tmp = v ; v = r ; r = tmp ;
366+ }
367+ /* eta is now >= 0. In what follows we're going to cancel out the bottom bits of g. No more
368+ * than i can be cancelled out (as we'd be done before that point), and no more than eta+1
369+ * can be done as its sign will flip once that happens. */
370+ limit = ((int )eta + 1 ) > i ? i : ((int )eta + 1 );
371+ /* m is a mask for the bottom min(limit, 8) bits (our table only supports 8 bits). */
372+ VERIFY_CHECK (limit > 0 && limit <= 30 );
373+ m = (UINT32_MAX >> (32 - limit )) & 255U ;
374+ /* Find what multiple of f must be added to g to cancel its bottom min(limit, 8) bits. */
375+ w = (g * secp256k1_modinv32_inv256 [(f >> 1 ) & 127 ]) & m ;
376+ /* Do so. */
377+ g += f * w ;
378+ q += u * w ;
379+ r += v * w ;
380+ VERIFY_CHECK ((g & m ) == 0 );
381+ }
382+ /* Return data in t and return value. */
383+ t -> u = (int32_t )u ;
384+ t -> v = (int32_t )v ;
385+ t -> q = (int32_t )q ;
386+ t -> r = (int32_t )r ;
387+ /* The determinant of t must be a power of two. This guarantees that multiplication with t
388+ * does not change the gcd of f and g, apart from adding a power-of-2 factor to it (which
389+ * will be divided out again). As each divstep's individual matrix has determinant 2 or -2,
390+ * the aggregate of 30 of them will have determinant 2^30 or -2^30. */
391+ VERIFY_CHECK ((int64_t )t -> u * t -> r - (int64_t )t -> v * t -> q == ((int64_t )1 ) << 30 ||
392+ (int64_t )t -> u * t -> r - (int64_t )t -> v * t -> q == - (((int64_t )1 ) << 30 ));
393+ * jacp = jac ;
394+ return eta ;
395+ }
396+
320397/* Compute (t/2^30) * [d, e] mod modulus, where t is a transition matrix for 30 divsteps.
321398 *
322399 * On input and output, d and e are in range (-2*modulus,modulus). All output limbs will be in range
@@ -584,4 +661,63 @@ static void secp256k1_modinv32_var(secp256k1_modinv32_signed30 *x, const secp256
584661 * x = d ;
585662}
586663
664+ /* Compute the Jacobi symbol of x modulo modinfo->modulus (variable time). gcd(x,modulus) must be 1. */
665+ static int secp256k1_jacobi32_maybe_var (const secp256k1_modinv32_signed30 * x , const secp256k1_modinv32_modinfo * modinfo ) {
666+ /* Start with f=modulus, g=x, eta=-1. */
667+ secp256k1_modinv32_signed30 f = modinfo -> modulus ;
668+ secp256k1_modinv32_signed30 g = * x ;
669+ int j , len = 9 ;
670+ int32_t eta = -1 ; /* eta = -delta; delta is initially 1 */
671+ int32_t cond , fn , gn ;
672+ int jac = 0 ;
673+ int count ;
674+
675+ /* Do up to 50 iterations of 30 posdivsteps (up to 1500 steps; more is extremely rare) each until f=1. */
676+ for (count = 0 ; count < 50 ; ++ count ) {
677+ /* Compute transition matrix and new eta after 30 posdivsteps. */
678+ secp256k1_modinv32_trans2x2 t ;
679+ eta = secp256k1_modinv32_posdivsteps_30_var (eta , f .v [0 ] | ((uint32_t )f .v [1 ] << 30 ), g .v [0 ] | ((uint32_t )g .v [1 ] << 30 ), & t , & jac );
680+ /* Update f,g using that transition matrix. */
681+ #ifdef VERIFY
682+ VERIFY_CHECK (secp256k1_modinv32_mul_cmp_30 (& f , len , & modinfo -> modulus , 0 ) > 0 ); /* f > 0 */
683+ VERIFY_CHECK (secp256k1_modinv32_mul_cmp_30 (& f , len , & modinfo -> modulus , 1 ) <= 0 ); /* f <= modulus */
684+ VERIFY_CHECK (secp256k1_modinv32_mul_cmp_30 (& g , len , & modinfo -> modulus , 0 ) > 0 ); /* g > 0 */
685+ VERIFY_CHECK (secp256k1_modinv32_mul_cmp_30 (& g , len , & modinfo -> modulus , 1 ) < 0 ); /* g < modulus */
686+ #endif
687+ secp256k1_modinv32_update_fg_30_var (len , & f , & g , & t );
688+ /* If the bottom limb of f is 1, there is a chance that f=1. */
689+ if (f .v [0 ] == 1 ) {
690+ cond = 0 ;
691+ /* Check if the other limbs are also 0. */
692+ for (j = 1 ; j < len ; ++ j ) {
693+ cond |= f .v [j ];
694+ }
695+ /* If so, we're done. */
696+ if (cond == 0 ) return 1 - 2 * (jac & 1 );
697+ }
698+
699+ /* Determine if len>1 and limb (len-1) of both f and g is 0. */
700+ fn = f .v [len - 1 ];
701+ gn = g .v [len - 1 ];
702+ cond = ((int32_t )len - 2 ) >> 31 ;
703+ cond |= fn ;
704+ cond |= gn ;
705+ /* If so, reduce length. */
706+ if (cond == 0 ) -- len ;
707+ #ifdef VERIFY
708+ VERIFY_CHECK (secp256k1_modinv32_mul_cmp_30 (& f , len , & modinfo -> modulus , 0 ) > 0 ); /* f > 0 */
709+ VERIFY_CHECK (secp256k1_modinv32_mul_cmp_30 (& f , len , & modinfo -> modulus , 1 ) <= 0 ); /* f <= modulus */
710+ VERIFY_CHECK (secp256k1_modinv32_mul_cmp_30 (& g , len , & modinfo -> modulus , 0 ) > 0 ); /* g > 0 */
711+ VERIFY_CHECK (secp256k1_modinv32_mul_cmp_30 (& g , len , & modinfo -> modulus , 1 ) < 0 ); /* g < modulus */
712+ #endif
713+ }
714+
715+ /* While we don't want production code to assume that the loop above always reaches f=1,
716+ * it's a reasonable thing to check for in test code (as long as we don't have a way
717+ * for constructing known bad examples in the tests). */
718+ VERIFY_CHECK (0 );
719+
720+ return 0 ;
721+ }
722+
587723#endif /* SECP256K1_MODINV32_IMPL_H */
0 commit comments