diff --git a/crypto/fipsmodule/ec/asm/p256-x86_64-asm.pl b/crypto/fipsmodule/ec/asm/p256-x86_64-asm.pl index 6a021dbcf..994cb82d5 100755 --- a/crypto/fipsmodule/ec/asm/p256-x86_64-asm.pl +++ b/crypto/fipsmodule/ec/asm/p256-x86_64-asm.pl @@ -3112,17 +3112,24 @@ $code.=<<___; or $acc5, $acc4 # see if result is zero or $acc0, $acc4 - or $acc1, $acc4 + or $acc1, $acc4 # !is_equal(U1, U2) - .byte 0x3e # predict taken - jnz .Ladd_proceed$x # is_equal(U1,U2)? movq %xmm2, $acc0 movq %xmm3, $acc1 - test $acc0, $acc0 - jnz .Ladd_proceed$x # (in1infty || in2infty)? - test $acc1, $acc1 - jz .Ladd_double$x # is_equal(S1,S2)? + or $acc0, $acc4 + .byte 0x3e # predict taken + jnz .Ladd_proceed$x # !is_equal(U1, U2) || in1infty || in2infty + # We now know A = B or A = -B and neither is infinity. Compare the + # y-coordinates via S1 and S2. + test $acc1, $acc1 + jz .Ladd_double$x # is_equal(S1, S2) + + # A = -B, so the result is infinity. + # + # TODO(davidben): Does .Ladd_proceed handle this case? It seems to, in + # which case we should eliminate this special-case and simplify the + # timing analysis. movq %xmm0, $r_ptr # restore $r_ptr pxor %xmm0, %xmm0 movdqu %xmm0, 0x00($r_ptr) diff --git a/crypto/fipsmodule/ec/ec_montgomery.c b/crypto/fipsmodule/ec/ec_montgomery.c index 6fb32c477..0cf1d910d 100644 --- a/crypto/fipsmodule/ec/ec_montgomery.c +++ b/crypto/fipsmodule/ec/ec_montgomery.c @@ -282,7 +282,8 @@ void ec_GFp_mont_add(const EC_GROUP *group, EC_RAW_POINT *out, BN_ULONG yneq = ec_felem_non_zero_mask(group, &r); // This case will never occur in the constant-time |ec_GFp_mont_mul|. - if (!xneq && !yneq && z1nz && z2nz) { + BN_ULONG is_nontrivial_double = ~xneq & ~yneq & z1nz & z2nz; + if (is_nontrivial_double) { ec_GFp_mont_dbl(group, out, a); return; } diff --git a/crypto/fipsmodule/ec/p224-64.c b/crypto/fipsmodule/ec/p224-64.c index cc88f15f6..f8af39bef 100644 --- a/crypto/fipsmodule/ec/p224-64.c +++ b/crypto/fipsmodule/ec/p224-64.c @@ -758,7 +758,9 @@ static void p224_point_add(p224_felem x3, p224_felem y3, p224_felem z3, z1_is_zero = p224_felem_is_zero(z1); z2_is_zero = p224_felem_is_zero(z2); // In affine coordinates, (X_1, Y_1) == (X_2, Y_2) - if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) { + p224_limb is_nontrivial_double = + x_equal & y_equal & (1 - z1_is_zero) & (1 - z2_is_zero); + if (is_nontrivial_double) { p224_point_double(x3, y3, z3, x1, y1, z1); return; } diff --git a/third_party/fiat/p256.c b/third_party/fiat/p256.c index 8426beb3c..23ec71f98 100644 --- a/third_party/fiat/p256.c +++ b/third_party/fiat/p256.c @@ -321,7 +321,10 @@ static void point_add(fe x3, fe y3, fe z3, const fe x1, limb_t yneq = fe_nz(r); - if (!xneq && !yneq && z1nz && z2nz) { + limb_t is_nontrivial_double = constant_time_is_zero_w(xneq | yneq) & + ~constant_time_is_zero_w(z1nz) & + ~constant_time_is_zero_w(z2nz); + if (is_nontrivial_double) { point_double(x3, y3, z3, x1, y1, z1); return; }