@pinkparrot/qsafe-mayo-wasm 0.0.3

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.
Files changed (97) hide show
  1. package/.gitmodules +3 -0
  2. package/.vscode/launch.json +12 -0
  3. package/LICENSE +201 -0
  4. package/bridge/mayo1_bridge.c +26 -0
  5. package/bridge/mayo2_bridge.c +26 -0
  6. package/bridge/randombytes_inject.c +44 -0
  7. package/build_mayo1.ps1 +36 -0
  8. package/build_mayo2.ps1 +36 -0
  9. package/dist/mayo.browser.min.js +216 -0
  10. package/dist/mayo1.js +0 -0
  11. package/dist/mayo2.js +0 -0
  12. package/dist/mayo_api.js +139 -0
  13. package/dist/package.json +1 -0
  14. package/gitignore +2 -0
  15. package/index.mjs +1 -0
  16. package/mayo-c/.astylerc +16 -0
  17. package/mayo-c/.cmake/flags.cmake +45 -0
  18. package/mayo-c/.cmake/sanitizers.cmake +81 -0
  19. package/mayo-c/.cmake/target.cmake +71 -0
  20. package/mayo-c/.github/workflows/ci_clang.yml +61 -0
  21. package/mayo-c/.github/workflows/ci_gcc.yml +60 -0
  22. package/mayo-c/.github/workflows/cmake.yml +160 -0
  23. package/mayo-c/.github/workflows/macos_m1.yml +68 -0
  24. package/mayo-c/CMakeLists.txt +35 -0
  25. package/mayo-c/KAT/PQCsignKAT_24_MAYO_1.req +900 -0
  26. package/mayo-c/KAT/PQCsignKAT_24_MAYO_1.rsp +902 -0
  27. package/mayo-c/KAT/PQCsignKAT_24_MAYO_2.req +900 -0
  28. package/mayo-c/KAT/PQCsignKAT_24_MAYO_2.rsp +902 -0
  29. package/mayo-c/KAT/PQCsignKAT_32_MAYO_3.req +900 -0
  30. package/mayo-c/KAT/PQCsignKAT_32_MAYO_3.rsp +902 -0
  31. package/mayo-c/KAT/PQCsignKAT_40_MAYO_5.req +900 -0
  32. package/mayo-c/KAT/PQCsignKAT_40_MAYO_5.rsp +902 -0
  33. package/mayo-c/LICENSE +202 -0
  34. package/mayo-c/META/MAYO-1_META.yml +52 -0
  35. package/mayo-c/META/MAYO-2_META.yml +52 -0
  36. package/mayo-c/META/MAYO-3_META.yml +52 -0
  37. package/mayo-c/META/MAYO-5_META.yml +52 -0
  38. package/mayo-c/NOTICE +13 -0
  39. package/mayo-c/README.md +183 -0
  40. package/mayo-c/apps/CMakeLists.txt +31 -0
  41. package/mayo-c/apps/PQCgenKAT_sign.c +281 -0
  42. package/mayo-c/apps/example.c +151 -0
  43. package/mayo-c/apps/example_nistapi.c +124 -0
  44. package/mayo-c/include/mayo.h +442 -0
  45. package/mayo-c/include/mem.h +25 -0
  46. package/mayo-c/include/randombytes.h +31 -0
  47. package/mayo-c/scripts/contstants.py +141 -0
  48. package/mayo-c/scripts/find_irred_poly.sage +39 -0
  49. package/mayo-c/src/AVX2/arithmetic_common.h +159 -0
  50. package/mayo-c/src/AVX2/echelon_form.h +91 -0
  51. package/mayo-c/src/AVX2/echelon_form_loop.h +58 -0
  52. package/mayo-c/src/AVX2/shuffle_arithmetic.h +442 -0
  53. package/mayo-c/src/CMakeLists.txt +98 -0
  54. package/mayo-c/src/arithmetic.c +128 -0
  55. package/mayo-c/src/arithmetic.h +124 -0
  56. package/mayo-c/src/common/aes128ctr.c +293 -0
  57. package/mayo-c/src/common/aes_c.c +741 -0
  58. package/mayo-c/src/common/aes_ctr.h +32 -0
  59. package/mayo-c/src/common/aes_neon.c +201 -0
  60. package/mayo-c/src/common/debug_bench_tools.h +69 -0
  61. package/mayo-c/src/common/fips202.c +1093 -0
  62. package/mayo-c/src/common/fips202.h +12 -0
  63. package/mayo-c/src/common/mem.c +19 -0
  64. package/mayo-c/src/common/randombytes_ctrdrbg.c +141 -0
  65. package/mayo-c/src/common/randombytes_system.c +399 -0
  66. package/mayo-c/src/generic/arithmetic_dynamic.h +68 -0
  67. package/mayo-c/src/generic/arithmetic_fixed.h +84 -0
  68. package/mayo-c/src/generic/echelon_form.h +152 -0
  69. package/mayo-c/src/generic/ef_inner_loop.h +56 -0
  70. package/mayo-c/src/generic/generic_arithmetic.h +294 -0
  71. package/mayo-c/src/mayo.c +675 -0
  72. package/mayo-c/src/mayo_1/api.c +46 -0
  73. package/mayo-c/src/mayo_1/api.h +43 -0
  74. package/mayo-c/src/mayo_2/api.c +46 -0
  75. package/mayo-c/src/mayo_2/api.h +43 -0
  76. package/mayo-c/src/mayo_3/api.c +46 -0
  77. package/mayo-c/src/mayo_3/api.h +43 -0
  78. package/mayo-c/src/mayo_5/api.c +46 -0
  79. package/mayo-c/src/mayo_5/api.h +43 -0
  80. package/mayo-c/src/neon/arithmetic_common.h +132 -0
  81. package/mayo-c/src/neon/echelon_form.h +55 -0
  82. package/mayo-c/src/neon/echelon_form_loop.h +58 -0
  83. package/mayo-c/src/neon/shuffle_arithmetic.h +462 -0
  84. package/mayo-c/src/params.c +42 -0
  85. package/mayo-c/src/simple_arithmetic.h +138 -0
  86. package/mayo-c/test/CMakeLists.txt +51 -0
  87. package/mayo-c/test/bench.c +166 -0
  88. package/mayo-c/test/m1cycles.c +155 -0
  89. package/mayo-c/test/m1cycles.h +13 -0
  90. package/mayo-c/test/test_kat.c +271 -0
  91. package/mayo-c/test/test_mayo.c +139 -0
  92. package/mayo-c/test/test_sample_solution.c +75 -0
  93. package/mayo-c/test/test_various.c +680 -0
  94. package/package.json +39 -0
  95. package/publish.bat +22 -0
  96. package/readme.md +80 -0
  97. package/test/test.mjs +42 -0
