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