/src/mbedtls/library/sha3.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * FIPS-202 compliant SHA3 implementation |
3 | | * |
4 | | * Copyright The Mbed TLS Contributors |
5 | | * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later |
6 | | */ |
7 | | /* |
8 | | * The SHA-3 Secure Hash Standard was published by NIST in 2015. |
9 | | * |
10 | | * https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf |
11 | | */ |
12 | | |
13 | | #include "common.h" |
14 | | |
15 | | #if defined(MBEDTLS_SHA3_C) |
16 | | |
17 | | /* |
18 | | * These macros select manually unrolled implementations of parts of the main permutation function. |
19 | | * |
20 | | * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot |
21 | | * from manually unrolling at higher optimisation levels. |
22 | | * |
23 | | * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust |
24 | | * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and |
25 | | * x86-64. |
26 | | */ |
27 | | #if !defined(MBEDTLS_SHA3_THETA_UNROLL) |
28 | | #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names |
29 | | #endif |
30 | | #if !defined(MBEDTLS_SHA3_CHI_UNROLL) |
31 | | #if defined(__OPTIMIZE_SIZE__) |
32 | | #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names |
33 | | #else |
34 | | #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names |
35 | | #endif |
36 | | #endif |
37 | | #if !defined(MBEDTLS_SHA3_PI_UNROLL) |
38 | | #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names |
39 | | #endif |
40 | | #if !defined(MBEDTLS_SHA3_RHO_UNROLL) |
41 | | #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names |
42 | | #endif |
43 | | |
44 | | #include "mbedtls/sha3.h" |
45 | | #include "mbedtls/platform_util.h" |
46 | | #include "mbedtls/error.h" |
47 | | |
48 | | #include <string.h> |
49 | | |
50 | | #if defined(MBEDTLS_SELF_TEST) |
51 | | #include "mbedtls/platform.h" |
52 | | #endif /* MBEDTLS_SELF_TEST */ |
53 | | |
54 | | #define XOR_BYTE 0x6 |
55 | | |
56 | | /* Precomputed masks for the iota transform. |
57 | | * |
58 | | * Each round uses a 64-bit mask value. In each mask values, only |
59 | | * bits whose position is of the form 2^k-1 can be set, thus only |
60 | | * 7 of 64 bits of the mask need to be known for each mask value. |
61 | | * |
62 | | * We use a compressed encoding of the mask where bits 63, 31 and 15 |
63 | | * are moved to bits 4-6. This allows us to make each mask value |
64 | | * 1 byte rather than 8 bytes, saving 7*24 = 168 bytes of data (with |
65 | | * perhaps a little variation due to alignment). Decompressing this |
66 | | * requires a little code, but much less than the savings on the table. |
67 | | * |
68 | | * The impact on performance depends on the platform and compiler. |
69 | | * There's a bit more computation, but less memory bandwidth. A quick |
70 | | * benchmark on x86_64 shows a 7% speed improvement with GCC and a |
71 | | * 5% speed penalty with Clang, compared to the naive uint64_t[24] table. |
72 | | * YMMV. |
73 | | */ |
74 | | /* Helper macro to set the values of the higher bits in unused low positions */ |
75 | | #define H(b63, b31, b15) (b63 << 6 | b31 << 5 | b15 << 4) |
76 | | static const uint8_t iota_r_packed[24] = { |
77 | | H(0, 0, 0) | 0x01, H(0, 0, 1) | 0x82, H(1, 0, 1) | 0x8a, H(1, 1, 1) | 0x00, |
78 | | H(0, 0, 1) | 0x8b, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x09, |
79 | | H(0, 0, 0) | 0x8a, H(0, 0, 0) | 0x88, H(0, 1, 1) | 0x09, H(0, 1, 0) | 0x0a, |
80 | | H(0, 1, 1) | 0x8b, H(1, 0, 0) | 0x8b, H(1, 0, 1) | 0x89, H(1, 0, 1) | 0x03, |
81 | | H(1, 0, 1) | 0x02, H(1, 0, 0) | 0x80, H(0, 0, 1) | 0x0a, H(1, 1, 0) | 0x0a, |
82 | | H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x80, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x08, |
83 | | }; |
84 | | #undef H |
85 | | |
86 | | static const uint32_t rho[6] = { |
87 | | 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832 |
88 | | }; |
89 | | |
90 | | static const uint32_t pi[6] = { |
91 | | 0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916 |
92 | | }; |
93 | | |
94 | 113M | #define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right |
95 | 4.50M | #define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \ |
96 | 2.27M | } while (0) |
97 | 30.2k | #define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3))) |
98 | 93.9M | #define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0) |
99 | | |
100 | | /* The permutation function. */ |
101 | | static void keccak_f1600(mbedtls_sha3_context *ctx) |
102 | 163k | { |
103 | 163k | uint64_t lane[5]; |
104 | 163k | uint64_t *s = ctx->state; |
105 | 163k | int i; |
106 | | |
107 | 4.07M | for (int round = 0; round < 24; round++) { |
108 | 3.91M | uint64_t t; |
109 | | |
110 | | /* Theta */ |
111 | 3.91M | #if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names |
112 | 23.4M | for (i = 0; i < 5; i++) { |
113 | 19.5M | lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20]; |
114 | 19.5M | } |
115 | 23.4M | for (i = 0; i < 5; i++) { |
116 | 19.5M | t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63); |
117 | 19.5M | s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t; |
118 | 19.5M | } |
119 | | #else |
120 | | lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; |
121 | | lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; |
122 | | lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; |
123 | | lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; |
124 | | lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; |
125 | | |
126 | | t = lane[4] ^ ROTR64(lane[1], 63); |
127 | | s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t; |
128 | | |
129 | | t = lane[0] ^ ROTR64(lane[2], 63); |
130 | | s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t; |
131 | | |
132 | | t = lane[1] ^ ROTR64(lane[3], 63); |
133 | | s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t; |
134 | | |
135 | | t = lane[2] ^ ROTR64(lane[4], 63); |
136 | | s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t; |
137 | | |
138 | | t = lane[3] ^ ROTR64(lane[0], 63); |
139 | | s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t; |
140 | | #endif |
141 | | |
142 | | /* Rho */ |
143 | 27.4M | for (i = 1; i < 25; i += 4) { |
144 | 23.4M | uint32_t r = rho[(i - 1) >> 2]; |
145 | | #if MBEDTLS_SHA3_RHO_UNROLL == 0 |
146 | | for (int j = i; j < i + 4; j++) { |
147 | | uint8_t r8 = (uint8_t) (r >> 24); |
148 | | r <<= 8; |
149 | | s[j] = ROTR64(s[j], r8); |
150 | | } |
151 | | #else |
152 | 23.4M | s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r)); |
153 | 23.4M | s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r)); |
154 | 23.4M | s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r)); |
155 | 23.4M | s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r)); |
156 | 23.4M | #endif |
157 | 23.4M | } |
158 | | |
159 | | /* Pi */ |
160 | 3.91M | t = s[1]; |
161 | | #if MBEDTLS_SHA3_PI_UNROLL == 0 |
162 | | for (i = 0; i < 24; i += 4) { |
163 | | uint32_t p = pi[i >> 2]; |
164 | | for (unsigned j = 0; j < 4; j++) { |
165 | | SWAP(s[p & 0xff], t); |
166 | | p >>= 8; |
167 | | } |
168 | | } |
169 | | #else |
170 | 3.91M | uint32_t p = pi[0]; |
171 | 3.91M | SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); |
172 | 3.91M | SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); |
173 | 3.91M | p = pi[1]; |
174 | 3.91M | SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); |
175 | 3.91M | SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); |
176 | 3.91M | p = pi[2]; |
177 | 3.91M | SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); |
178 | 3.91M | SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); |
179 | 3.91M | p = pi[3]; |
180 | 3.91M | SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); |
181 | 3.91M | SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); |
182 | 3.91M | p = pi[4]; |
183 | 3.91M | SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); |
184 | 3.91M | SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); |
185 | 3.91M | p = pi[5]; |
186 | 3.91M | SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t); |
187 | 3.91M | SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t); |
188 | 3.91M | #endif |
189 | | |
190 | | /* Chi */ |
191 | | #if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names |
192 | | for (i = 0; i <= 20; i += 5) { |
193 | | lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2]; |
194 | | lane[3] = s[i + 3]; lane[4] = s[i + 4]; |
195 | | s[i + 0] ^= (~lane[1]) & lane[2]; |
196 | | s[i + 1] ^= (~lane[2]) & lane[3]; |
197 | | s[i + 2] ^= (~lane[3]) & lane[4]; |
198 | | s[i + 3] ^= (~lane[4]) & lane[0]; |
199 | | s[i + 4] ^= (~lane[0]) & lane[1]; |
200 | | } |
201 | | #else |
202 | 3.91M | lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4]; |
203 | 3.91M | s[0] ^= (~lane[1]) & lane[2]; |
204 | 3.91M | s[1] ^= (~lane[2]) & lane[3]; |
205 | 3.91M | s[2] ^= (~lane[3]) & lane[4]; |
206 | 3.91M | s[3] ^= (~lane[4]) & lane[0]; |
207 | 3.91M | s[4] ^= (~lane[0]) & lane[1]; |
208 | | |
209 | 3.91M | lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9]; |
210 | 3.91M | s[5] ^= (~lane[1]) & lane[2]; |
211 | 3.91M | s[6] ^= (~lane[2]) & lane[3]; |
212 | 3.91M | s[7] ^= (~lane[3]) & lane[4]; |
213 | 3.91M | s[8] ^= (~lane[4]) & lane[0]; |
214 | 3.91M | s[9] ^= (~lane[0]) & lane[1]; |
215 | | |
216 | 3.91M | lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14]; |
217 | 3.91M | s[10] ^= (~lane[1]) & lane[2]; |
218 | 3.91M | s[11] ^= (~lane[2]) & lane[3]; |
219 | 3.91M | s[12] ^= (~lane[3]) & lane[4]; |
220 | 3.91M | s[13] ^= (~lane[4]) & lane[0]; |
221 | 3.91M | s[14] ^= (~lane[0]) & lane[1]; |
222 | | |
223 | 3.91M | lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19]; |
224 | 3.91M | s[15] ^= (~lane[1]) & lane[2]; |
225 | 3.91M | s[16] ^= (~lane[2]) & lane[3]; |
226 | 3.91M | s[17] ^= (~lane[3]) & lane[4]; |
227 | 3.91M | s[18] ^= (~lane[4]) & lane[0]; |
228 | 3.91M | s[19] ^= (~lane[0]) & lane[1]; |
229 | | |
230 | 3.91M | lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24]; |
231 | 3.91M | s[20] ^= (~lane[1]) & lane[2]; |
232 | 3.91M | s[21] ^= (~lane[2]) & lane[3]; |
233 | 3.91M | s[22] ^= (~lane[3]) & lane[4]; |
234 | 3.91M | s[23] ^= (~lane[4]) & lane[0]; |
235 | 3.91M | s[24] ^= (~lane[0]) & lane[1]; |
236 | 3.91M | #endif |
237 | | |
238 | | /* Iota */ |
239 | | /* Decompress the round masks (see definition of rc) */ |
240 | 3.91M | s[0] ^= ((iota_r_packed[round] & 0x40ull) << 57 | |
241 | 3.91M | (iota_r_packed[round] & 0x20ull) << 26 | |
242 | 3.91M | (iota_r_packed[round] & 0x10ull) << 11 | |
243 | 3.91M | (iota_r_packed[round] & 0x8f)); |
244 | 3.91M | } |
245 | 163k | } |
246 | | |
247 | | void mbedtls_sha3_init(mbedtls_sha3_context *ctx) |
248 | 695 | { |
249 | 695 | memset(ctx, 0, sizeof(mbedtls_sha3_context)); |
250 | 695 | } |
251 | | |
252 | | void mbedtls_sha3_free(mbedtls_sha3_context *ctx) |
253 | 1.37k | { |
254 | 1.37k | if (ctx == NULL) { |
255 | 0 | return; |
256 | 0 | } |
257 | | |
258 | 1.37k | mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context)); |
259 | 1.37k | } |
260 | | |
261 | | void mbedtls_sha3_clone(mbedtls_sha3_context *dst, |
262 | | const mbedtls_sha3_context *src) |
263 | 0 | { |
264 | 0 | *dst = *src; |
265 | 0 | } |
266 | | |
267 | | /* |
268 | | * SHA-3 context setup |
269 | | */ |
270 | | int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id) |
271 | 695 | { |
272 | 695 | switch (id) { |
273 | 144 | case MBEDTLS_SHA3_224: |
274 | 144 | ctx->olen = 224 / 8; |
275 | 144 | ctx->max_block_size = 1152 / 8; |
276 | 144 | break; |
277 | 182 | case MBEDTLS_SHA3_256: |
278 | 182 | ctx->olen = 256 / 8; |
279 | 182 | ctx->max_block_size = 1088 / 8; |
280 | 182 | break; |
281 | 175 | case MBEDTLS_SHA3_384: |
282 | 175 | ctx->olen = 384 / 8; |
283 | 175 | ctx->max_block_size = 832 / 8; |
284 | 175 | break; |
285 | 194 | case MBEDTLS_SHA3_512: |
286 | 194 | ctx->olen = 512 / 8; |
287 | 194 | ctx->max_block_size = 576 / 8; |
288 | 194 | break; |
289 | 0 | default: |
290 | 0 | return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA; |
291 | 695 | } |
292 | | |
293 | 695 | memset(ctx->state, 0, sizeof(ctx->state)); |
294 | 695 | ctx->index = 0; |
295 | | |
296 | 695 | return 0; |
297 | 695 | } |
298 | | |
299 | | /* |
300 | | * SHA-3 process buffer |
301 | | */ |
302 | | int mbedtls_sha3_update(mbedtls_sha3_context *ctx, |
303 | | const uint8_t *input, |
304 | | size_t ilen) |
305 | 2.81k | { |
306 | 2.81k | if (ilen >= 8) { |
307 | | // 8-byte align index |
308 | 2.12k | int align_bytes = 8 - (ctx->index % 8); |
309 | 2.12k | if (align_bytes) { |
310 | 15.0k | for (; align_bytes > 0; align_bytes--) { |
311 | 12.8k | ABSORB(ctx, ctx->index, *input++); |
312 | 12.8k | ilen--; |
313 | 12.8k | ctx->index++; |
314 | 12.8k | } |
315 | 2.12k | if ((ctx->index = ctx->index % ctx->max_block_size) == 0) { |
316 | 102 | keccak_f1600(ctx); |
317 | 102 | } |
318 | 2.12k | } |
319 | | |
320 | | // process input in 8-byte chunks |
321 | 2.25M | while (ilen >= 8) { |
322 | 2.25M | ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0)); |
323 | 2.25M | input += 8; |
324 | 2.25M | ilen -= 8; |
325 | 2.25M | if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) { |
326 | 162k | keccak_f1600(ctx); |
327 | 162k | } |
328 | 2.25M | } |
329 | 2.12k | } |
330 | | |
331 | | // handle remaining bytes |
332 | 10.4k | while (ilen-- > 0) { |
333 | 7.59k | ABSORB(ctx, ctx->index, *input++); |
334 | 7.59k | if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) { |
335 | 11 | keccak_f1600(ctx); |
336 | 11 | } |
337 | 7.59k | } |
338 | | |
339 | 2.81k | return 0; |
340 | 2.81k | } |
341 | | |
342 | | int mbedtls_sha3_finish(mbedtls_sha3_context *ctx, |
343 | | uint8_t *output, size_t olen) |
344 | 683 | { |
345 | 683 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
346 | | |
347 | | /* Catch SHA-3 families, with fixed output length */ |
348 | 683 | if (ctx->olen > 0) { |
349 | 683 | if (ctx->olen > olen) { |
350 | 0 | ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA; |
351 | 0 | goto exit; |
352 | 0 | } |
353 | 683 | olen = ctx->olen; |
354 | 683 | } |
355 | | |
356 | 683 | ABSORB(ctx, ctx->index, XOR_BYTE); |
357 | 683 | ABSORB(ctx, ctx->max_block_size - 1, 0x80); |
358 | 683 | keccak_f1600(ctx); |
359 | 683 | ctx->index = 0; |
360 | | |
361 | 30.8k | while (olen-- > 0) { |
362 | 30.2k | *output++ = SQUEEZE(ctx, ctx->index); |
363 | | |
364 | 30.2k | if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) { |
365 | 0 | keccak_f1600(ctx); |
366 | 0 | } |
367 | 30.2k | } |
368 | | |
369 | 683 | ret = 0; |
370 | | |
371 | 683 | exit: |
372 | 683 | mbedtls_sha3_free(ctx); |
373 | 683 | return ret; |
374 | 683 | } |
375 | | |
376 | | /* |
377 | | * output = SHA-3( input buffer ) |
378 | | */ |
379 | | int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input, |
380 | | size_t ilen, uint8_t *output, size_t olen) |
381 | 0 | { |
382 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
383 | 0 | mbedtls_sha3_context ctx; |
384 | |
|
385 | 0 | mbedtls_sha3_init(&ctx); |
386 | | |
387 | | /* Sanity checks are performed in every mbedtls_sha3_xxx() */ |
388 | 0 | if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) { |
389 | 0 | goto exit; |
390 | 0 | } |
391 | | |
392 | 0 | if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) { |
393 | 0 | goto exit; |
394 | 0 | } |
395 | | |
396 | 0 | if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) { |
397 | 0 | goto exit; |
398 | 0 | } |
399 | | |
400 | 0 | exit: |
401 | 0 | mbedtls_sha3_free(&ctx); |
402 | |
|
403 | 0 | return ret; |
404 | 0 | } |
405 | | |
406 | | /**************** Self-tests ****************/ |
407 | | |
408 | | #if defined(MBEDTLS_SELF_TEST) |
409 | | |
410 | | static const unsigned char test_data[2][4] = |
411 | | { |
412 | | "", |
413 | | "abc", |
414 | | }; |
415 | | |
416 | | static const size_t test_data_len[2] = |
417 | | { |
418 | | 0, /* "" */ |
419 | | 3 /* "abc" */ |
420 | | }; |
421 | | |
422 | | static const unsigned char test_hash_sha3_224[2][28] = |
423 | | { |
424 | | { /* "" */ |
425 | | 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7, |
426 | | 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB, |
427 | | 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F, |
428 | | 0x5B, 0x5A, 0x6B, 0xC7 |
429 | | }, |
430 | | { /* "abc" */ |
431 | | 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A, |
432 | | 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F, |
433 | | 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD, |
434 | | 0x73, 0xB4, 0x6F, 0xDF |
435 | | } |
436 | | }; |
437 | | |
438 | | static const unsigned char test_hash_sha3_256[2][32] = |
439 | | { |
440 | | { /* "" */ |
441 | | 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66, |
442 | | 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62, |
443 | | 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA, |
444 | | 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A |
445 | | }, |
446 | | { /* "abc" */ |
447 | | 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2, |
448 | | 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD, |
449 | | 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B, |
450 | | 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32 |
451 | | } |
452 | | }; |
453 | | |
454 | | static const unsigned char test_hash_sha3_384[2][48] = |
455 | | { |
456 | | { /* "" */ |
457 | | 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D, |
458 | | 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85, |
459 | | 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61, |
460 | | 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A, |
461 | | 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47, |
462 | | 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04 |
463 | | }, |
464 | | { /* "abc" */ |
465 | | 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9, |
466 | | 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D, |
467 | | 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25, |
468 | | 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2, |
469 | | 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5, |
470 | | 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25 |
471 | | } |
472 | | }; |
473 | | |
474 | | static const unsigned char test_hash_sha3_512[2][64] = |
475 | | { |
476 | | { /* "" */ |
477 | | 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5, |
478 | | 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E, |
479 | | 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59, |
480 | | 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6, |
481 | | 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C, |
482 | | 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58, |
483 | | 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3, |
484 | | 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26 |
485 | | }, |
486 | | { /* "abc" */ |
487 | | 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A, |
488 | | 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E, |
489 | | 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D, |
490 | | 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E, |
491 | | 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9, |
492 | | 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40, |
493 | | 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5, |
494 | | 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0 |
495 | | } |
496 | | }; |
497 | | |
498 | | static const unsigned char long_kat_hash_sha3_224[28] = |
499 | | { |
500 | | 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E, |
501 | | 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C, |
502 | | 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7, |
503 | | 0xA7, 0xFD, 0x65, 0x3C |
504 | | }; |
505 | | |
506 | | static const unsigned char long_kat_hash_sha3_256[32] = |
507 | | { |
508 | | 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34, |
509 | | 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6, |
510 | | 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99, |
511 | | 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1 |
512 | | }; |
513 | | |
514 | | static const unsigned char long_kat_hash_sha3_384[48] = |
515 | | { |
516 | | 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53, |
517 | | 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD, |
518 | | 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E, |
519 | | 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84, |
520 | | 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42, |
521 | | 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40 |
522 | | }; |
523 | | |
524 | | static const unsigned char long_kat_hash_sha3_512[64] = |
525 | | { |
526 | | 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB, |
527 | | 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E, |
528 | | 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF, |
529 | | 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59, |
530 | | 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE, |
531 | | 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66, |
532 | | 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E, |
533 | | 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87 |
534 | | }; |
535 | | |
536 | | static int mbedtls_sha3_kat_test(int verbose, |
537 | | const char *type_name, |
538 | | mbedtls_sha3_id id, |
539 | | int test_num) |
540 | 0 | { |
541 | 0 | uint8_t hash[64]; |
542 | 0 | int result; |
543 | |
|
544 | 0 | result = mbedtls_sha3(id, |
545 | 0 | test_data[test_num], test_data_len[test_num], |
546 | 0 | hash, sizeof(hash)); |
547 | 0 | if (result != 0) { |
548 | 0 | if (verbose != 0) { |
549 | 0 | mbedtls_printf(" %s test %d error code: %d\n", |
550 | 0 | type_name, test_num, result); |
551 | 0 | } |
552 | |
|
553 | 0 | return result; |
554 | 0 | } |
555 | | |
556 | 0 | switch (id) { |
557 | 0 | case MBEDTLS_SHA3_224: |
558 | 0 | result = memcmp(hash, test_hash_sha3_224[test_num], 28); |
559 | 0 | break; |
560 | 0 | case MBEDTLS_SHA3_256: |
561 | 0 | result = memcmp(hash, test_hash_sha3_256[test_num], 32); |
562 | 0 | break; |
563 | 0 | case MBEDTLS_SHA3_384: |
564 | 0 | result = memcmp(hash, test_hash_sha3_384[test_num], 48); |
565 | 0 | break; |
566 | 0 | case MBEDTLS_SHA3_512: |
567 | 0 | result = memcmp(hash, test_hash_sha3_512[test_num], 64); |
568 | 0 | break; |
569 | 0 | default: |
570 | 0 | break; |
571 | 0 | } |
572 | | |
573 | 0 | if (0 != result) { |
574 | 0 | if (verbose != 0) { |
575 | 0 | mbedtls_printf(" %s test %d failed\n", type_name, test_num); |
576 | 0 | } |
577 | |
|
578 | 0 | return -1; |
579 | 0 | } |
580 | | |
581 | 0 | if (verbose != 0) { |
582 | 0 | mbedtls_printf(" %s test %d passed\n", type_name, test_num); |
583 | 0 | } |
584 | |
|
585 | 0 | return 0; |
586 | 0 | } |
587 | | |
588 | | static int mbedtls_sha3_long_kat_test(int verbose, |
589 | | const char *type_name, |
590 | | mbedtls_sha3_id id) |
591 | 0 | { |
592 | 0 | mbedtls_sha3_context ctx; |
593 | 0 | unsigned char buffer[1000]; |
594 | 0 | unsigned char hash[64]; |
595 | 0 | int result = 0; |
596 | |
|
597 | 0 | memset(buffer, 'a', 1000); |
598 | |
|
599 | 0 | if (verbose != 0) { |
600 | 0 | mbedtls_printf(" %s long KAT test ", type_name); |
601 | 0 | } |
602 | |
|
603 | 0 | mbedtls_sha3_init(&ctx); |
604 | |
|
605 | 0 | result = mbedtls_sha3_starts(&ctx, id); |
606 | 0 | if (result != 0) { |
607 | 0 | if (verbose != 0) { |
608 | 0 | mbedtls_printf("setup failed\n "); |
609 | 0 | } |
610 | 0 | } |
611 | | |
612 | | /* Process 1,000,000 (one million) 'a' characters */ |
613 | 0 | for (int i = 0; i < 1000; i++) { |
614 | 0 | result = mbedtls_sha3_update(&ctx, buffer, 1000); |
615 | 0 | if (result != 0) { |
616 | 0 | if (verbose != 0) { |
617 | 0 | mbedtls_printf("update error code: %i\n", result); |
618 | 0 | } |
619 | |
|
620 | 0 | goto cleanup; |
621 | 0 | } |
622 | 0 | } |
623 | | |
624 | 0 | result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash)); |
625 | 0 | if (result != 0) { |
626 | 0 | if (verbose != 0) { |
627 | 0 | mbedtls_printf("finish error code: %d\n", result); |
628 | 0 | } |
629 | |
|
630 | 0 | goto cleanup; |
631 | 0 | } |
632 | | |
633 | 0 | switch (id) { |
634 | 0 | case MBEDTLS_SHA3_224: |
635 | 0 | result = memcmp(hash, long_kat_hash_sha3_224, 28); |
636 | 0 | break; |
637 | 0 | case MBEDTLS_SHA3_256: |
638 | 0 | result = memcmp(hash, long_kat_hash_sha3_256, 32); |
639 | 0 | break; |
640 | 0 | case MBEDTLS_SHA3_384: |
641 | 0 | result = memcmp(hash, long_kat_hash_sha3_384, 48); |
642 | 0 | break; |
643 | 0 | case MBEDTLS_SHA3_512: |
644 | 0 | result = memcmp(hash, long_kat_hash_sha3_512, 64); |
645 | 0 | break; |
646 | 0 | default: |
647 | 0 | break; |
648 | 0 | } |
649 | | |
650 | 0 | if (result != 0) { |
651 | 0 | if (verbose != 0) { |
652 | 0 | mbedtls_printf("failed\n"); |
653 | 0 | } |
654 | 0 | } |
655 | |
|
656 | 0 | if (verbose != 0) { |
657 | 0 | mbedtls_printf("passed\n"); |
658 | 0 | } |
659 | |
|
660 | 0 | cleanup: |
661 | 0 | mbedtls_sha3_free(&ctx); |
662 | 0 | return result; |
663 | 0 | } |
664 | | |
665 | | int mbedtls_sha3_self_test(int verbose) |
666 | 0 | { |
667 | 0 | int i; |
668 | | |
669 | | /* SHA-3 Known Answer Tests (KAT) */ |
670 | 0 | for (i = 0; i < 2; i++) { |
671 | 0 | if (0 != mbedtls_sha3_kat_test(verbose, |
672 | 0 | "SHA3-224", MBEDTLS_SHA3_224, i)) { |
673 | 0 | return 1; |
674 | 0 | } |
675 | | |
676 | 0 | if (0 != mbedtls_sha3_kat_test(verbose, |
677 | 0 | "SHA3-256", MBEDTLS_SHA3_256, i)) { |
678 | 0 | return 1; |
679 | 0 | } |
680 | | |
681 | 0 | if (0 != mbedtls_sha3_kat_test(verbose, |
682 | 0 | "SHA3-384", MBEDTLS_SHA3_384, i)) { |
683 | 0 | return 1; |
684 | 0 | } |
685 | | |
686 | 0 | if (0 != mbedtls_sha3_kat_test(verbose, |
687 | 0 | "SHA3-512", MBEDTLS_SHA3_512, i)) { |
688 | 0 | return 1; |
689 | 0 | } |
690 | 0 | } |
691 | | |
692 | | /* SHA-3 long KAT tests */ |
693 | 0 | if (0 != mbedtls_sha3_long_kat_test(verbose, |
694 | 0 | "SHA3-224", MBEDTLS_SHA3_224)) { |
695 | 0 | return 1; |
696 | 0 | } |
697 | | |
698 | 0 | if (0 != mbedtls_sha3_long_kat_test(verbose, |
699 | 0 | "SHA3-256", MBEDTLS_SHA3_256)) { |
700 | 0 | return 1; |
701 | 0 | } |
702 | | |
703 | 0 | if (0 != mbedtls_sha3_long_kat_test(verbose, |
704 | 0 | "SHA3-384", MBEDTLS_SHA3_384)) { |
705 | 0 | return 1; |
706 | 0 | } |
707 | | |
708 | 0 | if (0 != mbedtls_sha3_long_kat_test(verbose, |
709 | 0 | "SHA3-512", MBEDTLS_SHA3_512)) { |
710 | 0 | return 1; |
711 | 0 | } |
712 | | |
713 | 0 | if (verbose != 0) { |
714 | 0 | mbedtls_printf("\n"); |
715 | 0 | } |
716 | |
|
717 | 0 | return 0; |
718 | 0 | } |
719 | | #endif /* MBEDTLS_SELF_TEST */ |
720 | | |
721 | | #endif /* MBEDTLS_SHA3_C */ |