]>
Commit | Line | Data |
---|---|---|
b37fbc28 PW |
1 | /********************************************************************** |
2 | * Copyright (c) 2014 Pieter Wuille * | |
3 | * Distributed under the MIT software license, see the accompanying * | |
4 | * file COPYING or http://www.opensource.org/licenses/mit-license.php.* | |
5 | **********************************************************************/ | |
6 | ||
abe2d3e8 DR |
7 | #ifndef SECP256K1_HASH_IMPL_H |
8 | #define SECP256K1_HASH_IMPL_H | |
b37fbc28 PW |
9 | |
10 | #include "hash.h" | |
11 | ||
12 | #include <stdlib.h> | |
13 | #include <stdint.h> | |
039723d5 | 14 | #include <string.h> |
b37fbc28 PW |
15 | |
16 | #define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) | |
17 | #define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) | |
18 | #define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) | |
19 | #define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) | |
20 | #define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) | |
21 | #define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) | |
22 | ||
23 | #define Round(a,b,c,d,e,f,g,h,k,w) do { \ | |
24 | uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ | |
25 | uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ | |
26 | (d) += t1; \ | |
27 | (h) = t1 + t2; \ | |
28 | } while(0) | |
29 | ||
ae55e850 PW |
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 | |
b37fbc28 | 35 | |
d1dc9dfc | 36 | static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { |
b37fbc28 PW |
37 | hash->s[0] = 0x6a09e667ul; |
38 | hash->s[1] = 0xbb67ae85ul; | |
39 | hash->s[2] = 0x3c6ef372ul; | |
40 | hash->s[3] = 0xa54ff53aul; | |
41 | hash->s[4] = 0x510e527ful; | |
42 | hash->s[5] = 0x9b05688cul; | |
43 | hash->s[6] = 0x1f83d9abul; | |
44 | hash->s[7] = 0x5be0cd19ul; | |
45 | hash->bytes = 0; | |
46 | } | |
47 | ||
ae55e850 PW |
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) { | |
b37fbc28 PW |
50 | 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]; |
51 | uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; | |
52 | ||
ae55e850 PW |
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])); | |
b37fbc28 PW |
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 | ||
d1dc9dfc | 131 | static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) { |
ae55e850 PW |
132 | size_t bufsize = hash->bytes & 0x3F; |
133 | hash->bytes += len; | |
ec8f20ba TR |
134 | VERIFY_CHECK(hash->bytes >= len); |
135 | while (len >= 64 - bufsize) { | |
3627437d | 136 | /* Fill the buffer, and process it. */ |
c7680e57 TS |
137 | size_t chunk_len = 64 - bufsize; |
138 | memcpy(((unsigned char*)hash->buf) + bufsize, data, chunk_len); | |
139 | data += chunk_len; | |
140 | len -= chunk_len; | |
b37fbc28 PW |
141 | secp256k1_sha256_transform(hash->s, hash->buf); |
142 | bufsize = 0; | |
143 | } | |
ae55e850 | 144 | if (len) { |
3627437d | 145 | /* Fill the buffer with what remains. */ |
ae55e850 | 146 | memcpy(((unsigned char*)hash->buf) + bufsize, data, len); |
b37fbc28 PW |
147 | } |
148 | } | |
149 | ||
d1dc9dfc | 150 | static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) { |
b37fbc28 | 151 | 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}; |
ae55e850 PW |
152 | uint32_t sizedesc[2]; |
153 | uint32_t out[8]; | |
154 | int i = 0; | |
155 | sizedesc[0] = BE32(hash->bytes >> 29); | |
156 | sizedesc[1] = BE32(hash->bytes << 3); | |
b37fbc28 | 157 | secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); |
ae55e850 PW |
158 | secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8); |
159 | for (i = 0; i < 8; i++) { | |
160 | out[i] = BE32(hash->s[i]); | |
161 | hash->s[i] = 0; | |
162 | } | |
163 | memcpy(out32, (const unsigned char*)out, 32); | |
b37fbc28 PW |
164 | } |
165 | ||
d1dc9dfc | 166 | static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { |
c7680e57 | 167 | size_t n; |
b37fbc28 | 168 | unsigned char rkey[64]; |
c7680e57 | 169 | if (keylen <= sizeof(rkey)) { |
b37fbc28 | 170 | memcpy(rkey, key, keylen); |
c7680e57 | 171 | memset(rkey + keylen, 0, sizeof(rkey) - keylen); |
b37fbc28 | 172 | } else { |
d1dc9dfc | 173 | secp256k1_sha256 sha256; |
b37fbc28 PW |
174 | secp256k1_sha256_initialize(&sha256); |
175 | secp256k1_sha256_write(&sha256, key, keylen); | |
176 | secp256k1_sha256_finalize(&sha256, rkey); | |
177 | memset(rkey + 32, 0, 32); | |
178 | } | |
179 | ||
180 | secp256k1_sha256_initialize(&hash->outer); | |
c7680e57 | 181 | for (n = 0; n < sizeof(rkey); n++) { |
b37fbc28 | 182 | rkey[n] ^= 0x5c; |
26320197 | 183 | } |
c7680e57 | 184 | secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey)); |
b37fbc28 PW |
185 | |
186 | secp256k1_sha256_initialize(&hash->inner); | |
c7680e57 | 187 | for (n = 0; n < sizeof(rkey); n++) { |
b37fbc28 | 188 | rkey[n] ^= 0x5c ^ 0x36; |
26320197 | 189 | } |
c7680e57 TS |
190 | secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey)); |
191 | memset(rkey, 0, sizeof(rkey)); | |
b37fbc28 PW |
192 | } |
193 | ||
d1dc9dfc | 194 | static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) { |
b37fbc28 PW |
195 | secp256k1_sha256_write(&hash->inner, data, size); |
196 | } | |
197 | ||
d1dc9dfc | 198 | static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32) { |
b37fbc28 PW |
199 | unsigned char temp[32]; |
200 | secp256k1_sha256_finalize(&hash->inner, temp); | |
201 | secp256k1_sha256_write(&hash->outer, temp, 32); | |
202 | memset(temp, 0, 32); | |
203 | secp256k1_sha256_finalize(&hash->outer, out32); | |
204 | } | |
205 | ||
206 | ||
d1dc9dfc PW |
207 | static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { |
208 | secp256k1_hmac_sha256 hmac; | |
b37fbc28 PW |
209 | static const unsigned char zero[1] = {0x00}; |
210 | static const unsigned char one[1] = {0x01}; | |
211 | ||
33270bff GM |
212 | memset(rng->v, 0x01, 32); /* RFC6979 3.2.b. */ |
213 | memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ | |
b37fbc28 | 214 | |
33270bff | 215 | /* RFC6979 3.2.d. */ |
b37fbc28 PW |
216 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); |
217 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
218 | secp256k1_hmac_sha256_write(&hmac, zero, 1); | |
219 | secp256k1_hmac_sha256_write(&hmac, key, keylen); | |
b37fbc28 PW |
220 | secp256k1_hmac_sha256_finalize(&hmac, rng->k); |
221 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); | |
222 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
223 | secp256k1_hmac_sha256_finalize(&hmac, rng->v); | |
224 | ||
33270bff | 225 | /* RFC6979 3.2.f. */ |
b37fbc28 PW |
226 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); |
227 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
228 | secp256k1_hmac_sha256_write(&hmac, one, 1); | |
229 | secp256k1_hmac_sha256_write(&hmac, key, keylen); | |
b37fbc28 PW |
230 | secp256k1_hmac_sha256_finalize(&hmac, rng->k); |
231 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); | |
232 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
233 | secp256k1_hmac_sha256_finalize(&hmac, rng->v); | |
234 | rng->retry = 0; | |
235 | } | |
236 | ||
d1dc9dfc | 237 | static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { |
33270bff | 238 | /* RFC6979 3.2.h. */ |
b37fbc28 PW |
239 | static const unsigned char zero[1] = {0x00}; |
240 | if (rng->retry) { | |
d1dc9dfc | 241 | secp256k1_hmac_sha256 hmac; |
b37fbc28 PW |
242 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); |
243 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
244 | secp256k1_hmac_sha256_write(&hmac, zero, 1); | |
245 | secp256k1_hmac_sha256_finalize(&hmac, rng->k); | |
246 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); | |
247 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
248 | secp256k1_hmac_sha256_finalize(&hmac, rng->v); | |
249 | } | |
250 | ||
251 | while (outlen > 0) { | |
d1dc9dfc | 252 | secp256k1_hmac_sha256 hmac; |
792bcdb0 | 253 | int now = outlen; |
b37fbc28 PW |
254 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); |
255 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
256 | secp256k1_hmac_sha256_finalize(&hmac, rng->v); | |
b37fbc28 PW |
257 | if (now > 32) { |
258 | now = 32; | |
259 | } | |
260 | memcpy(out, rng->v, now); | |
261 | out += now; | |
262 | outlen -= now; | |
263 | } | |
264 | ||
265 | rng->retry = 1; | |
266 | } | |
267 | ||
d1dc9dfc | 268 | static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) { |
b37fbc28 PW |
269 | memset(rng->k, 0, 32); |
270 | memset(rng->v, 0, 32); | |
271 | rng->retry = 0; | |
272 | } | |
273 | ||
3f8b78e5 | 274 | #undef BE32 |
b37fbc28 | 275 | #undef Round |
b37fbc28 | 276 | #undef sigma1 |
3f8b78e5 | 277 | #undef sigma0 |
b37fbc28 | 278 | #undef Sigma1 |
3f8b78e5 | 279 | #undef Sigma0 |
b37fbc28 | 280 | #undef Maj |
3f8b78e5 | 281 | #undef Ch |
b37fbc28 | 282 | |
abe2d3e8 | 283 | #endif /* SECP256K1_HASH_IMPL_H */ |