Monero
Toggle main menu visibility
Loading...
Searching...
No Matches
src
crypto
keccak.c
Go to the documentation of this file.
1
// keccak.c
2
// 19-Nov-11 Markku-Juhani O. Saarinen <mjos@iki.fi>
3
// A baseline Keccak (3rd round) implementation.
4
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <unistd.h>
8
#include "
int-util.h
"
9
#include "
hash-ops.h
"
10
#include "
keccak.h
"
11
12
static
void
local_abort
(
const
char
*msg)
13
{
14
fprintf(stderr,
"%s\n"
, msg);
15
#ifdef NDEBUG
16
_exit(1);
17
#else
18
abort();
19
#endif
20
}
21
22
const
uint64_t
keccakf_rndc
[24] =
23
{
24
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
25
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
26
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
27
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
28
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
29
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
30
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
31
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
32
};
33
34
// update the state with given number of rounds
35
36
void
keccakf
(
uint64_t
st[25],
int
rounds)
37
{
38
int
round
;
39
uint64_t
t, bc[5];
40
41
for
(
round
= 0;
round
< rounds; ++
round
) {
42
// Theta
43
bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
44
bc[1] = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
45
bc[2] = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
46
bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
47
bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
48
49
#define THETA(i) { \
50
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); \
51
st[i ] ^= t; \
52
st[i + 5] ^= t; \
53
st[i + 10] ^= t; \
54
st[i + 15] ^= t; \
55
st[i + 20] ^= t; \
56
}
57
58
THETA
(0);
59
THETA
(1);
60
THETA
(2);
61
THETA
(3);
62
THETA
(4);
63
64
// Rho Pi
65
t = st[1];
66
st[ 1] =
ROTL64
(st[ 6], 44);
67
st[ 6] =
ROTL64
(st[ 9], 20);
68
st[ 9] =
ROTL64
(st[22], 61);
69
st[22] =
ROTL64
(st[14], 39);
70
st[14] =
ROTL64
(st[20], 18);
71
st[20] =
ROTL64
(st[ 2], 62);
72
st[ 2] =
ROTL64
(st[12], 43);
73
st[12] =
ROTL64
(st[13], 25);
74
st[13] =
ROTL64
(st[19], 8);
75
st[19] =
ROTL64
(st[23], 56);
76
st[23] =
ROTL64
(st[15], 41);
77
st[15] =
ROTL64
(st[ 4], 27);
78
st[ 4] =
ROTL64
(st[24], 14);
79
st[24] =
ROTL64
(st[21], 2);
80
st[21] =
ROTL64
(st[ 8], 55);
81
st[ 8] =
ROTL64
(st[16], 45);
82
st[16] =
ROTL64
(st[ 5], 36);
83
st[ 5] =
ROTL64
(st[ 3], 28);
84
st[ 3] =
ROTL64
(st[18], 21);
85
st[18] =
ROTL64
(st[17], 15);
86
st[17] =
ROTL64
(st[11], 10);
87
st[11] =
ROTL64
(st[ 7], 6);
88
st[ 7] =
ROTL64
(st[10], 3);
89
st[10] =
ROTL64
(t, 1);
90
91
// Chi
92
#define CHI(j) { \
93
const uint64_t st0 = st[j ]; \
94
const uint64_t st1 = st[j + 1]; \
95
const uint64_t st2 = st[j + 2]; \
96
const uint64_t st3 = st[j + 3]; \
97
const uint64_t st4 = st[j + 4]; \
98
st[j ] ^= ~st1 & st2; \
99
st[j + 1] ^= ~st2 & st3; \
100
st[j + 2] ^= ~st3 & st4; \
101
st[j + 3] ^= ~st4 & st0; \
102
st[j + 4] ^= ~st0 & st1; \
103
}
104
105
CHI
( 0);
106
CHI
( 5);
107
CHI
(10);
108
CHI
(15);
109
CHI
(20);
110
111
// Iota
112
st[0] ^=
keccakf_rndc
[
round
];
113
}
114
}
115
116
// compute a keccak hash (md) of given byte length from "in"
117
typedef
uint64_t
state_t
[25];
118
119
void
keccak
(
const
uint8_t
*in,
size_t
inlen,
uint8_t
*md,
int
mdlen)
120
{
121
state_t
st;
122
uint8_t
temp[144];
123
size_t
i, rsiz, rsizw;
124
125
static_assert
(
HASH_DATA_AREA
<=
sizeof
(temp),
"Bad keccak preconditions"
);
126
if
(mdlen <= 0 || (mdlen > 100 &&
sizeof
(st) != (
size_t
)mdlen))
127
{
128
local_abort
(
"Bad keccak use"
);
129
}
130
131
rsiz =
sizeof
(
state_t
) == mdlen ?
HASH_DATA_AREA
: 200 - 2 * mdlen;
132
rsizw = rsiz / 8;
133
134
memset(st, 0,
sizeof
(st));
135
136
for
( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) {
137
for
(i = 0; i < rsizw; i++) {
138
uint64_t
ina;
139
memcpy
(&ina, in + i * 8, 8);
140
st[i] ^=
swap64le
(ina);
141
}
142
keccakf
(st,
KECCAK_ROUNDS
);
143
}
144
145
// last block and padding
146
if
(inlen + 1 >=
sizeof
(temp) || inlen > rsiz || rsiz - inlen + inlen + 1 >=
sizeof
(temp) || rsiz == 0 || rsiz - 1 >=
sizeof
(temp) || rsizw * 8 >
sizeof
(temp))
147
{
148
local_abort
(
"Bad keccak use"
);
149
}
150
151
if
(inlen > 0)
152
memcpy
(temp, in, inlen);
153
temp[inlen++] = 1;
154
memset(temp + inlen, 0, rsiz - inlen);
155
temp[rsiz - 1] |= 0x80;
156
157
for
(i = 0; i < rsizw; i++)
158
st[i] ^=
swap64le
(((
uint64_t
*) temp)[i]);
159
160
keccakf
(st,
KECCAK_ROUNDS
);
161
162
if
(((
size_t
)mdlen %
sizeof
(
uint64_t
)) != 0)
163
{
164
local_abort
(
"Bad keccak use"
);
165
}
166
memcpy_swap64le
(md, st, mdlen/
sizeof
(
uint64_t
));
167
}
168
169
void
keccak1600
(
const
uint8_t
*in,
size_t
inlen,
uint8_t
*md)
170
{
171
keccak
(in, inlen, md,
sizeof
(
state_t
));
172
}
173
174
#define KECCAK_FINALIZED 0x80000000
175
#define KECCAK_BLOCKLEN 136
176
#define KECCAK_WORDS 17
177
#define KECCAK_DIGESTSIZE 32
178
#define KECCAK_PROCESS_BLOCK(st, block) { \
179
for (int i_ = 0; i_ < KECCAK_WORDS; i_++){ \
180
((st))[i_] ^= swap64le(((block))[i_]); \
181
}; \
182
keccakf(st, KECCAK_ROUNDS); }
183
184
185
void
keccak_init
(
KECCAK_CTX
* ctx){
186
memset(ctx, 0,
sizeof
(
KECCAK_CTX
));
187
}
188
189
void
keccak_update
(
KECCAK_CTX
* ctx,
const
uint8_t
*in,
size_t
inlen){
190
if
(ctx->
rest
&
KECCAK_FINALIZED
) {
191
local_abort
(
"Bad keccak use"
);
192
}
193
194
const
size_t
idx = ctx->
rest
;
195
ctx->
rest
= (ctx->
rest
+ inlen) %
KECCAK_BLOCKLEN
;
196
197
// fill partial block
198
if
(idx) {
199
size_t
left =
KECCAK_BLOCKLEN
- idx;
200
memcpy
((
char
*)ctx->
message
+ idx, in, (inlen < left ? inlen : left));
201
if
(inlen < left)
return
;
202
203
KECCAK_PROCESS_BLOCK
(ctx->
hash
, ctx->
message
);
204
205
in += left;
206
inlen -= left;
207
}
208
209
while
(inlen >=
KECCAK_BLOCKLEN
) {
210
memcpy
(ctx->
message
, in,
KECCAK_BLOCKLEN
);
211
212
KECCAK_PROCESS_BLOCK
(ctx->
hash
, ctx->
message
);
213
in +=
KECCAK_BLOCKLEN
;
214
inlen -=
KECCAK_BLOCKLEN
;
215
}
216
if
(inlen) {
217
memcpy
(ctx->
message
, in, inlen);
218
}
219
}
220
221
void
keccak_finish
(
KECCAK_CTX
* ctx,
uint8_t
*md){
222
if
(!(ctx->
rest
&
KECCAK_FINALIZED
))
223
{
224
// clear the rest of the data queue
225
memset((
char
*)ctx->
message
+ ctx->
rest
, 0,
KECCAK_BLOCKLEN
- ctx->
rest
);
226
((
char
*)ctx->
message
)[ctx->
rest
] |= 0x01;
227
((
char
*)ctx->
message
)[
KECCAK_BLOCKLEN
- 1] |= 0x80;
228
229
// process final block
230
KECCAK_PROCESS_BLOCK
(ctx->
hash
, ctx->
message
);
231
ctx->
rest
=
KECCAK_FINALIZED
;
// mark context as finalized
232
}
233
234
static_assert
(
KECCAK_BLOCKLEN
>
KECCAK_DIGESTSIZE
,
""
);
235
static_assert
(
KECCAK_DIGESTSIZE
%
sizeof
(
uint64_t
) == 0,
""
);
236
if
(md) {
237
memcpy_swap64le
(md, ctx->
hash
,
KECCAK_DIGESTSIZE
/
sizeof
(
uint64_t
));
238
}
239
}
round
#define round(rm, y, x, k)
Definition
aesb.c:52
memcpy
void * memcpy(void *a, const void *b, size_t c)
Definition
glibc_compat.cpp:16
hash-ops.h
HASH_DATA_AREA
@ HASH_DATA_AREA
Definition
hash-ops.h:78
KECCAK_BLOCKLEN
#define KECCAK_BLOCKLEN
Definition
hmac-keccak.c:32
int-util.h
memcpy_swap64le
#define memcpy_swap64le
Definition
int-util.h:291
swap64le
#define swap64le
Definition
int-util.h:287
state_t
uint64_t state_t[25]
Definition
keccak.c:117
keccak
void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen)
Definition
keccak.c:119
keccak_finish
void keccak_finish(KECCAK_CTX *ctx, uint8_t *md)
Definition
keccak.c:221
keccak1600
void keccak1600(const uint8_t *in, size_t inlen, uint8_t *md)
Definition
keccak.c:169
keccak_update
void keccak_update(KECCAK_CTX *ctx, const uint8_t *in, size_t inlen)
Definition
keccak.c:189
KECCAK_FINALIZED
#define KECCAK_FINALIZED
Definition
keccak.c:174
CHI
#define CHI(j)
keccakf_rndc
const uint64_t keccakf_rndc[24]
Definition
keccak.c:22
THETA
#define THETA(i)
keccakf
void keccakf(uint64_t st[25], int rounds)
Definition
keccak.c:36
KECCAK_PROCESS_BLOCK
#define KECCAK_PROCESS_BLOCK(st, block)
Definition
keccak.c:178
KECCAK_DIGESTSIZE
#define KECCAK_DIGESTSIZE
Definition
keccak.c:177
local_abort
static void local_abort(const char *msg)
Definition
keccak.c:12
keccak_init
void keccak_init(KECCAK_CTX *ctx)
Definition
keccak.c:185
keccak.h
ROTL64
#define ROTL64(x, y)
Definition
keccak.h:15
KECCAK_ROUNDS
#define KECCAK_ROUNDS
Definition
keccak.h:11
uint8_t
unsigned char uint8_t
Definition
stdint.h:124
uint64_t
unsigned __int64 uint64_t
Definition
stdint.h:136
KECCAK_CTX
Definition
keccak.h:20
KECCAK_CTX::rest
size_t rest
Definition
keccak.h:26
KECCAK_CTX::hash
uint64_t hash[25]
Definition
keccak.h:22
KECCAK_CTX::message
uint64_t message[17]
Definition
keccak.h:24
Generated on
for Monero by
1.17.0