Skip to content

Commit 010be47

Browse files
committed
Merge rustyrussell#18: sha256 implementation to replace openssl
2 parents 64da14f + 9ddef39 commit 010be47

File tree

5 files changed

+202
-20
lines changed

5 files changed

+202
-20
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
ITERATE_OBJS := iterate.o parse.o blockfiles.o io.o dump.o
1+
ITERATE_OBJS := iterate.o parse.o blockfiles.o io.o dump.o sha256.o
22
#CCAN_OBJS := ccan-asort.o ccan-breakpoint.o ccan-tal.o ccan-tal-path.o ccan-tal-str.o ccan-take.o ccan-list.o ccan-str.o ccan-opt-helpers.o ccan-opt.o ccan-opt-parse.o ccan-opt-usage.o ccan-htable.o ccan-rbuf.o
33
CCAN_OBJS := ccan-tal.o ccan-tal-path.o ccan-tal-str.o ccan-take.o ccan-list.o ccan-str.o ccan-opt-helpers.o ccan-opt.o ccan-opt-parse.o ccan-opt-usage.o ccan-htable.o ccan-rbuf.o ccan-hex.o ccan-tal-grab-file.o ccan-noerr.o
44
CCANDIR=ccan/
55
CFLAGS = -O3 -flto -ggdb -I $(CCANDIR) -Wall
66
LDFLAGS = -O3 -flto
77
#CFLAGS = -ggdb -I $(CCANDIR) -Wall
8-
LDLIBS := -lcrypto
8+
LDLIBS :=
99
BIN_DIR := /usr/local/bin
1010

1111
all: bitcoin-iterate doc/bitcoin-iterate.1

parse.c

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,14 @@ static void read_output(struct space *space, struct file *f, off_t *poff,
104104
pull_bytes(f, poff, output->script, output->script_length);
105105
}
106106

