From f7a7666aeb8db92b9171f4765f7d405b7b73d946 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 28 Jan 2022 18:19:00 -0500 Subject: [PATCH] Abstract out verify logic for fe_set_b32 --- src/field.h | 13 ++++++++++--- src/field_10x26_impl.h | 11 ++--------- src/field_5x52_impl.h | 11 ++--------- src/field_impl.h | 9 +++++++++ 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/field.h b/src/field.h index 4145d89c80..b1c434eaf6 100644 --- a/src/field.h +++ b/src/field.h @@ -85,6 +85,7 @@ static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST( # define secp256k1_fe_is_zero secp256k1_fe_impl_is_zero # define secp256k1_fe_is_odd secp256k1_fe_impl_is_odd # define secp256k1_fe_cmp_var secp256k1_fe_impl_cmp_var +# define secp256k1_fe_set_b32 secp256k1_fe_impl_set_b32 #endif /* !defined(VERIFY) */ /** Normalize a field element. @@ -173,9 +174,15 @@ static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b); */ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b); -/** Set a field element equal to 32-byte big endian value. - * Returns 1 if no overflow occurred, and then the output is normalized. - * Returns 0 if overflow occurred, and then the output is only weakly normalized. */ +/** Set a field element equal to a provided 32-byte big endian value. + * + * On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array. + * On output, r = a (mod p). It will have magnitude 1, and if (a < p), it will be normalized. + * If not, it will only be weakly normalized. Returns whether (a < p). + * + * Note that this function is unusual in that the normalization of the output depends on the + * run-time value of a. + */ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a); /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ diff --git a/src/field_10x26_impl.h b/src/field_10x26_impl.h index a7a0186b71..5e0b65d652 100644 --- a/src/field_10x26_impl.h +++ b/src/field_10x26_impl.h @@ -298,8 +298,7 @@ static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe * return 0; } -static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int ret; +static int secp256k1_fe_impl_set_b32(secp256k1_fe *r, const unsigned char *a) { r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24); r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22); r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20); @@ -311,13 +310,7 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24); r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14); - ret = !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); -#ifdef VERIFY - r->magnitude = 1; - r->normalized = ret; - secp256k1_fe_verify(r); -#endif - return ret; + return !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL)); } /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h index b4af5d69a0..b06b485b7f 100644 --- a/src/field_5x52_impl.h +++ b/src/field_5x52_impl.h @@ -244,8 +244,7 @@ static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe * return 0; } -static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { - int ret; +static int secp256k1_fe_impl_set_b32(secp256k1_fe *r, const unsigned char *a) { r->n[0] = (uint64_t)a[31] | ((uint64_t)a[30] << 8) | ((uint64_t)a[29] << 16) @@ -280,13 +279,7 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { | ((uint64_t)a[2] << 24) | ((uint64_t)a[1] << 32) | ((uint64_t)a[0] << 40); - ret = !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL)); -#ifdef VERIFY - r->magnitude = 1; - r->normalized = ret; - secp256k1_fe_verify(r); -#endif - return ret; + return !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL)); } /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ diff --git a/src/field_impl.h b/src/field_impl.h index 4424ddb173..304c428cb7 100644 --- a/src/field_impl.h +++ b/src/field_impl.h @@ -237,6 +237,15 @@ SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const se VERIFY_CHECK(b->normalized); return secp256k1_fe_impl_cmp_var(a, b); } + +static int secp256k1_fe_impl_set_b32(secp256k1_fe *r, const unsigned char *a); +SECP256K1_INLINE static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { + int ret = secp256k1_fe_impl_set_b32(r, a); + r->magnitude = 1; + r->normalized = ret; + secp256k1_fe_verify(r); + return ret; +} #endif /* defined(VERIFY) */ #endif /* SECP256K1_FIELD_IMPL_H */