pq_crypto 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yml +37 -0
- data/CHANGELOG.md +29 -0
- data/GET_STARTED.md +65 -0
- data/LICENSE.txt +21 -0
- data/README.md +135 -0
- data/SECURITY.md +57 -0
- data/ext/pqcrypto/extconf.rb +157 -0
- data/ext/pqcrypto/mldsa_api.h +51 -0
- data/ext/pqcrypto/mlkem_api.h +21 -0
- data/ext/pqcrypto/pqcrypto_ruby_secure.c +889 -0
- data/ext/pqcrypto/pqcrypto_secure.c +1178 -0
- data/ext/pqcrypto/pqcrypto_secure.h +135 -0
- data/ext/pqcrypto/vendor/.vendored +5 -0
- data/ext/pqcrypto/vendor/pqclean/common/aes.c +639 -0
- data/ext/pqcrypto/vendor/pqclean/common/aes.h +64 -0
- data/ext/pqcrypto/vendor/pqclean/common/compat.h +73 -0
- data/ext/pqcrypto/vendor/pqclean/common/crypto_declassify.h +7 -0
- data/ext/pqcrypto/vendor/pqclean/common/fips202.c +928 -0
- data/ext/pqcrypto/vendor/pqclean/common/fips202.h +166 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak2x/feat.S +168 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak2x/fips202x2.c +684 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak2x/fips202x2.h +60 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-times4-SIMD256.c +1028 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-times4-SnP.h +50 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/KeccakP-1600-unrolling.macros +198 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/Makefile +8 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/Makefile.Microsoft_nmake +8 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/SIMD256-config.h +3 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/align.h +34 -0
- data/ext/pqcrypto/vendor/pqclean/common/keccak4x/brg_endian.h +142 -0
- data/ext/pqcrypto/vendor/pqclean/common/nistseedexpander.c +101 -0
- data/ext/pqcrypto/vendor/pqclean/common/nistseedexpander.h +39 -0
- data/ext/pqcrypto/vendor/pqclean/common/randombytes.c +355 -0
- data/ext/pqcrypto/vendor/pqclean/common/randombytes.h +27 -0
- data/ext/pqcrypto/vendor/pqclean/common/sha2.c +769 -0
- data/ext/pqcrypto/vendor/pqclean/common/sha2.h +173 -0
- data/ext/pqcrypto/vendor/pqclean/common/sp800-185.c +156 -0
- data/ext/pqcrypto/vendor/pqclean/common/sp800-185.h +27 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/LICENSE +5 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/Makefile +19 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/Makefile.Microsoft_nmake +23 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/api.h +18 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/cbd.c +83 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/cbd.h +11 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/indcpa.c +327 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/indcpa.h +22 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/kem.c +164 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/kem.h +23 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/ntt.c +146 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/ntt.h +14 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/params.h +36 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/poly.c +299 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/poly.h +37 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/polyvec.c +188 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/polyvec.h +26 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/reduce.c +41 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/reduce.h +13 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/symmetric-shake.c +71 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/symmetric.h +30 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/verify.c +67 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_kem/ml-kem-768/clean/verify.h +13 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/LICENSE +5 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/Makefile +19 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/Makefile.Microsoft_nmake +23 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/api.h +50 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/ntt.c +98 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/ntt.h +10 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/packing.c +261 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/packing.h +31 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/params.h +44 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/poly.c +799 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/poly.h +52 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/polyvec.c +415 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/polyvec.h +65 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/reduce.c +69 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/reduce.h +17 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/rounding.c +92 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/rounding.h +14 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/sign.c +407 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/sign.h +47 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/symmetric-shake.c +26 -0
- data/ext/pqcrypto/vendor/pqclean/crypto_sign/ml-dsa-65/clean/symmetric.h +34 -0
- data/lib/pq_crypto/errors.rb +10 -0
- data/lib/pq_crypto/hybrid_kem.rb +106 -0
- data/lib/pq_crypto/kem.rb +199 -0
- data/lib/pq_crypto/serialization.rb +102 -0
- data/lib/pq_crypto/signature.rb +198 -0
- data/lib/pq_crypto/version.rb +5 -0
- data/lib/pq_crypto.rb +177 -0
- data/lib/pqcrypto.rb +3 -0
- data/script/vendor_libs.rb +199 -0
- metadata +195 -0
|
@@ -0,0 +1,684 @@
|
|
|
1
|
+
|
|
2
|
+
/*
|
|
3
|
+
* This file was originally licensed
|
|
4
|
+
* under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0.html)
|
|
5
|
+
* at https://github.com/GMUCERG/PQC_NEON/blob/main/neon/kyber or
|
|
6
|
+
* public domain at https://github.com/cothan/kyber/blob/master/neon
|
|
7
|
+
*
|
|
8
|
+
* We offer
|
|
9
|
+
* CC0 1.0 Universal or the following MIT License for this file.
|
|
10
|
+
* You may freely choose one of them that applies.
|
|
11
|
+
*
|
|
12
|
+
* MIT License
|
|
13
|
+
*
|
|
14
|
+
* Copyright (c) 2023: Hanno Becker, Vincent Hwang, Matthias J. Kannwischer, Bo-Yin Yang, and Shang-Yi Yang
|
|
15
|
+
*
|
|
16
|
+
*
|
|
17
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
18
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
19
|
+
* in the Software without restriction, including without limitation the rights
|
|
20
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
21
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
22
|
+
* furnished to do so, subject to the following conditions:
|
|
23
|
+
*
|
|
24
|
+
* The above copyright notice and this permission notice shall be included in
|
|
25
|
+
* all copies or substantial portions of the Software.
|
|
26
|
+
*
|
|
27
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
28
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
29
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
30
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
31
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
32
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
33
|
+
* SOFTWARE.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
#include "fips202x2.h"
|
|
37
|
+
#include <arm_neon.h>
|
|
38
|
+
|
|
39
|
+
#define NROUNDS 24
|
|
40
|
+
|
|
41
|
+
// Define NEON operation
|
|
42
|
+
// c = load(ptr)
|
|
43
|
+
#define vload(ptr) vld1q_u64(ptr);
|
|
44
|
+
// ptr <= c;
|
|
45
|
+
#define vstore(ptr, c) vst1q_u64(ptr, c);
|
|
46
|
+
// c = a ^ b
|
|
47
|
+
#define vxor(c, a, b) c = veorq_u64(a, b);
|
|
48
|
+
// Rotate by n bit ((a << offset) ^ (a >> (64-offset)))
|
|
49
|
+
#define vROL(out, a, offset) \
|
|
50
|
+
out = vshlq_n_u64(a, offset); \
|
|
51
|
+
out = vsriq_n_u64(out, a, 64 - offset);
|
|
52
|
+
// Xor chain: out = a ^ b ^ c ^ d ^ e
|
|
53
|
+
#define vXOR4(out, a, b, c, d, e) \
|
|
54
|
+
out = veorq_u64(a, b); \
|
|
55
|
+
out = veorq_u64(out, c); \
|
|
56
|
+
out = veorq_u64(out, d); \
|
|
57
|
+
out = veorq_u64(out, e);
|
|
58
|
+
// Not And c = ~a & b
|
|
59
|
+
// #define vbic(c, a, b) c = vbicq_u64(b, a);
|
|
60
|
+
// Xor Not And: out = a ^ ( (~b) & c)
|
|
61
|
+
#define vXNA(out, a, b, c) \
|
|
62
|
+
out = vbicq_u64(c, b); \
|
|
63
|
+
out = veorq_u64(out, a);
|
|
64
|
+
// Rotate by 1 bit, then XOR: a ^ ROL(b): SHA1 instruction, not support
|
|
65
|
+
#define vrxor(c, a, b) c = vrax1q_u64(a, b);
|
|
66
|
+
// End Define
|
|
67
|
+
|
|
68
|
+
/* Keccak round constants */
|
|
69
|
+
static const uint64_t neon_KeccakF_RoundConstants[NROUNDS] = {
|
|
70
|
+
(uint64_t)0x0000000000000001ULL,
|
|
71
|
+
(uint64_t)0x0000000000008082ULL,
|
|
72
|
+
(uint64_t)0x800000000000808aULL,
|
|
73
|
+
(uint64_t)0x8000000080008000ULL,
|
|
74
|
+
(uint64_t)0x000000000000808bULL,
|
|
75
|
+
(uint64_t)0x0000000080000001ULL,
|
|
76
|
+
(uint64_t)0x8000000080008081ULL,
|
|
77
|
+
(uint64_t)0x8000000000008009ULL,
|
|
78
|
+
(uint64_t)0x000000000000008aULL,
|
|
79
|
+
(uint64_t)0x0000000000000088ULL,
|
|
80
|
+
(uint64_t)0x0000000080008009ULL,
|
|
81
|
+
(uint64_t)0x000000008000000aULL,
|
|
82
|
+
(uint64_t)0x000000008000808bULL,
|
|
83
|
+
(uint64_t)0x800000000000008bULL,
|
|
84
|
+
(uint64_t)0x8000000000008089ULL,
|
|
85
|
+
(uint64_t)0x8000000000008003ULL,
|
|
86
|
+
(uint64_t)0x8000000000008002ULL,
|
|
87
|
+
(uint64_t)0x8000000000000080ULL,
|
|
88
|
+
(uint64_t)0x000000000000800aULL,
|
|
89
|
+
(uint64_t)0x800000008000000aULL,
|
|
90
|
+
(uint64_t)0x8000000080008081ULL,
|
|
91
|
+
(uint64_t)0x8000000000008080ULL,
|
|
92
|
+
(uint64_t)0x0000000080000001ULL,
|
|
93
|
+
(uint64_t)0x8000000080008008ULL
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/*************************************************
|
|
97
|
+
* Name: KeccakF1600_StatePermutex2
|
|
98
|
+
*
|
|
99
|
+
* Description: The Keccak F1600 Permutation
|
|
100
|
+
*
|
|
101
|
+
* Arguments: - uint64_t *state: pointer to input/output Keccak state
|
|
102
|
+
**************************************************/
|
|
103
|
+
extern void f1600x2(v128 *, const uint64_t *);
|
|
104
|
+
static inline
|
|
105
|
+
void KeccakF1600_StatePermutex2(v128 state[25]) {
|
|
106
|
+
#if (__APPLE__ && __ARM_FEATURE_CRYPTO) || (__ARM_FEATURE_SHA3) /* although not sure what is being implemented, we find something fast */
|
|
107
|
+
f1600x2(state, neon_KeccakF_RoundConstants);
|
|
108
|
+
#else
|
|
109
|
+
v128 Aba, Abe, Abi, Abo, Abu;
|
|
110
|
+
v128 Aga, Age, Agi, Ago, Agu;
|
|
111
|
+
v128 Aka, Ake, Aki, Ako, Aku;
|
|
112
|
+
v128 Ama, Ame, Ami, Amo, Amu;
|
|
113
|
+
v128 Asa, Ase, Asi, Aso, Asu;
|
|
114
|
+
v128 BCa, BCe, BCi, BCo, BCu; // tmp
|
|
115
|
+
v128 Da, De, Di, Do, Du; // D
|
|
116
|
+
v128 Eba, Ebe, Ebi, Ebo, Ebu;
|
|
117
|
+
v128 Ega, Ege, Egi, Ego, Egu;
|
|
118
|
+
v128 Eka, Eke, Eki, Eko, Eku;
|
|
119
|
+
v128 Ema, Eme, Emi, Emo, Emu;
|
|
120
|
+
v128 Esa, Ese, Esi, Eso, Esu;
|
|
121
|
+
|
|
122
|
+
//copyFromState(A, state)
|
|
123
|
+
Aba = state[0];
|
|
124
|
+
Abe = state[1];
|
|
125
|
+
Abi = state[2];
|
|
126
|
+
Abo = state[3];
|
|
127
|
+
Abu = state[4];
|
|
128
|
+
Aga = state[5];
|
|
129
|
+
Age = state[6];
|
|
130
|
+
Agi = state[7];
|
|
131
|
+
Ago = state[8];
|
|
132
|
+
Agu = state[9];
|
|
133
|
+
Aka = state[10];
|
|
134
|
+
Ake = state[11];
|
|
135
|
+
Aki = state[12];
|
|
136
|
+
Ako = state[13];
|
|
137
|
+
Aku = state[14];
|
|
138
|
+
Ama = state[15];
|
|
139
|
+
Ame = state[16];
|
|
140
|
+
Ami = state[17];
|
|
141
|
+
Amo = state[18];
|
|
142
|
+
Amu = state[19];
|
|
143
|
+
Asa = state[20];
|
|
144
|
+
Ase = state[21];
|
|
145
|
+
Asi = state[22];
|
|
146
|
+
Aso = state[23];
|
|
147
|
+
Asu = state[24];
|
|
148
|
+
|
|
149
|
+
for (int round = 0; round < NROUNDS; round += 2) {
|
|
150
|
+
// prepareTheta
|
|
151
|
+
vXOR4(BCa, Aba, Aga, Aka, Ama, Asa);
|
|
152
|
+
vXOR4(BCe, Abe, Age, Ake, Ame, Ase);
|
|
153
|
+
vXOR4(BCi, Abi, Agi, Aki, Ami, Asi);
|
|
154
|
+
vXOR4(BCo, Abo, Ago, Ako, Amo, Aso);
|
|
155
|
+
vXOR4(BCu, Abu, Agu, Aku, Amu, Asu);
|
|
156
|
+
|
|
157
|
+
//thetaRhoPiChiIotaPrepareTheta(round , A, E)
|
|
158
|
+
vROL(Da, BCe, 1);
|
|
159
|
+
vxor(Da, BCu, Da);
|
|
160
|
+
vROL(De, BCi, 1);
|
|
161
|
+
vxor(De, BCa, De);
|
|
162
|
+
vROL(Di, BCo, 1);
|
|
163
|
+
vxor(Di, BCe, Di);
|
|
164
|
+
vROL(Do, BCu, 1);
|
|
165
|
+
vxor(Do, BCi, Do);
|
|
166
|
+
vROL(Du, BCa, 1);
|
|
167
|
+
vxor(Du, BCo, Du);
|
|
168
|
+
|
|
169
|
+
vxor(Aba, Aba, Da);
|
|
170
|
+
vxor(Age, Age, De);
|
|
171
|
+
vROL(BCe, Age, 44);
|
|
172
|
+
vxor(Aki, Aki, Di);
|
|
173
|
+
vROL(BCi, Aki, 43);
|
|
174
|
+
vxor(Amo, Amo, Do);
|
|
175
|
+
vROL(BCo, Amo, 21);
|
|
176
|
+
vxor(Asu, Asu, Du);
|
|
177
|
+
vROL(BCu, Asu, 14);
|
|
178
|
+
vXNA(Eba, Aba, BCe, BCi);
|
|
179
|
+
vxor(Eba, Eba, vdupq_n_u64(neon_KeccakF_RoundConstants[round]));
|
|
180
|
+
vXNA(Ebe, BCe, BCi, BCo);
|
|
181
|
+
vXNA(Ebi, BCi, BCo, BCu);
|
|
182
|
+
vXNA(Ebo, BCo, BCu, Aba);
|
|
183
|
+
vXNA(Ebu, BCu, Aba, BCe);
|
|
184
|
+
|
|
185
|
+
vxor(Abo, Abo, Do);
|
|
186
|
+
vROL(BCa, Abo, 28);
|
|
187
|
+
vxor(Agu, Agu, Du);
|
|
188
|
+
vROL(BCe, Agu, 20);
|
|
189
|
+
vxor(Aka, Aka, Da);
|
|
190
|
+
vROL(BCi, Aka, 3);
|
|
191
|
+
vxor(Ame, Ame, De);
|
|
192
|
+
vROL(BCo, Ame, 45);
|
|
193
|
+
vxor(Asi, Asi, Di);
|
|
194
|
+
vROL(BCu, Asi, 61);
|
|
195
|
+
vXNA(Ega, BCa, BCe, BCi);
|
|
196
|
+
vXNA(Ege, BCe, BCi, BCo);
|
|
197
|
+
vXNA(Egi, BCi, BCo, BCu);
|
|
198
|
+
vXNA(Ego, BCo, BCu, BCa);
|
|
199
|
+
vXNA(Egu, BCu, BCa, BCe);
|
|
200
|
+
|
|
201
|
+
vxor(Abe, Abe, De);
|
|
202
|
+
vROL(BCa, Abe, 1);
|
|
203
|
+
vxor(Agi, Agi, Di);
|
|
204
|
+
vROL(BCe, Agi, 6);
|
|
205
|
+
vxor(Ako, Ako, Do);
|
|
206
|
+
vROL(BCi, Ako, 25);
|
|
207
|
+
vxor(Amu, Amu, Du);
|
|
208
|
+
vROL(BCo, Amu, 8);
|
|
209
|
+
vxor(Asa, Asa, Da);
|
|
210
|
+
vROL(BCu, Asa, 18);
|
|
211
|
+
vXNA(Eka, BCa, BCe, BCi);
|
|
212
|
+
vXNA(Eke, BCe, BCi, BCo);
|
|
213
|
+
vXNA(Eki, BCi, BCo, BCu);
|
|
214
|
+
vXNA(Eko, BCo, BCu, BCa);
|
|
215
|
+
vXNA(Eku, BCu, BCa, BCe);
|
|
216
|
+
|
|
217
|
+
vxor(Abu, Abu, Du);
|
|
218
|
+
vROL(BCa, Abu, 27);
|
|
219
|
+
vxor(Aga, Aga, Da);
|
|
220
|
+
vROL(BCe, Aga, 36);
|
|
221
|
+
vxor(Ake, Ake, De);
|
|
222
|
+
vROL(BCi, Ake, 10);
|
|
223
|
+
vxor(Ami, Ami, Di);
|
|
224
|
+
vROL(BCo, Ami, 15);
|
|
225
|
+
vxor(Aso, Aso, Do);
|
|
226
|
+
vROL(BCu, Aso, 56);
|
|
227
|
+
vXNA(Ema, BCa, BCe, BCi);
|
|
228
|
+
vXNA(Eme, BCe, BCi, BCo);
|
|
229
|
+
vXNA(Emi, BCi, BCo, BCu);
|
|
230
|
+
vXNA(Emo, BCo, BCu, BCa);
|
|
231
|
+
vXNA(Emu, BCu, BCa, BCe);
|
|
232
|
+
|
|
233
|
+
vxor(Abi, Abi, Di);
|
|
234
|
+
vROL(BCa, Abi, 62);
|
|
235
|
+
vxor(Ago, Ago, Do);
|
|
236
|
+
vROL(BCe, Ago, 55);
|
|
237
|
+
vxor(Aku, Aku, Du);
|
|
238
|
+
vROL(BCi, Aku, 39);
|
|
239
|
+
vxor(Ama, Ama, Da);
|
|
240
|
+
vROL(BCo, Ama, 41);
|
|
241
|
+
vxor(Ase, Ase, De);
|
|
242
|
+
vROL(BCu, Ase, 2);
|
|
243
|
+
vXNA(Esa, BCa, BCe, BCi);
|
|
244
|
+
vXNA(Ese, BCe, BCi, BCo);
|
|
245
|
+
vXNA(Esi, BCi, BCo, BCu);
|
|
246
|
+
vXNA(Eso, BCo, BCu, BCa);
|
|
247
|
+
vXNA(Esu, BCu, BCa, BCe);
|
|
248
|
+
|
|
249
|
+
// Next Round
|
|
250
|
+
|
|
251
|
+
// prepareTheta
|
|
252
|
+
vXOR4(BCa, Eba, Ega, Eka, Ema, Esa);
|
|
253
|
+
vXOR4(BCe, Ebe, Ege, Eke, Eme, Ese);
|
|
254
|
+
vXOR4(BCi, Ebi, Egi, Eki, Emi, Esi);
|
|
255
|
+
vXOR4(BCo, Ebo, Ego, Eko, Emo, Eso);
|
|
256
|
+
vXOR4(BCu, Ebu, Egu, Eku, Emu, Esu);
|
|
257
|
+
|
|
258
|
+
//thetaRhoPiChiIotaPrepareTheta(round+1, E, A)
|
|
259
|
+
vROL(Da, BCe, 1);
|
|
260
|
+
vxor(Da, BCu, Da);
|
|
261
|
+
vROL(De, BCi, 1);
|
|
262
|
+
vxor(De, BCa, De);
|
|
263
|
+
vROL(Di, BCo, 1);
|
|
264
|
+
vxor(Di, BCe, Di);
|
|
265
|
+
vROL(Do, BCu, 1);
|
|
266
|
+
vxor(Do, BCi, Do);
|
|
267
|
+
vROL(Du, BCa, 1);
|
|
268
|
+
vxor(Du, BCo, Du);
|
|
269
|
+
|
|
270
|
+
vxor(Eba, Eba, Da);
|
|
271
|
+
vxor(Ege, Ege, De);
|
|
272
|
+
vROL(BCe, Ege, 44);
|
|
273
|
+
vxor(Eki, Eki, Di);
|
|
274
|
+
vROL(BCi, Eki, 43);
|
|
275
|
+
vxor(Emo, Emo, Do);
|
|
276
|
+
vROL(BCo, Emo, 21);
|
|
277
|
+
vxor(Esu, Esu, Du);
|
|
278
|
+
vROL(BCu, Esu, 14);
|
|
279
|
+
vXNA(Aba, Eba, BCe, BCi);
|
|
280
|
+
vxor(Aba, Aba, vdupq_n_u64(neon_KeccakF_RoundConstants[round + 1]));
|
|
281
|
+
vXNA(Abe, BCe, BCi, BCo);
|
|
282
|
+
vXNA(Abi, BCi, BCo, BCu);
|
|
283
|
+
vXNA(Abo, BCo, BCu, Eba);
|
|
284
|
+
vXNA(Abu, BCu, Eba, BCe);
|
|
285
|
+
|
|
286
|
+
vxor(Ebo, Ebo, Do);
|
|
287
|
+
vROL(BCa, Ebo, 28);
|
|
288
|
+
vxor(Egu, Egu, Du);
|
|
289
|
+
vROL(BCe, Egu, 20);
|
|
290
|
+
vxor(Eka, Eka, Da);
|
|
291
|
+
vROL(BCi, Eka, 3);
|
|
292
|
+
vxor(Eme, Eme, De);
|
|
293
|
+
vROL(BCo, Eme, 45);
|
|
294
|
+
vxor(Esi, Esi, Di);
|
|
295
|
+
vROL(BCu, Esi, 61);
|
|
296
|
+
vXNA(Aga, BCa, BCe, BCi);
|
|
297
|
+
vXNA(Age, BCe, BCi, BCo);
|
|
298
|
+
vXNA(Agi, BCi, BCo, BCu);
|
|
299
|
+
vXNA(Ago, BCo, BCu, BCa);
|
|
300
|
+
vXNA(Agu, BCu, BCa, BCe);
|
|
301
|
+
|
|
302
|
+
vxor(Ebe, Ebe, De);
|
|
303
|
+
vROL(BCa, Ebe, 1);
|
|
304
|
+
vxor(Egi, Egi, Di);
|
|
305
|
+
vROL(BCe, Egi, 6);
|
|
306
|
+
vxor(Eko, Eko, Do);
|
|
307
|
+
vROL(BCi, Eko, 25);
|
|
308
|
+
vxor(Emu, Emu, Du);
|
|
309
|
+
vROL(BCo, Emu, 8);
|
|
310
|
+
vxor(Esa, Esa, Da);
|
|
311
|
+
vROL(BCu, Esa, 18);
|
|
312
|
+
vXNA(Aka, BCa, BCe, BCi);
|
|
313
|
+
vXNA(Ake, BCe, BCi, BCo);
|
|
314
|
+
vXNA(Aki, BCi, BCo, BCu);
|
|
315
|
+
vXNA(Ako, BCo, BCu, BCa);
|
|
316
|
+
vXNA(Aku, BCu, BCa, BCe);
|
|
317
|
+
|
|
318
|
+
vxor(Ebu, Ebu, Du);
|
|
319
|
+
vROL(BCa, Ebu, 27);
|
|
320
|
+
vxor(Ega, Ega, Da);
|
|
321
|
+
vROL(BCe, Ega, 36);
|
|
322
|
+
vxor(Eke, Eke, De);
|
|
323
|
+
vROL(BCi, Eke, 10);
|
|
324
|
+
vxor(Emi, Emi, Di);
|
|
325
|
+
vROL(BCo, Emi, 15);
|
|
326
|
+
vxor(Eso, Eso, Do);
|
|
327
|
+
vROL(BCu, Eso, 56);
|
|
328
|
+
vXNA(Ama, BCa, BCe, BCi);
|
|
329
|
+
vXNA(Ame, BCe, BCi, BCo);
|
|
330
|
+
vXNA(Ami, BCi, BCo, BCu);
|
|
331
|
+
vXNA(Amo, BCo, BCu, BCa);
|
|
332
|
+
vXNA(Amu, BCu, BCa, BCe);
|
|
333
|
+
|
|
334
|
+
vxor(Ebi, Ebi, Di);
|
|
335
|
+
vROL(BCa, Ebi, 62);
|
|
336
|
+
vxor(Ego, Ego, Do);
|
|
337
|
+
vROL(BCe, Ego, 55);
|
|
338
|
+
vxor(Eku, Eku, Du);
|
|
339
|
+
vROL(BCi, Eku, 39);
|
|
340
|
+
vxor(Ema, Ema, Da);
|
|
341
|
+
vROL(BCo, Ema, 41);
|
|
342
|
+
vxor(Ese, Ese, De);
|
|
343
|
+
vROL(BCu, Ese, 2);
|
|
344
|
+
vXNA(Asa, BCa, BCe, BCi);
|
|
345
|
+
vXNA(Ase, BCe, BCi, BCo);
|
|
346
|
+
vXNA(Asi, BCi, BCo, BCu);
|
|
347
|
+
vXNA(Aso, BCo, BCu, BCa);
|
|
348
|
+
vXNA(Asu, BCu, BCa, BCe);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
state[0] = Aba;
|
|
352
|
+
state[1] = Abe;
|
|
353
|
+
state[2] = Abi;
|
|
354
|
+
state[3] = Abo;
|
|
355
|
+
state[4] = Abu;
|
|
356
|
+
state[5] = Aga;
|
|
357
|
+
state[6] = Age;
|
|
358
|
+
state[7] = Agi;
|
|
359
|
+
state[8] = Ago;
|
|
360
|
+
state[9] = Agu;
|
|
361
|
+
state[10] = Aka;
|
|
362
|
+
state[11] = Ake;
|
|
363
|
+
state[12] = Aki;
|
|
364
|
+
state[13] = Ako;
|
|
365
|
+
state[14] = Aku;
|
|
366
|
+
state[15] = Ama;
|
|
367
|
+
state[16] = Ame;
|
|
368
|
+
state[17] = Ami;
|
|
369
|
+
state[18] = Amo;
|
|
370
|
+
state[19] = Amu;
|
|
371
|
+
state[20] = Asa;
|
|
372
|
+
state[21] = Ase;
|
|
373
|
+
state[22] = Asi;
|
|
374
|
+
state[23] = Aso;
|
|
375
|
+
state[24] = Asu;
|
|
376
|
+
#endif
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/*************************************************
|
|
380
|
+
* Name: keccakx2_absorb
|
|
381
|
+
*
|
|
382
|
+
* Description: Absorb step of Keccak;
|
|
383
|
+
* non-incremental, starts by zeroeing the state.
|
|
384
|
+
*
|
|
385
|
+
* Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state
|
|
386
|
+
* - unsigned int r: rate in bytes (e.g., 168 for SHAKE128)
|
|
387
|
+
* - const uint8_t *m: pointer to input to be absorbed into s
|
|
388
|
+
* - size_t mlen: length of input in bytes
|
|
389
|
+
* - uint8_t p: domain-separation byte for different
|
|
390
|
+
* Keccak-derived functions
|
|
391
|
+
**************************************************/
|
|
392
|
+
static
|
|
393
|
+
void keccakx2_absorb(v128 s[25],
|
|
394
|
+
unsigned int r,
|
|
395
|
+
const uint8_t *in0,
|
|
396
|
+
const uint8_t *in1,
|
|
397
|
+
size_t inlen,
|
|
398
|
+
uint8_t p) {
|
|
399
|
+
size_t i, pos = 0;
|
|
400
|
+
|
|
401
|
+
// Declare SIMD registers
|
|
402
|
+
v128 tmp, mask;
|
|
403
|
+
uint64x1_t a, b;
|
|
404
|
+
uint64x2_t a1, b1, atmp1, btmp1;
|
|
405
|
+
uint64x2x2_t a2, b2, atmp2, btmp2;
|
|
406
|
+
// End
|
|
407
|
+
|
|
408
|
+
for (i = 0; i < 25; ++i) {
|
|
409
|
+
s[i] = vdupq_n_u64(0);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Load in0[i] to register, then in1[i] to register, exchange them
|
|
413
|
+
while (inlen >= r) {
|
|
414
|
+
for (i = 0; i < r / 8 - 1; i += 4) {
|
|
415
|
+
a2 = vld1q_u64_x2((uint64_t *)&in0[pos]);
|
|
416
|
+
b2 = vld1q_u64_x2((uint64_t *)&in1[pos]);
|
|
417
|
+
// BD = zip1(AB and CD)
|
|
418
|
+
atmp2.val[0] = vzip1q_u64(a2.val[0], b2.val[0]);
|
|
419
|
+
atmp2.val[1] = vzip1q_u64(a2.val[1], b2.val[1]);
|
|
420
|
+
// AC = zip2(AB and CD)
|
|
421
|
+
btmp2.val[0] = vzip2q_u64(a2.val[0], b2.val[0]);
|
|
422
|
+
btmp2.val[1] = vzip2q_u64(a2.val[1], b2.val[1]);
|
|
423
|
+
|
|
424
|
+
vxor(s[i + 0], s[i + 0], atmp2.val[0]);
|
|
425
|
+
vxor(s[i + 1], s[i + 1], btmp2.val[0]);
|
|
426
|
+
vxor(s[i + 2], s[i + 2], atmp2.val[1]);
|
|
427
|
+
vxor(s[i + 3], s[i + 3], btmp2.val[1]);
|
|
428
|
+
|
|
429
|
+
pos += 8 * 2 * 2;
|
|
430
|
+
}
|
|
431
|
+
// Last iteration
|
|
432
|
+
i = r / 8 - 1;
|
|
433
|
+
a = vld1_u64((uint64_t *)&in0[pos]);
|
|
434
|
+
b = vld1_u64((uint64_t *)&in1[pos]);
|
|
435
|
+
tmp = vcombine_u64(a, b);
|
|
436
|
+
vxor(s[i], s[i], tmp);
|
|
437
|
+
pos += 8;
|
|
438
|
+
|
|
439
|
+
KeccakF1600_StatePermutex2(s);
|
|
440
|
+
inlen -= r;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
i = 0;
|
|
444
|
+
while (inlen >= 16) {
|
|
445
|
+
a1 = vld1q_u64((uint64_t *)&in0[pos]);
|
|
446
|
+
b1 = vld1q_u64((uint64_t *)&in1[pos]);
|
|
447
|
+
// BD = zip1(AB and CD)
|
|
448
|
+
atmp1 = vzip1q_u64(a1, b1);
|
|
449
|
+
// AC = zip2(AB and CD)
|
|
450
|
+
btmp1 = vzip2q_u64(a1, b1);
|
|
451
|
+
|
|
452
|
+
vxor(s[i + 0], s[i + 0], atmp1);
|
|
453
|
+
vxor(s[i + 1], s[i + 1], btmp1);
|
|
454
|
+
|
|
455
|
+
i += 2;
|
|
456
|
+
pos += 8 * 2;
|
|
457
|
+
inlen -= 8 * 2;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (inlen >= 8) {
|
|
461
|
+
a = vld1_u64((uint64_t *)&in0[pos]);
|
|
462
|
+
b = vld1_u64((uint64_t *)&in1[pos]);
|
|
463
|
+
tmp = vcombine_u64(a, b);
|
|
464
|
+
vxor(s[i], s[i], tmp);
|
|
465
|
+
|
|
466
|
+
i++;
|
|
467
|
+
pos += 8;
|
|
468
|
+
inlen -= 8;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (inlen) {
|
|
472
|
+
a = vld1_u64((uint64_t *)&in0[pos]);
|
|
473
|
+
b = vld1_u64((uint64_t *)&in1[pos]);
|
|
474
|
+
tmp = vcombine_u64(a, b);
|
|
475
|
+
mask = vdupq_n_u64((1ULL << (8 * inlen)) - 1);
|
|
476
|
+
tmp = vandq_u64(tmp, mask);
|
|
477
|
+
vxor(s[i], s[i], tmp);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
tmp = vdupq_n_u64((uint64_t)p << (8 * inlen));
|
|
481
|
+
vxor(s[i], s[i], tmp);
|
|
482
|
+
|
|
483
|
+
mask = vdupq_n_u64(1ULL << 63);
|
|
484
|
+
vxor(s[r / 8 - 1], s[r / 8 - 1], mask);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/*************************************************
|
|
488
|
+
* Name: keccak_squeezeblocks
|
|
489
|
+
*
|
|
490
|
+
* Description: Squeeze step of Keccak. Squeezes full blocks of r bytes each.
|
|
491
|
+
* Modifies the state. Can be called multiple times to keep
|
|
492
|
+
* squeezing, i.e., is incremental.
|
|
493
|
+
*
|
|
494
|
+
* Arguments: - uint8_t *out: pointer to output blocks
|
|
495
|
+
* - size_t nblocks: number of blocks to be squeezed (written to h)
|
|
496
|
+
* - unsigned int r: rate in bytes (e.g., 168 for SHAKE128)
|
|
497
|
+
* - uint64_t *s: pointer to input/output Keccak state
|
|
498
|
+
**************************************************/
|
|
499
|
+
static
|
|
500
|
+
void keccakx2_squeezeblocks(uint8_t *out0,
|
|
501
|
+
uint8_t *out1,
|
|
502
|
+
size_t nblocks,
|
|
503
|
+
unsigned int r,
|
|
504
|
+
v128 s[25]) {
|
|
505
|
+
unsigned int i;
|
|
506
|
+
|
|
507
|
+
uint64x1_t a, b;
|
|
508
|
+
uint64x2x2_t a2, b2;
|
|
509
|
+
|
|
510
|
+
while (nblocks > 0) {
|
|
511
|
+
KeccakF1600_StatePermutex2(s);
|
|
512
|
+
|
|
513
|
+
for (i = 0; i < r / 8 - 1; i += 4) {
|
|
514
|
+
a2.val[0] = vuzp1q_u64(s[i], s[i + 1]);
|
|
515
|
+
b2.val[0] = vuzp2q_u64(s[i], s[i + 1]);
|
|
516
|
+
a2.val[1] = vuzp1q_u64(s[i + 2], s[i + 3]);
|
|
517
|
+
b2.val[1] = vuzp2q_u64(s[i + 2], s[i + 3]);
|
|
518
|
+
vst1q_u64_x2((uint64_t *)out0, a2);
|
|
519
|
+
vst1q_u64_x2((uint64_t *)out1, b2);
|
|
520
|
+
|
|
521
|
+
out0 += 32;
|
|
522
|
+
out1 += 32;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
i = r / 8 - 1;
|
|
526
|
+
// Last iteration
|
|
527
|
+
a = vget_low_u64(s[i]);
|
|
528
|
+
b = vget_high_u64(s[i]);
|
|
529
|
+
vst1_u64((uint64_t *)out0, a);
|
|
530
|
+
vst1_u64((uint64_t *)out1, b);
|
|
531
|
+
|
|
532
|
+
out0 += 8;
|
|
533
|
+
out1 += 8;
|
|
534
|
+
|
|
535
|
+
--nblocks;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/*************************************************
|
|
540
|
+
* Name: shake128x2_absorb
|
|
541
|
+
*
|
|
542
|
+
* Description: Absorb step of the SHAKE128 XOF.
|
|
543
|
+
* non-incremental, starts by zeroeing the state.
|
|
544
|
+
*
|
|
545
|
+
* Arguments: - keccakx2_state *state: pointer to (uninitialized) output
|
|
546
|
+
* Keccak state
|
|
547
|
+
* - const uint8_t *in: pointer to input to be absorbed into s
|
|
548
|
+
* - size_t inlen: length of input in bytes
|
|
549
|
+
**************************************************/
|
|
550
|
+
void shake128x2_absorb(keccakx2_state *state,
|
|
551
|
+
const uint8_t *in0,
|
|
552
|
+
const uint8_t *in1,
|
|
553
|
+
size_t inlen) {
|
|
554
|
+
keccakx2_absorb(state->s, SHAKE128_RATE, in0, in1, inlen, 0x1F);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/*************************************************
|
|
558
|
+
* Name: shake128_squeezeblocks
|
|
559
|
+
*
|
|
560
|
+
* Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of
|
|
561
|
+
* SHAKE128_RATE bytes each. Modifies the state. Can be called
|
|
562
|
+
* multiple times to keep squeezing, i.e., is incremental.
|
|
563
|
+
*
|
|
564
|
+
* Arguments: - uint8_t *out: pointer to output blocks
|
|
565
|
+
* - size_t nblocks: number of blocks to be squeezed
|
|
566
|
+
* (written to output)
|
|
567
|
+
* - keccakx2_state *s: pointer to input/output Keccak state
|
|
568
|
+
**************************************************/
|
|
569
|
+
void shake128x2_squeezeblocks(uint8_t *out0,
|
|
570
|
+
uint8_t *out1,
|
|
571
|
+
size_t nblocks,
|
|
572
|
+
keccakx2_state *state) {
|
|
573
|
+
keccakx2_squeezeblocks(out0, out1, nblocks, SHAKE128_RATE, state->s);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/*************************************************
|
|
577
|
+
* Name: shake256_absorb
|
|
578
|
+
*
|
|
579
|
+
* Description: Absorb step of the SHAKE256 XOF.
|
|
580
|
+
* non-incremental, starts by zeroeing the state.
|
|
581
|
+
*
|
|
582
|
+
* Arguments: - keccakx2_state *s: pointer to (uninitialized) output Keccak state
|
|
583
|
+
* - const uint8_t *in: pointer to input to be absorbed into s
|
|
584
|
+
* - size_t inlen: length of input in bytes
|
|
585
|
+
**************************************************/
|
|
586
|
+
void shake256x2_absorb(keccakx2_state *state,
|
|
587
|
+
const uint8_t *in0,
|
|
588
|
+
const uint8_t *in1,
|
|
589
|
+
size_t inlen) {
|
|
590
|
+
keccakx2_absorb(state->s, SHAKE256_RATE, in0, in1, inlen, 0x1F);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/*************************************************
|
|
594
|
+
* Name: shake256_squeezeblocks
|
|
595
|
+
*
|
|
596
|
+
* Description: Squeeze step of SHAKE256 XOF. Squeezes full blocks of
|
|
597
|
+
* SHAKE256_RATE bytes each. Modifies the state. Can be called
|
|
598
|
+
* multiple times to keep squeezing, i.e., is incremental.
|
|
599
|
+
*
|
|
600
|
+
* Arguments: - uint8_t *out: pointer to output blocks
|
|
601
|
+
* - size_t nblocks: number of blocks to be squeezed
|
|
602
|
+
* (written to output)
|
|
603
|
+
* - keccakx2_state *s: pointer to input/output Keccak state
|
|
604
|
+
**************************************************/
|
|
605
|
+
void shake256x2_squeezeblocks(uint8_t *out0,
|
|
606
|
+
uint8_t *out1,
|
|
607
|
+
size_t nblocks,
|
|
608
|
+
keccakx2_state *state) {
|
|
609
|
+
keccakx2_squeezeblocks(out0, out1, nblocks, SHAKE256_RATE, state->s);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/*************************************************
|
|
613
|
+
* Name: shake128
|
|
614
|
+
*
|
|
615
|
+
* Description: SHAKE128 XOF with non-incremental API
|
|
616
|
+
*
|
|
617
|
+
* Arguments: - uint8_t *out: pointer to output
|
|
618
|
+
* - size_t outlen: requested output length in bytes
|
|
619
|
+
* - const uint8_t *in: pointer to input
|
|
620
|
+
* - size_t inlen: length of input in bytes
|
|
621
|
+
**************************************************/
|
|
622
|
+
void shake128x2(uint8_t *out0,
|
|
623
|
+
uint8_t *out1,
|
|
624
|
+
size_t outlen,
|
|
625
|
+
const uint8_t *in0,
|
|
626
|
+
const uint8_t *in1,
|
|
627
|
+
size_t inlen) {
|
|
628
|
+
unsigned int i;
|
|
629
|
+
size_t nblocks = outlen / SHAKE128_RATE;
|
|
630
|
+
uint8_t t[2][SHAKE128_RATE];
|
|
631
|
+
keccakx2_state state;
|
|
632
|
+
|
|
633
|
+
shake128x2_absorb(&state, in0, in1, inlen);
|
|
634
|
+
shake128x2_squeezeblocks(out0, out1, nblocks, &state);
|
|
635
|
+
|
|
636
|
+
out0 += nblocks * SHAKE128_RATE;
|
|
637
|
+
out1 += nblocks * SHAKE128_RATE;
|
|
638
|
+
outlen -= nblocks * SHAKE128_RATE;
|
|
639
|
+
|
|
640
|
+
if (outlen) {
|
|
641
|
+
shake128x2_squeezeblocks(t[0], t[1], 1, &state);
|
|
642
|
+
for (i = 0; i < outlen; ++i) {
|
|
643
|
+
out0[i] = t[0][i];
|
|
644
|
+
out1[i] = t[1][i];
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/*************************************************
|
|
650
|
+
* Name: shake256
|
|
651
|
+
*
|
|
652
|
+
* Description: SHAKE256 XOF with non-incremental API
|
|
653
|
+
*
|
|
654
|
+
* Arguments: - uint8_t *out: pointer to output
|
|
655
|
+
* - size_t outlen: requested output length in bytes
|
|
656
|
+
* - const uint8_t *in: pointer to input
|
|
657
|
+
* - size_t inlen: length of input in bytes
|
|
658
|
+
**************************************************/
|
|
659
|
+
void shake256x2(uint8_t *out0,
|
|
660
|
+
uint8_t *out1,
|
|
661
|
+
size_t outlen,
|
|
662
|
+
const uint8_t *in0,
|
|
663
|
+
const uint8_t *in1,
|
|
664
|
+
size_t inlen) {
|
|
665
|
+
unsigned int i;
|
|
666
|
+
size_t nblocks = outlen / SHAKE256_RATE;
|
|
667
|
+
uint8_t t[2][SHAKE256_RATE];
|
|
668
|
+
keccakx2_state state;
|
|
669
|
+
|
|
670
|
+
shake256x2_absorb(&state, in0, in1, inlen);
|
|
671
|
+
shake256x2_squeezeblocks(out0, out1, nblocks, &state);
|
|
672
|
+
|
|
673
|
+
out0 += nblocks * SHAKE256_RATE;
|
|
674
|
+
out1 += nblocks * SHAKE256_RATE;
|
|
675
|
+
outlen -= nblocks * SHAKE256_RATE;
|
|
676
|
+
|
|
677
|
+
if (outlen) {
|
|
678
|
+
shake256x2_squeezeblocks(t[0], t[1], 1, &state);
|
|
679
|
+
for (i = 0; i < outlen; ++i) {
|
|
680
|
+
out0[i] = t[0][i];
|
|
681
|
+
out1[i] = t[1][i];
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|