Skip to content

Commit ae55e85

Browse files
committed
Use faster byteswapping and avoid alignment-increasing casts.
1 parent 0bada0e commit ae55e85

File tree

3 files changed

+44
-55
lines changed

3 files changed

+44
-55
lines changed

configure.ac

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,8 @@ if test x"$use_endomorphism" = x"yes"; then
305305
AC_DEFINE(USE_ENDOMORPHISM, 1, [Define this symbol to use endomorphism optimization])
306306
fi
307307

308+
AC_C_BIGENDIAN()
309+
308310
AC_MSG_NOTICE([Using assembly optimizations: $set_asm])
309311
AC_MSG_NOTICE([Using field implementation: $set_field])
310312
AC_MSG_NOTICE([Using bignum implementation: $set_bignum])

src/hash.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
typedef struct {
1414
uint32_t s[32];
15-
unsigned char buf[64];
15+
uint32_t buf[16]; /* In big endian */
1616
size_t bytes;
1717
} secp256k1_sha256_t;
1818

src/hash_impl.h

Lines changed: 41 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
(h) = t1 + t2; \
2828
} while(0)
2929

30-
#define ReadBE32(p) (((uint32_t)((p)[0])) << 24 | ((uint32_t)((p)[1])) << 16 | ((uint32_t)((p)[2])) << 8 | ((uint32_t)((p)[3])))
31-
#define WriteBE32(p, v) do { (p)[0] = (v) >> 24; (p)[1] = (v) >> 16; (p)[2] = (v) >> 8; (p)[3] = (v); } while(0)
30+
#ifdef WORDS_BIGENDIAN
31+
#define BE32(x) (x)
32+
#else
33+
#define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24))
34+
#endif
3235

3336
static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) {
3437
hash->s[0] = 0x6a09e667ul;
@@ -42,27 +45,27 @@ static void secp256k1_sha256_initialize(secp256k1_sha256_t *hash) {
4245
hash->bytes = 0;
4346
}
4447

45-
/** Perform one SHA-256 transformation, processing a 64-byte chunk. */
46-
static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* chunk) {
48+
/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */
49+
static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) {
4750
uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
4851
uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
4952

50-
Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0));
51-
Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4));
52-
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8));
53-
Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12));
54-
Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16));
55-
Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20));
56-
Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24));
57-
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28));
58-
Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32));
59-
Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36));
60-
Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40));
61-
Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44));
62-
Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48));
63-
Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52));
64-
Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56));
65-
Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60));
53+
Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = BE32(chunk[0]));
54+
Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = BE32(chunk[1]));
55+
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = BE32(chunk[2]));
56+
Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = BE32(chunk[3]));
57+
Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = BE32(chunk[4]));
58+
Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = BE32(chunk[5]));
59+
Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = BE32(chunk[6]));
60+
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = BE32(chunk[7]));
61+
Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = BE32(chunk[8]));
62+
Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = BE32(chunk[9]));
63+
Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = BE32(chunk[10]));
64+
Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = BE32(chunk[11]));
65+
Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = BE32(chunk[12]));
66+
Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = BE32(chunk[13]));
67+
Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = BE32(chunk[14]));
68+
Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = BE32(chunk[15]));
6669

6770
Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
6871
Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
@@ -126,52 +129,36 @@ static void secp256k1_sha256_transform(uint32_t* s, const unsigned char* chunk)
126129
}
127130

128131
static void secp256k1_sha256_write(secp256k1_sha256_t *hash, const unsigned char *data, size_t len) {
129-
const unsigned char* end = data + len;
130-
size_t bufsize = hash->bytes % 64;
131-
if (bufsize && bufsize + len >= 64) {
132+
size_t bufsize = hash->bytes & 0x3F;
133+
hash->bytes += len;
134+
while (bufsize + len >= 64) {
132135
/* Fill the buffer, and process it. */
133-
memcpy(hash->buf + bufsize, data, 64 - bufsize);
134-
hash->bytes += 64 - bufsize;
136+
memcpy(((unsigned char*)hash->buf) + bufsize, data, 64 - bufsize);
135137
data += 64 - bufsize;
138+
len -= 64 - bufsize;
136139
secp256k1_sha256_transform(hash->s, hash->buf);
137140
bufsize = 0;
138141
}
139-
while (end >= data + 64) {
140-
/* Process full chunks directly from the source. */
141-
secp256k1_sha256_transform(hash->s, data);
142-
hash->bytes += 64;
143-
data += 64;
144-
}
145-
if (end > data) {
142+
if (len) {
146143
/* Fill the buffer with what remains. */
147-
memcpy(hash->buf + bufsize, data, end - data);
148-
hash->bytes += end - data;
144+
memcpy(((unsigned char*)hash->buf) + bufsize, data, len);
149145
}
150146
}
151147

152148
static void secp256k1_sha256_finalize(secp256k1_sha256_t *hash, unsigned char *out32) {
153149
static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
154-
unsigned char sizedesc[8];
155-
WriteBE32(sizedesc, hash->bytes >> 29);
156-
WriteBE32(sizedesc + 4, hash->bytes << 3);
150+
uint32_t sizedesc[2];
151+
uint32_t out[8];
152+
int i = 0;
153+
sizedesc[0] = BE32(hash->bytes >> 29);
154+
sizedesc[1] = BE32(hash->bytes << 3);
157155
secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64));
158-
secp256k1_sha256_write(hash, sizedesc, 8);
159-
WriteBE32(out32, hash->s[0]);
160-
hash->s[0] = 0;
161-
WriteBE32(out32 + 4, hash->s[1]);
162-
hash->s[1] = 0;
163-
WriteBE32(out32 + 8, hash->s[2]);
164-
hash->s[2] = 0;
165-
WriteBE32(out32 + 12, hash->s[3]);
166-
hash->s[3] = 0;
167-
WriteBE32(out32 + 16, hash->s[4]);
168-
hash->s[4] = 0;
169-
WriteBE32(out32 + 20, hash->s[5]);
170-
hash->s[5] = 0;
171-
WriteBE32(out32 + 24, hash->s[6]);
172-
hash->s[6] = 0;
173-
WriteBE32(out32 + 28, hash->s[7]);
174-
hash->s[7] = 0;
156+
secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8);
157+
for (i = 0; i < 8; i++) {
158+
out[i] = BE32(hash->s[i]);
159+
hash->s[i] = 0;
160+
}
161+
memcpy(out32, (const unsigned char*)out, 32);
175162
}
176163

177164
static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256_t *hash, const unsigned char *key, size_t keylen) {

0 commit comments

Comments
 (0)