/src/libgcrypt/cipher/keccak.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* keccak.c - SHA3 hash functions |
2 | | * Copyright (C) 2015 g10 Code GmbH |
3 | | * |
4 | | * This file is part of Libgcrypt. |
5 | | * |
6 | | * Libgcrypt is free software; you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Lesser General Public License as |
8 | | * published by the Free Software Foundation; either version 2.1 of |
9 | | * the License, or (at your option) any later version. |
10 | | * |
11 | | * Libgcrypt is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with this program; if not, see <http://www.gnu.org/licenses/>. |
18 | | */ |
19 | | |
20 | | |
21 | | #include <config.h> |
22 | | #include <string.h> |
23 | | #include "g10lib.h" |
24 | | #include "bithelp.h" |
25 | | #include "bufhelp.h" |
26 | | #include "cipher.h" |
27 | | #include "hash-common.h" |
28 | | |
29 | | |
30 | | |
31 | | /* USE_64BIT indicates whether to use 64-bit generic implementation. |
32 | | * USE_32BIT indicates whether to use 32-bit generic implementation. */ |
33 | | #undef USE_64BIT |
34 | | #if defined(__x86_64__) || SIZEOF_UNSIGNED_LONG == 8 |
35 | | # define USE_64BIT 1 |
36 | | #else |
37 | | # define USE_32BIT 1 |
38 | | #endif |
39 | | |
40 | | |
41 | | /* USE_64BIT_BMI2 indicates whether to compile with 64-bit Intel BMI2 code. */ |
42 | | #undef USE_64BIT_BMI2 |
43 | | #if defined(USE_64BIT) && defined(HAVE_GCC_INLINE_ASM_BMI2) && \ |
44 | | defined(HAVE_CPU_ARCH_X86) |
45 | | # define USE_64BIT_BMI2 1 |
46 | | #endif |
47 | | |
48 | | |
49 | | /* USE_64BIT_SHLD indicates whether to compile with 64-bit Intel SHLD code. */ |
50 | | #undef USE_64BIT_SHLD |
51 | | #if defined(USE_64BIT) && defined (__GNUC__) && defined(__x86_64__) && \ |
52 | | defined(HAVE_CPU_ARCH_X86) |
53 | | # define USE_64BIT_SHLD 1 |
54 | | #endif |
55 | | |
56 | | |
57 | | /* USE_32BIT_BMI2 indicates whether to compile with 32-bit Intel BMI2 code. */ |
58 | | #undef USE_32BIT_BMI2 |
59 | | #if defined(USE_32BIT) && defined(HAVE_GCC_INLINE_ASM_BMI2) && \ |
60 | | defined(HAVE_CPU_ARCH_X86) |
61 | | # define USE_32BIT_BMI2 1 |
62 | | #endif |
63 | | |
64 | | |
65 | | /* USE_64BIT_AVX512 indicates whether to compile with Intel AVX512 code. */ |
66 | | #undef USE_64BIT_AVX512 |
67 | | #if defined(USE_64BIT) && defined(__x86_64__) && \ |
68 | | defined(HAVE_GCC_INLINE_ASM_AVX512) && \ |
69 | | (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ |
70 | | defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) |
71 | | # define USE_64BIT_AVX512 1 |
72 | | #endif |
73 | | |
74 | | |
75 | | /* USE_64BIT_ARM_NEON indicates whether to enable 64-bit ARM/NEON assembly |
76 | | * code. */ |
77 | | #undef USE_64BIT_ARM_NEON |
78 | | #ifdef ENABLE_NEON_SUPPORT |
79 | | # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \ |
80 | | && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \ |
81 | | && defined(HAVE_GCC_INLINE_ASM_NEON) |
82 | | # define USE_64BIT_ARM_NEON 1 |
83 | | # endif |
84 | | #endif /*ENABLE_NEON_SUPPORT*/ |
85 | | |
86 | | |
87 | | /* USE_S390X_CRYPTO indicates whether to enable zSeries code. */ |
88 | | #undef USE_S390X_CRYPTO |
89 | | #if defined(HAVE_GCC_INLINE_ASM_S390X) |
90 | | # define USE_S390X_CRYPTO 1 |
91 | | #endif /* USE_S390X_CRYPTO */ |
92 | | |
93 | | |
94 | | /* x86-64 vector register assembly implementations use SystemV ABI, ABI |
95 | | * conversion needed on Win64 through function attribute. */ |
96 | | #undef ASM_FUNC_ABI |
97 | | #if defined(USE_64BIT_AVX512) && defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS) |
98 | | # define ASM_FUNC_ABI __attribute__((sysv_abi)) |
99 | | #else |
100 | | # define ASM_FUNC_ABI |
101 | | #endif |
102 | | |
103 | | |
104 | | #if defined(USE_64BIT) || defined(USE_64BIT_ARM_NEON) |
105 | | # define NEED_COMMON64 1 |
106 | | #endif |
107 | | |
108 | | #ifdef USE_32BIT |
109 | | # define NEED_COMMON32BI 1 |
110 | | #endif |
111 | | |
112 | | |
113 | 20.6k | #define SHA3_DELIMITED_SUFFIX 0x06 |
114 | 126 | #define SHAKE_DELIMITED_SUFFIX 0x1F |
115 | 0 | #define CSHAKE_DELIMITED_SUFFIX 0x04 |
116 | | |
117 | | typedef struct |
118 | | { |
119 | | union { |
120 | | #ifdef NEED_COMMON64 |
121 | | u64 state64[25]; |
122 | | #endif |
123 | | #ifdef NEED_COMMON32BI |
124 | | u32 state32bi[50]; |
125 | | #endif |
126 | | } u; |
127 | | } KECCAK_STATE; |
128 | | |
129 | | |
130 | | typedef struct |
131 | | { |
132 | | unsigned int (*permute)(KECCAK_STATE *hd); |
133 | | unsigned int (*absorb)(KECCAK_STATE *hd, int pos, const byte *lanes, |
134 | | size_t nlanes, int blocklanes); |
135 | | unsigned int (*extract) (KECCAK_STATE *hd, unsigned int pos, byte *outbuf, |
136 | | unsigned int outlen); |
137 | | } keccak_ops_t; |
138 | | |
139 | | |
140 | | typedef struct KECCAK_CONTEXT_S |
141 | | { |
142 | | KECCAK_STATE state; |
143 | | unsigned int outlen; |
144 | | unsigned int blocksize; |
145 | | unsigned int count; |
146 | | unsigned int suffix:8; |
147 | | unsigned int shake_in_extract_mode:1; |
148 | | unsigned int shake_in_read_mode:1; |
149 | | const keccak_ops_t *ops; |
150 | | #ifdef USE_S390X_CRYPTO |
151 | | unsigned int kimd_func; |
152 | | unsigned int buf_pos; |
153 | | byte buf[1344 / 8]; /* SHAKE128 requires biggest buffer, 1344 bits. */ |
154 | | #endif |
155 | | } KECCAK_CONTEXT; |
156 | | |
157 | | |
158 | | |
159 | | #ifdef NEED_COMMON64 |
160 | | |
161 | | const u64 _gcry_keccak_round_consts_64bit[24 + 1] = |
162 | | { |
163 | | U64_C(0x0000000000000001), U64_C(0x0000000000008082), |
164 | | U64_C(0x800000000000808A), U64_C(0x8000000080008000), |
165 | | U64_C(0x000000000000808B), U64_C(0x0000000080000001), |
166 | | U64_C(0x8000000080008081), U64_C(0x8000000000008009), |
167 | | U64_C(0x000000000000008A), U64_C(0x0000000000000088), |
168 | | U64_C(0x0000000080008009), U64_C(0x000000008000000A), |
169 | | U64_C(0x000000008000808B), U64_C(0x800000000000008B), |
170 | | U64_C(0x8000000000008089), U64_C(0x8000000000008003), |
171 | | U64_C(0x8000000000008002), U64_C(0x8000000000000080), |
172 | | U64_C(0x000000000000800A), U64_C(0x800000008000000A), |
173 | | U64_C(0x8000000080008081), U64_C(0x8000000000008080), |
174 | | U64_C(0x0000000080000001), U64_C(0x8000000080008008), |
175 | | U64_C(0xFFFFFFFFFFFFFFFF) |
176 | | }; |
177 | | |
178 | | static unsigned int |
179 | | keccak_extract64(KECCAK_STATE *hd, unsigned int pos, byte *outbuf, |
180 | | unsigned int outlen) |
181 | 18.3k | { |
182 | 18.3k | unsigned int i; |
183 | | |
184 | | /* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */ |
185 | | |
186 | 125k | for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++) |
187 | 106k | { |
188 | 106k | u64 tmp = hd->u.state64[i]; |
189 | 106k | buf_put_le64(outbuf, tmp); |
190 | 106k | outbuf += 8; |
191 | 106k | } |
192 | | |
193 | 18.3k | return 0; |
194 | 18.3k | } |
195 | | |
196 | | #endif /* NEED_COMMON64 */ |
197 | | |
198 | | |
199 | | #ifdef NEED_COMMON32BI |
200 | | |
201 | | static const u32 round_consts_32bit[2 * 24] = |
202 | | { |
203 | | 0x00000001UL, 0x00000000UL, 0x00000000UL, 0x00000089UL, |
204 | | 0x00000000UL, 0x8000008bUL, 0x00000000UL, 0x80008080UL, |
205 | | 0x00000001UL, 0x0000008bUL, 0x00000001UL, 0x00008000UL, |
206 | | 0x00000001UL, 0x80008088UL, 0x00000001UL, 0x80000082UL, |
207 | | 0x00000000UL, 0x0000000bUL, 0x00000000UL, 0x0000000aUL, |
208 | | 0x00000001UL, 0x00008082UL, 0x00000000UL, 0x00008003UL, |
209 | | 0x00000001UL, 0x0000808bUL, 0x00000001UL, 0x8000000bUL, |
210 | | 0x00000001UL, 0x8000008aUL, 0x00000001UL, 0x80000081UL, |
211 | | 0x00000000UL, 0x80000081UL, 0x00000000UL, 0x80000008UL, |
212 | | 0x00000000UL, 0x00000083UL, 0x00000000UL, 0x80008003UL, |
213 | | 0x00000001UL, 0x80008088UL, 0x00000000UL, 0x80000088UL, |
214 | | 0x00000001UL, 0x00008000UL, 0x00000000UL, 0x80008082UL |
215 | | }; |
216 | | |
217 | | static unsigned int |
218 | | keccak_extract32bi(KECCAK_STATE *hd, unsigned int pos, byte *outbuf, |
219 | | unsigned int outlen) |
220 | | { |
221 | | unsigned int i; |
222 | | u32 x0; |
223 | | u32 x1; |
224 | | u32 t; |
225 | | |
226 | | /* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */ |
227 | | |
228 | | for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++) |
229 | | { |
230 | | x0 = hd->u.state32bi[i * 2 + 0]; |
231 | | x1 = hd->u.state32bi[i * 2 + 1]; |
232 | | |
233 | | t = (x0 & 0x0000FFFFUL) + (x1 << 16); |
234 | | x1 = (x0 >> 16) + (x1 & 0xFFFF0000UL); |
235 | | x0 = t; |
236 | | t = (x0 ^ (x0 >> 8)) & 0x0000FF00UL; x0 = x0 ^ t ^ (t << 8); |
237 | | t = (x0 ^ (x0 >> 4)) & 0x00F000F0UL; x0 = x0 ^ t ^ (t << 4); |
238 | | t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0CUL; x0 = x0 ^ t ^ (t << 2); |
239 | | t = (x0 ^ (x0 >> 1)) & 0x22222222UL; x0 = x0 ^ t ^ (t << 1); |
240 | | t = (x1 ^ (x1 >> 8)) & 0x0000FF00UL; x1 = x1 ^ t ^ (t << 8); |
241 | | t = (x1 ^ (x1 >> 4)) & 0x00F000F0UL; x1 = x1 ^ t ^ (t << 4); |
242 | | t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0CUL; x1 = x1 ^ t ^ (t << 2); |
243 | | t = (x1 ^ (x1 >> 1)) & 0x22222222UL; x1 = x1 ^ t ^ (t << 1); |
244 | | |
245 | | buf_put_le32(&outbuf[0], x0); |
246 | | buf_put_le32(&outbuf[4], x1); |
247 | | outbuf += 8; |
248 | | } |
249 | | |
250 | | return 0; |
251 | | } |
252 | | |
253 | | static inline void |
254 | | keccak_absorb_lane32bi(u32 *lane, u32 x0, u32 x1) |
255 | | { |
256 | | u32 t; |
257 | | |
258 | | t = (x0 ^ (x0 >> 1)) & 0x22222222UL; x0 = x0 ^ t ^ (t << 1); |
259 | | t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0CUL; x0 = x0 ^ t ^ (t << 2); |
260 | | t = (x0 ^ (x0 >> 4)) & 0x00F000F0UL; x0 = x0 ^ t ^ (t << 4); |
261 | | t = (x0 ^ (x0 >> 8)) & 0x0000FF00UL; x0 = x0 ^ t ^ (t << 8); |
262 | | t = (x1 ^ (x1 >> 1)) & 0x22222222UL; x1 = x1 ^ t ^ (t << 1); |
263 | | t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0CUL; x1 = x1 ^ t ^ (t << 2); |
264 | | t = (x1 ^ (x1 >> 4)) & 0x00F000F0UL; x1 = x1 ^ t ^ (t << 4); |
265 | | t = (x1 ^ (x1 >> 8)) & 0x0000FF00UL; x1 = x1 ^ t ^ (t << 8); |
266 | | lane[0] ^= (x0 & 0x0000FFFFUL) + (x1 << 16); |
267 | | lane[1] ^= (x0 >> 16) + (x1 & 0xFFFF0000UL); |
268 | | } |
269 | | |
270 | | #endif /* NEED_COMMON32BI */ |
271 | | |
272 | | |
273 | | /* Construct generic 64-bit implementation. */ |
274 | | #ifdef USE_64BIT |
275 | | |
276 | | #if __GNUC__ >= 4 && defined(__x86_64__) |
277 | | |
278 | | static inline void absorb_lanes64_8(u64 *dst, const byte *in) |
279 | 950k | { |
280 | 950k | asm ("movdqu 0*16(%[dst]), %%xmm0\n\t" |
281 | 950k | "movdqu 0*16(%[in]), %%xmm4\n\t" |
282 | 950k | "movdqu 1*16(%[dst]), %%xmm1\n\t" |
283 | 950k | "movdqu 1*16(%[in]), %%xmm5\n\t" |
284 | 950k | "movdqu 2*16(%[dst]), %%xmm2\n\t" |
285 | 950k | "movdqu 3*16(%[dst]), %%xmm3\n\t" |
286 | 950k | "pxor %%xmm4, %%xmm0\n\t" |
287 | 950k | "pxor %%xmm5, %%xmm1\n\t" |
288 | 950k | "movdqu 2*16(%[in]), %%xmm4\n\t" |
289 | 950k | "movdqu 3*16(%[in]), %%xmm5\n\t" |
290 | 950k | "movdqu %%xmm0, 0*16(%[dst])\n\t" |
291 | 950k | "pxor %%xmm4, %%xmm2\n\t" |
292 | 950k | "movdqu %%xmm1, 1*16(%[dst])\n\t" |
293 | 950k | "pxor %%xmm5, %%xmm3\n\t" |
294 | 950k | "movdqu %%xmm2, 2*16(%[dst])\n\t" |
295 | 950k | "movdqu %%xmm3, 3*16(%[dst])\n\t" |
296 | 950k | : |
297 | 950k | : [dst] "r" (dst), [in] "r" (in) |
298 | 950k | : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "memory"); |
299 | 950k | } |
300 | | |
301 | | static inline void absorb_lanes64_4(u64 *dst, const byte *in) |
302 | 158k | { |
303 | 158k | asm ("movdqu 0*16(%[dst]), %%xmm0\n\t" |
304 | 158k | "movdqu 0*16(%[in]), %%xmm4\n\t" |
305 | 158k | "movdqu 1*16(%[dst]), %%xmm1\n\t" |
306 | 158k | "movdqu 1*16(%[in]), %%xmm5\n\t" |
307 | 158k | "pxor %%xmm4, %%xmm0\n\t" |
308 | 158k | "pxor %%xmm5, %%xmm1\n\t" |
309 | 158k | "movdqu %%xmm0, 0*16(%[dst])\n\t" |
310 | 158k | "movdqu %%xmm1, 1*16(%[dst])\n\t" |
311 | 158k | : |
312 | 158k | : [dst] "r" (dst), [in] "r" (in) |
313 | 158k | : "xmm0", "xmm1", "xmm4", "xmm5", "memory"); |
314 | 158k | } |
315 | | |
316 | | static inline void absorb_lanes64_2(u64 *dst, const byte *in) |
317 | 120k | { |
318 | 120k | asm ("movdqu 0*16(%[dst]), %%xmm0\n\t" |
319 | 120k | "movdqu 0*16(%[in]), %%xmm4\n\t" |
320 | 120k | "pxor %%xmm4, %%xmm0\n\t" |
321 | 120k | "movdqu %%xmm0, 0*16(%[dst])\n\t" |
322 | 120k | : |
323 | 120k | : [dst] "r" (dst), [in] "r" (in) |
324 | 120k | : "xmm0", "xmm4", "memory"); |
325 | 120k | } |
326 | | |
327 | | #else /* __x86_64__ */ |
328 | | |
329 | | static inline void absorb_lanes64_8(u64 *dst, const byte *in) |
330 | | { |
331 | | dst[0] ^= buf_get_le64(in + 8 * 0); |
332 | | dst[1] ^= buf_get_le64(in + 8 * 1); |
333 | | dst[2] ^= buf_get_le64(in + 8 * 2); |
334 | | dst[3] ^= buf_get_le64(in + 8 * 3); |
335 | | dst[4] ^= buf_get_le64(in + 8 * 4); |
336 | | dst[5] ^= buf_get_le64(in + 8 * 5); |
337 | | dst[6] ^= buf_get_le64(in + 8 * 6); |
338 | | dst[7] ^= buf_get_le64(in + 8 * 7); |
339 | | } |
340 | | |
341 | | static inline void absorb_lanes64_4(u64 *dst, const byte *in) |
342 | | { |
343 | | dst[0] ^= buf_get_le64(in + 8 * 0); |
344 | | dst[1] ^= buf_get_le64(in + 8 * 1); |
345 | | dst[2] ^= buf_get_le64(in + 8 * 2); |
346 | | dst[3] ^= buf_get_le64(in + 8 * 3); |
347 | | } |
348 | | |
349 | | static inline void absorb_lanes64_2(u64 *dst, const byte *in) |
350 | | { |
351 | | dst[0] ^= buf_get_le64(in + 8 * 0); |
352 | | dst[1] ^= buf_get_le64(in + 8 * 1); |
353 | | } |
354 | | |
355 | | #endif /* !__x86_64__ */ |
356 | | |
357 | | static inline void absorb_lanes64_1(u64 *dst, const byte *in) |
358 | 582k | { |
359 | 582k | dst[0] ^= buf_get_le64(in + 8 * 0); |
360 | 582k | } |
361 | | |
362 | | |
363 | 0 | # define ANDN64(x, y) (~(x) & (y)) |
364 | 0 | # define ROL64(x, n) (((x) << ((unsigned int)n & 63)) | \ |
365 | 0 | ((x) >> ((64 - (unsigned int)(n)) & 63))) |
366 | | |
367 | 0 | # define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute64 |
368 | | # define KECCAK_F1600_ABSORB_FUNC_NAME keccak_absorb_lanes64 |
369 | | # include "keccak_permute_64.h" |
370 | | |
371 | | # undef ANDN64 |
372 | | # undef ROL64 |
373 | | # undef KECCAK_F1600_PERMUTE_FUNC_NAME |
374 | | # undef KECCAK_F1600_ABSORB_FUNC_NAME |
375 | | |
376 | | static const keccak_ops_t keccak_generic64_ops = |
377 | | { |
378 | | .permute = keccak_f1600_state_permute64, |
379 | | .absorb = keccak_absorb_lanes64, |
380 | | .extract = keccak_extract64, |
381 | | }; |
382 | | |
383 | | #endif /* USE_64BIT */ |
384 | | |
385 | | |
386 | | /* Construct 64-bit Intel SHLD implementation. */ |
387 | | #ifdef USE_64BIT_SHLD |
388 | | |
389 | 0 | # define ANDN64(x, y) (~(x) & (y)) |
390 | 0 | # define ROL64(x, n) ({ \ |
391 | 0 | u64 tmp = (x); \ |
392 | 0 | asm ("shldq %1, %0, %0" \ |
393 | 0 | : "+r" (tmp) \ |
394 | 0 | : "J" ((n) & 63) \ |
395 | 0 | : "cc"); \ |
396 | 0 | tmp; }) |
397 | | |
398 | 0 | # define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute64_shld |
399 | | # define KECCAK_F1600_ABSORB_FUNC_NAME keccak_absorb_lanes64_shld |
400 | | # include "keccak_permute_64.h" |
401 | | |
402 | | # undef ANDN64 |
403 | | # undef ROL64 |
404 | | # undef KECCAK_F1600_PERMUTE_FUNC_NAME |
405 | | # undef KECCAK_F1600_ABSORB_FUNC_NAME |
406 | | |
407 | | static const keccak_ops_t keccak_shld_64_ops = |
408 | | { |
409 | | .permute = keccak_f1600_state_permute64_shld, |
410 | | .absorb = keccak_absorb_lanes64_shld, |
411 | | .extract = keccak_extract64, |
412 | | }; |
413 | | |
414 | | #endif /* USE_64BIT_SHLD */ |
415 | | |
416 | | |
417 | | /* Construct 64-bit Intel BMI2 implementation. */ |
418 | | #ifdef USE_64BIT_BMI2 |
419 | | |
420 | 438M | # define ANDN64(x, y) ({ \ |
421 | 438M | u64 tmp; \ |
422 | 438M | asm ("andnq %2, %1, %0" \ |
423 | 438M | : "=r" (tmp) \ |
424 | 438M | : "r0" (x), "rm" (y)); \ |
425 | 438M | tmp; }) |
426 | | |
427 | 508M | # define ROL64(x, n) ({ \ |
428 | 508M | u64 tmp; \ |
429 | 508M | asm ("rorxq %2, %1, %0" \ |
430 | 508M | : "=r" (tmp) \ |
431 | 508M | : "rm0" (x), "J" (64 - ((n) & 63))); \ |
432 | 508M | tmp; }) |
433 | | |
434 | 712k | # define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute64_bmi2 |
435 | | # define KECCAK_F1600_ABSORB_FUNC_NAME keccak_absorb_lanes64_bmi2 |
436 | | # include "keccak_permute_64.h" |
437 | | |
438 | | # undef ANDN64 |
439 | | # undef ROL64 |
440 | | # undef KECCAK_F1600_PERMUTE_FUNC_NAME |
441 | | # undef KECCAK_F1600_ABSORB_FUNC_NAME |
442 | | |
443 | | static const keccak_ops_t keccak_bmi2_64_ops = |
444 | | { |
445 | | .permute = keccak_f1600_state_permute64_bmi2, |
446 | | .absorb = keccak_absorb_lanes64_bmi2, |
447 | | .extract = keccak_extract64, |
448 | | }; |
449 | | |
450 | | #endif /* USE_64BIT_BMI2 */ |
451 | | |
452 | | |
453 | | /* 64-bit Intel AVX512 implementation. */ |
454 | | #ifdef USE_64BIT_AVX512 |
455 | | |
456 | | extern ASM_FUNC_ABI unsigned int |
457 | | _gcry_keccak_f1600_state_permute64_avx512(u64 *state, const u64 *rconst); |
458 | | |
459 | | extern ASM_FUNC_ABI unsigned int |
460 | | _gcry_keccak_absorb_blocks_avx512(u64 *state, const u64 *rconst, |
461 | | const byte *lanes, u64 nlanes, |
462 | | u64 blocklanes, u64 *new_lanes); |
463 | | |
464 | | static unsigned int |
465 | | keccak_f1600_state_permute64_avx512(KECCAK_STATE *hd) |
466 | 0 | { |
467 | 0 | return _gcry_keccak_f1600_state_permute64_avx512 ( |
468 | 0 | hd->u.state64, _gcry_keccak_round_consts_64bit); |
469 | 0 | } |
470 | | |
471 | | static unsigned int |
472 | | keccak_absorb_lanes64_avx512(KECCAK_STATE *hd, int pos, const byte *lanes, |
473 | | size_t nlanes, int blocklanes) |
474 | 0 | { |
475 | 0 | while (nlanes) |
476 | 0 | { |
477 | 0 | if (pos == 0 && blocklanes > 0 && nlanes >= (size_t)blocklanes) |
478 | 0 | { |
479 | | /* Get new pointer through u64 variable for "x32" compatibility. */ |
480 | 0 | u64 new_lanes; |
481 | 0 | nlanes = _gcry_keccak_absorb_blocks_avx512 ( |
482 | 0 | hd->u.state64, _gcry_keccak_round_consts_64bit, |
483 | 0 | lanes, nlanes, blocklanes, &new_lanes); |
484 | 0 | lanes = (const byte *)(uintptr_t)new_lanes; |
485 | 0 | } |
486 | |
|
487 | 0 | while (nlanes) |
488 | 0 | { |
489 | 0 | hd->u.state64[pos] ^= buf_get_le64 (lanes); |
490 | 0 | lanes += 8; |
491 | 0 | nlanes--; |
492 | |
|
493 | 0 | if (++pos == blocklanes) |
494 | 0 | { |
495 | 0 | keccak_f1600_state_permute64_avx512 (hd); |
496 | 0 | pos = 0; |
497 | 0 | break; |
498 | 0 | } |
499 | 0 | } |
500 | 0 | } |
501 | |
|
502 | 0 | return 0; |
503 | 0 | } |
504 | | |
505 | | static const keccak_ops_t keccak_avx512_64_ops = |
506 | | { |
507 | | .permute = keccak_f1600_state_permute64_avx512, |
508 | | .absorb = keccak_absorb_lanes64_avx512, |
509 | | .extract = keccak_extract64, |
510 | | }; |
511 | | |
512 | | #endif /* USE_64BIT_AVX512 */ |
513 | | |
514 | | |
515 | | /* 64-bit ARMv7/NEON implementation. */ |
516 | | #ifdef USE_64BIT_ARM_NEON |
517 | | |
518 | | unsigned int _gcry_keccak_permute_armv7_neon(u64 *state); |
519 | | unsigned int _gcry_keccak_absorb_lanes64_armv7_neon(u64 *state, int pos, |
520 | | const byte *lanes, |
521 | | size_t nlanes, |
522 | | int blocklanes); |
523 | | |
524 | | static unsigned int keccak_permute64_armv7_neon(KECCAK_STATE *hd) |
525 | | { |
526 | | return _gcry_keccak_permute_armv7_neon(hd->u.state64); |
527 | | } |
528 | | |
529 | | static unsigned int |
530 | | keccak_absorb_lanes64_armv7_neon(KECCAK_STATE *hd, int pos, const byte *lanes, |
531 | | size_t nlanes, int blocklanes) |
532 | | { |
533 | | if (blocklanes < 0) |
534 | | { |
535 | | /* blocklanes == -1, permutationless absorb from keccak_final. */ |
536 | | |
537 | | while (nlanes) |
538 | | { |
539 | | hd->u.state64[pos] ^= buf_get_le64(lanes); |
540 | | lanes += 8; |
541 | | nlanes--; |
542 | | } |
543 | | |
544 | | return 0; |
545 | | } |
546 | | else |
547 | | { |
548 | | return _gcry_keccak_absorb_lanes64_armv7_neon(hd->u.state64, pos, lanes, |
549 | | nlanes, blocklanes); |
550 | | } |
551 | | } |
552 | | |
553 | | static const keccak_ops_t keccak_armv7_neon_64_ops = |
554 | | { |
555 | | .permute = keccak_permute64_armv7_neon, |
556 | | .absorb = keccak_absorb_lanes64_armv7_neon, |
557 | | .extract = keccak_extract64, |
558 | | }; |
559 | | |
560 | | #endif /* USE_64BIT_ARM_NEON */ |
561 | | |
562 | | |
563 | | /* Construct generic 32-bit implementation. */ |
564 | | #ifdef USE_32BIT |
565 | | |
566 | | # define ANDN32(x, y) (~(x) & (y)) |
567 | | # define ROL32(x, n) (((x) << ((unsigned int)n & 31)) | \ |
568 | | ((x) >> ((32 - (unsigned int)(n)) & 31))) |
569 | | |
570 | | # define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute32bi |
571 | | # include "keccak_permute_32.h" |
572 | | |
573 | | # undef ANDN32 |
574 | | # undef ROL32 |
575 | | # undef KECCAK_F1600_PERMUTE_FUNC_NAME |
576 | | |
577 | | static unsigned int |
578 | | keccak_absorb_lanes32bi(KECCAK_STATE *hd, int pos, const byte *lanes, |
579 | | size_t nlanes, int blocklanes) |
580 | | { |
581 | | unsigned int burn = 0; |
582 | | |
583 | | while (nlanes) |
584 | | { |
585 | | keccak_absorb_lane32bi(&hd->u.state32bi[pos * 2], |
586 | | buf_get_le32(lanes + 0), |
587 | | buf_get_le32(lanes + 4)); |
588 | | lanes += 8; |
589 | | nlanes--; |
590 | | |
591 | | if (++pos == blocklanes) |
592 | | { |
593 | | burn = keccak_f1600_state_permute32bi(hd); |
594 | | pos = 0; |
595 | | } |
596 | | } |
597 | | |
598 | | return burn; |
599 | | } |
600 | | |
601 | | static const keccak_ops_t keccak_generic32bi_ops = |
602 | | { |
603 | | .permute = keccak_f1600_state_permute32bi, |
604 | | .absorb = keccak_absorb_lanes32bi, |
605 | | .extract = keccak_extract32bi, |
606 | | }; |
607 | | |
608 | | #endif /* USE_32BIT */ |
609 | | |
610 | | |
611 | | /* Construct 32-bit Intel BMI2 implementation. */ |
612 | | #ifdef USE_32BIT_BMI2 |
613 | | |
614 | | # define ANDN32(x, y) ({ \ |
615 | | u32 tmp; \ |
616 | | asm ("andnl %2, %1, %0" \ |
617 | | : "=r" (tmp) \ |
618 | | : "r0" (x), "rm" (y)); \ |
619 | | tmp; }) |
620 | | |
621 | | # define ROL32(x, n) ({ \ |
622 | | u32 tmp; \ |
623 | | asm ("rorxl %2, %1, %0" \ |
624 | | : "=r" (tmp) \ |
625 | | : "rm0" (x), "J" (32 - ((n) & 31))); \ |
626 | | tmp; }) |
627 | | |
628 | | # define KECCAK_F1600_PERMUTE_FUNC_NAME keccak_f1600_state_permute32bi_bmi2 |
629 | | # include "keccak_permute_32.h" |
630 | | |
631 | | # undef ANDN32 |
632 | | # undef ROL32 |
633 | | # undef KECCAK_F1600_PERMUTE_FUNC_NAME |
634 | | |
635 | | static inline u32 pext(u32 x, u32 mask) |
636 | | { |
637 | | u32 tmp; |
638 | | asm ("pextl %2, %1, %0" : "=r" (tmp) : "r0" (x), "rm" (mask)); |
639 | | return tmp; |
640 | | } |
641 | | |
642 | | static inline u32 pdep(u32 x, u32 mask) |
643 | | { |
644 | | u32 tmp; |
645 | | asm ("pdepl %2, %1, %0" : "=r" (tmp) : "r0" (x), "rm" (mask)); |
646 | | return tmp; |
647 | | } |
648 | | |
649 | | static inline void |
650 | | keccak_absorb_lane32bi_bmi2(u32 *lane, u32 x0, u32 x1) |
651 | | { |
652 | | x0 = pdep(pext(x0, 0x55555555), 0x0000ffff) | (pext(x0, 0xaaaaaaaa) << 16); |
653 | | x1 = pdep(pext(x1, 0x55555555), 0x0000ffff) | (pext(x1, 0xaaaaaaaa) << 16); |
654 | | |
655 | | lane[0] ^= (x0 & 0x0000FFFFUL) + (x1 << 16); |
656 | | lane[1] ^= (x0 >> 16) + (x1 & 0xFFFF0000UL); |
657 | | } |
658 | | |
659 | | static unsigned int |
660 | | keccak_absorb_lanes32bi_bmi2(KECCAK_STATE *hd, int pos, const byte *lanes, |
661 | | size_t nlanes, int blocklanes) |
662 | | { |
663 | | unsigned int burn = 0; |
664 | | |
665 | | while (nlanes) |
666 | | { |
667 | | keccak_absorb_lane32bi_bmi2(&hd->u.state32bi[pos * 2], |
668 | | buf_get_le32(lanes + 0), |
669 | | buf_get_le32(lanes + 4)); |
670 | | lanes += 8; |
671 | | nlanes--; |
672 | | |
673 | | if (++pos == blocklanes) |
674 | | { |
675 | | burn = keccak_f1600_state_permute32bi_bmi2(hd); |
676 | | pos = 0; |
677 | | } |
678 | | } |
679 | | |
680 | | return burn; |
681 | | } |
682 | | |
683 | | static unsigned int |
684 | | keccak_extract32bi_bmi2(KECCAK_STATE *hd, unsigned int pos, byte *outbuf, |
685 | | unsigned int outlen) |
686 | | { |
687 | | unsigned int i; |
688 | | u32 x0; |
689 | | u32 x1; |
690 | | u32 t; |
691 | | |
692 | | /* NOTE: when pos == 0, hd and outbuf may point to same memory (SHA-3). */ |
693 | | |
694 | | for (i = pos; i < pos + outlen / 8 + !!(outlen % 8); i++) |
695 | | { |
696 | | x0 = hd->u.state32bi[i * 2 + 0]; |
697 | | x1 = hd->u.state32bi[i * 2 + 1]; |
698 | | |
699 | | t = (x0 & 0x0000FFFFUL) + (x1 << 16); |
700 | | x1 = (x0 >> 16) + (x1 & 0xFFFF0000UL); |
701 | | x0 = t; |
702 | | |
703 | | x0 = pdep(pext(x0, 0xffff0001), 0xaaaaaaab) | pdep(x0 >> 1, 0x55555554); |
704 | | x1 = pdep(pext(x1, 0xffff0001), 0xaaaaaaab) | pdep(x1 >> 1, 0x55555554); |
705 | | |
706 | | buf_put_le32(&outbuf[0], x0); |
707 | | buf_put_le32(&outbuf[4], x1); |
708 | | outbuf += 8; |
709 | | } |
710 | | |
711 | | return 0; |
712 | | } |
713 | | |
714 | | static const keccak_ops_t keccak_bmi2_32bi_ops = |
715 | | { |
716 | | .permute = keccak_f1600_state_permute32bi_bmi2, |
717 | | .absorb = keccak_absorb_lanes32bi_bmi2, |
718 | | .extract = keccak_extract32bi_bmi2, |
719 | | }; |
720 | | |
721 | | #endif /* USE_32BIT_BMI2 */ |
722 | | |
723 | | |
724 | | #ifdef USE_S390X_CRYPTO |
725 | | #include "asm-inline-s390x.h" |
726 | | |
727 | | static inline void |
728 | | keccak_bwrite_s390x (void *context, const byte *in, size_t inlen) |
729 | | { |
730 | | KECCAK_CONTEXT *ctx = context; |
731 | | |
732 | | /* Write full-blocks. */ |
733 | | kimd_execute (ctx->kimd_func, &ctx->state, in, inlen); |
734 | | return; |
735 | | } |
736 | | |
737 | | static inline void |
738 | | keccak_final_s390x (void *context) |
739 | | { |
740 | | KECCAK_CONTEXT *ctx = context; |
741 | | |
742 | | if (ctx->suffix == SHA3_DELIMITED_SUFFIX) |
743 | | { |
744 | | klmd_execute (ctx->kimd_func, &ctx->state, ctx->buf, ctx->count); |
745 | | } |
746 | | else |
747 | | { |
748 | | gcry_assert(ctx->suffix == SHAKE_DELIMITED_SUFFIX); |
749 | | |
750 | | klmd_shake_execute (ctx->kimd_func, &ctx->state, NULL, 0, ctx->buf, |
751 | | ctx->count); |
752 | | ctx->count = 0; |
753 | | ctx->buf_pos = 0; |
754 | | } |
755 | | |
756 | | return; |
757 | | } |
758 | | |
759 | | static inline void |
760 | | keccak_bextract_s390x (void *context, byte *out, size_t outlen) |
761 | | { |
762 | | KECCAK_CONTEXT *ctx = context; |
763 | | |
764 | | /* Extract full-blocks. */ |
765 | | klmd_shake_execute (ctx->kimd_func | KLMD_PADDING_STATE, &ctx->state, |
766 | | out, outlen, NULL, 0); |
767 | | return; |
768 | | } |
769 | | |
770 | | static void |
771 | | keccak_write_s390x (void *context, const byte *inbuf, size_t inlen) |
772 | | { |
773 | | KECCAK_CONTEXT *hd = context; |
774 | | const size_t blocksize = hd->blocksize; |
775 | | size_t inblocks; |
776 | | size_t copylen; |
777 | | |
778 | | while (hd->count) |
779 | | { |
780 | | if (hd->count == blocksize) /* Flush the buffer. */ |
781 | | { |
782 | | keccak_bwrite_s390x (hd, hd->buf, blocksize); |
783 | | hd->count = 0; |
784 | | } |
785 | | else |
786 | | { |
787 | | copylen = inlen; |
788 | | if (copylen > blocksize - hd->count) |
789 | | copylen = blocksize - hd->count; |
790 | | |
791 | | if (copylen == 0) |
792 | | break; |
793 | | |
794 | | buf_cpy (&hd->buf[hd->count], inbuf, copylen); |
795 | | hd->count += copylen; |
796 | | inbuf += copylen; |
797 | | inlen -= copylen; |
798 | | } |
799 | | } |
800 | | |
801 | | if (inlen == 0) |
802 | | return; |
803 | | |
804 | | if (inlen >= blocksize) |
805 | | { |
806 | | inblocks = inlen / blocksize; |
807 | | keccak_bwrite_s390x (hd, inbuf, inblocks * blocksize); |
808 | | hd->count = 0; |
809 | | inlen -= inblocks * blocksize; |
810 | | inbuf += inblocks * blocksize; |
811 | | } |
812 | | |
813 | | if (inlen) |
814 | | { |
815 | | buf_cpy (hd->buf, inbuf, inlen); |
816 | | hd->count = inlen; |
817 | | } |
818 | | } |
819 | | |
820 | | static void |
821 | | keccak_extract_s390x (void *context, void *outbuf_arg, size_t outlen) |
822 | | { |
823 | | KECCAK_CONTEXT *hd = context; |
824 | | const size_t blocksize = hd->blocksize; |
825 | | byte *outbuf = outbuf_arg; |
826 | | |
827 | | while (outlen) |
828 | | { |
829 | | gcry_assert(hd->count == 0 || hd->buf_pos < hd->count); |
830 | | |
831 | | if (hd->buf_pos < hd->count && outlen) |
832 | | { |
833 | | size_t copylen = hd->count - hd->buf_pos; |
834 | | |
835 | | if (copylen > outlen) |
836 | | copylen = outlen; |
837 | | |
838 | | buf_cpy (outbuf, &hd->buf[hd->buf_pos], copylen); |
839 | | |
840 | | outbuf += copylen; |
841 | | outlen -= copylen; |
842 | | hd->buf_pos += copylen; |
843 | | } |
844 | | |
845 | | if (hd->buf_pos == hd->count) |
846 | | { |
847 | | hd->buf_pos = 0; |
848 | | hd->count = 0; |
849 | | } |
850 | | |
851 | | if (outlen == 0) |
852 | | return; |
853 | | |
854 | | if (outlen >= blocksize) |
855 | | { |
856 | | size_t outblocks = outlen / blocksize; |
857 | | |
858 | | keccak_bextract_s390x (context, outbuf, outblocks * blocksize); |
859 | | |
860 | | outlen -= outblocks * blocksize; |
861 | | outbuf += outblocks * blocksize; |
862 | | |
863 | | if (outlen == 0) |
864 | | return; |
865 | | } |
866 | | |
867 | | keccak_bextract_s390x (context, hd->buf, blocksize); |
868 | | hd->count = blocksize; |
869 | | } |
870 | | } |
871 | | #endif /* USE_S390X_CRYPTO */ |
872 | | |
873 | | |
874 | | static void |
875 | | keccak_write (void *context, const void *inbuf_arg, size_t inlen) |
876 | 135k | { |
877 | 135k | KECCAK_CONTEXT *ctx = context; |
878 | 135k | const size_t bsize = ctx->blocksize; |
879 | 135k | const size_t blocklanes = bsize / 8; |
880 | 135k | const byte *inbuf = inbuf_arg; |
881 | 135k | unsigned int nburn, burn = 0; |
882 | 135k | unsigned int count, i; |
883 | 135k | unsigned int pos; |
884 | 135k | size_t nlanes; |
885 | | |
886 | | #ifdef USE_S390X_CRYPTO |
887 | | if (ctx->kimd_func) |
888 | | { |
889 | | keccak_write_s390x (context, inbuf, inlen); |
890 | | return; |
891 | | } |
892 | | #endif |
893 | | |
894 | 135k | count = ctx->count; |
895 | | |
896 | 135k | if (inlen && (count % 8)) |
897 | 12.2k | { |
898 | 12.2k | byte lane[8] = { 0, }; |
899 | | |
900 | | /* Complete absorbing partial input lane. */ |
901 | | |
902 | 12.2k | pos = count / 8; |
903 | | |
904 | 39.1k | for (i = count % 8; inlen && i < 8; i++) |
905 | 26.9k | { |
906 | 26.9k | lane[i] = *inbuf++; |
907 | 26.9k | inlen--; |
908 | 26.9k | count++; |
909 | 26.9k | } |
910 | | |
911 | 12.2k | if (count == bsize) |
912 | 1.06k | count = 0; |
913 | | |
914 | 12.2k | nburn = ctx->ops->absorb(&ctx->state, pos, lane, 1, |
915 | 12.2k | (count % 8) ? -1 : blocklanes); |
916 | 12.2k | burn = nburn > burn ? nburn : burn; |
917 | 12.2k | } |
918 | | |
919 | | /* Absorb full input lanes. */ |
920 | | |
921 | 135k | pos = count / 8; |
922 | 135k | nlanes = inlen / 8; |
923 | 135k | if (nlanes > 0) |
924 | 28.7k | { |
925 | 28.7k | nburn = ctx->ops->absorb(&ctx->state, pos, inbuf, nlanes, blocklanes); |
926 | 28.7k | burn = nburn > burn ? nburn : burn; |
927 | 28.7k | inlen -= nlanes * 8; |
928 | 28.7k | inbuf += nlanes * 8; |
929 | 28.7k | count = ((size_t) count + nlanes * 8) % bsize; |
930 | 28.7k | } |
931 | | |
932 | 135k | if (inlen) |
933 | 15.6k | { |
934 | 15.6k | byte lane[8] = { 0, }; |
935 | | |
936 | | /* Absorb remaining partial input lane. */ |
937 | | |
938 | 15.6k | pos = count / 8; |
939 | | |
940 | 73.5k | for (i = count % 8; inlen && i < 8; i++) |
941 | 57.8k | { |
942 | 57.8k | lane[i] = *inbuf++; |
943 | 57.8k | inlen--; |
944 | 57.8k | count++; |
945 | 57.8k | } |
946 | | |
947 | 15.6k | nburn = ctx->ops->absorb(&ctx->state, pos, lane, 1, -1); |
948 | 15.6k | burn = nburn > burn ? nburn : burn; |
949 | | |
950 | 15.6k | gcry_assert(count < bsize); |
951 | 15.6k | } |
952 | | |
953 | 0 | ctx->count = count; |
954 | | |
955 | 135k | if (burn) |
956 | 11.9k | _gcry_burn_stack (burn); |
957 | 135k | } |
958 | | |
959 | | |
960 | | static void |
961 | | keccak_init (int algo, void *context, unsigned int flags) |
962 | 2.29k | { |
963 | 2.29k | KECCAK_CONTEXT *ctx = context; |
964 | 2.29k | KECCAK_STATE *hd = &ctx->state; |
965 | 2.29k | unsigned int features = _gcry_get_hw_features (); |
966 | | |
967 | 2.29k | (void)flags; |
968 | 2.29k | (void)features; |
969 | | |
970 | 2.29k | memset (hd, 0, sizeof *hd); |
971 | | |
972 | 2.29k | ctx->count = 0; |
973 | 2.29k | ctx->shake_in_extract_mode = 0; |
974 | 2.29k | ctx->shake_in_read_mode = 0; |
975 | | |
976 | | /* Select generic implementation. */ |
977 | 2.29k | #ifdef USE_64BIT |
978 | 2.29k | ctx->ops = &keccak_generic64_ops; |
979 | | #elif defined USE_32BIT |
980 | | ctx->ops = &keccak_generic32bi_ops; |
981 | | #endif |
982 | | |
983 | | /* Select optimized implementation based in hw features. */ |
984 | 2.29k | if (0) {} |
985 | 2.29k | #ifdef USE_64BIT_AVX512 |
986 | 2.29k | else if (features & HWF_INTEL_AVX512) |
987 | 0 | ctx->ops = &keccak_avx512_64_ops; |
988 | 2.29k | #endif |
989 | | #ifdef USE_64BIT_ARM_NEON |
990 | | else if (features & HWF_ARM_NEON) |
991 | | ctx->ops = &keccak_armv7_neon_64_ops; |
992 | | #endif |
993 | 2.29k | #ifdef USE_64BIT_BMI2 |
994 | 2.29k | else if (features & HWF_INTEL_BMI2) |
995 | 2.29k | ctx->ops = &keccak_bmi2_64_ops; |
996 | 0 | #endif |
997 | | #ifdef USE_32BIT_BMI2 |
998 | | else if (features & HWF_INTEL_BMI2) |
999 | | ctx->ops = &keccak_bmi2_32bi_ops; |
1000 | | #endif |
1001 | 0 | #ifdef USE_64BIT_SHLD |
1002 | 0 | else if (features & HWF_INTEL_FAST_SHLD) |
1003 | 0 | ctx->ops = &keccak_shld_64_ops; |
1004 | 2.29k | #endif |
1005 | | |
1006 | | /* Set input block size, in Keccak terms this is called 'rate'. */ |
1007 | | |
1008 | 2.29k | switch (algo) |
1009 | 2.29k | { |
1010 | 736 | case GCRY_MD_SHA3_224: |
1011 | 736 | ctx->suffix = SHA3_DELIMITED_SUFFIX; |
1012 | 736 | ctx->blocksize = 1152 / 8; |
1013 | 736 | ctx->outlen = 224 / 8; |
1014 | 736 | break; |
1015 | 478 | case GCRY_MD_SHA3_256: |
1016 | 478 | ctx->suffix = SHA3_DELIMITED_SUFFIX; |
1017 | 478 | ctx->blocksize = 1088 / 8; |
1018 | 478 | ctx->outlen = 256 / 8; |
1019 | 478 | break; |
1020 | 414 | case GCRY_MD_SHA3_384: |
1021 | 414 | ctx->suffix = SHA3_DELIMITED_SUFFIX; |
1022 | 414 | ctx->blocksize = 832 / 8; |
1023 | 414 | ctx->outlen = 384 / 8; |
1024 | 414 | break; |
1025 | 539 | case GCRY_MD_SHA3_512: |
1026 | 539 | ctx->suffix = SHA3_DELIMITED_SUFFIX; |
1027 | 539 | ctx->blocksize = 576 / 8; |
1028 | 539 | ctx->outlen = 512 / 8; |
1029 | 539 | break; |
1030 | 0 | case GCRY_MD_CSHAKE128: |
1031 | 74 | case GCRY_MD_SHAKE128: |
1032 | 74 | ctx->suffix = SHAKE_DELIMITED_SUFFIX; |
1033 | 74 | ctx->blocksize = 1344 / 8; |
1034 | 74 | ctx->outlen = 256 / 8; |
1035 | 74 | break; |
1036 | 0 | case GCRY_MD_CSHAKE256: |
1037 | 52 | case GCRY_MD_SHAKE256: |
1038 | 52 | ctx->suffix = SHAKE_DELIMITED_SUFFIX; |
1039 | 52 | ctx->blocksize = 1088 / 8; |
1040 | 52 | ctx->outlen = 512 / 8; |
1041 | 52 | break; |
1042 | 0 | default: |
1043 | 0 | BUG(); |
1044 | 2.29k | } |
1045 | | |
1046 | | #ifdef USE_S390X_CRYPTO |
1047 | | ctx->kimd_func = 0; |
1048 | | if ((features & HWF_S390X_MSA) != 0) |
1049 | | { |
1050 | | unsigned int kimd_func = 0; |
1051 | | |
1052 | | switch (algo) |
1053 | | { |
1054 | | case GCRY_MD_SHA3_224: |
1055 | | kimd_func = KMID_FUNCTION_SHA3_224; |
1056 | | break; |
1057 | | case GCRY_MD_SHA3_256: |
1058 | | kimd_func = KMID_FUNCTION_SHA3_256; |
1059 | | break; |
1060 | | case GCRY_MD_SHA3_384: |
1061 | | kimd_func = KMID_FUNCTION_SHA3_384; |
1062 | | break; |
1063 | | case GCRY_MD_SHA3_512: |
1064 | | kimd_func = KMID_FUNCTION_SHA3_512; |
1065 | | break; |
1066 | | case GCRY_MD_CSHAKE128: |
1067 | | case GCRY_MD_SHAKE128: |
1068 | | kimd_func = KMID_FUNCTION_SHAKE128; |
1069 | | break; |
1070 | | case GCRY_MD_CSHAKE256: |
1071 | | case GCRY_MD_SHAKE256: |
1072 | | kimd_func = KMID_FUNCTION_SHAKE256; |
1073 | | break; |
1074 | | } |
1075 | | |
1076 | | if ((kimd_query () & km_function_to_mask (kimd_func)) && |
1077 | | (klmd_query () & km_function_to_mask (kimd_func))) |
1078 | | { |
1079 | | ctx->kimd_func = kimd_func; |
1080 | | } |
1081 | | } |
1082 | | #endif |
1083 | 2.29k | } |
1084 | | |
1085 | | static void |
1086 | | sha3_224_init (void *context, unsigned int flags) |
1087 | 736 | { |
1088 | 736 | keccak_init (GCRY_MD_SHA3_224, context, flags); |
1089 | 736 | } |
1090 | | |
1091 | | static void |
1092 | | sha3_256_init (void *context, unsigned int flags) |
1093 | 478 | { |
1094 | 478 | keccak_init (GCRY_MD_SHA3_256, context, flags); |
1095 | 478 | } |
1096 | | |
1097 | | static void |
1098 | | sha3_384_init (void *context, unsigned int flags) |
1099 | 414 | { |
1100 | 414 | keccak_init (GCRY_MD_SHA3_384, context, flags); |
1101 | 414 | } |
1102 | | |
1103 | | static void |
1104 | | sha3_512_init (void *context, unsigned int flags) |
1105 | 539 | { |
1106 | 539 | keccak_init (GCRY_MD_SHA3_512, context, flags); |
1107 | 539 | } |
1108 | | |
1109 | | static void |
1110 | | shake128_init (void *context, unsigned int flags) |
1111 | 74 | { |
1112 | 74 | keccak_init (GCRY_MD_SHAKE128, context, flags); |
1113 | 74 | } |
1114 | | |
1115 | | static void |
1116 | | shake256_init (void *context, unsigned int flags) |
1117 | 52 | { |
1118 | 52 | keccak_init (GCRY_MD_SHAKE256, context, flags); |
1119 | 52 | } |
1120 | | |
1121 | | /* The routine final terminates the computation and |
1122 | | * returns the digest. |
1123 | | * The handle is prepared for a new cycle, but adding bytes to the |
1124 | | * handle will the destroy the returned buffer. |
1125 | | * Returns: 64 bytes representing the digest. When used for sha384, |
1126 | | * we take the leftmost 48 of those bytes. |
1127 | | */ |
1128 | | static void |
1129 | | keccak_final (void *context) |
1130 | 18.3k | { |
1131 | 18.3k | KECCAK_CONTEXT *ctx = context; |
1132 | 18.3k | KECCAK_STATE *hd = &ctx->state; |
1133 | 18.3k | const size_t bsize = ctx->blocksize; |
1134 | 18.3k | const byte suffix = ctx->suffix; |
1135 | 18.3k | unsigned int nburn, burn = 0; |
1136 | 18.3k | unsigned int lastbytes; |
1137 | 18.3k | byte lane[8]; |
1138 | | |
1139 | | #ifdef USE_S390X_CRYPTO |
1140 | | if (ctx->kimd_func) |
1141 | | { |
1142 | | keccak_final_s390x (context); |
1143 | | return; |
1144 | | } |
1145 | | #endif |
1146 | | |
1147 | 18.3k | lastbytes = ctx->count; |
1148 | | |
1149 | | /* Do the padding and switch to the squeezing phase */ |
1150 | | |
1151 | | /* Absorb the last few bits and add the first bit of padding (which |
1152 | | coincides with the delimiter in delimited suffix) */ |
1153 | 18.3k | buf_put_le64(lane, (u64)suffix << ((lastbytes % 8) * 8)); |
1154 | 18.3k | nburn = ctx->ops->absorb(&ctx->state, lastbytes / 8, lane, 1, -1); |
1155 | 18.3k | burn = nburn > burn ? nburn : burn; |
1156 | | |
1157 | | /* Add the second bit of padding. */ |
1158 | 18.3k | buf_put_le64(lane, (u64)0x80 << (((bsize - 1) % 8) * 8)); |
1159 | 18.3k | nburn = ctx->ops->absorb(&ctx->state, (bsize - 1) / 8, lane, 1, -1); |
1160 | 18.3k | burn = nburn > burn ? nburn : burn; |
1161 | | |
1162 | 18.3k | if (suffix == SHA3_DELIMITED_SUFFIX) |
1163 | 18.2k | { |
1164 | | /* Switch to the squeezing phase. */ |
1165 | 18.2k | nburn = ctx->ops->permute(hd); |
1166 | 18.2k | burn = nburn > burn ? nburn : burn; |
1167 | | |
1168 | | /* Squeeze out the SHA3 digest. */ |
1169 | 18.2k | nburn = ctx->ops->extract(hd, 0, (void *)hd, ctx->outlen); |
1170 | 18.2k | burn = nburn > burn ? nburn : burn; |
1171 | 18.2k | } |
1172 | 126 | else |
1173 | 126 | { |
1174 | | /* Output for SHAKE can now be read with md_extract(). */ |
1175 | | |
1176 | 126 | ctx->count = 0; |
1177 | 126 | } |
1178 | | |
1179 | 18.3k | wipememory(lane, sizeof(lane)); |
1180 | 18.3k | if (burn) |
1181 | 18.2k | _gcry_burn_stack (burn); |
1182 | 18.3k | } |
1183 | | |
1184 | | |
1185 | | static byte * |
1186 | | keccak_read (void *context) |
1187 | 18.2k | { |
1188 | 18.2k | KECCAK_CONTEXT *ctx = (KECCAK_CONTEXT *) context; |
1189 | 18.2k | KECCAK_STATE *hd = &ctx->state; |
1190 | 18.2k | return (byte *)&hd->u; |
1191 | 18.2k | } |
1192 | | |
1193 | | |
1194 | | static gcry_err_code_t |
1195 | | do_keccak_extract (void *context, void *out, size_t outlen) |
1196 | 126 | { |
1197 | 126 | KECCAK_CONTEXT *ctx = context; |
1198 | 126 | KECCAK_STATE *hd = &ctx->state; |
1199 | 126 | const size_t bsize = ctx->blocksize; |
1200 | 126 | unsigned int nburn, burn = 0; |
1201 | 126 | byte *outbuf = out; |
1202 | 126 | unsigned int nlanes; |
1203 | 126 | unsigned int nleft; |
1204 | 126 | unsigned int count; |
1205 | 126 | unsigned int i; |
1206 | 126 | byte lane[8]; |
1207 | | |
1208 | | #ifdef USE_S390X_CRYPTO |
1209 | | if (ctx->kimd_func) |
1210 | | { |
1211 | | keccak_extract_s390x (context, out, outlen); |
1212 | | return 0; |
1213 | | } |
1214 | | #endif |
1215 | | |
1216 | 126 | count = ctx->count; |
1217 | | |
1218 | 126 | while (count && outlen && (outlen < 8 || count % 8)) |
1219 | 0 | { |
1220 | | /* Extract partial lane. */ |
1221 | 0 | nburn = ctx->ops->extract(hd, count / 8, lane, 8); |
1222 | 0 | burn = nburn > burn ? nburn : burn; |
1223 | |
|
1224 | 0 | for (i = count % 8; outlen && i < 8; i++) |
1225 | 0 | { |
1226 | 0 | *outbuf++ = lane[i]; |
1227 | 0 | outlen--; |
1228 | 0 | count++; |
1229 | 0 | } |
1230 | |
|
1231 | 0 | gcry_assert(count <= bsize); |
1232 | | |
1233 | 0 | if (count == bsize) |
1234 | 0 | count = 0; |
1235 | 0 | } |
1236 | | |
1237 | 126 | if (outlen >= 8 && count) |
1238 | 0 | { |
1239 | | /* Extract tail of partial block. */ |
1240 | 0 | nlanes = outlen / 8; |
1241 | 0 | nleft = (bsize - count) / 8; |
1242 | 0 | nlanes = nlanes < nleft ? nlanes : nleft; |
1243 | |
|
1244 | 0 | nburn = ctx->ops->extract(hd, count / 8, outbuf, nlanes * 8); |
1245 | 0 | burn = nburn > burn ? nburn : burn; |
1246 | 0 | outlen -= nlanes * 8; |
1247 | 0 | outbuf += nlanes * 8; |
1248 | 0 | count += nlanes * 8; |
1249 | |
|
1250 | 0 | gcry_assert(count <= bsize); |
1251 | | |
1252 | 0 | if (count == bsize) |
1253 | 0 | count = 0; |
1254 | 0 | } |
1255 | | |
1256 | 126 | while (outlen >= bsize) |
1257 | 0 | { |
1258 | 0 | gcry_assert(count == 0); |
1259 | | |
1260 | | /* Squeeze more. */ |
1261 | 0 | nburn = ctx->ops->permute(hd); |
1262 | 0 | burn = nburn > burn ? nburn : burn; |
1263 | | |
1264 | | /* Extract full block. */ |
1265 | 0 | nburn = ctx->ops->extract(hd, 0, outbuf, bsize); |
1266 | 0 | burn = nburn > burn ? nburn : burn; |
1267 | |
|
1268 | 0 | outlen -= bsize; |
1269 | 0 | outbuf += bsize; |
1270 | 0 | } |
1271 | | |
1272 | 126 | if (outlen) |
1273 | 126 | { |
1274 | 126 | gcry_assert(outlen < bsize); |
1275 | | |
1276 | 126 | if (count == 0) |
1277 | 126 | { |
1278 | | /* Squeeze more. */ |
1279 | 126 | nburn = ctx->ops->permute(hd); |
1280 | 126 | burn = nburn > burn ? nburn : burn; |
1281 | 126 | } |
1282 | | |
1283 | 126 | if (outlen >= 8) |
1284 | 126 | { |
1285 | | /* Extract head of partial block. */ |
1286 | 126 | nlanes = outlen / 8; |
1287 | 126 | nburn = ctx->ops->extract(hd, count / 8, outbuf, nlanes * 8); |
1288 | 126 | burn = nburn > burn ? nburn : burn; |
1289 | 126 | outlen -= nlanes * 8; |
1290 | 126 | outbuf += nlanes * 8; |
1291 | 126 | count += nlanes * 8; |
1292 | | |
1293 | 126 | gcry_assert(count < bsize); |
1294 | 126 | } |
1295 | | |
1296 | 126 | if (outlen) |
1297 | 0 | { |
1298 | | /* Extract head of partial lane. */ |
1299 | 0 | nburn = ctx->ops->extract(hd, count / 8, lane, 8); |
1300 | 0 | burn = nburn > burn ? nburn : burn; |
1301 | |
|
1302 | 0 | for (i = count % 8; outlen && i < 8; i++) |
1303 | 0 | { |
1304 | 0 | *outbuf++ = lane[i]; |
1305 | 0 | outlen--; |
1306 | 0 | count++; |
1307 | 0 | } |
1308 | |
|
1309 | 0 | gcry_assert(count < bsize); |
1310 | 0 | } |
1311 | 126 | } |
1312 | | |
1313 | 0 | ctx->count = count; |
1314 | | |
1315 | 126 | if (burn) |
1316 | 126 | _gcry_burn_stack (burn); |
1317 | | |
1318 | 126 | return 0; |
1319 | 126 | } |
1320 | | |
1321 | | |
1322 | | static gcry_err_code_t |
1323 | | keccak_extract (void *context, void *out, size_t outlen) |
1324 | 126 | { |
1325 | 126 | KECCAK_CONTEXT *ctx = context; |
1326 | | |
1327 | 126 | if (ctx->shake_in_read_mode) |
1328 | 0 | return GPG_ERR_INV_STATE; |
1329 | 126 | if (!ctx->shake_in_extract_mode) |
1330 | 126 | ctx->shake_in_extract_mode = 1; |
1331 | | |
1332 | 126 | return do_keccak_extract (context, out, outlen); |
1333 | 126 | } |
1334 | | |
1335 | | |
1336 | | static byte * |
1337 | | keccak_shake_read (void *context) |
1338 | 0 | { |
1339 | 0 | KECCAK_CONTEXT *ctx = (KECCAK_CONTEXT *) context; |
1340 | 0 | KECCAK_STATE *hd = &ctx->state; |
1341 | |
|
1342 | 0 | if (ctx->shake_in_extract_mode) |
1343 | 0 | { |
1344 | | /* Already in extract mode. */ |
1345 | 0 | return NULL; |
1346 | 0 | } |
1347 | | |
1348 | 0 | if (!ctx->shake_in_read_mode) |
1349 | 0 | { |
1350 | 0 | byte tmpbuf[64]; |
1351 | |
|
1352 | 0 | gcry_assert(sizeof(tmpbuf) >= ctx->outlen); |
1353 | | |
1354 | 0 | ctx->shake_in_read_mode = 1; |
1355 | |
|
1356 | 0 | do_keccak_extract (context, tmpbuf, ctx->outlen); |
1357 | 0 | buf_cpy (&hd->u, tmpbuf, ctx->outlen); |
1358 | |
|
1359 | 0 | wipememory(tmpbuf, sizeof(tmpbuf)); |
1360 | 0 | } |
1361 | | |
1362 | 0 | return (byte *)&hd->u; |
1363 | 0 | } |
1364 | | |
1365 | | |
1366 | | /* Variant of the above shortcut function using multiple buffers. */ |
1367 | | static void |
1368 | | _gcry_sha3_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, |
1369 | | int iovcnt, const gcry_md_spec_t *spec) |
1370 | 127 | { |
1371 | 127 | KECCAK_CONTEXT hd; |
1372 | | |
1373 | 127 | spec->init (&hd, 0); |
1374 | 254 | for (;iovcnt > 0; iov++, iovcnt--) |
1375 | 127 | keccak_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); |
1376 | 127 | keccak_final (&hd); |
1377 | 127 | if (hd.suffix == SHA3_DELIMITED_SUFFIX) |
1378 | 127 | memcpy (outbuf, keccak_read (&hd), spec->mdlen); |
1379 | 0 | else |
1380 | 0 | do_keccak_extract (&hd, outbuf, nbytes); |
1381 | 127 | } |
1382 | | |
1383 | | |
1384 | | static void |
1385 | | _gcry_sha3_224_hash_buffers (void *outbuf, size_t nbytes, |
1386 | | const gcry_buffer_t *iov, int iovcnt) |
1387 | 28 | { |
1388 | 28 | _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, |
1389 | 28 | &_gcry_digest_spec_sha3_224); |
1390 | 28 | } |
1391 | | |
1392 | | static void |
1393 | | _gcry_sha3_256_hash_buffers (void *outbuf, size_t nbytes, |
1394 | | const gcry_buffer_t *iov, int iovcnt) |
1395 | 29 | { |
1396 | 29 | _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, |
1397 | 29 | &_gcry_digest_spec_sha3_256); |
1398 | 29 | } |
1399 | | |
1400 | | static void |
1401 | | _gcry_sha3_384_hash_buffers (void *outbuf, size_t nbytes, |
1402 | | const gcry_buffer_t *iov, int iovcnt) |
1403 | 27 | { |
1404 | 27 | _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, |
1405 | 27 | &_gcry_digest_spec_sha3_384); |
1406 | 27 | } |
1407 | | |
1408 | | static void |
1409 | | _gcry_sha3_512_hash_buffers (void *outbuf, size_t nbytes, |
1410 | | const gcry_buffer_t *iov, int iovcnt) |
1411 | 43 | { |
1412 | 43 | _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, |
1413 | 43 | &_gcry_digest_spec_sha3_512); |
1414 | 43 | } |
1415 | | |
1416 | | static void |
1417 | | _gcry_shake128_hash_buffers (void *outbuf, size_t nbytes, |
1418 | | const gcry_buffer_t *iov, int iovcnt) |
1419 | 0 | { |
1420 | 0 | _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, |
1421 | 0 | &_gcry_digest_spec_shake128); |
1422 | 0 | } |
1423 | | |
1424 | | static void |
1425 | | _gcry_shake256_hash_buffers (void *outbuf, size_t nbytes, |
1426 | | const gcry_buffer_t *iov, int iovcnt) |
1427 | 0 | { |
1428 | 0 | _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, |
1429 | 0 | &_gcry_digest_spec_shake256); |
1430 | 0 | } |
1431 | | |
1432 | | |
1433 | | static unsigned int |
1434 | | cshake_input_n (KECCAK_CONTEXT *ctx, const void *n, unsigned int n_len) |
1435 | 0 | { |
1436 | 0 | unsigned char buf[3]; |
1437 | |
|
1438 | 0 | buf[0] = 1; |
1439 | 0 | buf[1] = ctx->blocksize; |
1440 | 0 | keccak_write (ctx, buf, 2); |
1441 | | |
1442 | | /* Here, N_LEN must be less than 255 */ |
1443 | 0 | if (n_len < 32) |
1444 | 0 | { |
1445 | 0 | buf[0] = 1; |
1446 | 0 | buf[1] = n_len * 8; |
1447 | 0 | } |
1448 | 0 | else |
1449 | 0 | { |
1450 | 0 | buf[0] = 2; |
1451 | 0 | buf[1] = (n_len * 8) >> 8; |
1452 | 0 | buf[2] = (n_len * 8) & 0xff; |
1453 | 0 | } |
1454 | |
|
1455 | 0 | keccak_write (ctx, buf, buf[0] + 1); |
1456 | 0 | keccak_write (ctx, n, n_len); |
1457 | 0 | return 2 + buf[0] + 1 + n_len; |
1458 | 0 | } |
1459 | | |
1460 | | static void |
1461 | | cshake_input_s (KECCAK_CONTEXT *ctx, const void *s, unsigned int s_len, |
1462 | | unsigned int len_written) |
1463 | 0 | { |
1464 | 0 | unsigned char buf[168]; |
1465 | 0 | unsigned int padlen; |
1466 | | |
1467 | | /* Here, S_LEN must be less than 255 */ |
1468 | 0 | if (s_len < 32) |
1469 | 0 | { |
1470 | 0 | buf[0] = 1; |
1471 | 0 | buf[1] = s_len * 8; |
1472 | 0 | } |
1473 | 0 | else |
1474 | 0 | { |
1475 | 0 | buf[0] = 2; |
1476 | 0 | buf[1] = (s_len * 8) >> 8; |
1477 | 0 | buf[2] = (s_len * 8) & 0xff; |
1478 | 0 | } |
1479 | |
|
1480 | 0 | keccak_write (ctx, buf, buf[0] + 1); |
1481 | 0 | keccak_write (ctx, s, s_len); |
1482 | |
|
1483 | 0 | len_written += buf[0] + 1 + s_len; |
1484 | 0 | padlen = ctx->blocksize - (len_written % ctx->blocksize); |
1485 | 0 | memset (buf, 0, padlen); |
1486 | 0 | keccak_write (ctx, buf, padlen); |
1487 | 0 | } |
1488 | | |
1489 | | gpg_err_code_t |
1490 | | _gcry_cshake_customize (void *context, struct gcry_cshake_customization *p) |
1491 | 0 | { |
1492 | 0 | KECCAK_CONTEXT *ctx = (KECCAK_CONTEXT *) context; |
1493 | 0 | unsigned int len_written; |
1494 | |
|
1495 | 0 | if (p->n_len >= 255 || p->s_len >= 255) |
1496 | 0 | return GPG_ERR_TOO_LARGE; |
1497 | | |
1498 | 0 | if (p->n_len == 0 && p->s_len == 0) |
1499 | | /* No customization */ |
1500 | 0 | return 0; |
1501 | | |
1502 | 0 | ctx->suffix = CSHAKE_DELIMITED_SUFFIX; |
1503 | | #ifdef USE_S390X_CRYPTO |
1504 | | /* CSHAKE suffix is not supported by s390x/kimd. */ |
1505 | | ctx->kimd_func = 0; |
1506 | | #endif |
1507 | |
|
1508 | 0 | len_written = cshake_input_n (ctx, p->n, p->n_len); |
1509 | 0 | cshake_input_s (ctx, p->s, p->s_len, len_written); |
1510 | 0 | return 0; |
1511 | 0 | } |
1512 | | |
1513 | | |
1514 | | static void |
1515 | | cshake128_init (void *context, unsigned int flags) |
1516 | 0 | { |
1517 | 0 | keccak_init (GCRY_MD_CSHAKE128, context, flags); |
1518 | 0 | } |
1519 | | |
1520 | | static void |
1521 | | cshake256_init (void *context, unsigned int flags) |
1522 | 0 | { |
1523 | 0 | keccak_init (GCRY_MD_CSHAKE256, context, flags); |
1524 | 0 | } |
1525 | | |
1526 | | static void |
1527 | | cshake_hash_buffers (const gcry_md_spec_t *spec, void *outbuf, size_t nbytes, |
1528 | | const gcry_buffer_t *iov, int iovcnt) |
1529 | 0 | { |
1530 | 0 | KECCAK_CONTEXT ctx; |
1531 | |
|
1532 | 0 | spec->init (&ctx, 0); |
1533 | |
|
1534 | 0 | if (iovcnt < 2) |
1535 | 0 | ; /* No customization, do same as SHAKE does. */ |
1536 | 0 | else |
1537 | 0 | { |
1538 | 0 | if (iov[0].len != 0 || iov[1].len != 0) |
1539 | 0 | { |
1540 | 0 | const void *n = (unsigned char *)iov[0].data + iov[0].off; |
1541 | 0 | size_t n_len = iov[0].len; |
1542 | 0 | const void *s = (unsigned char *)iov[1].data + iov[1].off; |
1543 | 0 | size_t s_len = iov[1].len; |
1544 | 0 | size_t len; |
1545 | |
|
1546 | 0 | ctx.suffix = CSHAKE_DELIMITED_SUFFIX; |
1547 | | #ifdef USE_S390X_CRYPTO |
1548 | | /* CSHAKE suffix is not supported by s390x/kimd. */ |
1549 | | ctx.kimd_func = 0; |
1550 | | #endif |
1551 | |
|
1552 | 0 | len = cshake_input_n (&ctx, n, n_len); |
1553 | 0 | cshake_input_s (&ctx, s, s_len, len); |
1554 | 0 | } |
1555 | 0 | iovcnt -= 2; |
1556 | 0 | iov += 2; |
1557 | 0 | } |
1558 | |
|
1559 | 0 | for (;iovcnt > 0; iov++, iovcnt--) |
1560 | 0 | keccak_write (&ctx, (const char*)iov[0].data + iov[0].off, iov[0].len); |
1561 | 0 | keccak_final (&ctx); |
1562 | 0 | do_keccak_extract (&ctx, outbuf, nbytes); |
1563 | 0 | } |
1564 | | |
1565 | | static void |
1566 | | _gcry_cshake128_hash_buffers (void *outbuf, size_t nbytes, |
1567 | | const gcry_buffer_t *iov, int iovcnt) |
1568 | 0 | { |
1569 | 0 | const gcry_md_spec_t *spec = &_gcry_digest_spec_shake128; |
1570 | |
|
1571 | 0 | cshake_hash_buffers (spec, outbuf, nbytes, iov, iovcnt); |
1572 | 0 | } |
1573 | | |
1574 | | static void |
1575 | | _gcry_cshake256_hash_buffers (void *outbuf, size_t nbytes, |
1576 | | const gcry_buffer_t *iov, int iovcnt) |
1577 | 0 | { |
1578 | 0 | const gcry_md_spec_t *spec = &_gcry_digest_spec_shake256; |
1579 | |
|
1580 | 0 | cshake_hash_buffers (spec, outbuf, nbytes, iov, iovcnt); |
1581 | 0 | } |
1582 | | |
1583 | | /* |
1584 | | Self-test section. |
1585 | | */ |
1586 | | |
1587 | | |
1588 | | static gpg_err_code_t |
1589 | | selftests_keccak (int algo, int extended, selftest_report_func_t report) |
1590 | 0 | { |
1591 | 0 | const char *what; |
1592 | 0 | const char *errtxt; |
1593 | 0 | const char *short_hash; |
1594 | 0 | const char *long_hash; |
1595 | 0 | const char *one_million_a_hash; |
1596 | 0 | int hash_len; |
1597 | |
|
1598 | 0 | switch (algo) |
1599 | 0 | { |
1600 | 0 | default: |
1601 | 0 | BUG(); |
1602 | | |
1603 | 0 | case GCRY_MD_SHA3_224: |
1604 | 0 | short_hash = |
1605 | 0 | "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f" |
1606 | 0 | "\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf"; |
1607 | 0 | long_hash = |
1608 | 0 | "\x54\x3e\x68\x68\xe1\x66\x6c\x1a\x64\x36\x30\xdf\x77\x36\x7a\xe5" |
1609 | 0 | "\xa6\x2a\x85\x07\x0a\x51\xc1\x4c\xbf\x66\x5c\xbc"; |
1610 | 0 | one_million_a_hash = |
1611 | 0 | "\xd6\x93\x35\xb9\x33\x25\x19\x2e\x51\x6a\x91\x2e\x6d\x19\xa1\x5c" |
1612 | 0 | "\xb5\x1c\x6e\xd5\xc1\x52\x43\xe7\xa7\xfd\x65\x3c"; |
1613 | 0 | hash_len = 28; |
1614 | 0 | break; |
1615 | | |
1616 | 0 | case GCRY_MD_SHA3_256: |
1617 | 0 | short_hash = |
1618 | 0 | "\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd" |
1619 | 0 | "\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32"; |
1620 | 0 | long_hash = |
1621 | 0 | "\x91\x6f\x60\x61\xfe\x87\x97\x41\xca\x64\x69\xb4\x39\x71\xdf\xdb" |
1622 | 0 | "\x28\xb1\xa3\x2d\xc3\x6c\xb3\x25\x4e\x81\x2b\xe2\x7a\xad\x1d\x18"; |
1623 | 0 | one_million_a_hash = |
1624 | 0 | "\x5c\x88\x75\xae\x47\x4a\x36\x34\xba\x4f\xd5\x5e\xc8\x5b\xff\xd6" |
1625 | 0 | "\x61\xf3\x2a\xca\x75\xc6\xd6\x99\xd0\xcd\xcb\x6c\x11\x58\x91\xc1"; |
1626 | 0 | hash_len = 32; |
1627 | 0 | break; |
1628 | | |
1629 | 0 | case GCRY_MD_SHA3_384: |
1630 | 0 | short_hash = |
1631 | 0 | "\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad\x8d" |
1632 | 0 | "\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b\xe4\xb2" |
1633 | 0 | "\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28\x37\x6d\x25"; |
1634 | 0 | long_hash = |
1635 | 0 | "\x79\x40\x7d\x3b\x59\x16\xb5\x9c\x3e\x30\xb0\x98\x22\x97\x47\x91" |
1636 | 0 | "\xc3\x13\xfb\x9e\xcc\x84\x9e\x40\x6f\x23\x59\x2d\x04\xf6\x25\xdc" |
1637 | 0 | "\x8c\x70\x9b\x98\xb4\x3b\x38\x52\xb3\x37\x21\x61\x79\xaa\x7f\xc7"; |
1638 | 0 | one_million_a_hash = |
1639 | 0 | "\xee\xe9\xe2\x4d\x78\xc1\x85\x53\x37\x98\x34\x51\xdf\x97\xc8\xad" |
1640 | 0 | "\x9e\xed\xf2\x56\xc6\x33\x4f\x8e\x94\x8d\x25\x2d\x5e\x0e\x76\x84" |
1641 | 0 | "\x7a\xa0\x77\x4d\xdb\x90\xa8\x42\x19\x0d\x2c\x55\x8b\x4b\x83\x40"; |
1642 | 0 | hash_len = 48; |
1643 | 0 | break; |
1644 | | |
1645 | 0 | case GCRY_MD_SHA3_512: |
1646 | 0 | short_hash = |
1647 | 0 | "\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09\x6e" |
1648 | 0 | "\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2\x71\x2e" |
1649 | 0 | "\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47\xe3\x93\x40" |
1650 | 0 | "\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27\x4e\xec\x53\xf0"; |
1651 | 0 | long_hash = |
1652 | 0 | "\xaf\xeb\xb2\xef\x54\x2e\x65\x79\xc5\x0c\xad\x06\xd2\xe5\x78\xf9" |
1653 | 0 | "\xf8\xdd\x68\x81\xd7\xdc\x82\x4d\x26\x36\x0f\xee\xbf\x18\xa4\xfa" |
1654 | 0 | "\x73\xe3\x26\x11\x22\x94\x8e\xfc\xfd\x49\x2e\x74\xe8\x2e\x21\x89" |
1655 | 0 | "\xed\x0f\xb4\x40\xd1\x87\xf3\x82\x27\x0c\xb4\x55\xf2\x1d\xd1\x85"; |
1656 | 0 | one_million_a_hash = |
1657 | 0 | "\x3c\x3a\x87\x6d\xa1\x40\x34\xab\x60\x62\x7c\x07\x7b\xb9\x8f\x7e" |
1658 | 0 | "\x12\x0a\x2a\x53\x70\x21\x2d\xff\xb3\x38\x5a\x18\xd4\xf3\x88\x59" |
1659 | 0 | "\xed\x31\x1d\x0a\x9d\x51\x41\xce\x9c\xc5\xc6\x6e\xe6\x89\xb2\x66" |
1660 | 0 | "\xa8\xaa\x18\xac\xe8\x28\x2a\x0e\x0d\xb5\x96\xc9\x0b\x0a\x7b\x87"; |
1661 | 0 | hash_len = 64; |
1662 | 0 | break; |
1663 | | |
1664 | 0 | case GCRY_MD_CSHAKE128: |
1665 | 0 | case GCRY_MD_SHAKE128: |
1666 | 0 | short_hash = |
1667 | 0 | "\x58\x81\x09\x2d\xd8\x18\xbf\x5c\xf8\xa3\xdd\xb7\x93\xfb\xcb\xa7" |
1668 | 0 | "\x40\x97\xd5\xc5\x26\xa6\xd3\x5f\x97\xb8\x33\x51\x94\x0f\x2c\xc8"; |
1669 | 0 | long_hash = |
1670 | 0 | "\x7b\x6d\xf6\xff\x18\x11\x73\xb6\xd7\x89\x8d\x7f\xf6\x3f\xb0\x7b" |
1671 | 0 | "\x7c\x23\x7d\xaf\x47\x1a\x5a\xe5\x60\x2a\xdb\xcc\xef\x9c\xcf\x4b"; |
1672 | 0 | one_million_a_hash = |
1673 | 0 | "\x9d\x22\x2c\x79\xc4\xff\x9d\x09\x2c\xf6\xca\x86\x14\x3a\xa4\x11" |
1674 | 0 | "\xe3\x69\x97\x38\x08\xef\x97\x09\x32\x55\x82\x6c\x55\x72\xef\x58"; |
1675 | 0 | hash_len = 32; |
1676 | 0 | break; |
1677 | | |
1678 | 0 | case GCRY_MD_CSHAKE256: |
1679 | 0 | case GCRY_MD_SHAKE256: |
1680 | 0 | short_hash = |
1681 | 0 | "\x48\x33\x66\x60\x13\x60\xa8\x77\x1c\x68\x63\x08\x0c\xc4\x11\x4d" |
1682 | 0 | "\x8d\xb4\x45\x30\xf8\xf1\xe1\xee\x4f\x94\xea\x37\xe7\x8b\x57\x39"; |
1683 | 0 | long_hash = |
1684 | 0 | "\x98\xbe\x04\x51\x6c\x04\xcc\x73\x59\x3f\xef\x3e\xd0\x35\x2e\xa9" |
1685 | 0 | "\xf6\x44\x39\x42\xd6\x95\x0e\x29\xa3\x72\xa6\x81\xc3\xde\xaf\x45"; |
1686 | 0 | one_million_a_hash = |
1687 | 0 | "\x35\x78\xa7\xa4\xca\x91\x37\x56\x9c\xdf\x76\xed\x61\x7d\x31\xbb" |
1688 | 0 | "\x99\x4f\xca\x9c\x1b\xbf\x8b\x18\x40\x13\xde\x82\x34\xdf\xd1\x3a"; |
1689 | 0 | hash_len = 32; |
1690 | 0 | break; |
1691 | 0 | } |
1692 | | |
1693 | 0 | what = "short string"; |
1694 | 0 | errtxt = _gcry_hash_selftest_check_one (algo, 0, "abc", 3, short_hash, |
1695 | 0 | hash_len); |
1696 | 0 | if (errtxt) |
1697 | 0 | goto failed; |
1698 | | |
1699 | 0 | if (extended) |
1700 | 0 | { |
1701 | 0 | what = "long string"; |
1702 | 0 | errtxt = _gcry_hash_selftest_check_one |
1703 | 0 | (algo, 0, |
1704 | 0 | "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" |
1705 | 0 | "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, |
1706 | 0 | long_hash, hash_len); |
1707 | 0 | if (errtxt) |
1708 | 0 | goto failed; |
1709 | | |
1710 | 0 | what = "one million \"a\""; |
1711 | 0 | errtxt = _gcry_hash_selftest_check_one (algo, 1, NULL, 0, |
1712 | 0 | one_million_a_hash, hash_len); |
1713 | 0 | if (errtxt) |
1714 | 0 | goto failed; |
1715 | 0 | } |
1716 | | |
1717 | 0 | return 0; /* Succeeded. */ |
1718 | | |
1719 | 0 | failed: |
1720 | 0 | if (report) |
1721 | 0 | report ("digest", algo, what, errtxt); |
1722 | 0 | return GPG_ERR_SELFTEST_FAILED; |
1723 | 0 | } |
1724 | | |
1725 | | |
1726 | | /* Run a full self-test for ALGO and return 0 on success. */ |
1727 | | static gpg_err_code_t |
1728 | | run_selftests (int algo, int extended, selftest_report_func_t report) |
1729 | 0 | { |
1730 | 0 | gpg_err_code_t ec; |
1731 | |
|
1732 | 0 | switch (algo) |
1733 | 0 | { |
1734 | 0 | case GCRY_MD_SHA3_224: |
1735 | 0 | case GCRY_MD_SHA3_256: |
1736 | 0 | case GCRY_MD_SHA3_384: |
1737 | 0 | case GCRY_MD_SHA3_512: |
1738 | 0 | case GCRY_MD_CSHAKE128: |
1739 | 0 | case GCRY_MD_SHAKE128: |
1740 | 0 | case GCRY_MD_CSHAKE256: |
1741 | 0 | case GCRY_MD_SHAKE256: |
1742 | 0 | ec = selftests_keccak (algo, extended, report); |
1743 | 0 | break; |
1744 | 0 | default: |
1745 | 0 | ec = GPG_ERR_DIGEST_ALGO; |
1746 | 0 | break; |
1747 | 0 | } |
1748 | | |
1749 | 0 | return ec; |
1750 | 0 | } |
1751 | | |
1752 | | |
1753 | | |
1754 | | |
1755 | | /* Object IDs obtained from |
1756 | | * https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration#Hash |
1757 | | */ |
1758 | | static const byte sha3_224_asn[] = |
1759 | | { 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, |
1760 | | 0x01, 0x65, 0x03, 0x04, 0x02, 0x07, 0x05, 0x00, 0x04, |
1761 | | 0x1c |
1762 | | }; |
1763 | | static const gcry_md_oid_spec_t oid_spec_sha3_224[] = |
1764 | | { |
1765 | | { "2.16.840.1.101.3.4.2.7" }, |
1766 | | /* id-rsassa-pkcs1-v1-5-with-sha3-224 */ |
1767 | | { "2.16.840.1.101.3.4.3.13" }, |
1768 | | /* id-ecdsa-with-sha3-224 */ |
1769 | | { "2.16.840.1.101.3.4.3.9" }, |
1770 | | { NULL } |
1771 | | }; |
1772 | | static const byte sha3_256_asn[] = |
1773 | | { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, |
1774 | | 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, |
1775 | | 0x20 |
1776 | | }; |
1777 | | static const gcry_md_oid_spec_t oid_spec_sha3_256[] = |
1778 | | { |
1779 | | { "2.16.840.1.101.3.4.2.8" }, |
1780 | | /* id-rsassa-pkcs1-v1-5-with-sha3-256 */ |
1781 | | { "2.16.840.1.101.3.4.3.14" }, |
1782 | | /* id-ecdsa-with-sha3-256 */ |
1783 | | { "2.16.840.1.101.3.4.3.10" }, |
1784 | | { NULL } |
1785 | | }; |
1786 | | static const byte sha3_384_asn[] = |
1787 | | { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, |
1788 | | 0x01, 0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00, 0x04, |
1789 | | 0x30 |
1790 | | }; |
1791 | | static const gcry_md_oid_spec_t oid_spec_sha3_384[] = |
1792 | | { |
1793 | | { "2.16.840.1.101.3.4.2.9" }, |
1794 | | /* id-rsassa-pkcs1-v1-5-with-sha3-384 */ |
1795 | | { "2.16.840.1.101.3.4.3.15" }, |
1796 | | /* id-ecdsa-with-sha3-384 */ |
1797 | | { "2.16.840.1.101.3.4.3.11" }, |
1798 | | { NULL } |
1799 | | }; |
1800 | | static const byte sha3_512_asn[] = |
1801 | | { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, |
1802 | | 0x01, 0x65, 0x03, 0x04, 0x02, 0x0a, 0x05, 0x00, 0x04, |
1803 | | 0x40 |
1804 | | }; |
1805 | | static const gcry_md_oid_spec_t oid_spec_sha3_512[] = |
1806 | | { |
1807 | | { "2.16.840.1.101.3.4.2.10" }, |
1808 | | /* id-rsassa-pkcs1-v1-5-with-sha3-512 */ |
1809 | | { "2.16.840.1.101.3.4.3.16" }, |
1810 | | /* id-ecdsa-with-sha3-512 */ |
1811 | | { "2.16.840.1.101.3.4.3.12" }, |
1812 | | { NULL } |
1813 | | }; |
1814 | | static const byte shake128_asn[] = |
1815 | | { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, |
1816 | | 0x01, 0x65, 0x03, 0x04, 0x02, 0x0b, 0x05, 0x00, 0x04, |
1817 | | 0x20 |
1818 | | }; |
1819 | | static const gcry_md_oid_spec_t oid_spec_shake128[] = |
1820 | | { |
1821 | | { "2.16.840.1.101.3.4.2.11" }, |
1822 | | /* RFC 8692 id-RSASSA-PSS-SHAKE128 */ |
1823 | | { "1.3.6.1.5.5.7.6.30" }, |
1824 | | /* RFC 8692 id-ecdsa-with-shake128 */ |
1825 | | { "1.3.6.1.5.5.7.6.32" }, |
1826 | | { NULL } |
1827 | | }; |
1828 | | static const byte shake256_asn[] = |
1829 | | { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, |
1830 | | 0x01, 0x65, 0x03, 0x04, 0x02, 0x0c, 0x05, 0x00, 0x04, |
1831 | | 0x40 |
1832 | | }; |
1833 | | static const gcry_md_oid_spec_t oid_spec_shake256[] = |
1834 | | { |
1835 | | { "2.16.840.1.101.3.4.2.12" }, |
1836 | | /* RFC 8692 id-RSASSA-PSS-SHAKE256 */ |
1837 | | { "1.3.6.1.5.5.7.6.31" }, |
1838 | | /* RFC 8692 id-ecdsa-with-shake256 */ |
1839 | | { "1.3.6.1.5.5.7.6.33" }, |
1840 | | { NULL } |
1841 | | }; |
1842 | | |
1843 | | const gcry_md_spec_t _gcry_digest_spec_sha3_224 = |
1844 | | { |
1845 | | GCRY_MD_SHA3_224, {0, 1}, |
1846 | | "SHA3-224", sha3_224_asn, DIM (sha3_224_asn), oid_spec_sha3_224, 28, |
1847 | | sha3_224_init, keccak_write, keccak_final, keccak_read, NULL, |
1848 | | _gcry_sha3_224_hash_buffers, |
1849 | | sizeof (KECCAK_CONTEXT), |
1850 | | run_selftests |
1851 | | }; |
1852 | | const gcry_md_spec_t _gcry_digest_spec_sha3_256 = |
1853 | | { |
1854 | | GCRY_MD_SHA3_256, {0, 1}, |
1855 | | "SHA3-256", sha3_256_asn, DIM (sha3_256_asn), oid_spec_sha3_256, 32, |
1856 | | sha3_256_init, keccak_write, keccak_final, keccak_read, NULL, |
1857 | | _gcry_sha3_256_hash_buffers, |
1858 | | sizeof (KECCAK_CONTEXT), |
1859 | | run_selftests |
1860 | | }; |
1861 | | const gcry_md_spec_t _gcry_digest_spec_sha3_384 = |
1862 | | { |
1863 | | GCRY_MD_SHA3_384, {0, 1}, |
1864 | | "SHA3-384", sha3_384_asn, DIM (sha3_384_asn), oid_spec_sha3_384, 48, |
1865 | | sha3_384_init, keccak_write, keccak_final, keccak_read, NULL, |
1866 | | _gcry_sha3_384_hash_buffers, |
1867 | | sizeof (KECCAK_CONTEXT), |
1868 | | run_selftests |
1869 | | }; |
1870 | | const gcry_md_spec_t _gcry_digest_spec_sha3_512 = |
1871 | | { |
1872 | | GCRY_MD_SHA3_512, {0, 1}, |
1873 | | "SHA3-512", sha3_512_asn, DIM (sha3_512_asn), oid_spec_sha3_512, 64, |
1874 | | sha3_512_init, keccak_write, keccak_final, keccak_read, NULL, |
1875 | | _gcry_sha3_512_hash_buffers, |
1876 | | sizeof (KECCAK_CONTEXT), |
1877 | | run_selftests |
1878 | | }; |
1879 | | const gcry_md_spec_t _gcry_digest_spec_shake128 = |
1880 | | { |
1881 | | GCRY_MD_SHAKE128, {0, 1}, |
1882 | | "SHAKE128", shake128_asn, DIM (shake128_asn), oid_spec_shake128, 32, |
1883 | | shake128_init, keccak_write, keccak_final, keccak_shake_read, |
1884 | | keccak_extract, |
1885 | | _gcry_shake128_hash_buffers, |
1886 | | sizeof (KECCAK_CONTEXT), |
1887 | | run_selftests |
1888 | | }; |
1889 | | const gcry_md_spec_t _gcry_digest_spec_shake256 = |
1890 | | { |
1891 | | GCRY_MD_SHAKE256, {0, 1}, |
1892 | | "SHAKE256", shake256_asn, DIM (shake256_asn), oid_spec_shake256, 64, |
1893 | | shake256_init, keccak_write, keccak_final, keccak_shake_read, |
1894 | | keccak_extract, |
1895 | | _gcry_shake256_hash_buffers, |
1896 | | sizeof (KECCAK_CONTEXT), |
1897 | | run_selftests |
1898 | | }; |
1899 | | const gcry_md_spec_t _gcry_digest_spec_cshake128 = |
1900 | | { |
1901 | | GCRY_MD_CSHAKE128, {0, 1}, |
1902 | | "CSHAKE128", NULL, 0, NULL, 32, |
1903 | | cshake128_init, keccak_write, keccak_final, keccak_shake_read, |
1904 | | keccak_extract, _gcry_cshake128_hash_buffers, |
1905 | | sizeof (KECCAK_CONTEXT), |
1906 | | run_selftests |
1907 | | }; |
1908 | | const gcry_md_spec_t _gcry_digest_spec_cshake256 = |
1909 | | { |
1910 | | GCRY_MD_CSHAKE256, {0, 1}, |
1911 | | "CSHAKE256", NULL, 0, NULL, 64, |
1912 | | cshake256_init, keccak_write, keccak_final, keccak_shake_read, |
1913 | | keccak_extract, _gcry_cshake256_hash_buffers, |
1914 | | sizeof (KECCAK_CONTEXT), |
1915 | | run_selftests |
1916 | | }; |