]>
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" | |
0dccf98a | 11 | #include "util.h" |
b37fbc28 PW |
12 | |
13 | #include <stdlib.h> | |
14 | #include <stdint.h> | |
039723d5 | 15 | #include <string.h> |
b37fbc28 PW |
16 | |
17 | #define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) | |
18 | #define Maj(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) | |
19 | #define Sigma0(x) (((x) >> 2 | (x) << 30) ^ ((x) >> 13 | (x) << 19) ^ ((x) >> 22 | (x) << 10)) | |
20 | #define Sigma1(x) (((x) >> 6 | (x) << 26) ^ ((x) >> 11 | (x) << 21) ^ ((x) >> 25 | (x) << 7)) | |
21 | #define sigma0(x) (((x) >> 7 | (x) << 25) ^ ((x) >> 18 | (x) << 14) ^ ((x) >> 3)) | |
22 | #define sigma1(x) (((x) >> 17 | (x) << 15) ^ ((x) >> 19 | (x) << 13) ^ ((x) >> 10)) | |
23 | ||
24 | #define Round(a,b,c,d,e,f,g,h,k,w) do { \ | |
25 | uint32_t t1 = (h) + Sigma1(e) + Ch((e), (f), (g)) + (k) + (w); \ | |
26 | uint32_t t2 = Sigma0(a) + Maj((a), (b), (c)); \ | |
27 | (d) += t1; \ | |
28 | (h) = t1 + t2; \ | |
29 | } while(0) | |
30 | ||
0dccf98a | 31 | #if defined(SECP256K1_BIG_ENDIAN) |
ae55e850 | 32 | #define BE32(x) (x) |
0dccf98a | 33 | #elif defined(SECP256K1_LITTLE_ENDIAN) |
ae55e850 PW |
34 | #define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24)) |
35 | #endif | |
b37fbc28 | 36 | |
d1dc9dfc | 37 | static void secp256k1_sha256_initialize(secp256k1_sha256 *hash) { |
b37fbc28 PW |
38 | hash->s[0] = 0x6a09e667ul; |
39 | hash->s[1] = 0xbb67ae85ul; | |
40 | hash->s[2] = 0x3c6ef372ul; | |
41 | hash->s[3] = 0xa54ff53aul; | |
42 | hash->s[4] = 0x510e527ful; | |
43 | hash->s[5] = 0x9b05688cul; | |
44 | hash->s[6] = 0x1f83d9abul; | |
45 | hash->s[7] = 0x5be0cd19ul; | |
46 | hash->bytes = 0; | |
47 | } | |
48 | ||
ae55e850 PW |
49 | /** Perform one SHA-256 transformation, processing 16 big endian 32-bit words. */ |
50 | static void secp256k1_sha256_transform(uint32_t* s, const uint32_t* chunk) { | |
b37fbc28 PW |
51 | 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]; |
52 | uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15; | |
53 | ||
ae55e850 PW |
54 | Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = BE32(chunk[0])); |
55 | Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = BE32(chunk[1])); | |
56 | Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = BE32(chunk[2])); | |
57 | Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = BE32(chunk[3])); | |
58 | Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = BE32(chunk[4])); | |
59 | Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = BE32(chunk[5])); | |
60 | Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = BE32(chunk[6])); | |
61 | Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = BE32(chunk[7])); | |
62 | Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = BE32(chunk[8])); | |
63 | Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = BE32(chunk[9])); | |
64 | Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = BE32(chunk[10])); | |
65 | Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = BE32(chunk[11])); | |
66 | Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = BE32(chunk[12])); | |
67 | Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = BE32(chunk[13])); | |
68 | Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = BE32(chunk[14])); | |
69 | Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = BE32(chunk[15])); | |
b37fbc28 PW |
70 | |
71 | Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1)); | |
72 | Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2)); | |
73 | Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3)); | |
74 | Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4)); | |
75 | Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5)); | |
76 | Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6)); | |
77 | Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7)); | |
78 | Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8)); | |
79 | Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9)); | |
80 | Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10)); | |
81 | Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11)); | |
82 | Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12)); | |
83 | Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13)); | |
84 | Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14)); | |
85 | Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15)); | |
86 | Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0)); | |
87 | ||
88 | Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1)); | |
89 | Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2)); | |
90 | Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3)); | |
91 | Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4)); | |
92 | Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5)); | |
93 | Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6)); | |
94 | Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7)); | |
95 | Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8)); | |
96 | Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9)); | |
97 | Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10)); | |
98 | Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11)); | |
99 | Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12)); | |
100 | Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13)); | |
101 | Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14)); | |
102 | Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15)); | |
103 | Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0)); | |
104 | ||
105 | Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1)); | |
106 | Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2)); | |
107 | Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3)); | |
108 | Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4)); | |
109 | Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5)); | |
110 | Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6)); | |
111 | Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7)); | |
112 | Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8)); | |
113 | Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9)); | |
114 | Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10)); | |
115 | Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11)); | |
116 | Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12)); | |
117 | Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13)); | |
118 | Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14)); | |
119 | Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15)); | |
120 | Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0)); | |
121 | ||
122 | s[0] += a; | |
123 | s[1] += b; | |
124 | s[2] += c; | |
125 | s[3] += d; | |
126 | s[4] += e; | |
127 | s[5] += f; | |
128 | s[6] += g; | |
129 | s[7] += h; | |
130 | } | |
131 | ||
d1dc9dfc | 132 | static void secp256k1_sha256_write(secp256k1_sha256 *hash, const unsigned char *data, size_t len) { |
ae55e850 PW |
133 | size_t bufsize = hash->bytes & 0x3F; |
134 | hash->bytes += len; | |
ec8f20ba TR |
135 | VERIFY_CHECK(hash->bytes >= len); |
136 | while (len >= 64 - bufsize) { | |
3627437d | 137 | /* Fill the buffer, and process it. */ |
c7680e57 TS |
138 | size_t chunk_len = 64 - bufsize; |
139 | memcpy(((unsigned char*)hash->buf) + bufsize, data, chunk_len); | |
140 | data += chunk_len; | |
141 | len -= chunk_len; | |
b37fbc28 PW |
142 | secp256k1_sha256_transform(hash->s, hash->buf); |
143 | bufsize = 0; | |
144 | } | |
ae55e850 | 145 | if (len) { |
3627437d | 146 | /* Fill the buffer with what remains. */ |
ae55e850 | 147 | memcpy(((unsigned char*)hash->buf) + bufsize, data, len); |
b37fbc28 PW |
148 | } |
149 | } | |
150 | ||
d1dc9dfc | 151 | static void secp256k1_sha256_finalize(secp256k1_sha256 *hash, unsigned char *out32) { |
b37fbc28 | 152 | 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 |
153 | uint32_t sizedesc[2]; |
154 | uint32_t out[8]; | |
155 | int i = 0; | |
156 | sizedesc[0] = BE32(hash->bytes >> 29); | |
157 | sizedesc[1] = BE32(hash->bytes << 3); | |
b37fbc28 | 158 | secp256k1_sha256_write(hash, pad, 1 + ((119 - (hash->bytes % 64)) % 64)); |
ae55e850 PW |
159 | secp256k1_sha256_write(hash, (const unsigned char*)sizedesc, 8); |
160 | for (i = 0; i < 8; i++) { | |
161 | out[i] = BE32(hash->s[i]); | |
162 | hash->s[i] = 0; | |
163 | } | |
164 | memcpy(out32, (const unsigned char*)out, 32); | |
b37fbc28 PW |
165 | } |
166 | ||
d1dc9dfc | 167 | static void secp256k1_hmac_sha256_initialize(secp256k1_hmac_sha256 *hash, const unsigned char *key, size_t keylen) { |
c7680e57 | 168 | size_t n; |
b37fbc28 | 169 | unsigned char rkey[64]; |
c7680e57 | 170 | if (keylen <= sizeof(rkey)) { |
b37fbc28 | 171 | memcpy(rkey, key, keylen); |
c7680e57 | 172 | memset(rkey + keylen, 0, sizeof(rkey) - keylen); |
b37fbc28 | 173 | } else { |
d1dc9dfc | 174 | secp256k1_sha256 sha256; |
b37fbc28 PW |
175 | secp256k1_sha256_initialize(&sha256); |
176 | secp256k1_sha256_write(&sha256, key, keylen); | |
177 | secp256k1_sha256_finalize(&sha256, rkey); | |
178 | memset(rkey + 32, 0, 32); | |
179 | } | |
180 | ||
181 | secp256k1_sha256_initialize(&hash->outer); | |
c7680e57 | 182 | for (n = 0; n < sizeof(rkey); n++) { |
b37fbc28 | 183 | rkey[n] ^= 0x5c; |
26320197 | 184 | } |
c7680e57 | 185 | secp256k1_sha256_write(&hash->outer, rkey, sizeof(rkey)); |
b37fbc28 PW |
186 | |
187 | secp256k1_sha256_initialize(&hash->inner); | |
c7680e57 | 188 | for (n = 0; n < sizeof(rkey); n++) { |
b37fbc28 | 189 | rkey[n] ^= 0x5c ^ 0x36; |
26320197 | 190 | } |
c7680e57 TS |
191 | secp256k1_sha256_write(&hash->inner, rkey, sizeof(rkey)); |
192 | memset(rkey, 0, sizeof(rkey)); | |
b37fbc28 PW |
193 | } |
194 | ||
d1dc9dfc | 195 | static void secp256k1_hmac_sha256_write(secp256k1_hmac_sha256 *hash, const unsigned char *data, size_t size) { |
b37fbc28 PW |
196 | secp256k1_sha256_write(&hash->inner, data, size); |
197 | } | |
198 | ||
d1dc9dfc | 199 | static void secp256k1_hmac_sha256_finalize(secp256k1_hmac_sha256 *hash, unsigned char *out32) { |
b37fbc28 PW |
200 | unsigned char temp[32]; |
201 | secp256k1_sha256_finalize(&hash->inner, temp); | |
202 | secp256k1_sha256_write(&hash->outer, temp, 32); | |
203 | memset(temp, 0, 32); | |
204 | secp256k1_sha256_finalize(&hash->outer, out32); | |
205 | } | |
206 | ||
207 | ||
d1dc9dfc PW |
208 | static void secp256k1_rfc6979_hmac_sha256_initialize(secp256k1_rfc6979_hmac_sha256 *rng, const unsigned char *key, size_t keylen) { |
209 | secp256k1_hmac_sha256 hmac; | |
b37fbc28 PW |
210 | static const unsigned char zero[1] = {0x00}; |
211 | static const unsigned char one[1] = {0x01}; | |
212 | ||
33270bff GM |
213 | memset(rng->v, 0x01, 32); /* RFC6979 3.2.b. */ |
214 | memset(rng->k, 0x00, 32); /* RFC6979 3.2.c. */ | |
b37fbc28 | 215 | |
33270bff | 216 | /* RFC6979 3.2.d. */ |
b37fbc28 PW |
217 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); |
218 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
219 | secp256k1_hmac_sha256_write(&hmac, zero, 1); | |
220 | secp256k1_hmac_sha256_write(&hmac, key, keylen); | |
b37fbc28 PW |
221 | secp256k1_hmac_sha256_finalize(&hmac, rng->k); |
222 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); | |
223 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
224 | secp256k1_hmac_sha256_finalize(&hmac, rng->v); | |
225 | ||
33270bff | 226 | /* RFC6979 3.2.f. */ |
b37fbc28 PW |
227 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); |
228 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
229 | secp256k1_hmac_sha256_write(&hmac, one, 1); | |
230 | secp256k1_hmac_sha256_write(&hmac, key, keylen); | |
b37fbc28 PW |
231 | secp256k1_hmac_sha256_finalize(&hmac, rng->k); |
232 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); | |
233 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
234 | secp256k1_hmac_sha256_finalize(&hmac, rng->v); | |
235 | rng->retry = 0; | |
236 | } | |
237 | ||
d1dc9dfc | 238 | static void secp256k1_rfc6979_hmac_sha256_generate(secp256k1_rfc6979_hmac_sha256 *rng, unsigned char *out, size_t outlen) { |
33270bff | 239 | /* RFC6979 3.2.h. */ |
b37fbc28 PW |
240 | static const unsigned char zero[1] = {0x00}; |
241 | if (rng->retry) { | |
d1dc9dfc | 242 | secp256k1_hmac_sha256 hmac; |
b37fbc28 PW |
243 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); |
244 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
245 | secp256k1_hmac_sha256_write(&hmac, zero, 1); | |
246 | secp256k1_hmac_sha256_finalize(&hmac, rng->k); | |
247 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); | |
248 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
249 | secp256k1_hmac_sha256_finalize(&hmac, rng->v); | |
250 | } | |
251 | ||
252 | while (outlen > 0) { | |
d1dc9dfc | 253 | secp256k1_hmac_sha256 hmac; |
792bcdb0 | 254 | int now = outlen; |
b37fbc28 PW |
255 | secp256k1_hmac_sha256_initialize(&hmac, rng->k, 32); |
256 | secp256k1_hmac_sha256_write(&hmac, rng->v, 32); | |
257 | secp256k1_hmac_sha256_finalize(&hmac, rng->v); | |
b37fbc28 PW |
258 | if (now > 32) { |
259 | now = 32; | |
260 | } | |
261 | memcpy(out, rng->v, now); | |
262 | out += now; | |
263 | outlen -= now; | |
264 | } | |
265 | ||
266 | rng->retry = 1; | |
267 | } | |
268 | ||
d1dc9dfc | 269 | static void secp256k1_rfc6979_hmac_sha256_finalize(secp256k1_rfc6979_hmac_sha256 *rng) { |
b37fbc28 PW |
270 | memset(rng->k, 0, 32); |
271 | memset(rng->v, 0, 32); | |
272 | rng->retry = 0; | |
273 | } | |
274 | ||
3f8b78e5 | 275 | #undef BE32 |
b37fbc28 | 276 | #undef Round |
b37fbc28 | 277 | #undef sigma1 |
3f8b78e5 | 278 | #undef sigma0 |
b37fbc28 | 279 | #undef Sigma1 |
3f8b78e5 | 280 | #undef Sigma0 |
b37fbc28 | 281 | #undef Maj |
3f8b78e5 | 282 | #undef Ch |
b37fbc28 | 283 | |
abe2d3e8 | 284 | #endif /* SECP256K1_HASH_IMPL_H */ |