@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.
- package/.gitmodules +3 -0
- package/.vscode/launch.json +12 -0
- package/LICENSE +201 -0
- package/bridge/mayo1_bridge.c +26 -0
- package/bridge/mayo2_bridge.c +26 -0
- package/bridge/randombytes_inject.c +44 -0
- package/build_mayo1.ps1 +36 -0
- package/build_mayo2.ps1 +36 -0
- package/dist/mayo.browser.min.js +216 -0
- package/dist/mayo1.js +0 -0
- package/dist/mayo2.js +0 -0
- package/dist/mayo_api.js +139 -0
- package/dist/package.json +1 -0
- package/gitignore +2 -0
- package/index.mjs +1 -0
- package/mayo-c/.astylerc +16 -0
- package/mayo-c/.cmake/flags.cmake +45 -0
- package/mayo-c/.cmake/sanitizers.cmake +81 -0
- package/mayo-c/.cmake/target.cmake +71 -0
- package/mayo-c/.github/workflows/ci_clang.yml +61 -0
- package/mayo-c/.github/workflows/ci_gcc.yml +60 -0
- package/mayo-c/.github/workflows/cmake.yml +160 -0
- package/mayo-c/.github/workflows/macos_m1.yml +68 -0
- package/mayo-c/CMakeLists.txt +35 -0
- package/mayo-c/KAT/PQCsignKAT_24_MAYO_1.req +900 -0
- package/mayo-c/KAT/PQCsignKAT_24_MAYO_1.rsp +902 -0
- package/mayo-c/KAT/PQCsignKAT_24_MAYO_2.req +900 -0
- package/mayo-c/KAT/PQCsignKAT_24_MAYO_2.rsp +902 -0
- package/mayo-c/KAT/PQCsignKAT_32_MAYO_3.req +900 -0
- package/mayo-c/KAT/PQCsignKAT_32_MAYO_3.rsp +902 -0
- package/mayo-c/KAT/PQCsignKAT_40_MAYO_5.req +900 -0
- package/mayo-c/KAT/PQCsignKAT_40_MAYO_5.rsp +902 -0
- package/mayo-c/LICENSE +202 -0
- package/mayo-c/META/MAYO-1_META.yml +52 -0
- package/mayo-c/META/MAYO-2_META.yml +52 -0
- package/mayo-c/META/MAYO-3_META.yml +52 -0
- package/mayo-c/META/MAYO-5_META.yml +52 -0
- package/mayo-c/NOTICE +13 -0
- package/mayo-c/README.md +183 -0
- package/mayo-c/apps/CMakeLists.txt +31 -0
- package/mayo-c/apps/PQCgenKAT_sign.c +281 -0
- package/mayo-c/apps/example.c +151 -0
- package/mayo-c/apps/example_nistapi.c +124 -0
- package/mayo-c/include/mayo.h +442 -0
- package/mayo-c/include/mem.h +25 -0
- package/mayo-c/include/randombytes.h +31 -0
- package/mayo-c/scripts/contstants.py +141 -0
- package/mayo-c/scripts/find_irred_poly.sage +39 -0
- package/mayo-c/src/AVX2/arithmetic_common.h +159 -0
- package/mayo-c/src/AVX2/echelon_form.h +91 -0
- package/mayo-c/src/AVX2/echelon_form_loop.h +58 -0
- package/mayo-c/src/AVX2/shuffle_arithmetic.h +442 -0
- package/mayo-c/src/CMakeLists.txt +98 -0
- package/mayo-c/src/arithmetic.c +128 -0
- package/mayo-c/src/arithmetic.h +124 -0
- package/mayo-c/src/common/aes128ctr.c +293 -0
- package/mayo-c/src/common/aes_c.c +741 -0
- package/mayo-c/src/common/aes_ctr.h +32 -0
- package/mayo-c/src/common/aes_neon.c +201 -0
- package/mayo-c/src/common/debug_bench_tools.h +69 -0
- package/mayo-c/src/common/fips202.c +1093 -0
- package/mayo-c/src/common/fips202.h +12 -0
- package/mayo-c/src/common/mem.c +19 -0
- package/mayo-c/src/common/randombytes_ctrdrbg.c +141 -0
- package/mayo-c/src/common/randombytes_system.c +399 -0
- package/mayo-c/src/generic/arithmetic_dynamic.h +68 -0
- package/mayo-c/src/generic/arithmetic_fixed.h +84 -0
- package/mayo-c/src/generic/echelon_form.h +152 -0
- package/mayo-c/src/generic/ef_inner_loop.h +56 -0
- package/mayo-c/src/generic/generic_arithmetic.h +294 -0
- package/mayo-c/src/mayo.c +675 -0
- package/mayo-c/src/mayo_1/api.c +46 -0
- package/mayo-c/src/mayo_1/api.h +43 -0
- package/mayo-c/src/mayo_2/api.c +46 -0
- package/mayo-c/src/mayo_2/api.h +43 -0
- package/mayo-c/src/mayo_3/api.c +46 -0
- package/mayo-c/src/mayo_3/api.h +43 -0
- package/mayo-c/src/mayo_5/api.c +46 -0
- package/mayo-c/src/mayo_5/api.h +43 -0
- package/mayo-c/src/neon/arithmetic_common.h +132 -0
- package/mayo-c/src/neon/echelon_form.h +55 -0
- package/mayo-c/src/neon/echelon_form_loop.h +58 -0
- package/mayo-c/src/neon/shuffle_arithmetic.h +462 -0
- package/mayo-c/src/params.c +42 -0
- package/mayo-c/src/simple_arithmetic.h +138 -0
- package/mayo-c/test/CMakeLists.txt +51 -0
- package/mayo-c/test/bench.c +166 -0
- package/mayo-c/test/m1cycles.c +155 -0
- package/mayo-c/test/m1cycles.h +13 -0
- package/mayo-c/test/test_kat.c +271 -0
- package/mayo-c/test/test_mayo.c +139 -0
- package/mayo-c/test/test_sample_solution.c +75 -0
- package/mayo-c/test/test_various.c +680 -0
- package/package.json +39 -0
- package/publish.bat +22 -0
- package/readme.md +80 -0
- 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
|
+
|