aboutsummaryrefslogtreecommitdiffstats
path: root/800.c
blob: e55dcd45e3d0414cf74d151e99798c6010753134 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/* See LICENSE file for copyright and license details. */


/**
 * 32-bit Keccak-f round constants
 */
static const uint32_t rc32[] = {
	UINT32_C(0x00000001), UINT32_C(0x00008082), UINT32_C(0x0000808A), UINT32_C(0x80008000),
	UINT32_C(0x0000808B), UINT32_C(0x80000001), UINT32_C(0x80008081), UINT32_C(0x00008009),
	UINT32_C(0x0000008A), UINT32_C(0x00000088), UINT32_C(0x80008009), UINT32_C(0x8000000A),
	UINT32_C(0x8000808B), UINT32_C(0x0000008B), UINT32_C(0x00008089), UINT32_C(0x00008003),
	UINT32_C(0x00008002), UINT32_C(0x00000080), UINT32_C(0x0000800A), UINT32_C(0x8000000A),
	UINT32_C(0x80008081), UINT32_C(0x00008080)
};


/**
 * Rotate a 32-bit word
 * 
 * @param   x:uint32_t  The value to rotate
 * @param   n:long int  Rotation steps, may not be zero
 * @return   :uint32_t  The value rotated
 */
#define rotate32(x, n) ((uint32_t)(((uint32_t)(x) >> (32L - (n))) | ((uint32_t)(x) << (n))))


/**
 * 32-bit word version of `libkeccak_f_round`
 * 
 * @param  state  The hashing state
 * @param  rc     The round contant for this round
 */
LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__, __hot__)))
static void
libkeccak_f_round32(register struct libkeccak_state *state, register uint32_t rc)
{
	uint32_t *restrict A = state->S.w32;
	uint32_t B[25], C[5], da, db, dc, dd, de;

	/* θ step (step 1 of 3). */
#define X(N) C[N] = A[N * 5] ^ A[N * 5 + 1] ^ A[N * 5 + 2] ^ A[N * 5 + 3] ^ A[N * 5 + 4]
	LIST_5(X, ;);
#undef X

	/* θ step (step 2 of 3). */
	da = C[4] ^ rotate32(C[1], 1);
	dd = C[2] ^ rotate32(C[4], 1);
	db = C[0] ^ rotate32(C[2], 1);
	de = C[3] ^ rotate32(C[0], 1);
	dc = C[1] ^ rotate32(C[3], 1);

	/* ρ and π steps, with last two part of θ. */
#define X(bi, ai, dv, r) B[bi] = rotate32(A[ai] ^ dv, r)
	B[0] = A[0] ^ da;   X( 1, 15, dd, 28);  X( 2,  5, db,  1);  X( 3, 20, de, 27);  X( 4, 10, dc, 30);
	X( 5,  6, db, 12);  X( 6, 21, de, 20);  X( 7, 11, dc,  6);  X( 8,  1, da,  4);  X( 9, 16, dd, 23);
	X(10, 12, dc, 11);  X(11,  2, da,  3);  X(12, 17, dd, 25);  X(13,  7, db, 10);  X(14, 22, de,  7);
	X(15, 18, dd, 21);  X(16,  8, db, 13);  X(17, 23, de,  8);  X(18, 13, dc, 15);  X(19,  3, da,  9);
	X(20, 24, de, 14);  X(21, 14, dc, 29);  X(22,  4, da, 18);  X(23, 19, dd, 24);  X(24,  9, db,  2);
#undef X

	/* ξ step. */
#define X(N) A[N] = (uint32_t)(B[N] ^ ((~(B[(N + 5) % 25])) & B[(N + 10) % 25]))
	LIST_25(X, ;);
#undef X

	/* ι step. */
	A[0] ^= rc;
}


/**
 * 32-bit lane version of `libkeccak_to_lane`
 * 
 * @param   message  The message
 * @param   msglen   The length of the message
 * @param   rr       Bitrate in bytes
 * @param   off      The offset in the message
 * @return           The lane
 */
LIBKECCAK_GCC_ONLY(__attribute__((__nonnull__, __nothrow__, __pure__, __hot__, __warn_unused_result__, __gnu_inline__)))
static inline uint32_t
libkeccak_to_lane32(register const unsigned char *message, register size_t msglen, register long int rr, size_t off)
{
	register long int n = (long)((msglen < (size_t)rr ? msglen : (size_t)rr) - off);
	uint32_t rc = 0;
	message += off;
#define X(N) if (__builtin_expect(N < n, 1)) rc |= (uint32_t)message[N] << (N * 8);\
             else return rc
	LIST_4(X, ;);
#undef X
	return rc;
}