107-
static void sha_add(SHA256_CTX *sha256, struct file *f, off_t start, off_t len)
107+
static void sha_add(sha256_context *sha256, struct file *f, off_t start, off_t len)
108108
{
109109
if (likely(f->mmap)) {
110-
SHA256_Update(sha256, f->mmap + start, len);
110+
sha256_write(sha256, f->mmap + start, len);
111111
} else {
112112
u8 *buf = tal_arr(NULL, u8, len);
113113
file_read(f, start, len, buf);
114-
SHA256_Update(sha256, buf, len);
114+
sha256_write(sha256, buf, len);
115115
tal_free(buf);
116116
}
117117
}
@@ -156,10 +156,10 @@ void read_bitcoin_transaction(struct space *space,
156156
size_t i;
157157
const off_t start = *poff;
158158
off_t hash_start = *poff;
159-
SHA256_CTX sha256;
159+
sha256_context sha256;
160160
bool segwit = false;
161161

162-
SHA256_Init(&sha256);
162+
sha256_initialize(&sha256);
163163

164164
trans->version = pull_u32(f, poff);
165165
sha_add(&sha256, f, start, *poff - start);
@@ -211,10 +211,10 @@ void read_bitcoin_transaction(struct space *space,
211211
len += *poff - hash_start;
212212

213213
/* Bitcoin uses double sha (it's not quite known why...) */
214-
SHA256_Final(trans->sha256, &sha256);
215-
SHA256_Init(&sha256);
216-
SHA256_Update(&sha256, trans->sha256, sizeof(trans->sha256));
217-
SHA256_Final(trans->sha256, &sha256);
214+
sha256_finalize(&sha256, trans->sha256);
215+
sha256_initialize(&sha256);
216+
sha256_write(&sha256, trans->sha256, sizeof(trans->sha256));
217+
sha256_finalize(&sha256, trans->sha256);
218218

219219
trans->non_swlen = len;
220220
trans->total_len = *poff - start;
@@ -243,7 +243,7 @@ read_bitcoin_block_header(struct bitcoin_block *block,
243243
u8 block_md[SHA256_DIGEST_LENGTH],
244244
const u32 marker)
245245
{
246-
SHA256_CTX sha256;
246+
sha256_context sha256;
247247
off_t start;
248248

249249
block->D9B4BEF9 = pull_u32(f, off);
@@ -260,20 +260,20 @@ read_bitcoin_block_header(struct bitcoin_block *block,
260260
block->nonce = pull_u32(f, off);
261261

262262
/* Bitcoin uses double sha (it's not quite known why...) */
263-
SHA256_Init(&sha256);
263+
sha256_initialize(&sha256);
264264
if (likely(f->mmap)) {
265-
SHA256_Update(&sha256, f->mmap + start, *off - start);
265+
sha256_write(&sha256, f->mmap + start, *off - start);
266266
} else {
267267
u8 *buf = tal_arr(NULL, u8, *off - start);
268268
file_read(f, start, *off - start, buf);
269-
SHA256_Update(&sha256, buf, *off - start);
269+
sha256_write(&sha256, buf, *off - start);
270270
tal_free(buf);
271271
}
272-
SHA256_Final(block_md, &sha256);
272+
sha256_finalize(&sha256, block_md);
273273

274-
SHA256_Init(&sha256);
275-
SHA256_Update(&sha256, block_md, SHA256_DIGEST_LENGTH);
276-
SHA256_Final(block_md, &sha256);
274+
sha256_initialize(&sha256);
275+
sha256_write(&sha256, block_md, SHA256_DIGEST_LENGTH);
276+
sha256_finalize(&sha256, block_md);
277277

278278
block->transaction_count = pull_varint(f, off);
279279

sha256.c

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/**********************************************************************
2+
* Copyright (c) 2014, 2020 Pieter Wuille, Elichai Turkel *
3+
* Distributed under the MIT software license, see the accompanying *
4+
* file COPYING or http://www.opensource.org/licenses/mit-license.php.*
5+
**********************************************************************/
6+
7+
#include <assert.h>
8+
#include <ccan/endian/endian.h>
9+
#include <string.h>
10+
#include "sha256.h"
11+
12+
13+
#define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
14+
#define Maj(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
15+
#define Sigma0(x) \
16+
(((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10))
17+
#define Sigma1(x) \
18+
(((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7))
19+
#define sigma0(x) \
20+
(((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3))
21+
#define sigma1(x) \
22+
(((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10))
23+
24+
#define Round(a, b, c, d, e, f, g, h, k, w) \
25+
do { \
26+
u32 t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \
27+
u32 t2 = Sigma0(a) + Maj((a), (b), (c)); \
28+
(d) += t1; \
29+
(h) = t1 + t2; \
30+
} while (0)
31+
32+
void sha256_initialize(sha256_context* hash)
33+
{
34+
hash->s[0] = 0x6a09e667UL;
35+
hash->s[1] = 0xbb67ae85UL;
36+
hash->s[2] = 0x3c6ef372UL;
37+
hash->s[3] = 0xa54ff53aUL;
38+
hash->s[4] = 0x510e527fUL;
39+
hash->s[5] = 0x9b05688cUL;
40+
hash->s[6] = 0x1f83d9abUL;
41+
hash->s[7] = 0x5be0cd19UL;
42+
hash->bytes = 0;
43+
}
44+
45+
/** Perform one SHA-256 transformation, processing 16 big endian 32-bit words.
46+
*/
47+
static void sha256_transform(u32* s, const u32* chunk)
48+
{
49+
u32 a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6],
50+
h = s[7];
51+
u32 w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
52+
53+
Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = CPU_TO_BE32(chunk[0]));
54+
Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = CPU_TO_BE32(chunk[1]));
55+
Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = CPU_TO_BE32(chunk[2]));
56+
Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = CPU_TO_BE32(chunk[3]));
57+
Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = CPU_TO_BE32(chunk[4]));
58+
Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = CPU_TO_BE32(chunk[5]));
59+
Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = CPU_TO_BE32(chunk[6]));
60+
Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = CPU_TO_BE32(chunk[7]));
61+
Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = CPU_TO_BE32(chunk[8]));
62+
Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = CPU_TO_BE32(chunk[9]));
63+
Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = CPU_TO_BE32(chunk[10]));
64+
Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = CPU_TO_BE32(chunk[11]));
65+
Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = CPU_TO_BE32(chunk[12]));
66+
Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = CPU_TO_BE32(chunk[13]));
67+
Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = CPU_TO_BE32(chunk[14]));
68+
Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = CPU_TO_BE32(chunk[15]));
69+
70+
Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
71+
Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
72+
Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
73+
Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
74+
Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
75+
Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
76+
Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
77+
Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
78+
Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
79+
Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
80+
Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
81+
Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
82+
Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
83+
Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
84+
Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
85+
Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
86+
87+
Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
88+
Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
89+
Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
90+
Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
91+
Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
92+
Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
93+
Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
94+
Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
95+
Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
96+
Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
97+
Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
98+
Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
99+
Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
100+
Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
101+
Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
102+
Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
103+
104+
Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
105+
Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
106+
Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
107+
Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
108+
Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
109+
Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
110+
Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
111+
Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
112+
Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
113+
Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
114+
Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
115+
Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
116+
Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
117+
Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
118+
Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
119+
Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
120+
121+
s[0] += a;
122+
s[1] += b;
123+
s[2] += c;
124+
s[3] += d;
125+
s[4] += e;
126+
s[5] += f;
127+
s[6] += g;
128+
s[7] += h;
129+
}
130+
131+
void sha256_write(sha256_context* hash, const u8* data, size_t len)
132+
{
133+
size_t bufsize = hash->bytes & 0x3FUL;
134+
hash->bytes += len;
135+
assert(hash->bytes >= len);
136+
while (len >= 64 - bufsize) {
137+
/* Fill the buffer, and process it. */
138+
size_t chunk_len = 64 - bufsize;
139+
memcpy(((u8*)hash->buf) + bufsize, data, chunk_len);
140+
data += chunk_len;
141+
len -= chunk_len;
142+
sha256_transform(hash->s, hash->buf);
143+
bufsize = 0;
144+
}
145+
if (len) {
146+
/* Fill the buffer with what remains. */
147+
memcpy(((u8*)hash->buf) + bufsize, data, len);
148+
}
149+
}
150+
151+
void sha256_finalize(sha256_context* hash, u8* out32)
152+
{
153+
static const u8 pad[64] = { 0x80 };
154+
u32 sizedesc[2];
155+
u32 out[8];
156+
int i = 0;
157+
/* The maximum message size of SHA256 is 2^64-1 bits. */
158+
assert(hash->bytes < ((uint64_t)1 << 56));
159+
sizedesc[0] = CPU_TO_BE32(hash->bytes >> 29);
160+
sizedesc[1] = CPU_TO_BE32(hash->bytes << 3);
161+
sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64));
162+
sha256_write(hash, (const u8*)sizedesc, 8);
163+
for (i = 0; i < 8; i++) {
164+
out[i] = CPU_TO_BE32(hash->s[i]);
165+
hash->s[i] = 0;
166+
}
167+
memcpy(out32, (const u8*)out, 32);
168+
}

sha256.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include <ccan/short_types/short_types.h>
2+
#include <stddef.h>
3+
4+
typedef struct {
5+
u32 s[8];
6+
u32 buf[16]; /* In big endian */
7+
u64 bytes;
8+
} sha256_context;
9+
10+
#define SHA256_DIGEST_LENGTH 32
11+
12+
void sha256_initialize(sha256_context* hash);
13+
void sha256_write(sha256_context* hash, const u8* data, size_t size);
14+
void sha256_finalize(sha256_context* hash, u8* out32);

types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef BITCOIN_PARSE_TYPES_H
22
#define BITCOIN_PARSE_TYPES_H
33
#include <ccan/short_types/short_types.h>
4-
#include <openssl/sha.h>
4+
#include "sha256.h"
55

66
/* We unpack varints for our in-memory representation */
77
#define varint_t u64

0 commit comments

Comments
 (0)