Convert field code to strict C89 (+ long long, +__int128)

This makes the software more portable to embedded systems
 and static analysis tools.

Sadly, it can't result in identical binaries because C99 mixed
 declarations seem to make GCC emit superfluous stack-pointer
 updates. The compiler is also somewhat dependent on the
 declaration order.
This commit is contained in:
Gregory Maxwell
2015-01-23 05:48:27 +00:00
parent 3627437d80
commit 25b35c7ecb
4 changed files with 190 additions and 147 deletions

View File

@@ -59,8 +59,8 @@ static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
uint64_t m;
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x1000003D1ULL;
@@ -126,8 +126,8 @@ static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
uint64_t m;
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x1000003D1ULL;
@@ -169,12 +169,12 @@ static void secp256k1_fe_normalize_var(secp256k1_fe_t *r) {
static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
uint64_t z0, z1;
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL;
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x1000003D1ULL;
t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL;
@@ -190,22 +190,31 @@ static int secp256k1_fe_normalizes_to_zero(secp256k1_fe_t *r) {
}
static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe_t *r) {
uint64_t t0 = r->n[0], t4 = r->n[4];
uint64_t t0, t1, t2, t3, t4;
uint64_t z0, z1;
uint64_t x;
t0 = r->n[0];
t4 = r->n[4];
/* Reduce t4 at the start so there will be at most a single carry from the first pass */
uint64_t x = t4 >> 48;
x = t4 >> 48;
/* The first pass ensures the magnitude is 1, ... */
t0 += x * 0x1000003D1ULL;
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
uint64_t z0 = t0 & 0xFFFFFFFFFFFFFULL, z1 = z0 ^ 0x1000003D0ULL;
z0 = t0 & 0xFFFFFFFFFFFFFULL;
z1 = z0 ^ 0x1000003D0ULL;
/* Fast return path should catch the majority of cases */
if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL))
return 0;
uint64_t t1 = r->n[1], t2 = r->n[2], t3 = r->n[3];
t1 = r->n[1];
t2 = r->n[2];
t3 = r->n[3];
t4 &= 0x0FFFFFFFFFFFFULL;
t1 += (t0 >> 52); t0 = z0;
@@ -231,11 +240,11 @@ SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
}
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
const uint64_t *t = a->n;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
const uint64_t *t = a->n;
return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0;
}
@@ -248,23 +257,25 @@ SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
}
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe_t *a) {
int i;
#ifdef VERIFY
a->magnitude = 0;
a->normalized = 1;
#endif
for (int i=0; i<5; i++) {
for (i=0; i<5; i++) {
a->n[i] = 0;
}
}
static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
int i;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
VERIFY_CHECK(b->normalized);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
#endif
for (int i = 4; i >= 0; i--) {
for (i = 4; i >= 0; i--) {
if (a->n[i] > b->n[i]) return 1;
if (a->n[i] < b->n[i]) return -1;
}
@@ -272,9 +283,11 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b
}
static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
int i;
r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
for (int i=0; i<32; i++) {
for (int j=0; j<2; j++) {
for (i=0; i<32; i++) {
int j;
for (j=0; j<2; j++) {
int limb = (8*i+4*j)/52;
int shift = (8*i+4*j)%52;
r->n[limb] |= (uint64_t)((a[31-i] >> (4*j)) & 0xF) << shift;
@@ -293,13 +306,15 @@ static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) {
int i;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
for (int i=0; i<32; i++) {
for (i=0; i<32; i++) {
int j;
int c = 0;
for (int j=0; j<2; j++) {
for (j=0; j<2; j++) {
int limb = (8*i+4*j)/52;
int shift = (8*i+4*j)%52;
c |= ((a->n[limb] >> shift) & 0xF) << (4 * j);