xref: /netbsd-src/common/lib/libc/hash/sha3/keccak.c (revision 969998948d695be5e2710e8a39b23731441cccf5)
1*96999894Sriastradh /*	$NetBSD: keccak.c,v 1.1 2017/11/30 05:47:24 riastradh Exp $	*/
2*96999894Sriastradh 
3*96999894Sriastradh /*-
4*96999894Sriastradh  * Copyright (c) 2015 Taylor R. Campbell
5*96999894Sriastradh  * All rights reserved.
6*96999894Sriastradh  *
7*96999894Sriastradh  * Redistribution and use in source and binary forms, with or without
8*96999894Sriastradh  * modification, are permitted provided that the following conditions
9*96999894Sriastradh  * are met:
10*96999894Sriastradh  * 1. Redistributions of source code must retain the above copyright
11*96999894Sriastradh  *    notice, this list of conditions and the following disclaimer.
12*96999894Sriastradh  * 2. Redistributions in binary form must reproduce the above copyright
13*96999894Sriastradh  *    notice, this list of conditions and the following disclaimer in the
14*96999894Sriastradh  *    documentation and/or other materials provided with the distribution.
15*96999894Sriastradh  *
16*96999894Sriastradh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*96999894Sriastradh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*96999894Sriastradh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*96999894Sriastradh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*96999894Sriastradh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*96999894Sriastradh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*96999894Sriastradh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*96999894Sriastradh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*96999894Sriastradh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*96999894Sriastradh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*96999894Sriastradh  * SUCH DAMAGE.
27*96999894Sriastradh  */
28*96999894Sriastradh 
29*96999894Sriastradh #include <sys/cdefs.h>
30*96999894Sriastradh 
31*96999894Sriastradh #if defined(_KERNEL) || defined(_STANDALONE)
32*96999894Sriastradh __KERNEL_RCSID(0, "$NetBSD: keccak.c,v 1.1 2017/11/30 05:47:24 riastradh Exp $");
33*96999894Sriastradh 
34*96999894Sriastradh #include <sys/types.h>
35*96999894Sriastradh #else
36*96999894Sriastradh __RCSID("$NetBSD: keccak.c,v 1.1 2017/11/30 05:47:24 riastradh Exp $");
37*96999894Sriastradh 
38*96999894Sriastradh #include <stdint.h>
39*96999894Sriastradh #endif
40*96999894Sriastradh 
41*96999894Sriastradh #include "keccak.h"
42*96999894Sriastradh 
43*96999894Sriastradh #define	secret	/* can't use in variable-time operations, should zero */
44*96999894Sriastradh 
45*96999894Sriastradh #define	FOR5(X, STMT) do						      \
46*96999894Sriastradh {									      \
47*96999894Sriastradh 	(X) = 0; STMT;							      \
48*96999894Sriastradh 	(X) = 1; STMT;							      \
49*96999894Sriastradh 	(X) = 2; STMT;							      \
50*96999894Sriastradh 	(X) = 3; STMT;							      \
51*96999894Sriastradh 	(X) = 4; STMT;							      \
52*96999894Sriastradh } while (0)
53*96999894Sriastradh 
54*96999894Sriastradh static inline secret uint64_t
rol64(secret uint64_t v,unsigned c)55*96999894Sriastradh rol64(secret uint64_t v, unsigned c)
56*96999894Sriastradh {
57*96999894Sriastradh 
58*96999894Sriastradh 	return ((v << c) | (v >> (64 - c)));
59*96999894Sriastradh }
60*96999894Sriastradh 
61*96999894Sriastradh static inline void
keccakf1600_theta(secret uint64_t A[25])62*96999894Sriastradh keccakf1600_theta(secret uint64_t A[25])
63*96999894Sriastradh {
64*96999894Sriastradh 	secret uint64_t C0, C1, C2, C3, C4;
65*96999894Sriastradh 	unsigned y;
66*96999894Sriastradh 
67*96999894Sriastradh 	C0 = C1 = C2 = C3 = C4 = 0;
68*96999894Sriastradh 	FOR5(y, {
69*96999894Sriastradh 		C0 ^= A[0 + 5*y];
70*96999894Sriastradh 		C1 ^= A[1 + 5*y];
71*96999894Sriastradh 		C2 ^= A[2 + 5*y];
72*96999894Sriastradh 		C3 ^= A[3 + 5*y];
73*96999894Sriastradh 		C4 ^= A[4 + 5*y];
74*96999894Sriastradh 	});
75*96999894Sriastradh 	FOR5(y, {
76*96999894Sriastradh 		A[0 + 5*y] ^= C4 ^ rol64(C1, 1);
77*96999894Sriastradh 		A[1 + 5*y] ^= C0 ^ rol64(C2, 1);
78*96999894Sriastradh 		A[2 + 5*y] ^= C1 ^ rol64(C3, 1);
79*96999894Sriastradh 		A[3 + 5*y] ^= C2 ^ rol64(C4, 1);
80*96999894Sriastradh 		A[4 + 5*y] ^= C3 ^ rol64(C0, 1);
81*96999894Sriastradh 	});
82*96999894Sriastradh }
83*96999894Sriastradh 
84*96999894Sriastradh static inline void
keccakf1600_rho_pi(secret uint64_t A[25])85*96999894Sriastradh keccakf1600_rho_pi(secret uint64_t A[25])
86*96999894Sriastradh {
87*96999894Sriastradh 	secret uint64_t T, U;
88*96999894Sriastradh 
89*96999894Sriastradh 	/*
90*96999894Sriastradh 	 * Permute by (x,y) |---> (y, 2x + 3y mod 5) starting at (1,0),
91*96999894Sriastradh 	 * rotate the ith element by (i + 1)(i + 2)/2 mod 64.
92*96999894Sriastradh 	 */
93*96999894Sriastradh 	U = A[ 1];                       T = U;
94*96999894Sriastradh 	U = A[10]; A[10] = rol64(T,  1); T = U;
95*96999894Sriastradh 	U = A[ 7]; A[ 7] = rol64(T,  3); T = U;
96*96999894Sriastradh 	U = A[11]; A[11] = rol64(T,  6); T = U;
97*96999894Sriastradh 	U = A[17]; A[17] = rol64(T, 10); T = U;
98*96999894Sriastradh 	U = A[18]; A[18] = rol64(T, 15); T = U;
99*96999894Sriastradh 	U = A[ 3]; A[ 3] = rol64(T, 21); T = U;
100*96999894Sriastradh 	U = A[ 5]; A[ 5] = rol64(T, 28); T = U;
101*96999894Sriastradh 	U = A[16]; A[16] = rol64(T, 36); T = U;
102*96999894Sriastradh 	U = A[ 8]; A[ 8] = rol64(T, 45); T = U;
103*96999894Sriastradh 	U = A[21]; A[21] = rol64(T, 55); T = U;
104*96999894Sriastradh 	U = A[24]; A[24] = rol64(T,  2); T = U;
105*96999894Sriastradh 	U = A[ 4]; A[ 4] = rol64(T, 14); T = U;
106*96999894Sriastradh 	U = A[15]; A[15] = rol64(T, 27); T = U;
107*96999894Sriastradh 	U = A[23]; A[23] = rol64(T, 41); T = U;
108*96999894Sriastradh 	U = A[19]; A[19] = rol64(T, 56); T = U;
109*96999894Sriastradh 	U = A[13]; A[13] = rol64(T,  8); T = U;
110*96999894Sriastradh 	U = A[12]; A[12] = rol64(T, 25); T = U;
111*96999894Sriastradh 	U = A[ 2]; A[ 2] = rol64(T, 43); T = U;
112*96999894Sriastradh 	U = A[20]; A[20] = rol64(T, 62); T = U;
113*96999894Sriastradh 	U = A[14]; A[14] = rol64(T, 18); T = U;
114*96999894Sriastradh 	U = A[22]; A[22] = rol64(T, 39); T = U;
115*96999894Sriastradh 	U = A[ 9]; A[ 9] = rol64(T, 61); T = U;
116*96999894Sriastradh 	U = A[ 6]; A[ 6] = rol64(T, 20); T = U;
117*96999894Sriastradh 	           A[ 1] = rol64(T, 44);
118*96999894Sriastradh }
119*96999894Sriastradh 
120*96999894Sriastradh static inline void
keccakf1600_chi(secret uint64_t A[25])121*96999894Sriastradh keccakf1600_chi(secret uint64_t A[25])
122*96999894Sriastradh {
123*96999894Sriastradh 	secret uint64_t B0, B1, B2, B3, B4;
124*96999894Sriastradh 	unsigned y;
125*96999894Sriastradh 
126*96999894Sriastradh 	FOR5(y, {
127*96999894Sriastradh 		B0 = A[0 + 5*y];
128*96999894Sriastradh 		B1 = A[1 + 5*y];
129*96999894Sriastradh 		B2 = A[2 + 5*y];
130*96999894Sriastradh 		B3 = A[3 + 5*y];
131*96999894Sriastradh 		B4 = A[4 + 5*y];
132*96999894Sriastradh 		A[0 + 5*y] ^= ~B1 & B2;
133*96999894Sriastradh 		A[1 + 5*y] ^= ~B2 & B3;
134*96999894Sriastradh 		A[2 + 5*y] ^= ~B3 & B4;
135*96999894Sriastradh 		A[3 + 5*y] ^= ~B4 & B0;
136*96999894Sriastradh 		A[4 + 5*y] ^= ~B0 & B1;
137*96999894Sriastradh 	});
138*96999894Sriastradh }
139*96999894Sriastradh 
140*96999894Sriastradh static void
keccakf1600_round(secret uint64_t A[25])141*96999894Sriastradh keccakf1600_round(secret uint64_t A[25])
142*96999894Sriastradh {
143*96999894Sriastradh 
144*96999894Sriastradh 	keccakf1600_theta(A);
145*96999894Sriastradh 	keccakf1600_rho_pi(A);
146*96999894Sriastradh 	keccakf1600_chi(A);
147*96999894Sriastradh }
148*96999894Sriastradh 
149*96999894Sriastradh void
keccakf1600(secret uint64_t A[25])150*96999894Sriastradh keccakf1600(secret uint64_t A[25])
151*96999894Sriastradh {
152*96999894Sriastradh 	/*
153*96999894Sriastradh 	 * RC[i] = \sum_{j = 0,...,6} rc(j + 7i) 2^(2^j - 1),
154*96999894Sriastradh 	 * rc(t) = (x^t mod x^8 + x^6 + x^5 + x^4 + 1) mod x in GF(2)[x]
155*96999894Sriastradh 	 */
156*96999894Sriastradh 	static const uint64_t RC[24] = {
157*96999894Sriastradh 		0x0000000000000001ULL,
158*96999894Sriastradh 		0x0000000000008082ULL,
159*96999894Sriastradh 		0x800000000000808aULL,
160*96999894Sriastradh 		0x8000000080008000ULL,
161*96999894Sriastradh 		0x000000000000808bULL,
162*96999894Sriastradh 		0x0000000080000001ULL,
163*96999894Sriastradh 		0x8000000080008081ULL,
164*96999894Sriastradh 		0x8000000000008009ULL,
165*96999894Sriastradh 		0x000000000000008aULL,
166*96999894Sriastradh 		0x0000000000000088ULL,
167*96999894Sriastradh 		0x0000000080008009ULL,
168*96999894Sriastradh 		0x000000008000000aULL,
169*96999894Sriastradh 		0x000000008000808bULL,
170*96999894Sriastradh 		0x800000000000008bULL,
171*96999894Sriastradh 		0x8000000000008089ULL,
172*96999894Sriastradh 		0x8000000000008003ULL,
173*96999894Sriastradh 		0x8000000000008002ULL,
174*96999894Sriastradh 		0x8000000000000080ULL,
175*96999894Sriastradh 		0x000000000000800aULL,
176*96999894Sriastradh 		0x800000008000000aULL,
177*96999894Sriastradh 		0x8000000080008081ULL,
178*96999894Sriastradh 		0x8000000000008080ULL,
179*96999894Sriastradh 		0x0000000080000001ULL,
180*96999894Sriastradh 		0x8000000080008008ULL,
181*96999894Sriastradh 	};
182*96999894Sriastradh 	unsigned i;
183*96999894Sriastradh 
184*96999894Sriastradh 	for (i = 0; i < 24; i++) {
185*96999894Sriastradh 		keccakf1600_round(A);
186*96999894Sriastradh 		A[0] ^= RC[i];
187*96999894Sriastradh 	}
188*96999894Sriastradh }
189