Branch data Line data Source code
1 : : /* SHA512
2 : : * Daniel Beer <dlbeer@gmail.com>, 22 Apr 2014
3 : : *
4 : : * This file is in the public domain.
5 : : */
6 : :
7 : : #include "sha512.h"
8 : :
9 : : #if !defined(COMPACT_DISABLE_ED25519) || !defined(COMPACT_DISABLE_X25519_DERIVE)
10 : : const struct sha512_state sha512_initial_state = { {
11 : : 0x6a09e667f3bcc908LL, 0xbb67ae8584caa73bLL,
12 : : 0x3c6ef372fe94f82bLL, 0xa54ff53a5f1d36f1LL,
13 : : 0x510e527fade682d1LL, 0x9b05688c2b3e6c1fLL,
14 : : 0x1f83d9abfb41bd6bLL, 0x5be0cd19137e2179LL,
15 : : } };
16 : :
17 : : static const uint64_t round_k[80] = {
18 : : 0x428a2f98d728ae22LL, 0x7137449123ef65cdLL,
19 : : 0xb5c0fbcfec4d3b2fLL, 0xe9b5dba58189dbbcLL,
20 : : 0x3956c25bf348b538LL, 0x59f111f1b605d019LL,
21 : : 0x923f82a4af194f9bLL, 0xab1c5ed5da6d8118LL,
22 : : 0xd807aa98a3030242LL, 0x12835b0145706fbeLL,
23 : : 0x243185be4ee4b28cLL, 0x550c7dc3d5ffb4e2LL,
24 : : 0x72be5d74f27b896fLL, 0x80deb1fe3b1696b1LL,
25 : : 0x9bdc06a725c71235LL, 0xc19bf174cf692694LL,
26 : : 0xe49b69c19ef14ad2LL, 0xefbe4786384f25e3LL,
27 : : 0x0fc19dc68b8cd5b5LL, 0x240ca1cc77ac9c65LL,
28 : : 0x2de92c6f592b0275LL, 0x4a7484aa6ea6e483LL,
29 : : 0x5cb0a9dcbd41fbd4LL, 0x76f988da831153b5LL,
30 : : 0x983e5152ee66dfabLL, 0xa831c66d2db43210LL,
31 : : 0xb00327c898fb213fLL, 0xbf597fc7beef0ee4LL,
32 : : 0xc6e00bf33da88fc2LL, 0xd5a79147930aa725LL,
33 : : 0x06ca6351e003826fLL, 0x142929670a0e6e70LL,
34 : : 0x27b70a8546d22ffcLL, 0x2e1b21385c26c926LL,
35 : : 0x4d2c6dfc5ac42aedLL, 0x53380d139d95b3dfLL,
36 : : 0x650a73548baf63deLL, 0x766a0abb3c77b2a8LL,
37 : : 0x81c2c92e47edaee6LL, 0x92722c851482353bLL,
38 : : 0xa2bfe8a14cf10364LL, 0xa81a664bbc423001LL,
39 : : 0xc24b8b70d0f89791LL, 0xc76c51a30654be30LL,
40 : : 0xd192e819d6ef5218LL, 0xd69906245565a910LL,
41 : : 0xf40e35855771202aLL, 0x106aa07032bbd1b8LL,
42 : : 0x19a4c116b8d2d0c8LL, 0x1e376c085141ab53LL,
43 : : 0x2748774cdf8eeb99LL, 0x34b0bcb5e19b48a8LL,
44 : : 0x391c0cb3c5c95a63LL, 0x4ed8aa4ae3418acbLL,
45 : : 0x5b9cca4f7763e373LL, 0x682e6ff3d6b2b8a3LL,
46 : : 0x748f82ee5defb2fcLL, 0x78a5636f43172f60LL,
47 : : 0x84c87814a1f0ab72LL, 0x8cc702081a6439ecLL,
48 : : 0x90befffa23631e28LL, 0xa4506cebde82bde9LL,
49 : : 0xbef9a3f7b2c67915LL, 0xc67178f2e372532bLL,
50 : : 0xca273eceea26619cLL, 0xd186b8c721c0c207LL,
51 : : 0xeada7dd6cde0eb1eLL, 0xf57d4f7fee6ed178LL,
52 : : 0x06f067aa72176fbaLL, 0x0a637dc5a2c898a6LL,
53 : : 0x113f9804bef90daeLL, 0x1b710b35131c471bLL,
54 : : 0x28db77f523047d84LL, 0x32caab7b40c72493LL,
55 : : 0x3c9ebe0a15c9bebcLL, 0x431d67c49c100d4cLL,
56 : : 0x4cc5d4becb3e42b6LL, 0x597f299cfc657e2aLL,
57 : : 0x5fcb6fab3ad6faecLL, 0x6c44198c4a475817LL,
58 : : };
59 : :
60 : 416 : static inline uint64_t load64(const uint8_t *x)
61 : : {
62 : 416 : uint64_t r;
63 : :
64 : 416 : r = *(x++);
65 : 416 : r = (r << 8) | *(x++);
66 : 416 : r = (r << 8) | *(x++);
67 : 416 : r = (r << 8) | *(x++);
68 : 416 : r = (r << 8) | *(x++);
69 : 416 : r = (r << 8) | *(x++);
70 : 416 : r = (r << 8) | *(x++);
71 : 416 : r = (r << 8) | *(x++);
72 : :
73 : 416 : return r;
74 : : }
75 : :
76 : 72 : static inline void store64(uint8_t *x, uint64_t v)
77 : : {
78 : 72 : x += 7;
79 : 72 : *(x--) = v;
80 : 72 : v >>= 8;
81 : 72 : *(x--) = v;
82 : 72 : v >>= 8;
83 : 72 : *(x--) = v;
84 : 72 : v >>= 8;
85 : 72 : *(x--) = v;
86 : 72 : v >>= 8;
87 : 72 : *(x--) = v;
88 : 72 : v >>= 8;
89 : 72 : *(x--) = v;
90 : 72 : v >>= 8;
91 : 72 : *(x--) = v;
92 : 72 : v >>= 8;
93 : 72 : *(x--) = v;
94 : 72 : }
95 : :
96 : 20800 : static inline uint64_t rot64(uint64_t x, int bits)
97 : : {
98 : 20800 : return (x >> bits) | (x << (64 - bits));
99 : : }
100 : :
101 : 26 : void sha512_block(struct sha512_state *s, const uint8_t *blk)
102 : : {
103 : 26 : uint64_t w[16];
104 : 26 : uint64_t a, b, c, d, e, f, g, h;
105 : 26 : int i;
106 : :
107 [ + + ]: 442 : for (i = 0; i < 16; i++) {
108 : 416 : w[i] = load64(blk);
109 : 416 : blk += 8;
110 : : }
111 : :
112 : : /* Load state */
113 : 26 : a = s->h[0];
114 : 26 : b = s->h[1];
115 : 26 : c = s->h[2];
116 : 26 : d = s->h[3];
117 : 26 : e = s->h[4];
118 : 26 : f = s->h[5];
119 : 26 : g = s->h[6];
120 : 26 : h = s->h[7];
121 : :
122 [ + + ]: 2106 : for (i = 0; i < 80; i++) {
123 : : /* Compute value of w[i + 16]. w[wrap(i)] is currently w[i] */
124 : 2080 : const uint64_t wi = w[i & 15];
125 : 2080 : const uint64_t wi15 = w[(i + 1) & 15];
126 : 2080 : const uint64_t wi2 = w[(i + 14) & 15];
127 : 2080 : const uint64_t wi7 = w[(i + 9) & 15];
128 : 2080 : const uint64_t s0 =
129 : 2080 : rot64(wi15, 1) ^ rot64(wi15, 8) ^ (wi15 >> 7);
130 : 2080 : const uint64_t s1 =
131 : 2080 : rot64(wi2, 19) ^ rot64(wi2, 61) ^ (wi2 >> 6);
132 : :
133 : : /* Round calculations */
134 : 2080 : const uint64_t S0 = rot64(a, 28) ^ rot64(a, 34) ^ rot64(a, 39);
135 : 2080 : const uint64_t S1 = rot64(e, 14) ^ rot64(e, 18) ^ rot64(e, 41);
136 : 2080 : const uint64_t ch = (e & f) ^ ((~e) & g);
137 : 2080 : const uint64_t temp1 = h + S1 + ch + round_k[i] + wi;
138 : 2080 : const uint64_t maj = (a & b) ^ (a & c) ^ (b & c);
139 : 2080 : const uint64_t temp2 = S0 + maj;
140 : :
141 : : /* Update round state */
142 : 2080 : h = g;
143 : 2080 : g = f;
144 : 2080 : f = e;
145 : 2080 : e = d + temp1;
146 : 2080 : d = c;
147 : 2080 : c = b;
148 : 2080 : b = a;
149 : 2080 : a = temp1 + temp2;
150 : :
151 : : /* w[wrap(i)] becomes w[i + 16] */
152 : 2080 : w[i & 15] = wi + s0 + wi7 + s1;
153 : : }
154 : :
155 : : /* Store state */
156 : 26 : s->h[0] += a;
157 : 26 : s->h[1] += b;
158 : 26 : s->h[2] += c;
159 : 26 : s->h[3] += d;
160 : 26 : s->h[4] += e;
161 : 26 : s->h[5] += f;
162 : 26 : s->h[6] += g;
163 : 26 : s->h[7] += h;
164 : 26 : }
165 : :
166 : 8 : void sha512_final(struct sha512_state *s, const uint8_t *blk,
167 : : size_t total_size)
168 : : {
169 : 8 : uint8_t temp[SHA512_BLOCK_SIZE] = {0};
170 : 8 : const size_t last_size = total_size & (SHA512_BLOCK_SIZE - 1);
171 : :
172 [ + - ]: 8 : if (last_size)
173 : 8 : memcpy(temp, blk, last_size);
174 : 8 : temp[last_size] = 0x80;
175 : :
176 [ + + ]: 8 : if (last_size > 111) {
177 : 2 : sha512_block(s, temp);
178 : 2 : memset(temp, 0, sizeof(temp));
179 : : }
180 : :
181 : : /* Note: we assume total_size fits in 61 bits */
182 : 8 : store64(temp + SHA512_BLOCK_SIZE - 8, total_size << 3);
183 : 8 : sha512_block(s, temp);
184 : 8 : }
185 : :
186 : 8 : void sha512_get(const struct sha512_state *s, uint8_t *hash,
187 : : unsigned int offset, unsigned int len)
188 : : {
189 : 8 : int i;
190 : :
191 [ + - ]: 8 : if (offset > SHA512_BLOCK_SIZE)
192 : : return;
193 : :
194 : 8 : if (len > SHA512_BLOCK_SIZE - offset)
195 : : len = SHA512_BLOCK_SIZE - offset;
196 : :
197 : : /* Skip whole words */
198 : 8 : i = offset >> 3;
199 : 8 : offset &= 7;
200 : :
201 : : /* Skip/read out bytes */
202 [ - + ]: 8 : if (offset) {
203 : 0 : uint8_t tmp[8];
204 : 0 : unsigned int c = 8 - offset;
205 : :
206 : 0 : if (c > len)
207 : : c = len;
208 : :
209 : 0 : store64(tmp, s->h[i++]);
210 : 0 : memcpy(hash, tmp + offset, c);
211 : 0 : len -= c;
212 : 0 : hash += c;
213 : : }
214 : :
215 : : /* Read out whole words */
216 [ + + ]: 72 : while (len >= 8) {
217 : 64 : store64(hash, s->h[i++]);
218 : 64 : hash += 8;
219 : 64 : len -= 8;
220 : : }
221 : :
222 : : /* Read out bytes */
223 [ - + ]: 8 : if (len) {
224 : 0 : uint8_t tmp[8];
225 : :
226 : 0 : store64(tmp, s->h[i]);
227 : 0 : memcpy(hash, tmp, len);
228 : : }
229 : : }
230 : : #endif
|