/src/dovecot/src/lib/sha3.c
Line | Count | Source |
1 | | /* ------------------------------------------------------------------------- |
2 | | * Works when compiled for either 32-bit or 64-bit targets, optimized for |
3 | | * 64 bit. |
4 | | * |
5 | | * Canonical implementation of Init/Update/Finalize for SHA-3 byte input. |
6 | | * |
7 | | * SHA3-256, SHA3-384, SHA-512 are implemented. SHA-224 can easily be added. |
8 | | * |
9 | | * Based on code from http://keccak.noekeon.org/ . |
10 | | * |
11 | | * I place the code that I wrote into public domain, free to use. |
12 | | * |
13 | | * I would appreciate if you give credits to this work if you used it to |
14 | | * write or test * your code. |
15 | | * |
16 | | * Aug 2015. Andrey Jivsov. crypto@brainhub.org |
17 | | * |
18 | | * Modified for Dovecot oy use |
19 | | * Oct 2016. Aki Tuomi <aki.tuomi@dovecot.fi> |
20 | | |
21 | | * ---------------------------------------------------------------------- */ |
22 | | #include "lib.h" |
23 | | #include "sha3.h" |
24 | | |
25 | | #include <stdio.h> |
26 | | #include <stdint.h> |
27 | | #include <string.h> |
28 | | |
29 | | #if defined(_MSC_VER) |
30 | | #define SHA3_CONST(x) x |
31 | | #else |
32 | 0 | #define SHA3_CONST(x) x##L |
33 | | #endif |
34 | | |
35 | | /* The following state definition should normally be in a separate |
36 | | * header file |
37 | | */ |
38 | | |
39 | | #ifndef SHA3_ROTL64 |
40 | | #define SHA3_ROTL64(x, y) \ |
41 | 0 | (((x) << (y)) | ((x) >> ((sizeof(uint64_t)*8) - (y)))) |
42 | | #endif |
43 | | |
44 | | static const uint64_t keccakf_rndc[24] = { |
45 | | SHA3_CONST(0x0000000000000001UL), SHA3_CONST(0x0000000000008082UL), |
46 | | SHA3_CONST(0x800000000000808aUL), SHA3_CONST(0x8000000080008000UL), |
47 | | SHA3_CONST(0x000000000000808bUL), SHA3_CONST(0x0000000080000001UL), |
48 | | SHA3_CONST(0x8000000080008081UL), SHA3_CONST(0x8000000000008009UL), |
49 | | SHA3_CONST(0x000000000000008aUL), SHA3_CONST(0x0000000000000088UL), |
50 | | SHA3_CONST(0x0000000080008009UL), SHA3_CONST(0x000000008000000aUL), |
51 | | SHA3_CONST(0x000000008000808bUL), SHA3_CONST(0x800000000000008bUL), |
52 | | SHA3_CONST(0x8000000000008089UL), SHA3_CONST(0x8000000000008003UL), |
53 | | SHA3_CONST(0x8000000000008002UL), SHA3_CONST(0x8000000000000080UL), |
54 | | SHA3_CONST(0x000000000000800aUL), SHA3_CONST(0x800000008000000aUL), |
55 | | SHA3_CONST(0x8000000080008081UL), SHA3_CONST(0x8000000000008080UL), |
56 | | SHA3_CONST(0x0000000080000001UL), SHA3_CONST(0x8000000080008008UL) |
57 | | }; |
58 | | |
59 | | static const unsigned keccakf_rotc[24] = { |
60 | | 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, |
61 | | 18, 39, 61, 20, 44 |
62 | | }; |
63 | | |
64 | | static const unsigned keccakf_piln[24] = { |
65 | | 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, |
66 | | 14, 22, 9, 6, 1 |
67 | | }; |
68 | | |
69 | | /* generally called after SHA3_KECCAK_SPONGE_WORDS-ctx->capacityWords words |
70 | | * are XORed into the state s |
71 | | */ |
72 | | static void ATTR_UNSIGNED_WRAPS |
73 | | keccakf(uint64_t s[25]) |
74 | 0 | { |
75 | 0 | int i, j, round; |
76 | 0 | uint64_t t, bc[5]; |
77 | 0 | #define KECCAK_ROUNDS 24 |
78 | |
|
79 | 0 | for(round = 0; round < KECCAK_ROUNDS; round++) { |
80 | | |
81 | | /* Theta */ |
82 | 0 | for(i = 0; i < 5; i++) |
83 | 0 | bc[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; |
84 | |
|
85 | 0 | for(i = 0; i < 5; i++) { |
86 | 0 | t = bc[(i + 4) % 5] ^ SHA3_ROTL64(bc[(i + 1) % 5], 1); |
87 | 0 | for(j = 0; j < 25; j += 5) |
88 | 0 | s[j + i] ^= t; |
89 | 0 | } |
90 | | |
91 | | /* Rho Pi */ |
92 | 0 | t = s[1]; |
93 | 0 | for(i = 0; i < 24; i++) { |
94 | 0 | j = keccakf_piln[i]; |
95 | 0 | bc[0] = s[j]; |
96 | 0 | s[j] = SHA3_ROTL64(t, keccakf_rotc[i]); |
97 | 0 | t = bc[0]; |
98 | 0 | } |
99 | | |
100 | | /* Chi */ |
101 | 0 | for(j = 0; j < 25; j += 5) { |
102 | 0 | for(i = 0; i < 5; i++) |
103 | 0 | bc[i] = s[j + i]; |
104 | 0 | for(i = 0; i < 5; i++) |
105 | 0 | s[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; |
106 | 0 | } |
107 | | |
108 | | /* Iota */ |
109 | 0 | s[0] ^= keccakf_rndc[round]; |
110 | 0 | } |
111 | 0 | } |
112 | | |
113 | | /* *************************** Public Interface ************************ */ |
114 | | |
115 | | void sha3_256_init(void *context) |
116 | 0 | { |
117 | 0 | struct sha3_ctx *ctx = context; |
118 | 0 | i_zero(ctx); |
119 | 0 | ctx->capacityWords = 2 * 256 / (8 * sizeof(uint64_t)); |
120 | 0 | } |
121 | | |
122 | | void sha3_512_init(void *context) |
123 | 0 | { |
124 | 0 | struct sha3_ctx *ctx = context; |
125 | 0 | i_zero(ctx); |
126 | 0 | ctx->capacityWords = 2 * 512 / (8 * sizeof(uint64_t)); |
127 | 0 | } |
128 | | |
129 | | void sha3_loop(void *context, const void *data, size_t len) |
130 | 0 | { |
131 | 0 | struct sha3_ctx *ctx = context; |
132 | | /* 0...7 -- how much is needed to have a word */ |
133 | 0 | unsigned old_tail = (8 - ctx->byteIndex) & 7; |
134 | |
|
135 | 0 | size_t words; |
136 | 0 | unsigned tail; |
137 | 0 | size_t i; |
138 | |
|
139 | 0 | const uint8_t *buf = data; |
140 | |
|
141 | 0 | i_assert(ctx->byteIndex < 8); |
142 | 0 | i_assert(ctx->wordIndex < sizeof(ctx->s) / sizeof(ctx->s[0])); |
143 | | |
144 | 0 | if(len < old_tail) { /* have no complete word or haven't started |
145 | | * the word yet */ |
146 | | /* endian-independent code follows: */ |
147 | 0 | while (len > 0) { |
148 | 0 | len--; |
149 | 0 | ctx->saved |= (uint64_t) (*(buf++)) << |
150 | 0 | ((ctx->byteIndex++) * 8); |
151 | 0 | } |
152 | 0 | i_assert(ctx->byteIndex < 8); |
153 | 0 | return; |
154 | 0 | } |
155 | | |
156 | 0 | if(old_tail != 0) { /* will have one word to process */ |
157 | | /* endian-independent code follows: */ |
158 | 0 | len -= old_tail; |
159 | 0 | while (old_tail > 0) { |
160 | 0 | old_tail--; |
161 | 0 | ctx->saved |= (uint64_t) (*(buf++)) << |
162 | 0 | ((ctx->byteIndex++) * 8); |
163 | 0 | } |
164 | | |
165 | | /* now ready to add saved to the sponge */ |
166 | 0 | ctx->s[ctx->wordIndex] ^= ctx->saved; |
167 | 0 | i_assert(ctx->byteIndex == 8); |
168 | 0 | ctx->byteIndex = 0; |
169 | 0 | ctx->saved = 0; |
170 | 0 | if(++ctx->wordIndex == |
171 | 0 | (SHA3_KECCAK_SPONGE_WORDS - |
172 | 0 | ctx->capacityWords)) { |
173 | 0 | keccakf(ctx->s); |
174 | 0 | ctx->wordIndex = 0; |
175 | 0 | } |
176 | 0 | } |
177 | | |
178 | | /* now work in full words directly from input */ |
179 | | |
180 | 0 | i_assert(ctx->byteIndex == 0); |
181 | | |
182 | 0 | words = len / sizeof(uint64_t); |
183 | 0 | tail = len - words * sizeof(uint64_t); |
184 | |
|
185 | 0 | for(i = 0; i < words; i++, buf += sizeof(uint64_t)) { |
186 | 0 | const uint64_t t = (uint64_t) (buf[0]) | |
187 | 0 | ((uint64_t) (buf[1]) << 8 * 1) | |
188 | 0 | ((uint64_t) (buf[2]) << 8 * 2) | |
189 | 0 | ((uint64_t) (buf[3]) << 8 * 3) | |
190 | 0 | ((uint64_t) (buf[4]) << 8 * 4) | |
191 | 0 | ((uint64_t) (buf[5]) << 8 * 5) | |
192 | 0 | ((uint64_t) (buf[6]) << 8 * 6) | |
193 | 0 | ((uint64_t) (buf[7]) << 8 * 7); |
194 | 0 | #if defined(__x86_64__ ) || defined(__i386__) |
195 | 0 | i_assert(memcmp(&t, buf, 8) == 0); |
196 | 0 | #endif |
197 | 0 | ctx->s[ctx->wordIndex] ^= t; |
198 | 0 | if(++ctx->wordIndex == |
199 | 0 | (SHA3_KECCAK_SPONGE_WORDS - ctx->capacityWords)) { |
200 | 0 | keccakf(ctx->s); |
201 | 0 | ctx->wordIndex = 0; |
202 | 0 | } |
203 | 0 | } |
204 | | |
205 | | /* finally, save the partial word */ |
206 | 0 | i_assert(ctx->byteIndex == 0 && tail < 8); |
207 | 0 | while (tail > 0) { |
208 | 0 | tail--; |
209 | 0 | ctx->saved |= (uint64_t) (*(buf++)) << ((ctx->byteIndex++) * 8); |
210 | 0 | } |
211 | 0 | i_assert(ctx->byteIndex < 8); |
212 | 0 | } |
213 | | |
214 | | /* This is simply the 'update' with the padding block. |
215 | | * The padding block is 0x01 || 0x00* || 0x80. First 0x01 and last 0x80 |
216 | | * bytes are always present, but they can be the same byte. |
217 | | */ |
218 | | static void |
219 | | sha3_finalize(struct sha3_ctx *ctx) |
220 | 0 | { |
221 | | /* Append 2-bit suffix 01, per SHA-3 spec. Instead of 1 for padding we |
222 | | * use 1<<2 below. The 0x02 below corresponds to the suffix 01. |
223 | | * Overall, we feed 0, then 1, and finally 1 to start padding. Without |
224 | | * M || 01, we would simply use 1 to start padding. */ |
225 | | |
226 | | /* SHA3 version */ |
227 | 0 | ctx->s[ctx->wordIndex] ^= |
228 | 0 | (ctx->saved ^ ((uint64_t) ((uint64_t) (0x02 | (1 << 2)) << |
229 | 0 | ((ctx->byteIndex) * 8)))); |
230 | |
|
231 | 0 | ctx->s[SHA3_KECCAK_SPONGE_WORDS - ctx->capacityWords - 1] ^= |
232 | 0 | SHA3_CONST(0x8000000000000000UL); |
233 | 0 | keccakf(ctx->s); |
234 | |
|
235 | | #ifdef WORDS_BIGENDIAN |
236 | | { |
237 | | unsigned i; |
238 | | for(i = 0; i < SHA3_KECCAK_SPONGE_WORDS; i++) { |
239 | | const unsigned t1 = (uint32_t) ctx->s[i]; |
240 | | const unsigned t2 = (uint32_t) ((ctx->s[i] >> 16) >> 16); |
241 | | ctx->sb[i * 8 + 0] = (uint8_t) (t1); |
242 | | ctx->sb[i * 8 + 1] = (uint8_t) (t1 >> 8); |
243 | | ctx->sb[i * 8 + 2] = (uint8_t) (t1 >> 16); |
244 | | ctx->sb[i * 8 + 3] = (uint8_t) (t1 >> 24); |
245 | | ctx->sb[i * 8 + 4] = (uint8_t) (t2); |
246 | | ctx->sb[i * 8 + 5] = (uint8_t) (t2 >> 8); |
247 | | ctx->sb[i * 8 + 6] = (uint8_t) (t2 >> 16); |
248 | | ctx->sb[i * 8 + 7] = (uint8_t) (t2 >> 24); |
249 | | } |
250 | | } |
251 | | #endif |
252 | 0 | } |
253 | | |
254 | | void sha3_256_result(void *context, |
255 | | unsigned char digest[STATIC_ARRAY SHA256_RESULTLEN]) |
256 | 0 | { |
257 | 0 | struct sha3_ctx *ctx = context; |
258 | 0 | sha3_finalize(ctx); |
259 | 0 | memcpy(digest, ctx->sb, SHA256_RESULTLEN); |
260 | 0 | } |
261 | | |
262 | | |
263 | | void sha3_512_result(void *context, |
264 | | unsigned char digest[STATIC_ARRAY SHA512_RESULTLEN]) |
265 | 0 | { |
266 | 0 | struct sha3_ctx *ctx = context; |
267 | 0 | sha3_finalize(ctx); |
268 | 0 | memcpy(digest, ctx->sb, SHA512_RESULTLEN); |
269 | 0 | } |
270 | | |
271 | | |
272 | | void sha3_256_get_digest(const void *data, size_t size, |
273 | | unsigned char digest[STATIC_ARRAY SHA256_RESULTLEN]) |
274 | 0 | { |
275 | 0 | struct sha3_ctx ctx; |
276 | 0 | sha3_256_init(&ctx); |
277 | 0 | sha3_loop(&ctx, data, size); |
278 | 0 | sha3_256_result(&ctx, digest); |
279 | 0 | } |
280 | | |
281 | | void sha3_512_get_digest(const void *data, size_t size, |
282 | | unsigned char digest[STATIC_ARRAY SHA512_RESULTLEN]) |
283 | 0 | { |
284 | 0 | struct sha3_ctx ctx; |
285 | 0 | sha3_512_init(&ctx); |
286 | 0 | sha3_loop(&ctx, data, size); |
287 | 0 | sha3_512_result(&ctx, digest); |
288 | 0 | } |
289 | | |
290 | | static void hash_method_init_sha3_256(void *context) |
291 | 0 | { |
292 | 0 | sha3_256_init(context); |
293 | 0 | } |
294 | | |
295 | | static void hash_method_loop_sha3(void *context, const void *data, size_t size) |
296 | 0 | { |
297 | 0 | sha3_loop(context, data, size); |
298 | 0 | } |
299 | | |
300 | | static void hash_method_result_sha3_256(void *context, unsigned char *result_r) |
301 | 0 | { |
302 | 0 | sha3_256_result(context, result_r); |
303 | 0 | } |
304 | | |
305 | | const struct hash_method hash_method_sha3_256 = { |
306 | | .name = "sha3-256", |
307 | | .block_size = SHA256_BLOCK_SIZE, |
308 | | .context_size = sizeof(struct sha3_ctx), |
309 | | .digest_size = SHA256_RESULTLEN, |
310 | | |
311 | | .init = hash_method_init_sha3_256, |
312 | | .loop = hash_method_loop_sha3, |
313 | | .result = hash_method_result_sha3_256, |
314 | | }; |
315 | | |
316 | | static void hash_method_init_sha3_512(void *context) |
317 | 0 | { |
318 | 0 | sha3_512_init(context); |
319 | 0 | } |
320 | | |
321 | | static void hash_method_result_sha3_512(void *context, unsigned char *result_r) |
322 | 0 | { |
323 | 0 | sha3_512_result(context, result_r); |
324 | 0 | } |
325 | | |
326 | | const struct hash_method hash_method_sha3_512 = { |
327 | | .name = "sha3-512", |
328 | | .block_size = SHA512_BLOCK_SIZE, |
329 | | .context_size = sizeof(struct sha3_ctx), |
330 | | .digest_size = SHA512_RESULTLEN, |
331 | | |
332 | | .init = hash_method_init_sha3_512, |
333 | | .loop = hash_method_loop_sha3, |
334 | | .result = hash_method_result_sha3_512, |
335 | | }; |