out[3] += in[3];
}
-/* Get negative value: out = -in */
-/* Assumes in[i] < 2^57 */
-static void felem_neg(felem out, const felem in)
-{
- static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2);
- static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2);
- static const limb two58m42m2 = (((limb) 1) << 58) -
- (((limb) 1) << 42) - (((limb) 1) << 2);
-
- /* Set to 0 mod 2^224-2^96+1 to ensure out > in */
- out[0] = two58p2 - in[0];
- out[1] = two58m42m2 - in[1];
- out[2] = two58m2 - in[2];
- out[3] = two58m2 - in[3];
-}
-
/* Subtract field elements: out -= in */
/* Assumes in[i] < 2^57 */
static void felem_diff(felem out, const felem in)
out[3] = tmp[3];
}
+/*
+ * Get negative value: out = -in
+ * Requires in[i] < 2^63,
+ * ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16
+ */
+static void felem_neg(felem out, const felem in)
+{
+ widefelem tmp = {0};
+ felem_diff_128_64(tmp, in);
+ felem_reduce(out, tmp);
+}
+
/*
* Zero-check: returns 1 if input is 0, and 0 otherwise. We know that field
* elements are reduced to in < 2^225, so we only need to check three cases:
if (!TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, Q_CHECK, ctx)))
goto err;
+ /* regression test for felem_neg bug */
+ if (!TEST_true(BN_set_word(m, 32))
+ || !TEST_true(BN_set_word(n, 31))
+ || !TEST_true(EC_POINT_copy(P, G))
+ || !TEST_true(EC_POINT_invert(NISTP, P, ctx))
+ || !TEST_true(EC_POINT_mul(NISTP, Q, m, P, n, ctx))
+ || !TEST_int_eq(0, EC_POINT_cmp(NISTP, Q, G, ctx)))
+ goto err;
+
r = group_order_tests(NISTP);
err:
EC_GROUP_free(NISTP);