xref: /optee_os/core/lib/libtomcrypt/sha3_accel.c (revision 1478437e65c44163f7c96f8a4c5d1532a9312bc3)
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