From 7fa51955592ccf4fb424a7a538372ad159e77293 Mon Sep 17 00:00:00 2001
From: Pieter Wuille <pieter@wuille.net>
Date: Tue, 1 Feb 2022 11:15:09 -0500
Subject: [PATCH] Bugfix: correct SECP256K1_FE_CONST mag/norm fields

---
 src/field.h       | 20 ++++++++++++++++++++
 src/field_10x26.h |  6 ------
 src/field_5x52.h  |  6 ------
 3 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/src/field.h b/src/field.h
index 28ebe85ac1f00..3914f6b47a8e0 100644
--- a/src/field.h
+++ b/src/field.h
@@ -45,6 +45,26 @@
 #error "Please select wide multiplication implementation"
 #endif
 
+#ifdef VERIFY
+/* Magnitude and normalized value for constants. */
+#define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0) \
+    /* Magnitude is 0 for constant 0; 1 otherwise. */ \
+    , (((d7) | (d6) | (d5) | (d4) | (d3) | (d2) | (d1) | (d0)) != 0) \
+    /* Normalized is 1 unless sum(d_i<<(32*i) for i=0..7) exceeds field modulus. */ \
+    , (!(((d7) & (d6) & (d5) & (d4) & (d3) & (d2)) == 0xfffffffful && ((d1) == 0xfffffffful || ((d1) == 0xfffffffe && (d0 >= 0xfffffc2f)))))
+#else
+#define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0)
+#endif
+
+/** This expands to an initializer for a secp256k1_fe valued sum((i*32) * d_i, i=0..7) mod p.
+ *
+ * It has magnitude 1, unless d_i are all 0, in which case the magnitude is 0.
+ * It is normalized, unless sum(2^(i*32) * d_i, i=0..7) >= p.
+ *
+ * SECP256K1_FE_CONST_INNER is provided by the implementation.
+ */
+#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) SECP256K1_FE_VERIFY_CONST((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) }
+
 static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
 static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
     0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
diff --git a/src/field_10x26.h b/src/field_10x26.h
index 4fe36d08e2368..203c10167c3fe 100644
--- a/src/field_10x26.h
+++ b/src/field_10x26.h
@@ -47,12 +47,6 @@ typedef struct {
     (((uint32_t)d7) >> 10) \
 }
 
-#ifdef VERIFY
-#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1}
-#else
-#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))}
-#endif
-
 typedef struct {
     uint32_t n[8];
 } secp256k1_fe_storage;
diff --git a/src/field_5x52.h b/src/field_5x52.h
index e4646a56be69a..f20c246fdd517 100644
--- a/src/field_5x52.h
+++ b/src/field_5x52.h
@@ -42,12 +42,6 @@ typedef struct {
     ((uint64_t)(d6) >> 16) | (((uint64_t)(d7)) << 16) \
 }
 
-#ifdef VERIFY
-#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)), 1, 1}
-#else
-#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0))}
-#endif
-
 typedef struct {
     uint64_t n[4];
 } secp256k1_fe_storage;