xref: /openbsd-src/lib/libcrypto/sha/sha3.c (revision 45e2a6c14ed10445bf25cf41b23047f745abbde7)
1*45e2a6c1Sjsing /*	$OpenBSD: sha3.c,v 1.16 2024/11/23 15:38:12 jsing Exp $	*/
29bb5e18bSjsing /*
39bb5e18bSjsing  * The MIT License (MIT)
49bb5e18bSjsing  *
59bb5e18bSjsing  * Copyright (c) 2015 Markku-Juhani O. Saarinen
69bb5e18bSjsing  *
79bb5e18bSjsing  * Permission is hereby granted, free of charge, to any person obtaining a copy
89bb5e18bSjsing  * of this software and associated documentation files (the "Software"), to deal
99bb5e18bSjsing  * in the Software without restriction, including without limitation the rights
109bb5e18bSjsing  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
119bb5e18bSjsing  * copies of the Software, and to permit persons to whom the Software is
129bb5e18bSjsing  * furnished to do so, subject to the following conditions:
139bb5e18bSjsing  *
149bb5e18bSjsing  * The above copyright notice and this permission notice shall be included in all
159bb5e18bSjsing  * copies or substantial portions of the Software.
169bb5e18bSjsing  *
179bb5e18bSjsing  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
189bb5e18bSjsing  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
199bb5e18bSjsing  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
209bb5e18bSjsing  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
219bb5e18bSjsing  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
229bb5e18bSjsing  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
239bb5e18bSjsing  * SOFTWARE.
249bb5e18bSjsing  */
259bb5e18bSjsing 
26ac5713a6Sjsing #include <endian.h>
270d9460fdSjsing #include <string.h>
28ac5713a6Sjsing 
29c0cd1c8bSjsing #include "sha3_internal.h"
30e70bbf9bSjsing 
31d44d5087Sjsing #define KECCAKF_ROUNDS 24
32d44d5087Sjsing 
33d44d5087Sjsing #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
34d44d5087Sjsing 
355c0ae387Sjsing static const uint64_t sha3_keccakf_rndc[24] = {
36e70bbf9bSjsing 	0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
37e70bbf9bSjsing 	0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
38e70bbf9bSjsing 	0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
39e70bbf9bSjsing 	0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
40e70bbf9bSjsing 	0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
41e70bbf9bSjsing 	0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
42e70bbf9bSjsing 	0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
43e70bbf9bSjsing 	0x8000000000008080, 0x0000000080000001, 0x8000000080008008
44e70bbf9bSjsing };
455c0ae387Sjsing static const int sha3_keccakf_rotc[24] = {
46e70bbf9bSjsing 	1,  3,  6,  10, 15, 21, 28, 36, 45, 55, 2,  14,
47e70bbf9bSjsing 	27, 41, 56, 8,  25, 43, 62, 18, 39, 61, 20, 44
48e70bbf9bSjsing };
495c0ae387Sjsing static const int sha3_keccakf_piln[24] = {
50e70bbf9bSjsing 	10, 7,  11, 17, 18, 3, 5,  16, 8,  21, 24, 4,
51e70bbf9bSjsing 	15, 23, 19, 13, 12, 2, 20, 14, 22, 9,  6,  1
52e70bbf9bSjsing };
53e70bbf9bSjsing 
548e11058eSjsing static void
555c0ae387Sjsing sha3_keccakf(uint64_t st[25])
565c0ae387Sjsing {
57e70bbf9bSjsing 	uint64_t t, bc[5];
585c0ae387Sjsing 	int i, j, r;
59e70bbf9bSjsing 
60*45e2a6c1Sjsing 	for (i = 0; i < 25; i++)
61*45e2a6c1Sjsing 		st[i] = le64toh(st[i]);
62e70bbf9bSjsing 
63e70bbf9bSjsing 	for (r = 0; r < KECCAKF_ROUNDS; r++) {
64e70bbf9bSjsing 
65e967e4e7Sjsing 		/* Theta */
66e70bbf9bSjsing 		for (i = 0; i < 5; i++)
67e70bbf9bSjsing 			bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20];
68e70bbf9bSjsing 
69e70bbf9bSjsing 		for (i = 0; i < 5; i++) {
70e70bbf9bSjsing 			t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
71e70bbf9bSjsing 			for (j = 0; j < 25; j += 5)
72e70bbf9bSjsing 				st[j + i] ^= t;
73e70bbf9bSjsing 		}
74e70bbf9bSjsing 
75e967e4e7Sjsing 		/* Rho Pi */
76e70bbf9bSjsing 		t = st[1];
77e70bbf9bSjsing 		for (i = 0; i < 24; i++) {
785c0ae387Sjsing 			j = sha3_keccakf_piln[i];
79e70bbf9bSjsing 			bc[0] = st[j];
805c0ae387Sjsing 			st[j] = ROTL64(t, sha3_keccakf_rotc[i]);
81e70bbf9bSjsing 			t = bc[0];
82e70bbf9bSjsing 		}
83e70bbf9bSjsing 
84e967e4e7Sjsing 		/* Chi */
85e70bbf9bSjsing 		for (j = 0; j < 25; j += 5) {
86e70bbf9bSjsing 			for (i = 0; i < 5; i++)
87e70bbf9bSjsing 				bc[i] = st[j + i];
88e70bbf9bSjsing 			for (i = 0; i < 5; i++)
89e70bbf9bSjsing 				st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5];
90e70bbf9bSjsing 		}
91e70bbf9bSjsing 
92e967e4e7Sjsing 		/* Iota */
935c0ae387Sjsing 		st[0] ^= sha3_keccakf_rndc[r];
94e70bbf9bSjsing 	}
95e70bbf9bSjsing 
96*45e2a6c1Sjsing 	for (i = 0; i < 25; i++)
97*45e2a6c1Sjsing 		st[i] = htole64(st[i]);
98e70bbf9bSjsing }
99e70bbf9bSjsing 
1008a4ba2fcSjsing int
101f1b36196Sjsing sha3_init(sha3_ctx *c, int mdlen)
102e70bbf9bSjsing {
103aae7803dSjsing 	if (mdlen < 0 || mdlen >= KECCAK_BYTE_WIDTH / 2)
104aae7803dSjsing 		return 0;
105aae7803dSjsing 
1060d9460fdSjsing 	memset(c, 0, sizeof(*c));
107e70bbf9bSjsing 
108e70bbf9bSjsing 	c->mdlen = mdlen;
109aae7803dSjsing 	c->rsize = KECCAK_BYTE_WIDTH - 2 * mdlen;
110e70bbf9bSjsing 
111e70bbf9bSjsing 	return 1;
112e70bbf9bSjsing }
113e70bbf9bSjsing 
1148a4ba2fcSjsing int
115f1b36196Sjsing sha3_update(sha3_ctx *c, const void *data, size_t len)
116e70bbf9bSjsing {
117acc18af8Sjsing 	size_t i, j;
118e70bbf9bSjsing 
119e70bbf9bSjsing 	j = c->pt;
120e70bbf9bSjsing 	for (i = 0; i < len; i++) {
121ee266ad5Sjsing 		c->state.b[j++] ^= ((const uint8_t *) data)[i];
122acc18af8Sjsing 		if (j >= c->rsize) {
123ee266ad5Sjsing 			sha3_keccakf(c->state.q);
124e70bbf9bSjsing 			j = 0;
125e70bbf9bSjsing 		}
126e70bbf9bSjsing 	}
127e70bbf9bSjsing 	c->pt = j;
128e70bbf9bSjsing 
129e70bbf9bSjsing 	return 1;
130e70bbf9bSjsing }
131e70bbf9bSjsing 
1328a4ba2fcSjsing int
133f1b36196Sjsing sha3_final(void *md, sha3_ctx *c)
134e70bbf9bSjsing {
135e70bbf9bSjsing 	int i;
136e70bbf9bSjsing 
137ee266ad5Sjsing 	c->state.b[c->pt] ^= 0x06;
138acc18af8Sjsing 	c->state.b[c->rsize - 1] ^= 0x80;
139ee266ad5Sjsing 	sha3_keccakf(c->state.q);
140e70bbf9bSjsing 
141e70bbf9bSjsing 	for (i = 0; i < c->mdlen; i++) {
142ee266ad5Sjsing 		((uint8_t *) md)[i] = c->state.b[i];
143e70bbf9bSjsing 	}
144e70bbf9bSjsing 
145e70bbf9bSjsing 	return 1;
146e70bbf9bSjsing }
147e70bbf9bSjsing 
148e967e4e7Sjsing /* SHAKE128 and SHAKE256 extensible-output functionality. */
1498a4ba2fcSjsing void
150f1b36196Sjsing shake_xof(sha3_ctx *c)
151e70bbf9bSjsing {
152ee266ad5Sjsing 	c->state.b[c->pt] ^= 0x1F;
153acc18af8Sjsing 	c->state.b[c->rsize - 1] ^= 0x80;
154ee266ad5Sjsing 	sha3_keccakf(c->state.q);
155e70bbf9bSjsing 	c->pt = 0;
156e70bbf9bSjsing }
157e70bbf9bSjsing 
1588a4ba2fcSjsing void
159f1b36196Sjsing shake_out(sha3_ctx *c, void *out, size_t len)
160e70bbf9bSjsing {
161acc18af8Sjsing 	size_t i, j;
162e70bbf9bSjsing 
163e70bbf9bSjsing 	j = c->pt;
164e70bbf9bSjsing 	for (i = 0; i < len; i++) {
165acc18af8Sjsing 		if (j >= c->rsize) {
166ee266ad5Sjsing 			sha3_keccakf(c->state.q);
167e70bbf9bSjsing 			j = 0;
168e70bbf9bSjsing 		}
169ee266ad5Sjsing 		((uint8_t *) out)[i] = c->state.b[j++];
170e70bbf9bSjsing 	}
171e70bbf9bSjsing 	c->pt = j;
172e70bbf9bSjsing }
173