1*1478437eSJens Wiklander /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2*1478437eSJens Wiklander /* SPDX-License-Identifier: Unlicense */
3*1478437eSJens Wiklander /*
4*1478437eSJens Wiklander * Copyright (c) 2023, Linaro Limited
5*1478437eSJens Wiklander */
6*1478437eSJens Wiklander
7*1478437eSJens Wiklander /* based on https://github.com/brainhub/SHA3IUF (public domain) */
8*1478437eSJens Wiklander
9*1478437eSJens Wiklander #include <crypto/crypto_accel.h>
10*1478437eSJens Wiklander #include <io.h>
11*1478437eSJens Wiklander #include <tomcrypt_private.h>
12*1478437eSJens Wiklander
13*1478437eSJens Wiklander #ifdef LTC_SHA3
14*1478437eSJens Wiklander
15*1478437eSJens Wiklander const struct ltc_hash_descriptor sha3_224_desc =
16*1478437eSJens Wiklander {
17*1478437eSJens Wiklander "sha3-224", /* name of hash */
18*1478437eSJens Wiklander 17, /* internal ID */
19*1478437eSJens Wiklander 28, /* Size of digest in octets */
20*1478437eSJens Wiklander 144, /* Input block size in octets */
21*1478437eSJens Wiklander { 2,16,840,1,101,3,4,2,7 }, /* ASN.1 OID */
22*1478437eSJens Wiklander 9, /* Length OID */
23*1478437eSJens Wiklander &sha3_224_init,
24*1478437eSJens Wiklander &sha3_process,
25*1478437eSJens Wiklander &sha3_done,
26*1478437eSJens Wiklander &sha3_224_test,
27*1478437eSJens Wiklander NULL
28*1478437eSJens Wiklander };
29*1478437eSJens Wiklander
30*1478437eSJens Wiklander const struct ltc_hash_descriptor sha3_256_desc =
31*1478437eSJens Wiklander {
32*1478437eSJens Wiklander "sha3-256", /* name of hash */
33*1478437eSJens Wiklander 18, /* internal ID */
34*1478437eSJens Wiklander 32, /* Size of digest in octets */
35*1478437eSJens Wiklander 136, /* Input block size in octets */
36*1478437eSJens Wiklander { 2,16,840,1,101,3,4,2,8 }, /* ASN.1 OID */
37*1478437eSJens Wiklander 9, /* Length OID */
38*1478437eSJens Wiklander &sha3_256_init,
39*1478437eSJens Wiklander &sha3_process,
40*1478437eSJens Wiklander &sha3_done,
41*1478437eSJens Wiklander &sha3_256_test,
42*1478437eSJens Wiklander NULL
43*1478437eSJens Wiklander };
44*1478437eSJens Wiklander
45*1478437eSJens Wiklander const struct ltc_hash_descriptor sha3_384_desc =
46*1478437eSJens Wiklander {
47*1478437eSJens Wiklander "sha3-384", /* name of hash */
48*1478437eSJens Wiklander 19, /* internal ID */
49*1478437eSJens Wiklander 48, /* Size of digest in octets */
50*1478437eSJens Wiklander 104, /* Input block size in octets */
51*1478437eSJens Wiklander { 2,16,840,1,101,3,4,2,9 }, /* ASN.1 OID */
52*1478437eSJens Wiklander 9, /* Length OID */
53*1478437eSJens Wiklander &sha3_384_init,
54*1478437eSJens Wiklander &sha3_process,
55*1478437eSJens Wiklander &sha3_done,
56*1478437eSJens Wiklander &sha3_384_test,
57*1478437eSJens Wiklander NULL
58*1478437eSJens Wiklander };
59*1478437eSJens Wiklander
60*1478437eSJens Wiklander const struct ltc_hash_descriptor sha3_512_desc =
61*1478437eSJens Wiklander {
62*1478437eSJens Wiklander "sha3-512", /* name of hash */
63*1478437eSJens Wiklander 20, /* internal ID */
64*1478437eSJens Wiklander 64, /* Size of digest in octets */
65*1478437eSJens Wiklander 72, /* Input block size in octets */
66*1478437eSJens Wiklander { 2,16,840,1,101,3,4,2,10 }, /* ASN.1 OID */
67*1478437eSJens Wiklander 9, /* Length OID */
68*1478437eSJens Wiklander &sha3_512_init,
69*1478437eSJens Wiklander &sha3_process,
70*1478437eSJens Wiklander &sha3_done,
71*1478437eSJens Wiklander &sha3_512_test,
72*1478437eSJens Wiklander NULL
73*1478437eSJens Wiklander };
74*1478437eSJens Wiklander
75*1478437eSJens Wiklander /* Public Inteface */
76*1478437eSJens Wiklander
sha3_224_init(hash_state * md)77*1478437eSJens Wiklander int sha3_224_init(hash_state *md)
78*1478437eSJens Wiklander {
79*1478437eSJens Wiklander LTC_ARGCHK(md != NULL);
80*1478437eSJens Wiklander XMEMSET(&md->sha3, 0, sizeof(md->sha3));
81*1478437eSJens Wiklander md->sha3.capacity_words = 2 * 224 / (8 * sizeof(ulong64));
82*1478437eSJens Wiklander return CRYPT_OK;
83*1478437eSJens Wiklander }
84*1478437eSJens Wiklander
sha3_256_init(hash_state * md)85*1478437eSJens Wiklander int sha3_256_init(hash_state *md)
86*1478437eSJens Wiklander {
87*1478437eSJens Wiklander LTC_ARGCHK(md != NULL);
88*1478437eSJens Wiklander XMEMSET(&md->sha3, 0, sizeof(md->sha3));
89*1478437eSJens Wiklander md->sha3.capacity_words = 2 * 256 / (8 * sizeof(ulong64));
90*1478437eSJens Wiklander return CRYPT_OK;
91*1478437eSJens Wiklander }
92*1478437eSJens Wiklander
sha3_384_init(hash_state * md)93*1478437eSJens Wiklander int sha3_384_init(hash_state *md)
94*1478437eSJens Wiklander {
95*1478437eSJens Wiklander LTC_ARGCHK(md != NULL);
96*1478437eSJens Wiklander XMEMSET(&md->sha3, 0, sizeof(md->sha3));
97*1478437eSJens Wiklander md->sha3.capacity_words = 2 * 384 / (8 * sizeof(ulong64));
98*1478437eSJens Wiklander return CRYPT_OK;
99*1478437eSJens Wiklander }
100*1478437eSJens Wiklander
sha3_512_init(hash_state * md)101*1478437eSJens Wiklander int sha3_512_init(hash_state *md)
102*1478437eSJens Wiklander {
103*1478437eSJens Wiklander LTC_ARGCHK(md != NULL);
104*1478437eSJens Wiklander XMEMSET(&md->sha3, 0, sizeof(md->sha3));
105*1478437eSJens Wiklander md->sha3.capacity_words = 2 * 512 / (8 * sizeof(ulong64));
106*1478437eSJens Wiklander return CRYPT_OK;
107*1478437eSJens Wiklander }
108*1478437eSJens Wiklander
sha3_shake_init(hash_state * md,int num)109*1478437eSJens Wiklander int sha3_shake_init(hash_state *md, int num)
110*1478437eSJens Wiklander {
111*1478437eSJens Wiklander LTC_ARGCHK(md != NULL);
112*1478437eSJens Wiklander if (num != 128 && num != 256) return CRYPT_INVALID_ARG;
113*1478437eSJens Wiklander XMEMSET(&md->sha3, 0, sizeof(md->sha3));
114*1478437eSJens Wiklander md->sha3.capacity_words = (unsigned short)(2 * num / (8 * sizeof(ulong64)));
115*1478437eSJens Wiklander return CRYPT_OK;
116*1478437eSJens Wiklander }
117*1478437eSJens Wiklander
sha3_process(hash_state * md,const unsigned char * in,unsigned long inlen)118*1478437eSJens Wiklander int sha3_process(hash_state *md, const unsigned char *in, unsigned long inlen)
119*1478437eSJens Wiklander {
120*1478437eSJens Wiklander unsigned int digest_size = 0;
121*1478437eSJens Wiklander unsigned int block_count = 0;
122*1478437eSJens Wiklander unsigned int block_size = 0;
123*1478437eSJens Wiklander void *state = NULL;
124*1478437eSJens Wiklander unsigned int l = 0;
125*1478437eSJens Wiklander
126*1478437eSJens Wiklander if (!inlen)
127*1478437eSJens Wiklander return CRYPT_OK;
128*1478437eSJens Wiklander LTC_ARGCHK(md);
129*1478437eSJens Wiklander LTC_ARGCHK(in);
130*1478437eSJens Wiklander
131*1478437eSJens Wiklander block_size = 200 - md->sha3.capacity_words * 8;
132*1478437eSJens Wiklander digest_size = md->sha3.capacity_words * 8 / 2;
133*1478437eSJens Wiklander state = md->sha3.s;
134*1478437eSJens Wiklander
135*1478437eSJens Wiklander if (md->sha3.byte_index) {
136*1478437eSJens Wiklander l = MIN(block_size - md->sha3.byte_index, inlen);
137*1478437eSJens Wiklander memcpy(md->sha3.sb + md->sha3.byte_index, in, l);
138*1478437eSJens Wiklander in += l;
139*1478437eSJens Wiklander inlen -= l;
140*1478437eSJens Wiklander md->sha3.byte_index += l;
141*1478437eSJens Wiklander if (md->sha3.byte_index == block_size) {
142*1478437eSJens Wiklander crypto_accel_sha3_compress(state, md->sha3.sb, 1,
143*1478437eSJens Wiklander digest_size);
144*1478437eSJens Wiklander md->sha3.byte_index = 0;
145*1478437eSJens Wiklander }
146*1478437eSJens Wiklander
147*1478437eSJens Wiklander if (!inlen)
148*1478437eSJens Wiklander return CRYPT_OK;
149*1478437eSJens Wiklander }
150*1478437eSJens Wiklander
151*1478437eSJens Wiklander if (inlen > block_size) {
152*1478437eSJens Wiklander block_count = inlen / block_size;
153*1478437eSJens Wiklander crypto_accel_sha3_compress(state, in, block_count,
154*1478437eSJens Wiklander digest_size);
155*1478437eSJens Wiklander in += block_count * block_size;
156*1478437eSJens Wiklander inlen -= block_count * block_size;
157*1478437eSJens Wiklander }
158*1478437eSJens Wiklander
159*1478437eSJens Wiklander memcpy(md->sha3.sb + md->sha3.byte_index, in, inlen);
160*1478437eSJens Wiklander md->sha3.byte_index += inlen;
161*1478437eSJens Wiklander
162*1478437eSJens Wiklander return CRYPT_OK;
163*1478437eSJens Wiklander }
164*1478437eSJens Wiklander
copy_out_digest(ulong64 * s,unsigned int digest_size,unsigned char * out)165*1478437eSJens Wiklander static void copy_out_digest(ulong64 *s, unsigned int digest_size,
166*1478437eSJens Wiklander unsigned char *out)
167*1478437eSJens Wiklander {
168*1478437eSJens Wiklander unsigned int n = 0;
169*1478437eSJens Wiklander
170*1478437eSJens Wiklander for (n = 0; n < digest_size / sizeof(uint64_t); n++) {
171*1478437eSJens Wiklander put_unaligned_le64(out, s[n]);
172*1478437eSJens Wiklander out += sizeof(uint64_t);
173*1478437eSJens Wiklander }
174*1478437eSJens Wiklander
175*1478437eSJens Wiklander if (digest_size % sizeof(uint64_t))
176*1478437eSJens Wiklander put_unaligned_le32(out, s[n]);
177*1478437eSJens Wiklander }
178*1478437eSJens Wiklander
sha3_done(hash_state * md,unsigned char * out)179*1478437eSJens Wiklander int sha3_done(hash_state *md, unsigned char *out)
180*1478437eSJens Wiklander {
181*1478437eSJens Wiklander unsigned int digest_size = 0;
182*1478437eSJens Wiklander unsigned int block_size = 0;
183*1478437eSJens Wiklander void *state = NULL;
184*1478437eSJens Wiklander uint8_t *buf = NULL;
185*1478437eSJens Wiklander
186*1478437eSJens Wiklander LTC_ARGCHK(md != NULL);
187*1478437eSJens Wiklander LTC_ARGCHK(out != NULL);
188*1478437eSJens Wiklander
189*1478437eSJens Wiklander block_size = 200 - md->sha3.capacity_words * 8;
190*1478437eSJens Wiklander digest_size = md->sha3.capacity_words * 8 / 2;
191*1478437eSJens Wiklander state = md->sha3.s;
192*1478437eSJens Wiklander buf = md->sha3.sb;
193*1478437eSJens Wiklander
194*1478437eSJens Wiklander buf[md->sha3.byte_index++] = 0x06;
195*1478437eSJens Wiklander memset(buf + md->sha3.byte_index, 0, block_size - md->sha3.byte_index);
196*1478437eSJens Wiklander buf[block_size - 1] |= 0x80;
197*1478437eSJens Wiklander crypto_accel_sha3_compress(state, buf, 1, digest_size);
198*1478437eSJens Wiklander
199*1478437eSJens Wiklander copy_out_digest(state, digest_size, out);
200*1478437eSJens Wiklander
201*1478437eSJens Wiklander return CRYPT_OK;
202*1478437eSJens Wiklander }
203*1478437eSJens Wiklander
204*1478437eSJens Wiklander
sha3_shake_done(hash_state * md,unsigned char * out,unsigned long outlen)205*1478437eSJens Wiklander int sha3_shake_done(hash_state *md, unsigned char *out, unsigned long outlen)
206*1478437eSJens Wiklander {
207*1478437eSJens Wiklander unsigned int digest_size = 0;
208*1478437eSJens Wiklander unsigned int block_size = 0;
209*1478437eSJens Wiklander void *state = NULL;
210*1478437eSJens Wiklander uint8_t *buf = NULL;
211*1478437eSJens Wiklander unsigned int n = 0;
212*1478437eSJens Wiklander
213*1478437eSJens Wiklander LTC_ARGCHK(md != NULL);
214*1478437eSJens Wiklander LTC_ARGCHK(out != NULL);
215*1478437eSJens Wiklander
216*1478437eSJens Wiklander block_size = 200 - md->sha3.capacity_words * 8;
217*1478437eSJens Wiklander digest_size = md->sha3.capacity_words * 8 / 2;
218*1478437eSJens Wiklander state = md->sha3.s;
219*1478437eSJens Wiklander buf = md->sha3.sb;
220*1478437eSJens Wiklander
221*1478437eSJens Wiklander if (!md->sha3.xof_flag) {
222*1478437eSJens Wiklander buf[md->sha3.byte_index++] = 0x1f;
223*1478437eSJens Wiklander memset(buf + md->sha3.byte_index, 0,
224*1478437eSJens Wiklander block_size - md->sha3.byte_index);
225*1478437eSJens Wiklander buf[block_size - 1] |= 0x80;
226*1478437eSJens Wiklander crypto_accel_sha3_compress(state, buf, 1, digest_size);
227*1478437eSJens Wiklander md->sha3.byte_index = 0;
228*1478437eSJens Wiklander copy_out_digest(state, block_size, buf);
229*1478437eSJens Wiklander md->sha3.xof_flag = 1;
230*1478437eSJens Wiklander }
231*1478437eSJens Wiklander
232*1478437eSJens Wiklander for (n = 0; n < outlen; n++) {
233*1478437eSJens Wiklander if (md->sha3.byte_index >= block_size) {
234*1478437eSJens Wiklander memset(buf, 0, block_size);
235*1478437eSJens Wiklander crypto_accel_sha3_compress(state, buf, 1, digest_size);
236*1478437eSJens Wiklander md->sha3.byte_index = 0;
237*1478437eSJens Wiklander copy_out_digest(state, block_size, buf);
238*1478437eSJens Wiklander }
239*1478437eSJens Wiklander out[n] = buf[md->sha3.byte_index];
240*1478437eSJens Wiklander md->sha3.byte_index++;
241*1478437eSJens Wiklander }
242*1478437eSJens Wiklander
243*1478437eSJens Wiklander return CRYPT_OK;
244*1478437eSJens Wiklander }
245*1478437eSJens Wiklander #endif
246