1 #include "api.h"
2 #include "inner.h"
3 #include "randombytes.h"
4 #include <stddef.h>
5 #include <string.h>
6 /*
7 * Wrapper for implementing the PQClean API.
8 */
9
10
11
12 #define NONCELEN 40
13 #define SEEDLEN 48
14
15 /*
16 * Encoding formats (nnnn = log of degree, 9 for Falcon-512, 10 for Falcon-1024)
17 *
18 * private key:
19 * header byte: 0101nnnn
20 * private f (6 or 5 bits by element, depending on degree)
21 * private g (6 or 5 bits by element, depending on degree)
22 * private F (8 bits by element)
23 *
24 * public key:
25 * header byte: 0000nnnn
26 * public h (14 bits by element)
27 *
28 * signature:
29 * header byte: 0011nnnn
30 * nonce 40 bytes
31 * value (12 bits by element)
32 *
33 * message + signature:
34 * signature length (2 bytes, big-endian)
35 * nonce 40 bytes
36 * message
37 * header byte: 0010nnnn
38 * value (12 bits by element)
39 * (signature length is 1+len(value), not counting the nonce)
40 */
41
42 /* see api.h */
43 int
PQCLEAN_FALCON512_AVX2_crypto_sign_keypair(unsigned char * pk,unsigned char * sk)44 PQCLEAN_FALCON512_AVX2_crypto_sign_keypair(unsigned char *pk, unsigned char *sk) {
45 union {
46 uint8_t b[FALCON_KEYGEN_TEMP_9];
47 uint64_t dummy_u64;
48 fpr dummy_fpr;
49 } tmp;
50 int8_t f[512], g[512], F[512];
51 uint16_t h[512];
52 unsigned char seed[SEEDLEN];
53 inner_shake256_context rng;
54 size_t u, v;
55
56 /*
57 * Generate key pair.
58 */
59 randombytes(seed, sizeof seed);
60 inner_shake256_init(&rng);
61 inner_shake256_inject(&rng, seed, sizeof seed);
62 inner_shake256_flip(&rng);
63 PQCLEAN_FALCON512_AVX2_keygen(&rng, f, g, F, NULL, h, 9, tmp.b);
64 inner_shake256_ctx_release(&rng);
65
66 /*
67 * Encode private key.
68 */
69 sk[0] = 0x50 + 9;
70 u = 1;
71 v = PQCLEAN_FALCON512_AVX2_trim_i8_encode(
72 sk + u, PQCLEAN_FALCON512_AVX2_CRYPTO_SECRETKEYBYTES - u,
73 f, 9, PQCLEAN_FALCON512_AVX2_max_fg_bits[9]);
74 if (v == 0) {
75 return -1;
76 }
77 u += v;
78 v = PQCLEAN_FALCON512_AVX2_trim_i8_encode(
79 sk + u, PQCLEAN_FALCON512_AVX2_CRYPTO_SECRETKEYBYTES - u,
80 g, 9, PQCLEAN_FALCON512_AVX2_max_fg_bits[9]);
81 if (v == 0) {
82 return -1;
83 }
84 u += v;
85 v = PQCLEAN_FALCON512_AVX2_trim_i8_encode(
86 sk + u, PQCLEAN_FALCON512_AVX2_CRYPTO_SECRETKEYBYTES - u,
87 F, 9, PQCLEAN_FALCON512_AVX2_max_FG_bits[9]);
88 if (v == 0) {
89 return -1;
90 }
91 u += v;
92 if (u != PQCLEAN_FALCON512_AVX2_CRYPTO_SECRETKEYBYTES) {
93 return -1;
94 }
95
96 /*
97 * Encode public key.
98 */
99 pk[0] = 0x00 + 9;
100 v = PQCLEAN_FALCON512_AVX2_modq_encode(
101 pk + 1, PQCLEAN_FALCON512_AVX2_CRYPTO_PUBLICKEYBYTES - 1,
102 h, 9);
103 if (v != PQCLEAN_FALCON512_AVX2_CRYPTO_PUBLICKEYBYTES - 1) {
104 return -1;
105 }
106
107 return 0;
108 }
109
110 /*
111 * Compute the signature. nonce[] receives the nonce and must have length
112 * NONCELEN bytes. sigbuf[] receives the signature value (without nonce
113 * or header byte), with *sigbuflen providing the maximum value length and
114 * receiving the actual value length.
115 *
116 * If a signature could be computed but not encoded because it would
117 * exceed the output buffer size, then a new signature is computed. If
118 * the provided buffer size is too low, this could loop indefinitely, so
119 * the caller must provide a size that can accommodate signatures with a
120 * large enough probability.
121 *
122 * Return value: 0 on success, -1 on error.
123 */
124 static int
do_sign(uint8_t * nonce,uint8_t * sigbuf,size_t * sigbuflen,const uint8_t * m,size_t mlen,const uint8_t * sk)125 do_sign(uint8_t *nonce, uint8_t *sigbuf, size_t *sigbuflen,
126 const uint8_t *m, size_t mlen, const uint8_t *sk) {
127 union {
128 uint8_t b[72 * 512];
129 uint64_t dummy_u64;
130 fpr dummy_fpr;
131 } tmp;
132 int8_t f[512], g[512], F[512], G[512];
133 union {
134 int16_t sig[512];
135 uint16_t hm[512];
136 } r;
137 unsigned char seed[SEEDLEN];
138 inner_shake256_context sc;
139 size_t u, v;
140
141 /*
142 * Decode the private key.
143 */
144 if (sk[0] != 0x50 + 9) {
145 return -1;
146 }
147 u = 1;
148 v = PQCLEAN_FALCON512_AVX2_trim_i8_decode(
149 f, 9, PQCLEAN_FALCON512_AVX2_max_fg_bits[9],
150 sk + u, PQCLEAN_FALCON512_AVX2_CRYPTO_SECRETKEYBYTES - u);
151 if (v == 0) {
152 return -1;
153 }
154 u += v;
155 v = PQCLEAN_FALCON512_AVX2_trim_i8_decode(
156 g, 9, PQCLEAN_FALCON512_AVX2_max_fg_bits[9],
157 sk + u, PQCLEAN_FALCON512_AVX2_CRYPTO_SECRETKEYBYTES - u);
158 if (v == 0) {
159 return -1;
160 }
161 u += v;
162 v = PQCLEAN_FALCON512_AVX2_trim_i8_decode(
163 F, 9, PQCLEAN_FALCON512_AVX2_max_FG_bits[9],
164 sk + u, PQCLEAN_FALCON512_AVX2_CRYPTO_SECRETKEYBYTES - u);
165 if (v == 0) {
166 return -1;
167 }
168 u += v;
169 if (u != PQCLEAN_FALCON512_AVX2_CRYPTO_SECRETKEYBYTES) {
170 return -1;
171 }
172 if (!PQCLEAN_FALCON512_AVX2_complete_private(G, f, g, F, 9, tmp.b)) {
173 return -1;
174 }
175
176 /*
177 * Create a random nonce (40 bytes).
178 */
179 randombytes(nonce, NONCELEN);
180
181 /*
182 * Hash message nonce + message into a vector.
183 */
184 inner_shake256_init(&sc);
185 inner_shake256_inject(&sc, nonce, NONCELEN);
186 inner_shake256_inject(&sc, m, mlen);
187 inner_shake256_flip(&sc);
188 PQCLEAN_FALCON512_AVX2_hash_to_point_ct(&sc, r.hm, 9, tmp.b);
189 inner_shake256_ctx_release(&sc);
190
191 /*
192 * Initialize a RNG.
193 */
194 randombytes(seed, sizeof seed);
195 inner_shake256_init(&sc);
196 inner_shake256_inject(&sc, seed, sizeof seed);
197 inner_shake256_flip(&sc);
198
199 /*
200 * Compute and return the signature. This loops until a signature
201 * value is found that fits in the provided buffer.
202 */
203 for (;;) {
204 PQCLEAN_FALCON512_AVX2_sign_dyn(r.sig, &sc, f, g, F, G, r.hm, 9, tmp.b);
205 v = PQCLEAN_FALCON512_AVX2_comp_encode(sigbuf, *sigbuflen, r.sig, 9);
206 if (v != 0) {
207 inner_shake256_ctx_release(&sc);
208 *sigbuflen = v;
209 return 0;
210 }
211 }
212 }
213
214 /*
215 * Verify a sigature. The nonce has size NONCELEN bytes. sigbuf[]
216 * (of size sigbuflen) contains the signature value, not including the
217 * header byte or nonce. Return value is 0 on success, -1 on error.
218 */
219 static int
do_verify(const uint8_t * nonce,const uint8_t * sigbuf,size_t sigbuflen,const uint8_t * m,size_t mlen,const uint8_t * pk)220 do_verify(
221 const uint8_t *nonce, const uint8_t *sigbuf, size_t sigbuflen,
222 const uint8_t *m, size_t mlen, const uint8_t *pk) {
223 union {
224 uint8_t b[2 * 512];
225 uint64_t dummy_u64;
226 fpr dummy_fpr;
227 } tmp;
228 uint16_t h[512], hm[512];
229 int16_t sig[512];
230 inner_shake256_context sc;
231
232 /*
233 * Decode public key.
234 */
235 if (pk[0] != 0x00 + 9) {
236 return -1;
237 }
238 if (PQCLEAN_FALCON512_AVX2_modq_decode(h, 9,
239 pk + 1, PQCLEAN_FALCON512_AVX2_CRYPTO_PUBLICKEYBYTES - 1)
240 != PQCLEAN_FALCON512_AVX2_CRYPTO_PUBLICKEYBYTES - 1) {
241 return -1;
242 }
243 PQCLEAN_FALCON512_AVX2_to_ntt_monty(h, 9);
244
245 /*
246 * Decode signature.
247 */
248 if (sigbuflen == 0) {
249 return -1;
250 }
251 if (PQCLEAN_FALCON512_AVX2_comp_decode(sig, 9, sigbuf, sigbuflen) != sigbuflen) {
252 return -1;
253 }
254
255 /*
256 * Hash nonce + message into a vector.
257 */
258 inner_shake256_init(&sc);
259 inner_shake256_inject(&sc, nonce, NONCELEN);
260 inner_shake256_inject(&sc, m, mlen);
261 inner_shake256_flip(&sc);
262 PQCLEAN_FALCON512_AVX2_hash_to_point_ct(&sc, hm, 9, tmp.b);
263 inner_shake256_ctx_release(&sc);
264
265 /*
266 * Verify signature.
267 */
268 if (!PQCLEAN_FALCON512_AVX2_verify_raw(hm, sig, h, 9, tmp.b)) {
269 return -1;
270 }
271 return 0;
272 }
273
274 /* see api.h */
275 int
PQCLEAN_FALCON512_AVX2_crypto_sign_signature(uint8_t * sig,size_t * siglen,const uint8_t * m,size_t mlen,const uint8_t * sk)276 PQCLEAN_FALCON512_AVX2_crypto_sign_signature(
277 uint8_t *sig, size_t *siglen,
278 const uint8_t *m, size_t mlen, const uint8_t *sk) {
279 /*
280 * The PQCLEAN_FALCON512_AVX2_CRYPTO_BYTES constant is used for
281 * the signed message object (as produced by PQCLEAN_FALCON512_AVX2_crypto_sign())
282 * and includes a two-byte length value, so we take care here
283 * to only generate signatures that are two bytes shorter than
284 * the maximum. This is done to ensure that PQCLEAN_FALCON512_AVX2_crypto_sign()
285 * and PQCLEAN_FALCON512_AVX2_crypto_sign_signature() produce the exact same signature
286 * value, if used on the same message, with the same private key,
287 * and using the same output from randombytes() (this is for
288 * reproducibility of tests).
289 */
290 size_t vlen;
291
292 vlen = PQCLEAN_FALCON512_AVX2_CRYPTO_BYTES - NONCELEN - 3;
293 if (do_sign(sig + 1, sig + 1 + NONCELEN, &vlen, m, mlen, sk) < 0) {
294 return -1;
295 }
296 sig[0] = 0x30 + 9;
297 *siglen = 1 + NONCELEN + vlen;
298 return 0;
299 }
300
301 /* see api.h */
302 int
PQCLEAN_FALCON512_AVX2_crypto_sign_verify(const uint8_t * sig,size_t siglen,const uint8_t * m,size_t mlen,const uint8_t * pk)303 PQCLEAN_FALCON512_AVX2_crypto_sign_verify(
304 const uint8_t *sig, size_t siglen,
305 const uint8_t *m, size_t mlen, const uint8_t *pk) {
306 if (siglen < 1 + NONCELEN) {
307 return -1;
308 }
309 if (sig[0] != 0x30 + 9) {
310 return -1;
311 }
312 return do_verify(sig + 1,
313 sig + 1 + NONCELEN, siglen - 1 - NONCELEN, m, mlen, pk);
314 }
315
316 /* see api.h */
317 int
PQCLEAN_FALCON512_AVX2_crypto_sign(uint8_t * sm,size_t * smlen,const uint8_t * m,size_t mlen,const uint8_t * sk)318 PQCLEAN_FALCON512_AVX2_crypto_sign(
319 uint8_t *sm, size_t *smlen,
320 const uint8_t *m, size_t mlen, const uint8_t *sk) {
321 uint8_t *pm, *sigbuf;
322 size_t sigbuflen;
323
324 /*
325 * Move the message to its final location; this is a memmove() so
326 * it handles overlaps properly.
327 */
328 memmove(sm + 2 + NONCELEN, m, mlen);
329 pm = sm + 2 + NONCELEN;
330 sigbuf = pm + 1 + mlen;
331 sigbuflen = PQCLEAN_FALCON512_AVX2_CRYPTO_BYTES - NONCELEN - 3;
332 if (do_sign(sm + 2, sigbuf, &sigbuflen, pm, mlen, sk) < 0) {
333 return -1;
334 }
335 pm[mlen] = 0x20 + 9;
336 sigbuflen ++;
337 sm[0] = (uint8_t)(sigbuflen >> 8);
338 sm[1] = (uint8_t)sigbuflen;
339 *smlen = mlen + 2 + NONCELEN + sigbuflen;
340 return 0;
341 }
342
343 /* see api.h */
344 int
PQCLEAN_FALCON512_AVX2_crypto_sign_open(uint8_t * m,size_t * mlen,const uint8_t * sm,size_t smlen,const uint8_t * pk)345 PQCLEAN_FALCON512_AVX2_crypto_sign_open(
346 uint8_t *m, size_t *mlen,
347 const uint8_t *sm, size_t smlen, const uint8_t *pk) {
348 const uint8_t *sigbuf;
349 size_t pmlen, sigbuflen;
350
351 if (smlen < 3 + NONCELEN) {
352 return -1;
353 }
354 sigbuflen = ((size_t)sm[0] << 8) | (size_t)sm[1];
355 if (sigbuflen < 2 || sigbuflen > (smlen - NONCELEN - 2)) {
356 return -1;
357 }
358 sigbuflen --;
359 pmlen = smlen - NONCELEN - 3 - sigbuflen;
360 if (sm[2 + NONCELEN + pmlen] != 0x20 + 9) {
361 return -1;
362 }
363 sigbuf = sm + 2 + NONCELEN + pmlen + 1;
364
365 /*
366 * The 2-byte length header and the one-byte signature header
367 * have been verified. Nonce is at sm+2, followed by the message
368 * itself. Message length is in pmlen. sigbuf/sigbuflen point to
369 * the signature value (excluding the header byte).
370 */
371 if (do_verify(sm + 2, sigbuf, sigbuflen,
372 sm + 2 + NONCELEN, pmlen, pk) < 0) {
373 return -1;
374 }
375
376 /*
377 * Signature is correct, we just have to copy/move the message
378 * to its final destination. The memmove() properly handles
379 * overlaps.
380 */
381 memmove(m, sm + 2 + NONCELEN, pmlen);
382 *mlen = pmlen;
383 return 0;
384 }
385