aboutsummaryrefslogtreecommitdiff
path: root/src/field_impl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/field_impl.h')
-rw-r--r--src/field_impl.h46
1 files changed, 33 insertions, 13 deletions
diff --git a/src/field_impl.h b/src/field_impl.h
index e6ec11e8f2..77f4aae2f9 100644
--- a/src/field_impl.h
+++ b/src/field_impl.h
@@ -21,15 +21,24 @@
#error "Please select field implementation"
#endif
-SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
- secp256k1_fe_t na;
+SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) {
+ secp256k1_fe na;
secp256k1_fe_negate(&na, a, 1);
secp256k1_fe_add(&na, b);
return secp256k1_fe_normalizes_to_zero_var(&na);
}
-static int secp256k1_fe_sqrt_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
- secp256k1_fe_t x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
+static int secp256k1_fe_sqrt_var(secp256k1_fe *r, const secp256k1_fe *a) {
+ /** Given that p is congruent to 3 mod 4, we can compute the square root of
+ * a mod p as the (p+1)/4'th power of a.
+ *
+ * As (p+1)/4 is an even number, it will have the same result for a and for
+ * (-a). Only one of these two numbers actually has a square root however,
+ * so we test at the end by squaring and comparing to the input.
+ * Also because (p+1)/4 is an even number, the computed square root is
+ * itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
+ */
+ secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
int j;
/** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
@@ -117,8 +126,8 @@ static int secp256k1_fe_sqrt_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
return secp256k1_fe_equal_var(&t1, a);
}
-static void secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
- secp256k1_fe_t x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
+static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a) {
+ secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
int j;
/** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in
@@ -207,11 +216,15 @@ static void secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
secp256k1_fe_mul(r, a, &t1);
}
-static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
+static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a) {
#if defined(USE_FIELD_INV_BUILTIN)
secp256k1_fe_inv(r, a);
#elif defined(USE_FIELD_INV_NUM)
- secp256k1_num_t n, m;
+ secp256k1_num n, m;
+ static const secp256k1_fe negone = SECP256K1_FE_CONST(
+ 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL,
+ 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFEUL, 0xFFFFFC2EUL
+ );
/* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
static const unsigned char prime[32] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
@@ -220,21 +233,28 @@ static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
};
unsigned char b[32];
- secp256k1_fe_t c = *a;
+ int res;
+ secp256k1_fe c = *a;
secp256k1_fe_normalize_var(&c);
secp256k1_fe_get_b32(b, &c);
secp256k1_num_set_bin(&n, b, 32);
secp256k1_num_set_bin(&m, prime, 32);
secp256k1_num_mod_inverse(&n, &n, &m);
secp256k1_num_get_bin(b, 32, &n);
- VERIFY_CHECK(secp256k1_fe_set_b32(r, b));
+ res = secp256k1_fe_set_b32(r, b);
+ (void)res;
+ VERIFY_CHECK(res);
+ /* Verify the result is the (unique) valid inverse using non-GMP code. */
+ secp256k1_fe_mul(&c, &c, r);
+ secp256k1_fe_add(&c, &negone);
+ CHECK(secp256k1_fe_normalizes_to_zero_var(&c));
#else
#error "Please select field inverse implementation"
#endif
}
-static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t *r, const secp256k1_fe_t *a) {
- secp256k1_fe_t u;
+static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe *r, const secp256k1_fe *a) {
+ secp256k1_fe u;
size_t i;
if (len < 1) {
return;
@@ -252,7 +272,7 @@ static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t *r, const secp25
secp256k1_fe_inv_var(&u, &r[--i]);
while (i > 0) {
- int j = i--;
+ size_t j = i--;
secp256k1_fe_mul(&r[j], &r[i], &u);
secp256k1_fe_mul(&u, &u, &a[j]);
}