@@ -0,0 +1,675 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+
3
+ #include <mem.h>
4
+ #include <mayo.h>
5
+ #include <randombytes.h>
6
+ #include <aes_ctr.h>
7
+ #include <arithmetic.h>
8
+ #include <simple_arithmetic.h>
9
+ #include <fips202.h>
10
+ #include <stdlib.h>
11
+ #include <string.h>
12
+ #include <stdalign.h>
13
+ #ifdef ENABLE_CT_TESTING
14
+ #include <valgrind/memcheck.h>
15
+ #endif
16
+
17
+ #define MAYO_MIN(x, y) (((x) < (y)) ? (x) : (y))
18
+ #define PK_PRF AES_128_CTR
19
+
20
+ static void decode(const unsigned char *m, unsigned char *mdec, int mdeclen) {
21
+ int i;
22
+ for (i = 0; i < mdeclen / 2; ++i) {
23
+ *mdec++ = m[i] & 0xf;
24
+ *mdec++ = m[i] >> 4;
25
+ }
26
+
27
+ if (mdeclen % 2 == 1) {
28
+ *mdec++ = m[i] & 0x0f;
29
+ }
30
+ }
31
+
32
+ static void encode(const unsigned char *m, unsigned char *menc, int mlen) {
33
+ int i;
34
+ for (i = 0; i < mlen / 2; ++i, m += 2) {
35
+ menc[i] = (*m) | (*(m + 1) << 4);
36
+ }
37
+
38
+ if (mlen % 2 == 1) {
39
+ menc[i] = (*m);
40
+ }
41
+ }
42
+
43
+ static void compute_rhs(const mayo_params_t *p, uint64_t *vPv, const unsigned char *t, unsigned char *y){
44
+ #ifndef ENABLE_PARAMS_DYNAMIC
45
+ (void) p;
46
+ #endif
47
+
48
+ const size_t top_pos = ((PARAM_m(p) - 1) % 16) * 4;
49
+ const size_t m_vec_limbs = PARAM_m_vec_limbs(p);
50
+
51
+ // zero out tails of m_vecs if neccesary
52
+ if(PARAM_m(p) % 16 != 0){
53
+ uint64_t mask = 1;
54
+ mask <<= ((PARAM_m(p) % 16)*4);
55
+ mask -= 1;
56
+ for (int i = 0; i < PARAM_k(p)*PARAM_k(p); i++)
57
+ {
58
+ vPv[i*m_vec_limbs + m_vec_limbs - 1] &= mask;
59
+ }
60
+ }
61
+
62
+ uint64_t temp[M_VEC_LIMBS_MAX] = {0};
63
+ unsigned char *temp_bytes = (unsigned char *) temp;
64
+ for (int i = PARAM_k(p) - 1; i >= 0 ; i--) {
65
+ for (int j = i; j < PARAM_k(p); j++) {
66
+ // multiply by X (shift up 4 bits)
67
+ unsigned char top = (temp[m_vec_limbs-1] >> top_pos) % 16;
68
+ temp[m_vec_limbs-1] <<= 4;
69
+ for(int k = m_vec_limbs - 2; k>=0; k--){
70
+ temp[k+1] ^= temp[k] >> 60;
71
+ temp[k] <<= 4;
72
+ }
73
+ // reduce mod f(X)
74
+ for (int jj = 0; jj < F_TAIL_LEN; jj++) {
75
+ if(jj%2 == 0){
76
+ #ifdef TARGET_BIG_ENDIAN
77
+ temp_bytes[(((jj/2 + 8) / 8) * 8) - 1 - (jj/2)%8] ^= mul_f(top, PARAM_f_tail(p)[jj]);
78
+ #else
79
+ temp_bytes[jj/2] ^= mul_f(top, PARAM_f_tail(p)[jj]);
80
+ #endif
81
+ }
82
+ else {
83
+ #ifdef TARGET_BIG_ENDIAN
84
+ temp_bytes[(((jj/2 + 8) / 8) * 8) - 1 - (jj/2)%8] ^= mul_f(top, PARAM_f_tail(p)[jj]) << 4;
85
+ #else
86
+ temp_bytes[jj/2] ^= mul_f(top, PARAM_f_tail(p)[jj]) << 4;
87
+ #endif
88
+ }
89
+ }
90
+
91
+ // extract from vPv and add
92
+ for(size_t k=0; k < m_vec_limbs; k ++){
93
+ temp[k] ^= vPv[( i * PARAM_k(p) + j )* m_vec_limbs + k] ^ ((i!=j)*vPv[( j * PARAM_k(p) + i )* m_vec_limbs + k]);
94
+ }
95
+ }
96
+ }
97
+
98
+ // compute y
99
+ for (int i = 0; i < PARAM_m(p); i+=2)
100
+ {
101
+ #ifdef TARGET_BIG_ENDIAN
102
+ y[i] = t[i] ^ (temp_bytes[(((i/2 + 8) / 8) * 8) - 1 - (i/2)%8] & 0xF);
103
+ y[i+1] = t[i+1] ^ (temp_bytes[(((i/2 + 8) / 8) * 8) - 1 - (i/2)%8] >> 4);
104
+ #else
105
+ y[i] = t[i] ^ (temp_bytes[i/2] & 0xF);
106
+ y[i+1] = t[i+1] ^ (temp_bytes[i/2] >> 4);
107
+ #endif
108
+ }
109
+ }
110
+
111
+ static void transpose_16x16_nibbles(uint64_t *M){
112
+ static const uint64_t even_nibbles = 0x0f0f0f0f0f0f0f0f;
113
+ static const uint64_t even_bytes = 0x00ff00ff00ff00ff;
114
+ static const uint64_t even_2bytes = 0x0000ffff0000ffff;
115
+ static const uint64_t even_half = 0x00000000ffffffff;
116
+
117
+ for (size_t i = 0; i < 16; i+=2)
118
+ {
119
+ uint64_t t = ((M[i] >> 4 ) ^ M[i+1]) & even_nibbles;
120
+ M[i ] ^= t << 4;
121
+ M[i+1] ^= t;
122
+ }
123
+
124
+ for (size_t i = 0; i < 16; i+=4)
125
+ {
126
+ uint64_t t0 = ((M[i ] >> 8) ^ M[i+2]) & even_bytes;
127
+ uint64_t t1 = ((M[i+1] >> 8) ^ M[i+3]) & even_bytes;
128
+ M[i ] ^= (t0 << 8);
129
+ M[i+1] ^= (t1 << 8);
130
+ M[i+2] ^= t0;
131
+ M[i+3] ^= t1;
132
+ }
133
+
134
+ for (size_t i = 0; i < 4; i++)
135
+ {
136
+ uint64_t t0 = ((M[i ] >> 16) ^ M[i+ 4]) & even_2bytes;
137
+ uint64_t t1 = ((M[i+8] >> 16) ^ M[i+12]) & even_2bytes;
138
+
139
+ M[i ] ^= t0 << 16;
140
+ M[i+ 8] ^= t1 << 16;
141
+ M[i+ 4] ^= t0;
142
+ M[i+12] ^= t1;
143
+ }
144
+
145
+ for (size_t i = 0; i < 8; i++)
146
+ {
147
+ uint64_t t = ((M[i]>>32) ^ M[i+8]) & even_half;
148
+ M[i ] ^= t << 32;
149
+ M[i+8] ^= t;
150
+ }
151
+ }
152
+
153
+ #define MAYO_M_OVER_8 ((M_MAX + 7) / 8)
154
+ static void compute_A(const mayo_params_t *p, uint64_t *VtL, unsigned char *A_out) {
155
+ #ifndef ENABLE_PARAMS_DYNAMIC
156
+ (void) p;
157
+ #endif
158
+
159
+ int bits_to_shift = 0;
160
+ int words_to_shift = 0;
161
+ const int m_vec_limbs = PARAM_m_vec_limbs(p);
162
+ uint64_t A[(((O_MAX*K_MAX+15)/16)*16)*MAYO_M_OVER_8] = {0};
163
+ size_t A_width = ((PARAM_o(p)*PARAM_k(p) + 15)/16)*16;
164
+ const uint64_t *Mi, *Mj;
165
+
166
+ // zero out tails of m_vecs if neccesary
167
+ if(PARAM_m(p) % 16 != 0){
168
+ uint64_t mask = 1;
169
+ mask <<= (PARAM_m(p) % 16)*4;
170
+ mask -= 1;
171
+ for (int i = 0; i < PARAM_o(p)*PARAM_k(p); i++)
172
+ {
173
+ VtL[i*m_vec_limbs + m_vec_limbs - 1] &= mask;
174
+ }
175
+ }
176
+
177
+ for (int i = 0; i <= PARAM_k(p) - 1; ++i) {
178
+ for (int j = PARAM_k(p) - 1; j >= i; --j) {
179
+ // add the M_i and M_j to A, shifted "down" by l positions
180
+ Mj = VtL + j * m_vec_limbs * PARAM_o(p);
181
+ for (int c = 0; c < PARAM_o(p); c++) {
182
+ for (int k = 0; k < m_vec_limbs; k++)
183
+ {
184
+ A[ PARAM_o(p) * i + c + (k + words_to_shift)*A_width] ^= Mj[k + c*m_vec_limbs] << bits_to_shift;
185
+ if(bits_to_shift > 0){
186
+ A[ PARAM_o(p) * i + c + (k + words_to_shift + 1)*A_width] ^= Mj[k + c*m_vec_limbs] >> (64-bits_to_shift);
187
+ }
188
+ }
189
+ }
190
+
191
+ if (i != j) {
192
+ Mi = VtL + i * m_vec_limbs * PARAM_o(p);
193
+ for (int c = 0; c < PARAM_o(p); c++) {
194
+ for (int k = 0; k < m_vec_limbs; k++)
195
+ {
196
+ A[PARAM_o(p) * j + c + (k + words_to_shift)*A_width] ^= Mi[k + c*m_vec_limbs] << bits_to_shift;
197
+ if(bits_to_shift > 0){
198
+ A[PARAM_o(p) * j + c + (k + words_to_shift + 1)*A_width] ^= Mi[k + c*m_vec_limbs] >> (64-bits_to_shift);
199
+ }
200
+ }
201
+ }
202
+ }
203
+
204
+ bits_to_shift += 4;
205
+ if(bits_to_shift == 64){
206
+ words_to_shift ++;
207
+ bits_to_shift = 0;
208
+ }
209
+ }
210
+ }
211
+
212
+ for (size_t c = 0; c < A_width*((PARAM_m(p) + (PARAM_k(p)+1)*PARAM_k(p)/2 +15)/16) ; c+= 16)
213
+ {
214
+ transpose_16x16_nibbles(A + c);
215
+ }
216
+
217
+ unsigned char tab[F_TAIL_LEN*4] = {0};
218
+ for (size_t i = 0; i < F_TAIL_LEN; i++)
219
+ {
220
+ tab[4*i] = mul_f(PARAM_f_tail(p)[i],1);
221
+ tab[4*i+1] = mul_f(PARAM_f_tail(p)[i],2);
222
+ tab[4*i+2] = mul_f(PARAM_f_tail(p)[i],4);
223
+ tab[4*i+3] = mul_f(PARAM_f_tail(p)[i],8);
224
+ }
225
+
226
+ uint64_t low_bit_in_nibble = 0x1111111111111111;
227
+
228
+ for (size_t c = 0; c < A_width; c+= 16)
229
+ {
230
+ for (int r = PARAM_m(p); r < PARAM_m(p) + (PARAM_k(p)+1)*PARAM_k(p)/2 ; r++)
231
+ {
232
+ size_t pos = (r/16)*A_width + c + (r%16);
233
+ uint64_t t0 = A[pos] & low_bit_in_nibble;
234
+ uint64_t t1 = (A[pos] >> 1) & low_bit_in_nibble;
235
+ uint64_t t2 = (A[pos] >> 2) & low_bit_in_nibble;
236
+ uint64_t t3 = (A[pos] >> 3) & low_bit_in_nibble;
237
+ for (size_t t = 0; t < F_TAIL_LEN; t++)
238
+ {
239
+ A[((r+t-PARAM_m(p))/16)*A_width + c + ((r+t-PARAM_m(p))%16)] ^= t0*tab[4*t+0] ^ t1*tab[4*t+1] ^ t2*tab[4*t+2] ^ t3*tab[4*t+3];
240
+ }
241
+ }
242
+ }
243
+
244
+ #ifdef TARGET_BIG_ENDIAN
245
+ for (int i = 0; i < (((PARAM_o(p)*PARAM_k(p)+15)/16)*16)*MAYO_M_OVER_8; ++i)
246
+ A[i] = BSWAP64(A[i]);
247
+ #endif
248
+
249
+
250
+ for (int r = 0; r < PARAM_m(p); r+=16)
251
+ {
252
+ for (int c = 0; c < PARAM_A_cols(p)-1 ; c+=16)
253
+ {
254
+ for (int i = 0; i + r < PARAM_m(p); i++)
255
+ {
256
+ decode( (unsigned char *) &A[r*A_width/16 + c + i], A_out + PARAM_A_cols(p)*(r+i) + c, MAYO_MIN(16, PARAM_A_cols(p)-1-c));
257
+ }
258
+ }
259
+ }
260
+ }
261
+
262
+ static void unpack_m_vecs(const unsigned char *in, uint64_t *out, int vecs, int m){
263
+ const int m_vec_limbs = (m + 15) / 16;
264
+ unsigned char *_out = (unsigned char *) out;
265
+ uint64_t tmp[ (M_MAX + 15) / 16] = {0};
266
+ for (int i = vecs-1; i >= 0; i--)
267
+ {
268
+ memcpy(tmp, in + i*m/2, m/2);
269
+ memcpy(_out + i*m_vec_limbs*sizeof(uint64_t), tmp, m_vec_limbs*sizeof(uint64_t));
270
+ }
271
+ }
272
+ static void pack_m_vecs(const uint64_t *in, unsigned char *out, int vecs, int m){
273
+ const int m_vec_limbs = (m + 15) / 16;
274
+ unsigned char *_in = (unsigned char *) in;
275
+ for (int i = 0; i < vecs; i++)
276
+ {
277
+ memmove(out + (i*m/2), _in + i*m_vec_limbs*sizeof(uint64_t), m/2);
278
+ }
279
+ }
280
+ static void expand_P1_P2(const mayo_params_t *p, uint64_t *P, const unsigned char *seed_pk) {
281
+ #ifndef ENABLE_PARAMS_DYNAMIC
282
+ (void) p;
283
+ #endif
284
+ PK_PRF((unsigned char *)P, PARAM_P1_bytes(p) + PARAM_P2_bytes(p), seed_pk, PARAM_pk_seed_bytes(p));
285
+ unpack_m_vecs((unsigned char *)P, P, (PARAM_P1_limbs(p) + PARAM_P2_limbs(p))/PARAM_m_vec_limbs(p), PARAM_m(p));
286
+ }
287
+
288
+ static void eval_public_map(const mayo_params_t *p, const unsigned char *s, const uint64_t *P1, const uint64_t *P2, const uint64_t *P3, unsigned char *eval){
289
+ uint64_t SPS[K_MAX * K_MAX * M_VEC_LIMBS_MAX] = {0};
290
+ // combine computing PS and SPS in a single step
291
+ m_calculate_PS_SPS(p, P1, P2, P3, s, SPS);
292
+ unsigned char zero[M_MAX] = {0};
293
+ compute_rhs(p, SPS, zero, eval);
294
+ }
295
+
296
+ // Public API
297
+
298
+ int mayo_keypair(const mayo_params_t *p, unsigned char *pk, unsigned char *sk) {
299
+ int ret = 0;
300
+
301
+ ret = mayo_keypair_compact(p, pk, sk);
302
+ if (ret != MAYO_OK) {
303
+ goto err;
304
+ }
305
+
306
+ err:
307
+ return ret;
308
+ }
309
+
310
+ int mayo_expand_sk(const mayo_params_t *p, const unsigned char *csk,
311
+ sk_t *sk) {
312
+ int ret = MAYO_OK;
313
+ unsigned char S[PK_SEED_BYTES_MAX + O_BYTES_MAX];
314
+ uint64_t *P = sk->p;
315
+ unsigned char *O = sk->O;
316
+
317
+ const int param_o = PARAM_o(p);
318
+ const int param_v = PARAM_v(p);
319
+ const int param_O_bytes = PARAM_O_bytes(p);
320
+ const int param_pk_seed_bytes = PARAM_pk_seed_bytes(p);
321
+ const int param_sk_seed_bytes = PARAM_sk_seed_bytes(p);
322
+
323
+ const unsigned char *seed_sk = csk;
324
+ unsigned char *seed_pk = S;
325
+
326
+ shake256(S, param_pk_seed_bytes + param_O_bytes, seed_sk,
327
+ param_sk_seed_bytes);
328
+ decode(S + param_pk_seed_bytes, O, param_v * param_o);
329
+
330
+ #ifdef ENABLE_CT_TESTING
331
+ VALGRIND_MAKE_MEM_DEFINED(seed_pk, param_pk_seed_bytes);
332
+ #endif
333
+
334
+ expand_P1_P2(p, P, seed_pk);
335
+ #ifdef TARGET_BIG_ENDIAN
336
+ for (int i = 0; i < PARAM_P1_limbs(p) + PARAM_P2_limbs(p); ++i) {
337
+ P[i] = BSWAP64(P[i]);
338
+ }
339
+ #endif
340
+
341
+ uint64_t *P2 = P + PARAM_P1_limbs(p);
342
+
343
+ uint64_t *P1 = P;
344
+
345
+ // compute L_i = (P1 + P1^t)*O + P2
346
+ uint64_t *L = P2;
347
+ P1P1t_times_O(p, P1, O, L);
348
+
349
+ #ifdef TARGET_BIG_ENDIAN
350
+ for (int i = 0; i < PARAM_P1_limbs(p) + PARAM_P2_limbs(p); ++i) {
351
+ P[i] = BSWAP64(P[i]);
352
+ }
353
+ #endif
354
+
355
+ mayo_secure_clear(S, PK_SEED_BYTES_MAX + O_BYTES_MAX);
356
+ return ret;
357
+ }
358
+
359
+ int mayo_sign_signature(const mayo_params_t *p, unsigned char *sig,
360
+ size_t *siglen, const unsigned char *m,
361
+ size_t mlen, const unsigned char *csk) {
362
+ int ret = MAYO_OK;
363
+ unsigned char tenc[M_BYTES_MAX], t[M_MAX]; // no secret data
364
+ unsigned char y[M_MAX]; // secret data
365
+ unsigned char salt[SALT_BYTES_MAX]; // not secret data
366
+ unsigned char V[K_MAX * V_BYTES_MAX + R_BYTES_MAX], Vdec[V_MAX * K_MAX]; // secret data
367
+ unsigned char A[((M_MAX+7)/8*8) * (K_MAX * O_MAX + 1)] = { 0 }; // secret data
368
+ unsigned char x[K_MAX * N_MAX]; // not secret data
369
+ unsigned char r[K_MAX * O_MAX + 1] = { 0 }; // secret data
370
+ unsigned char s[K_MAX * N_MAX]; // not secret data
371
+ const unsigned char *seed_sk;
372
+ alignas(32) sk_t sk; // secret data
373
+ unsigned char Ox[V_MAX]; // secret data
374
+ unsigned char tmp[DIGEST_BYTES_MAX + SALT_BYTES_MAX + SK_SEED_BYTES_MAX + 1];
375
+ unsigned char *ctrbyte;
376
+ unsigned char *vi;
377
+
378
+ const int param_m = PARAM_m(p);
379
+ const int param_n = PARAM_n(p);
380
+ const int param_o = PARAM_o(p);
381
+ const int param_k = PARAM_k(p);
382
+ const int param_v = PARAM_v(p);
383
+ const int param_m_bytes = PARAM_m_bytes(p);
384
+ const int param_v_bytes = PARAM_v_bytes(p);
385
+ const int param_r_bytes = PARAM_r_bytes(p);
386
+ const int param_sig_bytes = PARAM_sig_bytes(p);
387
+ const int param_A_cols = PARAM_A_cols(p);
388
+ const int param_digest_bytes = PARAM_digest_bytes(p);
389
+ const int param_sk_seed_bytes = PARAM_sk_seed_bytes(p);
390
+ const int param_salt_bytes = PARAM_salt_bytes(p);
391
+
392
+ ret = mayo_expand_sk(p, csk, &sk);
393
+ if (ret != MAYO_OK) {
394
+ goto err;
395
+ }
396
+
397
+ seed_sk = csk;
398
+
399
+
400
+ // hash message
401
+ shake256(tmp, param_digest_bytes, m, mlen);
402
+
403
+ uint64_t *P1 = sk.p;
404
+ uint64_t *L = P1 + PARAM_P1_limbs(p);
405
+ uint64_t Mtmp[K_MAX * O_MAX * M_VEC_LIMBS_MAX] = {0};
406
+
407
+ #ifdef TARGET_BIG_ENDIAN
408
+ for (int i = 0; i < PARAM_P1_limbs(p); ++i) {
409
+ P1[i] = BSWAP64(P1[i]);
410
+ }
411
+ for (int i = 0; i < PARAM_P2_limbs(p); ++i) {
412
+ L[i] = BSWAP64(L[i]);
413
+ }
414
+ #endif
415
+
416
+ // choose the randomizer
417
+ #if defined(PQM4) || defined(HAVE_RANDOMBYTES_NORETVAL)
418
+ randombytes(tmp + param_digest_bytes, param_salt_bytes);
419
+ #else
420
+ if (randombytes(tmp + param_digest_bytes, param_salt_bytes) != MAYO_OK) {
421
+ ret = MAYO_ERR;
422
+ goto err;
423
+ }
424
+ #endif
425
+
426
+ // hashing to salt
427
+ memcpy(tmp + param_digest_bytes + param_salt_bytes, seed_sk,
428
+ param_sk_seed_bytes);
429
+ shake256(salt, param_salt_bytes, tmp,
430
+ param_digest_bytes + param_salt_bytes + param_sk_seed_bytes);
431
+
432
+ #ifdef ENABLE_CT_TESTING
433
+ VALGRIND_MAKE_MEM_DEFINED(salt, SALT_BYTES_MAX); // Salt is not secret
434
+ #endif
435
+
436
+ // hashing to t
437
+ memcpy(tmp + param_digest_bytes, salt, param_salt_bytes);
438
+ ctrbyte = tmp + param_digest_bytes + param_salt_bytes + param_sk_seed_bytes;
439
+
440
+ shake256(tenc, param_m_bytes, tmp, param_digest_bytes + param_salt_bytes);
441
+
442
+ decode(tenc, t, param_m); // may not be necessary
443
+
444
+ for (int ctr = 0; ctr <= 255; ++ctr) {
445
+ *ctrbyte = (unsigned char)ctr;
446
+
447
+ shake256(V, param_k * param_v_bytes + param_r_bytes, tmp,
448
+ param_digest_bytes + param_salt_bytes + param_sk_seed_bytes + 1);
449
+
450
+ // decode the v_i vectors
451
+ for (int i = 0; i <= param_k - 1; ++i) {
452
+ decode(V + i * param_v_bytes, Vdec + i * param_v, param_v);
453
+ }
454
+
455
+ // compute M_i matrices and all v_i*P1*v_j
456
+ compute_M_and_VPV(p, Vdec, L, P1, Mtmp, (uint64_t*) A);
457
+
458
+ compute_rhs(p, (uint64_t*) A, t, y);
459
+ compute_A(p, Mtmp, A);
460
+
461
+ for (int i = 0; i < param_m; i++)
462
+ {
463
+ A[(1+i)*(param_k*param_o + 1) - 1] = 0;
464
+ }
465
+
466
+ decode(V + param_k * param_v_bytes, r,
467
+ param_k *
468
+ param_o);
469
+
470
+ if (sample_solution(p, A, y, r, x, param_k, param_o, param_m, param_A_cols)) {
471
+ break;
472
+ } else {
473
+ memset(Mtmp, 0, sizeof(Mtmp));
474
+ memset(A, 0, sizeof(A));
475
+ }
476
+ }
477
+
478
+ for (int i = 0; i <= param_k - 1; ++i) {
479
+ vi = Vdec + i * (param_n - param_o);
480
+ mat_mul(sk.O, x + i * param_o, Ox, param_o, param_n - param_o, 1);
481
+ mat_add(vi, Ox, s + i * param_n, param_n - param_o, 1);
482
+ memcpy(s + i * param_n + (param_n - param_o), x + i * param_o, param_o);
483
+ }
484
+ encode(s, sig, param_n * param_k);
485
+
486
+ memcpy(sig + param_sig_bytes - param_salt_bytes, salt, param_salt_bytes);
487
+ *siglen = param_sig_bytes;
488
+
489
+ err:
490
+ mayo_secure_clear(V, sizeof(V));
491
+ mayo_secure_clear(Vdec, sizeof(Vdec));
492
+ mayo_secure_clear(A, sizeof(A));
493
+ mayo_secure_clear(r, sizeof(r));
494
+ mayo_secure_clear(sk.O, sizeof(sk.O));
495
+ mayo_secure_clear(&sk, sizeof(sk_t));
496
+ mayo_secure_clear(Ox, sizeof(Ox));
497
+ mayo_secure_clear(tmp, sizeof(tmp));
498
+ mayo_secure_clear(Mtmp, sizeof(Mtmp));
499
+ return ret;
500
+ }
501
+
502
+ int mayo_sign(const mayo_params_t *p, unsigned char *sm,
503
+ size_t *smlen, const unsigned char *m,
504
+ size_t mlen, const unsigned char *csk) {
505
+ int ret = MAYO_OK;
506
+ const int param_sig_bytes = PARAM_sig_bytes(p);
507
+ size_t siglen;
508
+ memmove(sm + param_sig_bytes, m, mlen);
509
+ ret = mayo_sign_signature(p, sm, &siglen, sm + param_sig_bytes, mlen, csk);
510
+ if (ret != MAYO_OK || siglen != (size_t) param_sig_bytes){
511
+ memset(sm, 0, siglen + mlen);
512
+ goto err;
513
+ }
514
+
515
+ *smlen = siglen + mlen;
516
+ err:
517
+ return ret;
518
+ }
519
+
520
+ int mayo_open(const mayo_params_t *p, unsigned char *m,
521
+ size_t *mlen, const unsigned char *sm,
522
+ size_t smlen, const unsigned char *pk) {
523
+ const int param_sig_bytes = PARAM_sig_bytes(p);
524
+ if (smlen < (size_t)param_sig_bytes) {
525
+ return MAYO_ERR;
526
+ }
527
+ int result = mayo_verify(p, sm + param_sig_bytes, smlen - param_sig_bytes, sm,
528
+ pk);
529
+
530
+ if (result == MAYO_OK) {
531
+ *mlen = smlen - param_sig_bytes;
532
+ memmove(m, sm + param_sig_bytes, *mlen);
533
+ }
534
+
535
+ return result;
536
+ }
537
+
538
+ int mayo_keypair_compact(const mayo_params_t *p, unsigned char *cpk,
539
+ unsigned char *csk) {
540
+ int ret = MAYO_OK;
541
+ unsigned char *seed_sk = csk;
542
+ unsigned char S[PK_SEED_BYTES_MAX + O_BYTES_MAX];
543
+ uint64_t P[P1_LIMBS_MAX + P2_LIMBS_MAX];
544
+ uint64_t P3[O_MAX*O_MAX*M_VEC_LIMBS_MAX] = {0};
545
+
546
+ unsigned char *seed_pk;
547
+ unsigned char O[(V_MAX)*O_MAX];
548
+
549
+ const int m_vec_limbs = PARAM_m_vec_limbs(p);
550
+ const int param_m = PARAM_m(p);
551
+ const int param_v = PARAM_v(p);
552
+ const int param_o = PARAM_o(p);
553
+ const int param_O_bytes = PARAM_O_bytes(p);
554
+ const int param_P1_limbs = PARAM_P1_limbs(p);
555
+ const int param_P3_limbs = PARAM_P3_limbs(p);
556
+ const int param_pk_seed_bytes = PARAM_pk_seed_bytes(p);
557
+ const int param_sk_seed_bytes = PARAM_sk_seed_bytes(p);
558
+
559
+ uint64_t *P1 = P;
560
+ uint64_t *P2 = P + param_P1_limbs;
561
+
562
+ // seed_sk $←- B^(sk_seed bytes)
563
+ #if defined(PQM4) || defined(HAVE_RANDOMBYTES_NORETVAL)
564
+ randombytes(seed_sk, param_sk_seed_bytes);
565
+ #else
566
+ if (randombytes(seed_sk, param_sk_seed_bytes) != MAYO_OK) {
567
+ ret = MAYO_ERR;
568
+ goto err;
569
+ }
570
+ #endif
571
+
572
+ // S ← shake256(seedsk, pk seed bytes + O bytes)
573
+ shake256(S, param_pk_seed_bytes + param_O_bytes, seed_sk,
574
+ param_sk_seed_bytes);
575
+ // seed_pk ← s[0 : pk_seed_bytes]
576
+ seed_pk = S;
577
+
578
+ // o ← Decode_o(s[pk_seed_bytes : pk_seed_bytes + o_bytes])
579
+ decode(S + param_pk_seed_bytes, O, param_v * param_o);
580
+
581
+ #ifdef ENABLE_CT_TESTING
582
+ VALGRIND_MAKE_MEM_DEFINED(seed_pk, param_pk_seed_bytes);
583
+ #endif
584
+
585
+ expand_P1_P2(p, P, seed_pk);
586
+
587
+ // compute P3 (modifies P2 in the process)
588
+ compute_P3(p, P1, P2, O, P3);
589
+
590
+ // store seed_pk in cpk
591
+ memcpy(cpk, seed_pk, param_pk_seed_bytes);
592
+
593
+ uint64_t P3_upper[P3_LIMBS_MAX];
594
+
595
+ // compute Upper(P3) and store in cpk
596
+ m_upper(p, P3, P3_upper, param_o);
597
+ pack_m_vecs(P3_upper, cpk + param_pk_seed_bytes, param_P3_limbs/m_vec_limbs, param_m);
598
+
599
+ #if !defined(PQM4) && !defined(HAVE_RANDOMBYTES_NORETVAL)
600
+ err:
601
+ #endif
602
+ mayo_secure_clear(O, sizeof(O));
603
+ mayo_secure_clear(P2, PARAM_P2_limbs(p)*sizeof(uint64_t));
604
+ mayo_secure_clear(P3, sizeof(P3));
605
+ return ret;
606
+ }
607
+
608
+ int mayo_expand_pk(const mayo_params_t *p, const unsigned char *cpk,
609
+ uint64_t *pk) {
610
+ expand_P1_P2(p, pk, cpk);
611
+
612
+ unpack_m_vecs(cpk + PARAM_pk_seed_bytes(p), pk + PARAM_P1_limbs(p) + PARAM_P2_limbs(p), PARAM_P3_limbs(p)/PARAM_m_vec_limbs(p), PARAM_m(p));
613
+
614
+ return MAYO_OK;
615
+ }
616
+
617
+ int mayo_verify(const mayo_params_t *p, const unsigned char *m,
618
+ size_t mlen, const unsigned char *sig,
619
+ const unsigned char *cpk) {
620
+ unsigned char tEnc[M_BYTES_MAX];
621
+ unsigned char t[M_MAX];
622
+ unsigned char y[2 * M_MAX] = {0}; // extra space for reduction mod f(X)
623
+ unsigned char s[K_MAX * N_MAX];
624
+ uint64_t pk[P1_LIMBS_MAX + P2_LIMBS_MAX + P3_LIMBS_MAX] = {0};
625
+ unsigned char tmp[DIGEST_BYTES_MAX + SALT_BYTES_MAX];
626
+
627
+ const int param_m = PARAM_m(p);
628
+ const int param_n = PARAM_n(p);
629
+ const int param_k = PARAM_k(p);
630
+ const int param_m_bytes = PARAM_m_bytes(p);
631
+ const int param_sig_bytes = PARAM_sig_bytes(p);
632
+ const int param_digest_bytes = PARAM_digest_bytes(p);
633
+ const int param_salt_bytes = PARAM_salt_bytes(p);
634
+
635
+ int ret = mayo_expand_pk(p, cpk, pk);
636
+ if (ret != MAYO_OK) {
637
+ return MAYO_ERR;
638
+ }
639
+
640
+ uint64_t *P1 = pk;
641
+ uint64_t *P2 = P1 + PARAM_P1_limbs(p);
642
+ uint64_t *P3 = P2 + PARAM_P2_limbs(p);
643
+
644
+ #ifdef TARGET_BIG_ENDIAN
645
+ for (int i = 0; i < PARAM_P1_limbs(p); ++i) {
646
+ P1[i] = BSWAP64(P1[i]);
647
+ }
648
+ for (int i = 0; i < PARAM_P2_limbs(p); ++i) {
649
+ P2[i] = BSWAP64(P2[i]);
650
+ }
651
+ for (int i = 0; i < PARAM_P3_limbs(p); ++i) {
652
+ P3[i] = BSWAP64(P3[i]);
653
+ }
654
+ #endif
655
+
656
+ // hash m
657
+ shake256(tmp, param_digest_bytes, m, mlen);
658
+
659
+ // compute t
660
+ memcpy(tmp + param_digest_bytes, sig + param_sig_bytes - param_salt_bytes,
661
+ param_salt_bytes);
662
+ shake256(tEnc, param_m_bytes, tmp, param_digest_bytes + param_salt_bytes);
663
+ decode(tEnc, t, param_m);
664
+
665
+ // decode s
666
+ decode(sig, s, param_k * param_n);
667
+
668
+ eval_public_map(p, s, P1, P2, P3, y);
669
+
670
+ if (memcmp(y, t, param_m) == 0) {
671
+ return MAYO_OK; // good signature
672
+ }
673
+ return MAYO_ERR; // bad signature
674
+ }
675
+