@@ -330,11 +330,11 @@ static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
330330}
331331
332332SECP256K1_FORCE_INLINE static void secp256k1_scalar_reduce_512 (secp256k1_scalar * r , const uint64_t * l ) {
333+ secp256k1_uint128 acc ;
334+ uint64_t p0 , p1 , p2 , p3 , p4 ;
333335#ifdef USE_ASM_X86_64
334336 /* Reduce 512 bits into 385. */
335337 uint64_t m0 , m1 , m2 , m3 , m4 , m5 , m6 ;
336- uint64_t p0 , p1 , p2 , p3 , p4 ;
337- uint64_t c ;
338338
339339 __asm__ __volatile__(
340340 /* Preload. */
@@ -534,64 +534,10 @@ SECP256K1_FORCE_INLINE static void secp256k1_scalar_reduce_512(secp256k1_scalar
534534 SECP256K1_CHECKMEM_MSAN_DEFINE (& p3 , sizeof (p3 ));
535535 SECP256K1_CHECKMEM_MSAN_DEFINE (& p4 , sizeof (p4 ));
536536
537- /* Reduce 258 bits into 256. */
538- __asm__ __volatile__(
539- /* Preload */
540- "movq %q5, %%r10\n"
541- /* (rax,rdx) = p4 * c0 */
542- "movq %7, %%rax\n"
543- "mulq %%r10\n"
544- /* (rax,rdx) += p0 */
545- "addq %q1, %%rax\n"
546- "adcq $0, %%rdx\n"
547- /* extract r0 */
548- "movq %%rax, 0(%q6)\n"
549- /* Move to (r8,r9) */
550- "movq %%rdx, %%r8\n"
551- "xorq %%r9, %%r9\n"
552- /* (r8,r9) += p1 */
553- "addq %q2, %%r8\n"
554- "adcq $0, %%r9\n"
555- /* (r8,r9) += p4 * c1 */
556- "movq %8, %%rax\n"
557- "mulq %%r10\n"
558- "addq %%rax, %%r8\n"
559- "adcq %%rdx, %%r9\n"
560- /* Extract r1 */
561- "movq %%r8, 8(%q6)\n"
562- "xorq %%r8, %%r8\n"
563- /* (r9,r8) += p4 */
564- "addq %%r10, %%r9\n"
565- "adcq $0, %%r8\n"
566- /* (r9,r8) += p2 */
567- "addq %q3, %%r9\n"
568- "adcq $0, %%r8\n"
569- /* Extract r2 */
570- "movq %%r9, 16(%q6)\n"
571- "xorq %%r9, %%r9\n"
572- /* (r8,r9) += p3 */
573- "addq %q4, %%r8\n"
574- "adcq $0, %%r9\n"
575- /* Extract r3 */
576- "movq %%r8, 24(%q6)\n"
577- /* Extract c */
578- "movq %%r9, %q0\n"
579- : "=g" (c )
580- : "g" (p0 ), "g" (p1 ), "g" (p2 ), "g" (p3 ), "g" (p4 ), "D" (r ), "i" (SECP256K1_N_C_0 ), "i" (SECP256K1_N_C_1 )
581- : "rax" , "rdx" , "r8" , "r9" , "r10" , "cc" , "memory" );
582-
583- SECP256K1_CHECKMEM_MSAN_DEFINE (r , sizeof (* r ));
584- SECP256K1_CHECKMEM_MSAN_DEFINE (& c , sizeof (c ));
585-
586537#else
587- secp256k1_uint128 c128 ;
588- uint64_t c ;
589- secp256k1_uint128 acc ;
590538 uint64_t n0 = l [4 ], n1 = l [5 ], n2 = l [6 ], n3 = l [7 ];
591539 uint64_t m0 , m1 , m2 , m3 , m4 , m5 ;
592540 uint32_t m6 ;
593- uint64_t p0 , p1 , p2 , p3 ;
594- uint32_t p4 ;
595541
596542 /* Reduce 512 bits into 385. */
597543 /* m[0..6] = l[0..3] + n[0..3] * SECP256K1_N_C. */
@@ -642,25 +588,58 @@ SECP256K1_FORCE_INLINE static void secp256k1_scalar_reduce_512(secp256k1_scalar
642588 extract_fast (p4 );
643589 p4 += m6 ;
644590 VERIFY_CHECK (p4 <= 2 );
645-
646- /* Reduce 258 bits into 256. */
647- /* r[0..3] = p[0..3] + p[4] * SECP256K1_N_C. */
648- secp256k1_u128_from_u64 (& c128 , p0 );
649- secp256k1_u128_accum_mul (& c128 , SECP256K1_N_C_0 , p4 );
650- r -> d [0 ] = secp256k1_u128_to_u64 (& c128 ); secp256k1_u128_rshift (& c128 , 64 );
651- secp256k1_u128_accum_u64 (& c128 , p1 );
652- secp256k1_u128_accum_mul (& c128 , SECP256K1_N_C_1 , p4 );
653- r -> d [1 ] = secp256k1_u128_to_u64 (& c128 ); secp256k1_u128_rshift (& c128 , 64 );
654- secp256k1_u128_accum_u64 (& c128 , p2 );
655- secp256k1_u128_accum_u64 (& c128 , p4 );
656- r -> d [2 ] = secp256k1_u128_to_u64 (& c128 ); secp256k1_u128_rshift (& c128 , 64 );
657- secp256k1_u128_accum_u64 (& c128 , p3 );
658- r -> d [3 ] = secp256k1_u128_to_u64 (& c128 );
659- c = secp256k1_u128_hi_u64 (& c128 );
660591#endif
661592
662- /* Final reduction of r. */
663- secp256k1_scalar_reduce (r , c + secp256k1_scalar_check_overflow (r ));
593+ /* R = p[0..3] + p4*N_C is congruent to X = p[0..3] + p4*2^256 mod N,
594+ * and p4 <= 2 gives R < 2N. Dropping p4*2^256 and adding (p4+1)*N_C
595+ * computes R + N_C, whose carry out of limb 3 is 1 iff R >= N, leaving
596+ * R - N; otherwise adding N back leaves R. */
597+ ++ p4 ;
598+
599+ /* Reduce 258 bits into 256 using the same 128-bit accumulator. */
600+ secp256k1_u128_mul (& acc , p4 , SECP256K1_N_C_0 );
601+ secp256k1_u128_accum_u64 (& acc , p0 );
602+ p0 = secp256k1_u128_to_u64 (& acc );
603+ secp256k1_u128_rshift (& acc , 64 );
604+ secp256k1_u128_accum_mul (& acc , p4 , SECP256K1_N_C_1 );
605+ secp256k1_u128_accum_u64 (& acc , p1 );
606+ p1 = secp256k1_u128_to_u64 (& acc );
607+ secp256k1_u128_rshift (& acc , 64 );
608+ secp256k1_u128_accum_u64 (& acc , p4 );
609+ secp256k1_u128_accum_u64 (& acc , p2 );
610+ p2 = secp256k1_u128_to_u64 (& acc );
611+ secp256k1_u128_rshift (& acc , 64 );
612+ secp256k1_u128_accum_u64 (& acc , p3 );
613+ p3 = secp256k1_u128_to_u64 (& acc );
614+ secp256k1_u128_rshift (& acc , 64 );
615+ p4 = secp256k1_u128_to_u64 (& acc );
616+ VERIFY_CHECK (p4 <= 1 );
617+
618+ /* uint64_t underflow gives UINT64_MAX for carry 0, and 0 for carry 1. */
619+ -- p4 ;
620+ secp256k1_u128_from_u64 (& acc , p0 );
621+ secp256k1_u128_accum_u64 (& acc , p4 & SECP256K1_N_0 );
622+ p0 = secp256k1_u128_to_u64 (& acc );
623+ secp256k1_u128_rshift (& acc , 64 );
624+ secp256k1_u128_accum_u64 (& acc , p1 );
625+ secp256k1_u128_accum_u64 (& acc , p4 & SECP256K1_N_1 );
626+ p1 = secp256k1_u128_to_u64 (& acc );
627+ secp256k1_u128_rshift (& acc , 64 );
628+ secp256k1_u128_accum_u64 (& acc , p2 );
629+ secp256k1_u128_accum_u64 (& acc , p4 & SECP256K1_N_2 );
630+ p2 = secp256k1_u128_to_u64 (& acc );
631+ secp256k1_u128_rshift (& acc , 64 );
632+ secp256k1_u128_accum_u64 (& acc , p3 );
633+ secp256k1_u128_accum_u64 (& acc , p4 & SECP256K1_N_3 );
634+ p3 = secp256k1_u128_to_u64 (& acc );
635+ secp256k1_u128_rshift (& acc , 64 );
636+ VERIFY_CHECK (secp256k1_u128_to_u64 (& acc ) + p4 == 0 );
637+
638+ r -> d [0 ] = p0 ;
639+ r -> d [1 ] = p1 ;
640+ r -> d [2 ] = p2 ;
641+ r -> d [3 ] = p3 ;
642+ SECP256K1_SCALAR_VERIFY (r );
664643}
665644
666645SECP256K1_FORCE_INLINE static void secp256k1_scalar_mul_512 (uint64_t * l8 , const secp256k1_scalar * a , const secp256k1_scalar * b ) {
0 commit comments