1#![no_std]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4#![allow(clippy::identity_op)]
5#![allow(clippy::excessive_precision)]
6#![allow(clippy::len_zero)]
7#![allow(clippy::needless_borrow)]
8#![allow(clippy::needless_range_loop)]
9#![allow(clippy::needless_return)]
10#![allow(clippy::redundant_field_names)]
11#![allow(clippy::too_many_arguments)]
12
13mod flr;
101mod poly;
102mod sampler;
103
104use core::fmt;
105use tide_fn_dsa_comm::{codec, hash_to_point, hash_to_point_falcon, mq, shake, PRNG};
106use zeroize::{Zeroize, ZeroizeOnDrop};
107
108pub use tide_fn_dsa_comm::{
110 sign_key_size, vrfy_key_size, signature_size,
111 FN_DSA_LOGN_512, FN_DSA_LOGN_1024,
112 SIGN_KEY_SIZE_512, SIGN_KEY_SIZE_1024,
113 VRFY_KEY_SIZE_512, VRFY_KEY_SIZE_1024,
114 SIGNATURE_SIZE_512, SIGNATURE_SIZE_1024,
115 FalconProfile,
116 FALCON_NONCE_LEN,
117 TIDECOIN_LEGACY_FALCON512_SIG_BODY_MAX,
118 HashIdentifier,
119 HASH_ID_RAW,
120 HASH_ID_SHA256,
121 HASH_ID_SHA384,
122 HASH_ID_SHA512,
123 HASH_ID_SHA512_256,
124 HASH_ID_SHA3_256,
125 HASH_ID_SHA3_384,
126 HASH_ID_SHA3_512,
127 HASH_ID_SHAKE128,
128 HASH_ID_SHAKE256,
129 DomainContext,
130 DOMAIN_NONE,
131 CryptoRng, RngCore, RngError,
132};
133
134#[derive(Copy, Clone, Debug, Eq, PartialEq)]
136pub enum SigningKeyError {
137 InvalidVerifyingKeyBufferLen { expected: usize, actual: usize },
139
140 InvalidSignatureBufferLen { expected: usize, actual: usize },
142
143 InvalidSignatureBufferLenAtLeast { min: usize, actual: usize },
145
146 UnsupportedFalconProfileForDegree { profile: FalconProfile, logn: u32 },
148}
149
150impl fmt::Display for SigningKeyError {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 match *self {
153 Self::InvalidVerifyingKeyBufferLen { expected, actual } => write!(
154 f,
155 "invalid verifying key buffer length: expected {expected} bytes, got {actual}"
156 ),
157 Self::InvalidSignatureBufferLen { expected, actual } => write!(
158 f,
159 "invalid signature buffer length: expected {expected} bytes, got {actual}"
160 ),
161 Self::InvalidSignatureBufferLenAtLeast { min, actual } => write!(
162 f,
163 "invalid signature buffer length: expected at least {min} bytes, got {actual}"
164 ),
165 Self::UnsupportedFalconProfileForDegree { profile, logn } => write!(
166 f,
167 "falcon profile {profile} does not support degree parameter logn={logn}"
168 ),
169 }
170 }
171}
172
173pub trait SigningKey: Sized {
183
184 fn decode(sec: &[u8]) -> Option<Self>;
192
193 fn get_logn(&self) -> u32;
198
199 fn to_verifying_key(&self, vrfy_key: &mut [u8])
203 -> Result<(), SigningKeyError>;
204
205 fn sign<T: CryptoRng + RngCore>(&mut self, rng: &mut T,
218 ctx: &DomainContext, id: &HashIdentifier, hv: &[u8], sig: &mut [u8])
219 -> Result<(), SigningKeyError>;
220
221 fn sign_falcon<T: CryptoRng + RngCore>(&mut self, rng: &mut T,
225 profile: FalconProfile, message: &[u8], sig: &mut [u8])
226 -> Result<usize, SigningKeyError>;
227}
228
229macro_rules! sign_key_impl {
230 ($typename:ident, $logn_min:expr_2021, $logn_max:expr_2021) =>
231{
232 #[doc = concat!("Signature generator for degrees (`logn`) ",
233 stringify!($logn_min), " to ", stringify!($logn_max), " only.")]
234 #[derive(Zeroize, ZeroizeOnDrop)]
235 pub struct $typename {
236 f: [i8; 1 << ($logn_max)],
237 g: [i8; 1 << ($logn_max)],
238 F: [i8; 1 << ($logn_max)],
239 G: [i8; 1 << ($logn_max)],
240 vrfy_key: [u8; 1 + (7 << (($logn_max) - 2))],
241 hashed_vrfy_key: [u8; 64],
242 tmp_i16: [i16; 1 << ($logn_max)],
243 tmp_u16: [u16; 2 << ($logn_max)],
244 tmp_flr: [flr::FLR; 9 << ($logn_max)],
245
246 #[cfg(not(feature = "small_context"))]
248 basis: [flr::FLR; 4 << ($logn_max)],
249
250 logn: u32,
251
252 #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
257 use_avx2: bool,
258 }
259
260 impl $typename {
261
262 fn decode_key(&mut self, src: &[u8]) -> Option<u32> {
263 #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
264 if self.use_avx2 {
265 unsafe {
266 return sign_avx2::decode_avx2_inner($logn_min, $logn_max,
267 &mut self.f[..], &mut self.g[..],
268 &mut self.F[..], &mut self.G[..],
269 &mut self.vrfy_key[..], &mut self.hashed_vrfy_key[..],
270 &mut self.tmp_u16[..], src);
271 }
272 }
273
274 decode_inner($logn_min, $logn_max,
275 &mut self.f[..], &mut self.g[..],
276 &mut self.F[..], &mut self.G[..],
277 &mut self.vrfy_key[..], &mut self.hashed_vrfy_key[..],
278 &mut self.tmp_u16[..], src)
279 }
280
281 #[cfg(not(feature = "small_context"))]
282 fn compute_basis(&mut self) {
283 let n = 1usize << self.logn;
284
285 #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
286 if self.use_avx2 {
287 unsafe {
288 sign_avx2::compute_basis_avx2_inner(self.logn,
289 &self.f[..n], &self.g[..n], &self.F[..n], &self.G[..n],
290 &mut self.basis[..(4 * n)]);
291 }
292 return;
293 }
294
295 compute_basis_inner(self.logn,
296 &self.f[..n], &self.g[..n], &self.F[..n], &self.G[..n],
297 &mut self.basis[..(4 * n)]);
298 }
299 }
300
301 impl SigningKey for $typename {
302
303 fn decode(src: &[u8]) -> Option<Self> {
304 let f = [0i8; 1 << ($logn_max)];
305 let g = [0i8; 1 << ($logn_max)];
306 let F = [0i8; 1 << ($logn_max)];
307 let G = [0i8; 1 << ($logn_max)];
308 let vrfy_key = [0u8; 1 + (7 << (($logn_max) - 2))];
309 let hashed_vrfy_key = [0u8; 64];
310 let tmp_i16 = [0i16; 1 << ($logn_max)];
311 let tmp_u16 = [0u16; 2 << ($logn_max)];
312 let tmp_flr = [flr::FLR::ZERO; 9 << ($logn_max)];
313
314 #[cfg(not(feature = "small_context"))]
315 let basis = [flr::FLR::ZERO; 4 << ($logn_max)];
316
317 let mut sk = Self {
318 f, g, F, G, vrfy_key, hashed_vrfy_key,
319 tmp_i16, tmp_u16, tmp_flr,
320 #[cfg(not(feature = "small_context"))]
321 basis,
322 logn: 0,
323 #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
324 use_avx2: tide_fn_dsa_comm::has_avx2(),
325 };
326 sk.logn = sk.decode_key(src)?;
327
328 #[cfg(not(feature = "small_context"))]
329 sk.compute_basis();
330
331 Some(sk)
332 }
333
334 fn get_logn(&self) -> u32 {
335 self.logn
336 }
337
338 fn to_verifying_key(&self, vrfy_key: &mut [u8])
339 -> Result<(), SigningKeyError>
340 {
341 let len = vrfy_key_size(self.logn).unwrap();
342 if vrfy_key.len() != len {
343 return Err(SigningKeyError::InvalidVerifyingKeyBufferLen {
344 expected: len,
345 actual: vrfy_key.len(),
346 });
347 }
348 vrfy_key.copy_from_slice(&self.vrfy_key[..len]);
349 Ok(())
350 }
351
352 fn sign<T: CryptoRng + RngCore>(&mut self, rng: &mut T,
353 ctx: &DomainContext, id: &HashIdentifier, hv: &[u8], sig: &mut [u8])
354 -> Result<(), SigningKeyError>
355 {
356 let n = 1usize << self.logn;
357 let expected_len = signature_size(self.logn).unwrap();
358 if sig.len() != expected_len {
359 return Err(SigningKeyError::InvalidSignatureBufferLen {
360 expected: expected_len,
361 actual: sig.len(),
362 });
363 }
364
365 #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
366 if self.use_avx2 {
367 unsafe {
368 #[cfg(feature = "shake256x4")]
369 sign_avx2::sign_avx2_inner::<T, shake::SHAKE256x4>(
370 self.logn, rng,
371 &self.f[..n], &self.g[..n], &self.F[..n], &self.G[..n],
372 &self.hashed_vrfy_key, ctx, id, hv, sig,
373 #[cfg(not(feature = "small_context"))]
374 &self.basis[..(4 * n)],
375 &mut self.tmp_i16, &mut self.tmp_u16,
376 &mut self.tmp_flr)?;
377
378 #[cfg(not(feature = "shake256x4"))]
379 sign_avx2::sign_avx2_inner::<T, shake::SHAKE256_PRNG>(
380 self.logn, rng,
381 &self.f[..n], &self.g[..n], &self.F[..n], &self.G[..n],
382 &self.hashed_vrfy_key, ctx, id, hv, sig,
383 #[cfg(not(feature = "small_context"))]
384 &self.basis[..(4 * n)],
385 &mut self.tmp_i16, &mut self.tmp_u16,
386 &mut self.tmp_flr)?;
387 }
388 return Ok(());
389 }
390
391 #[cfg(feature = "shake256x4")]
392 sign_inner::<T, shake::SHAKE256x4>(self.logn, rng,
393 &self.f[..n], &self.g[..n], &self.F[..n], &self.G[..n],
394 &self.hashed_vrfy_key, ctx, id, hv, sig,
395 #[cfg(not(feature = "small_context"))]
396 &self.basis[..(4 * n)],
397 &mut self.tmp_i16, &mut self.tmp_u16, &mut self.tmp_flr)?;
398
399 #[cfg(not(feature = "shake256x4"))]
400 sign_inner::<T, shake::SHAKE256_PRNG>(self.logn, rng,
401 &self.f[..n], &self.g[..n], &self.F[..n], &self.G[..n],
402 &self.hashed_vrfy_key, ctx, id, hv, sig,
403 #[cfg(not(feature = "small_context"))]
404 &self.basis[..(4 * n)],
405 &mut self.tmp_i16, &mut self.tmp_u16, &mut self.tmp_flr)?;
406 Ok(())
407 }
408
409 fn sign_falcon<T: CryptoRng + RngCore>(&mut self, rng: &mut T,
410 profile: FalconProfile, message: &[u8], sig: &mut [u8])
411 -> Result<usize, SigningKeyError>
412 {
413 let n = 1usize << self.logn;
414 #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
415 if self.use_avx2 {
416 unsafe {
417 #[cfg(feature = "shake256x4")]
418 return sign_avx2::sign_falcon_avx2_inner::<T, shake::SHAKE256x4>(
419 profile, self.logn, rng,
420 &self.f[..n], &self.g[..n], &self.F[..n], &self.G[..n],
421 message, sig,
422 #[cfg(not(feature = "small_context"))]
423 &self.basis[..(4 * n)],
424 &mut self.tmp_i16, &mut self.tmp_u16, &mut self.tmp_flr,
425 );
426
427 #[cfg(not(feature = "shake256x4"))]
428 return sign_avx2::sign_falcon_avx2_inner::<T, shake::SHAKE256_PRNG>(
429 profile, self.logn, rng,
430 &self.f[..n], &self.g[..n], &self.F[..n], &self.G[..n],
431 message, sig,
432 #[cfg(not(feature = "small_context"))]
433 &self.basis[..(4 * n)],
434 &mut self.tmp_i16, &mut self.tmp_u16, &mut self.tmp_flr,
435 );
436 }
437 }
438
439 #[cfg(feature = "shake256x4")]
440 {
441 sign_falcon_inner::<T, shake::SHAKE256x4>(
442 profile, self.logn, rng,
443 &self.f[..n], &self.g[..n], &self.F[..n], &self.G[..n],
444 message, sig,
445 #[cfg(not(feature = "small_context"))]
446 &self.basis[..(4 * n)],
447 &mut self.tmp_i16, &mut self.tmp_u16, &mut self.tmp_flr,
448 )
449 }
450
451 #[cfg(not(feature = "shake256x4"))]
452 {
453 sign_falcon_inner::<T, shake::SHAKE256_PRNG>(
454 profile, self.logn, rng,
455 &self.f[..n], &self.g[..n], &self.F[..n], &self.G[..n],
456 message, sig,
457 #[cfg(not(feature = "small_context"))]
458 &self.basis[..(4 * n)],
459 &mut self.tmp_i16, &mut self.tmp_u16, &mut self.tmp_flr,
460 )
461 }
462 }
463 }
464} }
465
466sign_key_impl!(SigningKeyStandard, 9, 10);
468
469sign_key_impl!(SigningKey512, 9, 9);
472
473sign_key_impl!(SigningKey1024, 10, 10);
476
477sign_key_impl!(SigningKeyWeak, 2, 8);
480
481#[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
482mod sign_avx2;
483
484fn decode_inner(logn_min: u32, logn_max: u32,
486 f: &mut [i8], g: &mut [i8], F: &mut [i8], G: &mut [i8],
487 vrfy_key: &mut [u8], hashed_vrfy_key: &mut [u8],
488 tmp_u16: &mut [u16], src: &[u8]) -> Option<u32>
489{
490 if src.len() < 1 {
491 return None;
492 }
493 let head = src[0];
494 if (head & 0xF0) != 0x50 {
495 return None;
496 }
497 let logn = (head & 0x0F) as u32;
498 if logn < logn_min || logn > logn_max {
499 return None;
500 }
501 if src.len() != sign_key_size(logn).unwrap() {
502 return None;
503 }
504 let n = 1usize << logn;
505 assert!(f.len() >= n);
506 assert!(g.len() >= n);
507 assert!(F.len() >= n);
508 assert!(G.len() >= n);
509 assert!(vrfy_key.len() >= vrfy_key_size(logn).unwrap());
510 assert!(hashed_vrfy_key.len() == 64);
511 let f = &mut f[..n];
512 let g = &mut g[..n];
513 let F = &mut F[..n];
514 let G = &mut G[..n];
515 let vk = &mut vrfy_key[..vrfy_key_size(logn).unwrap()];
516
517 let nbits_fg = match logn {
519 2..=5 => 8,
520 6..=7 => 7,
521 8..=9 => 6,
522 _ => 5,
523 };
524 let j = 1 + codec::trim_i8_decode(&src[1..], f, nbits_fg).ok()?;
525 let j = j + codec::trim_i8_decode(&src[j..], g, nbits_fg).ok()?;
526 let j = j + codec::trim_i8_decode(&src[j..], F, 8).ok()?;
527 assert!(j == src.len());
530
531 let (w0, w1) = tmp_u16.split_at_mut(n);
541
542 mq::mqpoly_small_to_int(logn, &*g, w0);
544 mq::mqpoly_small_to_int(logn, &*f, w1);
545 mq::mqpoly_int_to_NTT(logn, w0);
546 mq::mqpoly_int_to_NTT(logn, w1);
547 if !mq::mqpoly_div_ntt(logn, w0, w1) {
548 return None;
550 }
551
552 mq::mqpoly_small_to_int(logn, &*F, w1);
554 mq::mqpoly_int_to_NTT(logn, w1);
555 mq::mqpoly_mul_ntt(logn, w1, w0);
556
557 mq::mqpoly_NTT_to_int(logn, w0);
559 mq::mqpoly_int_to_ext(logn, w0);
560 vk[0] = 0x00 + (logn as u8);
561 let j = 1 + codec::modq_encode(&w0[..n], &mut vk[1..]).unwrap();
562 assert!(j == vk.len());
563 let mut sh = shake::SHAKE256::new();
564 sh.inject(vk).unwrap();
565 sh.flip().unwrap();
566 sh.extract(hashed_vrfy_key).unwrap();
567
568 mq::mqpoly_NTT_to_int(logn, w1);
571 if !mq::mqpoly_int_to_small(logn, w1, G) {
572 return None;
573 }
574
575 Some(logn)
577}
578
579fn compute_basis_inner(logn: u32,
580 f: &[i8], g: &[i8], F: &[i8], G: &[i8], basis: &mut [flr::FLR])
581{
582 let n = 1usize << logn;
583
584 let (b00, work) = basis.split_at_mut(n);
586 let (b01, work) = work.split_at_mut(n);
587 let (b10, work) = work.split_at_mut(n);
588 let (b11, _) = work.split_at_mut(n);
589
590 poly::poly_set_small(logn, b01, f);
591 poly::poly_set_small(logn, b00, g);
592 poly::poly_set_small(logn, b11, F);
593 poly::poly_set_small(logn, b10, G);
594 poly::FFT(logn, b01);
595 poly::FFT(logn, b00);
596 poly::FFT(logn, b11);
597 poly::FFT(logn, b10);
598 poly::poly_neg(logn, b01);
599 poly::poly_neg(logn, b11);
600}
601
602const INV_Q: flr::FLR = flr::FLR::scaled(6004310871091074, -66);
604
605fn falcon_profile_supports_logn(profile: FalconProfile, logn: u32) -> bool {
606 match profile {
607 FalconProfile::PqClean => logn == 9 || logn == 10,
608 FalconProfile::TidecoinLegacyFalcon512 => logn == 9,
609 }
610}
611
612fn falcon_profile_retry_uses_fresh_nonce(profile: FalconProfile) -> bool {
613 match profile {
614 FalconProfile::PqClean => true,
615 FalconProfile::TidecoinLegacyFalcon512 => false,
616 }
617}
618
619fn falcon_profile_sig_body_cap(profile: FalconProfile, total_sig_len: usize) -> usize {
620 let cap = total_sig_len.saturating_sub(1 + FALCON_NONCE_LEN);
621 match profile {
622 FalconProfile::PqClean => cap,
623 FalconProfile::TidecoinLegacyFalcon512 => {
624 core::cmp::min(cap, TIDECOIN_LEGACY_FALCON512_SIG_BODY_MAX)
625 }
626 }
627}
628
629fn sign_inner<T: CryptoRng + RngCore, P: PRNG>(logn: u32, rng: &mut T,
630 f: &[i8], g: &[i8], F: &[i8], G: &[i8], hashed_vrfy_key: &[u8],
631 ctx: &DomainContext, id: &HashIdentifier, hv: &[u8], sig: &mut [u8],
632 #[cfg(not(feature = "small_context"))]
633 basis: &[flr::FLR],
634 tmp_i16: &mut [i16], tmp_u16: &mut [u16], tmp_flr: &mut [flr::FLR])
635 -> Result<(), SigningKeyError>
636{
637 let n = 1usize << logn;
638 assert!(f.len() == n);
639 assert!(g.len() == n);
640 assert!(F.len() == n);
641 assert!(G.len() == n);
642 assert!(sig.len() == signature_size(logn).unwrap());
643
644 let mut nonce = [0u8; 40];
647
648 loop {
653 let hm = &mut tmp_u16[0..n];
654 rng.fill_bytes(&mut nonce);
655 if hash_to_point(&nonce, hashed_vrfy_key, ctx, id, hv, hm).is_err() {
656 unreachable!();
657 }
658
659 let mut seed = [0u8; 56];
663 rng.fill_bytes(&mut seed);
664 let mut samp = sampler::Sampler::<P>::new(logn, &seed);
665
666 #[cfg(feature = "small_context")]
682 {
683 compute_basis_inner(logn, f, g, F, G, tmp_flr);
685
686 let (b00, work) = tmp_flr.split_at_mut(n);
687 let (b01, work) = work.split_at_mut(n);
688 let (b10, work) = work.split_at_mut(n);
689 let (b11, work) = work.split_at_mut(n);
690 let (t0, work) = work.split_at_mut(n);
691 let (t1, _) = work.split_at_mut(n);
692
693 t0.copy_from_slice(&*b01);
695 poly::poly_mulownadj_fft(logn, t0);
696
697 t1.copy_from_slice(&*b00);
699 poly::poly_muladj_fft(logn, t1, b10);
700
701 poly::poly_mulownadj_fft(logn, b00);
703
704 poly::poly_add(logn, b00, t0);
706
707 t0.copy_from_slice(b01);
709
710 poly::poly_muladj_fft(logn, b01, b11);
712 poly::poly_add(logn, b01, t1);
713
714 poly::poly_mulownadj_fft(logn, b10);
716
717 t1.copy_from_slice(b11);
719 poly::poly_mulownadj_fft(logn, t1);
720 poly::poly_add(logn, b10, t1);
721 }
722
723 #[cfg(not(feature = "small_context"))]
724 {
725 let (b00, work) = basis.split_at(n);
727 let (b01, work) = work.split_at(n);
728 let (b10, work) = work.split_at(n);
729 let (b11, _) = work.split_at(n);
730
731 let (g00, work) = tmp_flr.split_at_mut(n);
732 let (g01, work) = work.split_at_mut(n);
733 let (g11, work) = work.split_at_mut(n);
734 let (t0, work) = work.split_at_mut(n);
735 let (t1, _) = work.split_at_mut(n);
736
737 g00.copy_from_slice(b00);
738 poly::poly_mulownadj_fft(logn, g00);
739 t0.copy_from_slice(b01);
740 poly::poly_mulownadj_fft(logn, t0);
741 poly::poly_add(logn, g00, t0);
742
743 g01.copy_from_slice(b00);
744 poly::poly_muladj_fft(logn, g01, b10);
745 t0.copy_from_slice(b01);
746 poly::poly_muladj_fft(logn, t0, b11);
747 poly::poly_add(logn, g01, t0);
748
749 g11.copy_from_slice(b10);
750 poly::poly_mulownadj_fft(logn, g11);
751 t0.copy_from_slice(b11);
752 poly::poly_mulownadj_fft(logn, t0);
753 poly::poly_add(logn, g11, t0);
754
755 t0.copy_from_slice(b11);
756 t1.copy_from_slice(b01);
757 }
758
759 {
763 let (_, work) = tmp_flr.split_at_mut(3 * n);
764 let (b11, work) = work.split_at_mut(n);
765 let (b01, work) = work.split_at_mut(n);
766 let (t0, work) = work.split_at_mut(n);
767 let (t1, _) = work.split_at_mut(n);
768
769 for i in 0..n {
773 t0[i] = flr::FLR::from_i32(hm[i] as i32);
774 }
775
776 poly::FFT(logn, t0);
779 t1.copy_from_slice(t0);
780 poly::poly_mul_fft(logn, t1, b01);
781 poly::poly_mulconst(logn, t1, -INV_Q);
782 poly::poly_mul_fft(logn, t0, b11);
783 poly::poly_mulconst(logn, t0, INV_Q);
784 }
785
786 tmp_flr.copy_within((5 * n)..(7 * n), 3 * n);
788
789 {
793 let (g00, work) = tmp_flr.split_at_mut(n);
795 let (g01, work) = work.split_at_mut(n);
796 let (g11, work) = work.split_at_mut(n);
797 let (t0, work) = work.split_at_mut(n);
798 let (t1, work) = work.split_at_mut(n);
799 samp.ffsamp_fft(t0, t1, g00, g01, g11, work);
800 }
801
802 tmp_flr.copy_within((3 * n)..(5 * n), 4 * n);
805
806 #[cfg(feature = "small_context")]
807 compute_basis_inner(logn, f, g, F, G, tmp_flr);
808
809 #[cfg(not(feature = "small_context"))]
810 tmp_flr[..(4 * n)].copy_from_slice(&basis[..(4 * n)]);
811
812 let (b00, work) = tmp_flr.split_at_mut(n);
813 let (b01, work) = work.split_at_mut(n);
814 let (b10, work) = work.split_at_mut(n);
815 let (b11, work) = work.split_at_mut(n);
816 let (t0, work) = work.split_at_mut(n);
817 let (t1, work) = work.split_at_mut(n);
818 let (tx, work) = work.split_at_mut(n);
819 let (ty, _) = work.split_at_mut(n);
820
821 tx.copy_from_slice(t0);
823 ty.copy_from_slice(t1);
824 poly::poly_mul_fft(logn, tx, b00);
825 poly::poly_mul_fft(logn, ty, b10);
826 poly::poly_add(logn, tx, ty);
827 ty.copy_from_slice(t0);
828 poly::poly_mul_fft(logn, ty, b01);
829 t0.copy_from_slice(tx);
830 poly::poly_mul_fft(logn, t1, b11);
831 poly::poly_add(logn, t1, ty);
832 poly::iFFT(logn, t0);
833 poly::iFFT(logn, t1);
834
835 let mut sqn = 0u32;
842 let mut ng = 0;
843 for i in 0..n {
844 let z = (hm[i] as i32) - (t0[i].rint() as i32);
845 let z = (z as i16) as i32;
846 sqn = sqn.wrapping_add((z * z) as u32);
847 ng |= sqn;
848 }
849
850 let s2 = &mut tmp_i16[..n];
855 for i in 0..n {
856 let sz = (-t1[i].rint()) as i16;
857 let z = sz as i32;
858 sqn = sqn.wrapping_add((z * z) as u32);
859 ng |= sqn;
860 s2[i] = sz;
861 }
862
863 sqn |= ((ng as i32) >> 31) as u32;
868 if sqn > mq::SQBETA[logn as usize] {
869 continue;
870 }
871
872 if codec::comp_encode(s2, &mut sig[41..]).is_ok() {
876 sig[0] = 0x30 + (logn as u8);
877 sig[1..41].copy_from_slice(&nonce);
878 return Ok(());
879 }
880 }
881}
882
883fn sign_falcon_inner<T: CryptoRng + RngCore, P: PRNG>(
884 profile: FalconProfile,
885 logn: u32,
886 rng: &mut T,
887 f: &[i8],
888 g: &[i8],
889 F: &[i8],
890 G: &[i8],
891 message: &[u8],
892 sig: &mut [u8],
893 #[cfg(not(feature = "small_context"))]
894 basis: &[flr::FLR],
895 tmp_i16: &mut [i16],
896 tmp_u16: &mut [u16],
897 tmp_flr: &mut [flr::FLR],
898) -> Result<usize, SigningKeyError> {
899 let n = 1usize << logn;
900 assert!(f.len() == n);
901 assert!(g.len() == n);
902 assert!(F.len() == n);
903 assert!(G.len() == n);
904 if !falcon_profile_supports_logn(profile, logn) {
905 return Err(SigningKeyError::UnsupportedFalconProfileForDegree { profile, logn });
906 }
907 let min_len = 1 + FALCON_NONCE_LEN + 1;
908 if sig.len() < min_len {
909 return Err(SigningKeyError::InvalidSignatureBufferLenAtLeast {
910 min: min_len,
911 actual: sig.len(),
912 });
913 }
914
915 let mut nonce = [0u8; FALCON_NONCE_LEN];
916 let mut first = true;
917 loop {
918 let hm = &mut tmp_u16[0..n];
919 if first || falcon_profile_retry_uses_fresh_nonce(profile) {
920 rng.fill_bytes(&mut nonce);
921 hash_to_point_falcon(&nonce, message, hm).unwrap();
922 first = false;
923 }
924
925 let mut seed = [0u8; 56];
926 rng.fill_bytes(&mut seed);
927 let mut samp = sampler::Sampler::<P>::new(logn, &seed);
928
929 #[cfg(feature = "small_context")]
930 {
931 compute_basis_inner(logn, f, g, F, G, tmp_flr);
932
933 let (b00, work) = tmp_flr.split_at_mut(n);
934 let (b01, work) = work.split_at_mut(n);
935 let (b10, work) = work.split_at_mut(n);
936 let (b11, work) = work.split_at_mut(n);
937 let (t0, work) = work.split_at_mut(n);
938 let (t1, _) = work.split_at_mut(n);
939
940 t0.copy_from_slice(&*b01);
941 poly::poly_mulownadj_fft(logn, t0);
942 t1.copy_from_slice(&*b00);
943 poly::poly_muladj_fft(logn, t1, b10);
944 poly::poly_mulownadj_fft(logn, b00);
945 poly::poly_add(logn, b00, t0);
946 t0.copy_from_slice(b01);
947 poly::poly_muladj_fft(logn, b01, b11);
948 poly::poly_add(logn, b01, t1);
949 poly::poly_mulownadj_fft(logn, b10);
950 t1.copy_from_slice(b11);
951 poly::poly_mulownadj_fft(logn, t1);
952 poly::poly_add(logn, b10, t1);
953 }
954
955 #[cfg(not(feature = "small_context"))]
956 {
957 let (b00, work) = basis.split_at(n);
958 let (b01, work) = work.split_at(n);
959 let (b10, work) = work.split_at(n);
960 let (b11, _) = work.split_at(n);
961
962 let (g00, work) = tmp_flr.split_at_mut(n);
963 let (g01, work) = work.split_at_mut(n);
964 let (g11, work) = work.split_at_mut(n);
965 let (t0, work) = work.split_at_mut(n);
966 let (t1, _) = work.split_at_mut(n);
967
968 g00.copy_from_slice(b00);
969 poly::poly_mulownadj_fft(logn, g00);
970 t0.copy_from_slice(b01);
971 poly::poly_mulownadj_fft(logn, t0);
972 poly::poly_add(logn, g00, t0);
973
974 g01.copy_from_slice(b00);
975 poly::poly_muladj_fft(logn, g01, b10);
976 t0.copy_from_slice(b01);
977 poly::poly_muladj_fft(logn, t0, b11);
978 poly::poly_add(logn, g01, t0);
979
980 g11.copy_from_slice(b10);
981 poly::poly_mulownadj_fft(logn, g11);
982 t0.copy_from_slice(b11);
983 poly::poly_mulownadj_fft(logn, t0);
984 poly::poly_add(logn, g11, t0);
985
986 t0.copy_from_slice(b11);
987 t1.copy_from_slice(b01);
988 }
989
990 {
991 let (_, work) = tmp_flr.split_at_mut(3 * n);
992 let (b11, work) = work.split_at_mut(n);
993 let (b01, work) = work.split_at_mut(n);
994 let (t0, work) = work.split_at_mut(n);
995 let (t1, _) = work.split_at_mut(n);
996
997 for i in 0..n {
998 t0[i] = flr::FLR::from_i32(hm[i] as i32);
999 }
1000 poly::FFT(logn, t0);
1001 t1.copy_from_slice(t0);
1002 poly::poly_mul_fft(logn, t1, b01);
1003 poly::poly_mulconst(logn, t1, -INV_Q);
1004 poly::poly_mul_fft(logn, t0, b11);
1005 poly::poly_mulconst(logn, t0, INV_Q);
1006 }
1007
1008 tmp_flr.copy_within((5 * n)..(7 * n), 3 * n);
1009
1010 {
1011 let (g00, work) = tmp_flr.split_at_mut(n);
1012 let (g01, work) = work.split_at_mut(n);
1013 let (g11, work) = work.split_at_mut(n);
1014 let (t0, work) = work.split_at_mut(n);
1015 let (t1, work) = work.split_at_mut(n);
1016 samp.ffsamp_fft(t0, t1, g00, g01, g11, work);
1017 }
1018
1019 tmp_flr.copy_within((3 * n)..(5 * n), 4 * n);
1020
1021 #[cfg(feature = "small_context")]
1022 compute_basis_inner(logn, f, g, F, G, tmp_flr);
1023
1024 #[cfg(not(feature = "small_context"))]
1025 tmp_flr[..(4 * n)].copy_from_slice(&basis[..(4 * n)]);
1026
1027 let (b00, work) = tmp_flr.split_at_mut(n);
1028 let (b01, work) = work.split_at_mut(n);
1029 let (b10, work) = work.split_at_mut(n);
1030 let (b11, work) = work.split_at_mut(n);
1031 let (t0, work) = work.split_at_mut(n);
1032 let (t1, work) = work.split_at_mut(n);
1033 let (tx, work) = work.split_at_mut(n);
1034 let (ty, _) = work.split_at_mut(n);
1035
1036 tx.copy_from_slice(t0);
1037 ty.copy_from_slice(t1);
1038 poly::poly_mul_fft(logn, tx, b00);
1039 poly::poly_mul_fft(logn, ty, b10);
1040 poly::poly_add(logn, tx, ty);
1041 ty.copy_from_slice(t0);
1042 poly::poly_mul_fft(logn, ty, b01);
1043 t0.copy_from_slice(tx);
1044 poly::poly_mul_fft(logn, t1, b11);
1045 poly::poly_add(logn, t1, ty);
1046 poly::iFFT(logn, t0);
1047 poly::iFFT(logn, t1);
1048
1049 let mut sqn = 0u32;
1050 let mut ng = 0;
1051 for i in 0..n {
1052 let z = (hm[i] as i32) - (t0[i].rint() as i32);
1053 let z = (z as i16) as i32;
1054 sqn = sqn.wrapping_add((z * z) as u32);
1055 ng |= sqn;
1056 }
1057
1058 let s2 = &mut tmp_i16[..n];
1059 for i in 0..n {
1060 let sz = (-t1[i].rint()) as i16;
1061 let z = sz as i32;
1062 sqn = sqn.wrapping_add((z * z) as u32);
1063 ng |= sqn;
1064 s2[i] = sz;
1065 }
1066
1067 sqn |= ((ng as i32) >> 31) as u32;
1068 if sqn > mq::SQBETA[logn as usize] {
1069 continue;
1070 }
1071
1072 let body_cap = falcon_profile_sig_body_cap(profile, sig.len());
1073 if let Ok(body_len) = codec::comp_encode(s2, &mut sig[41..(41 + body_cap)]) {
1074 sig[0] = 0x30 + (logn as u8);
1075 sig[1..41].copy_from_slice(&nonce);
1076 return Ok(41 + body_len);
1077 }
1078 }
1079}
1080
1081#[cfg(test)]
1082pub(crate) mod tests {
1083
1084 use super::*;
1085 use tide_fn_dsa_comm::shake::SHAKE256;
1086
1087 #[cfg(feature = "shake256x4")]
1091 pub(crate) use tide_fn_dsa_comm::shake::SHAKE256x4;
1092
1093 #[cfg(not(feature = "shake256x4"))]
1094 #[derive(Copy, Clone, Debug)]
1095 pub(crate) struct SHAKE256x4 {
1096 sh: [SHAKE256; 4],
1097 buf: [u8; 4 * 136],
1098 ptr: usize,
1099 }
1100
1101 #[cfg(not(feature = "shake256x4"))]
1102 impl SHAKE256x4 {
1103 pub fn new(seed: &[u8]) -> Self {
1104 let mut sh = [
1105 SHAKE256::new(),
1106 SHAKE256::new(),
1107 SHAKE256::new(),
1108 SHAKE256::new(),
1109 ];
1110 for i in 0..4 {
1111 sh[i].inject(seed).unwrap();
1112 sh[i].inject(&[i as u8]).unwrap();
1113 sh[i].flip().unwrap();
1114 }
1115 Self {
1116 sh,
1117 buf: [0u8; 4 * 136],
1118 ptr: 4 * 136,
1119 }
1120 }
1121
1122 fn refill(&mut self) {
1123 self.ptr = 0;
1124 for i in 0..(4 * 136 / 32) {
1125 for j in 0..4 {
1126 let k = 32 * i + 8 * j;
1127 self.sh[j].extract(&mut self.buf[k..(k + 8)]).unwrap();
1128 }
1129 }
1130 }
1131
1132 pub fn next_u8(&mut self) -> u8 {
1133 if self.ptr >= 4 * 136 {
1134 self.refill();
1135 }
1136 let x = self.buf[self.ptr];
1137 self.ptr += 1;
1138 x
1139 }
1140
1141 pub fn next_u16(&mut self) -> u16 {
1142 if self.ptr >= 4 * 136 - 1 {
1143 self.refill();
1144 }
1145 let x = u16::from_le_bytes(*<&[u8; 2]>::try_from(
1146 &self.buf[self.ptr..self.ptr + 2]).unwrap());
1147 self.ptr += 2;
1148 x
1149 }
1150
1151 pub fn next_u64(&mut self) -> u64 {
1152 if self.ptr >= 4 * 136 - 7 {
1153 self.refill();
1154 }
1155 let x = u64::from_le_bytes(*<&[u8; 8]>::try_from(
1156 &self.buf[self.ptr..self.ptr + 8]).unwrap());
1157 self.ptr += 8;
1158 x
1159 }
1160 }
1161
1162 #[cfg(not(feature = "shake256x4"))]
1163 impl tide_fn_dsa_comm::PRNG for SHAKE256x4 {
1164
1165 fn new(seed: &[u8]) -> Self {
1166 SHAKE256x4::new(seed)
1167 }
1168
1169 fn next_u8(&mut self) -> u8 {
1170 SHAKE256x4::next_u8(self)
1171 }
1172
1173 fn next_u16(&mut self) -> u16 {
1174 SHAKE256x4::next_u16(self)
1175 }
1176
1177 fn next_u64(&mut self) -> u64 {
1178 SHAKE256x4::next_u64(self)
1179 }
1180 }
1181
1182 #[derive(Clone, Copy, Debug)]
1186 struct ChaCha20PRNG {
1187 buf: [u8; 512],
1188 state: [u8; 256],
1189 ptr: usize,
1190 }
1191
1192 const CW: [u32; 4] = [
1193 0x61707865, 0x3320646E, 0x79622D32, 0x6B206574
1194 ];
1195
1196 impl ChaCha20PRNG {
1197
1198 fn refill(&mut self) {
1199 let mut cc = u64::from_le_bytes(
1200 *<&[u8; 8]>::try_from(&self.state[48..56]).unwrap());
1201 for i in 0..8 {
1202 let mut state = [0u32; 16];
1203 state[0..4].copy_from_slice(&CW);
1204 for j in 0..12 {
1205 state[4 + j] = u32::from_le_bytes(
1206 *<&[u8; 4]>::try_from(
1207 &self.state[(4 * j)..(4 * j + 4)]).unwrap());
1208 }
1209 state[14] ^= cc as u32;
1210 state[15] ^= (cc >> 32) as u32;
1211 for _ in 0..10 {
1212 fn qround(st: &mut [u32; 16],
1213 a: usize, b: usize, c: usize, d: usize)
1214 {
1215 st[a] = st[a].wrapping_add(st[b]);
1216 st[d] ^= st[a];
1217 st[d] = st[d].rotate_left(16);
1218 st[c] = st[c].wrapping_add(st[d]);
1219 st[b] ^= st[c];
1220 st[b] = st[b].rotate_left(12);
1221 st[a] = st[a].wrapping_add(st[b]);
1222 st[d] ^= st[a];
1223 st[d] = st[d].rotate_left(8);
1224 st[c] = st[c].wrapping_add(st[d]);
1225 st[b] ^= st[c];
1226 st[b] = st[b].rotate_left(7);
1227 }
1228 qround(&mut state, 0, 4, 8, 12);
1229 qround(&mut state, 1, 5, 9, 13);
1230 qround(&mut state, 2, 6, 10, 14);
1231 qround(&mut state, 3, 7, 11, 15);
1232 qround(&mut state, 0, 5, 10, 15);
1233 qround(&mut state, 1, 6, 11, 12);
1234 qround(&mut state, 2, 7, 8, 13);
1235 qround(&mut state, 3, 4, 9, 14);
1236 }
1237
1238 for j in 0..4 {
1239 state[j] = state[j].wrapping_add(CW[j]);
1240 }
1241 for j in 0..10 {
1242 state[4 + j] = state[4 + j].wrapping_add(
1243 u32::from_le_bytes(*<&[u8; 4]>::try_from(
1244 &self.state[(4 * j)..(4 * j + 4)]).unwrap()));
1245 }
1246 state[14] = state[14].wrapping_add(
1247 u32::from_le_bytes(*<&[u8; 4]>::try_from(
1248 &self.state[40..44]).unwrap()) ^ (cc as u32));
1249 state[15] = state[15].wrapping_add(
1250 u32::from_le_bytes(*<&[u8; 4]>::try_from(
1251 &self.state[44..48]).unwrap()) ^ ((cc >> 32) as u32));
1252 cc += 1;
1253
1254 for j in 0..16 {
1255 let k = (i << 2) + (j << 5);
1256 self.buf[k..(k + 4)].copy_from_slice(
1257 &state[j].to_le_bytes());
1258 }
1259 }
1260 self.state[48..56].copy_from_slice(&cc.to_le_bytes());
1261 self.ptr = 0;
1262 }
1263 }
1264
1265 impl PRNG for ChaCha20PRNG {
1266
1267 fn new(seed: &[u8]) -> Self {
1268 let mut p = Self {
1269 buf: [0u8; 512],
1270 state: [0u8; 256],
1271 ptr: 0,
1272 };
1273 p.state[..56].copy_from_slice(seed);
1274 p.refill();
1275 p
1276 }
1277
1278 fn next_u8(&mut self) -> u8 {
1279 if self.ptr == self.buf.len() {
1280 self.refill();
1281 }
1282 let x = self.buf[self.ptr];
1283 self.ptr += 1;
1284 x
1285 }
1286
1287 fn next_u16(&mut self) -> u16 {
1288 let x0 = self.next_u8();
1289 let x1 = self.next_u8();
1290 (x0 as u16) | ((x1 as u16) << 1)
1291 }
1292
1293 fn next_u64(&mut self) -> u64 {
1294 let mut i = self.ptr;
1295 if i >= (self.buf.len() - 9) {
1296 self.refill();
1297 i = 0;
1298 }
1299 self.ptr = i + 8;
1300 u64::from_le_bytes(
1301 *<&[u8; 8]>::try_from(&self.buf[i..(i + 8)]).unwrap())
1302 }
1303 }
1304
1305 const KAT_RNG_1: [u64; 128] = [
1306 0xDB1F30843AAD694C, 0xFAD9C14E86D5B53C, 0x7F84F914F46C439F,
1307 0xC46A6E399A376C6D, 0x47A5CD6F8C6B1789, 0x1E85D879707DA987,
1308 0xC7B0CE6C2C1DB3E7, 0xA65795537B3D977C, 0x748457A98AC7F19C,
1309 0xD8C8F161EEB7231F, 0xE81CAE53A7E8967F, 0x27EAD55A75ED57F8,
1310 0x9680953F3A192413, 0x784145D6687EA318, 0x9B454489BE56BAEB,
1311 0xF546834B0F799C67, 0xAC8E4F657C93FB88, 0xD0E6C7610CC4028B,
1312 0x417296FB7E1124BD, 0xE7968F18E3221DDC, 0x1DDEC33FC7F2D5FB,
1313 0x76556A8C07FB48EE, 0x7910EAA4C163BC2F, 0xAAC5C6291F779D17,
1314 0x575B2692885C4CFA, 0x0664AA8C3E99DA19, 0xFA55C1AE9A615133,
1315 0x7F1DB1A620F63220, 0xE740AE9AF9CC9755, 0x8393056E1D0D81E1,
1316 0x556EEF4483B434AA, 0xC6D17BEF7C2FB0C3, 0x27D142BD5BBF6014,
1317 0x6FD90B14DB4AA0BB, 0x7ACDD6F240530D0D, 0xE980F9F9DBE6109A,
1318 0xA30C677211C7BF37, 0x1E41FD290B90CE8B, 0x478FCD48D5E4A9ED,
1319 0x10586F987EA5FA7A, 0x691891C568F5DAC7, 0x3277735ED18D9107,
1320 0x78FCC576E47E8D71, 0x940A2C6777E3BEBB, 0x814612E210DD9715,
1321 0xABBCAFCC6B54279B, 0x2550E2538A063BFC, 0x7965EFC9D3F8A5BE,
1322 0xAE35E74B5A0B8717, 0xD855D6ABB96EA3AF, 0xAB4689B903C01C4E,
1323 0x8D8018988CA554AC, 0x0BB6689524F3A2B1, 0xAC0676FCBB193A87,
1324 0xD0A83D30F34F65EC, 0x26D3A8C167CA09F4, 0x7D17403D2B1DD9A0,
1325 0x47B1C836A0224550, 0xF6ABECF6422C5A56, 0x6FB1B2FF5CDDEC25,
1326 0x118276B244B55F88, 0x1FB953EF9E6C2C41, 0xF351C2717ACE9BF3,
1327 0xDF787B64D51A5440, 0xE4B8B81149B8A70B, 0x337E5363F506228B,
1328 0x48948ADE314B5980, 0x7FBF7A7139004610, 0xA6CB33F6802C96C7,
1329 0x745888A51A99BBED, 0x49D411403BA9CFDA, 0xA547A6EA4BDD5538,
1330 0x2D65DCF44F045E9F, 0x734FBE9360EFCC44, 0x1131E0AD573D37A0,
1331 0xADF3E9199FD90113, 0x8EDF3EAF50E6E00B, 0xFE0240D04C171901,
1332 0x45A97204596F7C46, 0x54D1D1F962484BC5, 0xEBAC109CDB975ED4,
1333 0x51182BF46BD2D61C, 0xF12D0EC8A80092D3, 0x69CA22BA55B34270,
1334 0x5FF97BBE7A525BF7, 0xF4E19780A4149ACA, 0x2CD5AE45826309FC,
1335 0xF0EF1F0A309C1BCF, 0xC16AF49962FE8A87, 0x2CD2575C27761E54,
1336 0xD9199411E9CC816D, 0xA0C397A63D036B05, 0xF439D283DFE4C172,
1337 0x5DAAD309E61F2A60, 0x2E7DDC8F9CD47E91, 0x2E1BFCDDC439FD58,
1338 0x8E62B7C84C3C27F8, 0xECD06ED0C1938A5E, 0x0335351E644A9155,
1339 0x71A735982C6DBBF7, 0xD8FE9FAF2DDF9AFF, 0x06BC9F654B9814E7,
1340 0x2DF46A488EC46052, 0x80CB8E04CDEF7F98, 0x9B65042EE20B4DAF,
1341 0x203BF49ACB5B34D2, 0x54E8F69957D8903B, 0x84D63D4BA389AF36,
1342 0x7A2D4A2230D0DC82, 0x3052659534D82FB8, 0xC5058A8EC3716238,
1343 0xB8063774064F4A27, 0x2F0BE0CE382BFD5B, 0xEE4CEAD41973DA0F,
1344 0xFB56581EB2424A5A, 0x09F21B654D835F66, 0x1968C7264664F9CC,
1345 0x2CBD6BB3DD21732C, 0xA9FB1E69F446231C, 0xDBEAD8399CB25257,
1346 0x28FF84E3ECC86113, 0x19A3B2D11BA6E80F, 0xC3ADAE73363651E7,
1347 0xF33FFB4923D82396, 0x36FE16582AD8C34C, 0x728910D4AA3BB137,
1348 0x2F351F2EF8B05525, 0x8727C7A39A617AE4
1349 ];
1350
1351 const KAT_RNG_2: [u8; 1024] = [
1352 0xC9, 0x45, 0xBC, 0xC4, 0x5B, 0x67, 0xA3, 0x25, 0x97, 0x19,
1353 0x64, 0x67, 0x4A, 0x98, 0xD4, 0xB7, 0xA7, 0x83, 0x18, 0xC8,
1354 0x40, 0xE2, 0x7F, 0xB8, 0x25, 0x8B, 0x7E, 0x92, 0x4A, 0x8C,
1355 0x68, 0x1B, 0x77, 0x61, 0x1E, 0x70, 0xED, 0xC2, 0xC4, 0xA5,
1356 0xDF, 0x9E, 0x76, 0xED, 0x49, 0x84, 0x3D, 0x08, 0xFE, 0xFE,
1357 0x99, 0xE2, 0xC6, 0xEF, 0xFE, 0x2C, 0xD4, 0xC0, 0x04, 0xD8,
1358 0x9A, 0x51, 0x21, 0xCD, 0x5B, 0xDB, 0x9F, 0x0B, 0x9C, 0x47,
1359 0xCF, 0xE8, 0x38, 0x6B, 0xB4, 0x94, 0xDC, 0xCD, 0x9A, 0x9B,
1360 0xB7, 0xED, 0xEE, 0x82, 0x64, 0x53, 0x20, 0xA0, 0x8F, 0x59,
1361 0xB2, 0x4F, 0xE2, 0x5A, 0x35, 0x88, 0x39, 0x5B, 0x6C, 0x59,
1362 0x59, 0x8C, 0x10, 0xC5, 0x2B, 0xF3, 0x7C, 0x49, 0xFD, 0x99,
1363 0x0C, 0x86, 0x07, 0x9E, 0x35, 0x71, 0x8E, 0x23, 0x7B, 0x9D,
1364 0x23, 0x34, 0x7A, 0xC8, 0x8A, 0x17, 0xDA, 0x7B, 0xA2, 0x97,
1365 0x0A, 0x78, 0x2B, 0x19, 0xAD, 0xB1, 0x35, 0xBD, 0xB1, 0xE7,
1366 0x74, 0x4B, 0x82, 0xFB, 0x72, 0x9C, 0x8C, 0x51, 0x3B, 0xE3,
1367 0xF0, 0x31, 0x11, 0xAA, 0x59, 0xA4, 0x66, 0xAC, 0xAA, 0x9E,
1368 0x85, 0xD9, 0x2D, 0xAD, 0xCA, 0x2B, 0x69, 0x5E, 0x19, 0x9F,
1369 0x77, 0x15, 0x43, 0xF0, 0xC9, 0x9F, 0xBC, 0x5B, 0x66, 0x26,
1370 0x7F, 0x7D, 0x7C, 0x95, 0x5D, 0x60, 0xE0, 0x49, 0x15, 0xC4,
1371 0x56, 0x47, 0x7E, 0x8D, 0x68, 0x3C, 0x54, 0x6F, 0x20, 0xF9,
1372 0x00, 0x43, 0xB4, 0x52, 0xD8, 0x46, 0x51, 0xFC, 0x0B, 0x92,
1373 0x15, 0xEF, 0x56, 0x45, 0x49, 0x94, 0xC2, 0xD0, 0x5E, 0x95,
1374 0xC4, 0x6D, 0x00, 0xDD, 0x13, 0x93, 0x78, 0xC2, 0x85, 0x21,
1375 0x5D, 0x18, 0x92, 0xB9, 0x48, 0xD2, 0x96, 0x45, 0x89, 0x0D,
1376 0x69, 0x2B, 0x85, 0x5D, 0x23, 0x5D, 0x10, 0x92, 0xD7, 0xDC,
1377 0xDC, 0xF8, 0x60, 0x5E, 0xED, 0x1F, 0x21, 0xB2, 0x19, 0x27,
1378 0xB7, 0xB7, 0xCD, 0x49, 0x98, 0x29, 0x90, 0xC9, 0x81, 0xCD,
1379 0x4E, 0x44, 0xB5, 0x39, 0x56, 0xED, 0x2B, 0xAA, 0x53, 0x34,
1380 0x3B, 0xB0, 0xBA, 0x1F, 0xBC, 0xF8, 0x58, 0x5F, 0x3E, 0xD0,
1381 0x4D, 0xB3, 0xA8, 0x5E, 0xC9, 0xB8, 0xD2, 0x70, 0xD3, 0x30,
1382 0xC0, 0x3C, 0x45, 0x89, 0x9B, 0x4C, 0x5F, 0xE8, 0x05, 0x7F,
1383 0x78, 0x99, 0x48, 0x3A, 0xD7, 0xCB, 0x96, 0x9A, 0x33, 0x97,
1384 0x62, 0xE9, 0xBD, 0xCE, 0x04, 0x72, 0x4D, 0x85, 0x67, 0x51,
1385 0x69, 0xFB, 0xD3, 0x12, 0xBC, 0xFC, 0xB5, 0x77, 0x56, 0x3B,
1386 0xB9, 0xB5, 0x3D, 0x5D, 0x7D, 0x2B, 0x34, 0xB0, 0x36, 0x2D,
1387 0x56, 0xE9, 0x24, 0xC2, 0x5A, 0xE9, 0x2A, 0xF8, 0xEE, 0x83,
1388 0x74, 0xC1, 0x0C, 0x80, 0xAD, 0x43, 0x5C, 0x04, 0x49, 0xB0,
1389 0x41, 0xD2, 0x29, 0x32, 0x9C, 0x7D, 0x70, 0xD5, 0x3D, 0xFE,
1390 0x82, 0x27, 0x8A, 0x38, 0x19, 0x12, 0x14, 0x78, 0xAA, 0x2A,
1391 0x29, 0xE2, 0x2B, 0xBB, 0x87, 0x4F, 0x7A, 0xDC, 0xC0, 0x72,
1392 0x30, 0xB6, 0xDE, 0x73, 0x7C, 0x04, 0x2D, 0xB6, 0xDF, 0x5E,
1393 0x4C, 0x3B, 0x82, 0xF6, 0x10, 0xE4, 0x94, 0xCE, 0x90, 0xD4,
1394 0x23, 0x0C, 0xBD, 0xCA, 0x56, 0xB7, 0x09, 0x6C, 0xAC, 0x35,
1395 0xA8, 0x47, 0xF0, 0x94, 0x21, 0xBD, 0xD5, 0x09, 0x18, 0x78,
1396 0x7C, 0x8D, 0x1E, 0x03, 0x15, 0xB1, 0x1A, 0xE8, 0x72, 0xB7,
1397 0x98, 0x5F, 0x23, 0x3A, 0x91, 0xB2, 0xDF, 0xFD, 0x70, 0x69,
1398 0xC4, 0x3B, 0xFA, 0x73, 0x17, 0xCC, 0xFB, 0xCF, 0xA6, 0xCF,
1399 0xC1, 0x32, 0x3E, 0x74, 0x0C, 0xCC, 0x73, 0xB2, 0xBE, 0x73,
1400 0xAC, 0x8E, 0x44, 0x51, 0x45, 0xED, 0xF6, 0x60, 0x21, 0x3D,
1401 0x0C, 0xE3, 0x3E, 0x1B, 0x11, 0x55, 0x68, 0x1A, 0x15, 0x97,
1402 0x80, 0x67, 0x23, 0x4F, 0x37, 0xF5, 0x30, 0x3D, 0x05, 0x4E,
1403 0xCF, 0x0E, 0x03, 0xB9, 0x2F, 0xD1, 0xD5, 0xD6, 0x5F, 0x79,
1404 0xF6, 0x61, 0x15, 0xBC, 0x79, 0x80, 0xA4, 0xD7, 0x98, 0x5B,
1405 0x38, 0x7A, 0x07, 0x9B, 0x02, 0xB2, 0x47, 0x89, 0xB2, 0x25,
1406 0xEF, 0x7B, 0xB1, 0xB0, 0xA5, 0x35, 0x39, 0xEB, 0xA0, 0x1C,
1407 0x24, 0xF4, 0xDB, 0x0C, 0x6C, 0x2B, 0xA3, 0x75, 0x47, 0x00,
1408 0xA3, 0xC8, 0xBC, 0x1E, 0x15, 0x3A, 0xC6, 0x1D, 0x91, 0x19,
1409 0xBA, 0xB4, 0xCA, 0x28, 0xD2, 0x57, 0x7C, 0x0D, 0x71, 0x4A,
1410 0x03, 0xD5, 0xAE, 0x96, 0x6D, 0x92, 0x70, 0x27, 0x82, 0x88,
1411 0xB6, 0x12, 0x1A, 0x84, 0x38, 0x1B, 0x74, 0x2F, 0x74, 0x33,
1412 0xE0, 0xA1, 0x82, 0x93, 0x62, 0xB6, 0x5B, 0x9E, 0x4E, 0xC2,
1413 0xE6, 0x5B, 0x49, 0x7E, 0x4A, 0x68, 0x8D, 0x08, 0xA9, 0xD8,
1414 0xEA, 0x47, 0xFC, 0xD2, 0x31, 0x21, 0x38, 0xEE, 0xE4, 0xE4,
1415 0x97, 0xFA, 0x91, 0x90, 0xC4, 0x26, 0x4B, 0xA5, 0xB3, 0x7D,
1416 0x33, 0x7F, 0x5A, 0x2D, 0x54, 0xB3, 0x01, 0xCF, 0x9C, 0x0D,
1417 0x9E, 0x97, 0x01, 0xE8, 0x54, 0x3C, 0xC2, 0x13, 0x69, 0x0C,
1418 0x35, 0xCD, 0x63, 0x02, 0x70, 0xC8, 0xA1, 0x1F, 0xC2, 0xBE,
1419 0x8F, 0xFC, 0xCE, 0x05, 0xA7, 0x3F, 0xCC, 0x04, 0x3D, 0x18,
1420 0xC4, 0x13, 0x38, 0x0D, 0x4C, 0xEE, 0x81, 0xFA, 0x02, 0xF8,
1421 0xFC, 0x4F, 0x21, 0xD0, 0xE6, 0xF2, 0x7B, 0x92, 0x76, 0xC5,
1422 0x8E, 0x96, 0x6C, 0x53, 0x84, 0x3E, 0x74, 0x1D, 0xD5, 0x0F,
1423 0x98, 0x03, 0x0E, 0x6A, 0x9D, 0x49, 0x03, 0xAE, 0xBE, 0x70,
1424 0x61, 0x5B, 0x45, 0xC0, 0x1E, 0x2F, 0x94, 0x42, 0xFA, 0x16,
1425 0x9F, 0xFA, 0xD5, 0x9B, 0x60, 0x88, 0x92, 0x19, 0x08, 0x02,
1426 0x31, 0x99, 0x6D, 0xA1, 0x72, 0xCB, 0x45, 0xC6, 0x93, 0xBA,
1427 0xA8, 0x71, 0x42, 0xC6, 0x85, 0x28, 0x6C, 0x1B, 0x60, 0x7C,
1428 0x14, 0x2F, 0x9A, 0x17, 0x10, 0x34, 0x27, 0x48, 0x36, 0xB2,
1429 0xE8, 0xD3, 0xEA, 0xE4, 0x9D, 0x67, 0xE4, 0x46, 0x2E, 0xC6,
1430 0x41, 0xE1, 0x83, 0x42, 0xB8, 0x82, 0x5F, 0x79, 0x61, 0xA3,
1431 0x0C, 0x63, 0x00, 0xCB, 0x7C, 0xB9, 0x30, 0x53, 0xF4, 0xFC,
1432 0xAF, 0xAC, 0x22, 0x71, 0x87, 0x4D, 0x4B, 0x4B, 0x9E, 0xAE,
1433 0x69, 0xB5, 0x58, 0x04, 0x9C, 0x03, 0x57, 0x58, 0x8D, 0x2F,
1434 0x82, 0x95, 0x57, 0x2F, 0xC3, 0xA1, 0xC5, 0xB1, 0xF1, 0xF1,
1435 0x98, 0x9A, 0xF8, 0x99, 0x74, 0x5C, 0xC5, 0xAC, 0x4A, 0x32,
1436 0xE9, 0x24, 0xCF, 0x1D, 0x1E, 0x29, 0x18, 0x7C, 0xBF, 0x43,
1437 0x74, 0x23, 0x28, 0xB0, 0x3D, 0xD1, 0xB3, 0x8C, 0xE1, 0x28,
1438 0x02, 0x3E, 0x8F, 0x7F, 0xDD, 0xF0, 0x5B, 0x4D, 0x37, 0x96,
1439 0xF7, 0x73, 0x73, 0x7F, 0xBC, 0xAD, 0x6C, 0x84, 0xFC, 0x47,
1440 0xD2, 0x1E, 0xAB, 0xEB, 0xB6, 0xCA, 0x4E, 0x3A, 0x2C, 0x47,
1441 0x59, 0x61, 0x0D, 0xA0, 0x17, 0xCF, 0xDD, 0x62, 0x6F, 0xA3,
1442 0xF4, 0x72, 0x2D, 0xB0, 0xB2, 0x34, 0x2A, 0xE1, 0x63, 0xC3,
1443 0x5B, 0xAC, 0xE8, 0x6F, 0x92, 0x77, 0x78, 0xE2, 0x34, 0xAD,
1444 0x4F, 0x6C, 0xFF, 0x71, 0xE1, 0x92, 0xFD, 0xED, 0xA1, 0x20,
1445 0xCA, 0xCB, 0x80, 0x32, 0xD1, 0x78, 0x72, 0x68, 0xFE, 0xAE,
1446 0x73, 0x22, 0xD7, 0x60, 0x23, 0x1D, 0x3D, 0x06, 0xD6, 0x2A,
1447 0x81, 0xC4, 0x43, 0x98, 0xFD, 0x4E, 0xBD, 0x85, 0x09, 0x29,
1448 0x11, 0xE8, 0x36, 0xE1, 0xCE, 0xCF, 0x07, 0xA7, 0x45, 0x8C,
1449 0xCB, 0xB2, 0xDC, 0xD0, 0x98, 0xB9, 0x93, 0x33, 0x8A, 0x2A,
1450 0x13, 0x82, 0x36, 0x3D, 0x22, 0xB0, 0x9C, 0x74, 0x3F, 0xCE,
1451 0x6F, 0xCC, 0x69, 0xFF, 0x81, 0xE8, 0xAE, 0xC8, 0x57, 0x0D,
1452 0x98, 0xEB, 0xC5, 0x2A, 0x45, 0x55, 0xDC, 0xBB, 0x0A, 0x5B,
1453 0x3D, 0xB4, 0x61, 0xC4, 0xAE, 0x11, 0x68, 0x7D, 0xD4, 0x45,
1454 0x83, 0xAE, 0x66, 0xC8
1455 ];
1456
1457 #[test]
1458 fn chacha20_prng() {
1459 let mut sh = SHAKE256::new();
1460 sh.inject(&b"rng"[..]).unwrap();
1461 sh.flip().unwrap();
1462 let mut seed = [0u8; 56];
1463 sh.extract(&mut seed).unwrap();
1464 let mut p = ChaCha20PRNG::new(&seed);
1465
1466 for i in 0..KAT_RNG_1.len() {
1467 assert!(p.next_u64() == KAT_RNG_1[i]);
1468 }
1469 for i in 0..KAT_RNG_2.len() {
1470 assert!(p.next_u8() == KAT_RNG_2[i]);
1471 }
1472 }
1473
1474 struct FakeCryptoRng(usize);
1476 impl CryptoRng for FakeCryptoRng {}
1477 impl RngCore for FakeCryptoRng {
1478 fn next_u32(&mut self) -> u32 {
1479 unimplemented!();
1480 }
1481 fn next_u64(&mut self) -> u64 {
1482 unimplemented!();
1483 }
1484 fn fill_bytes(&mut self, dest: &mut [u8]) {
1485 dest.copy_from_slice(&KAT_512_RND[self.0..(self.0 + dest.len())]);
1486 self.0 += dest.len();
1487 }
1488 fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), RngError> {
1489 self.fill_bytes(dest);
1490 Ok(())
1491 }
1492 }
1493
1494 #[test]
1495 fn sign_512() {
1496 let mut rng = FakeCryptoRng(0);
1498
1499 let mut tmp_i16 = [0i16; 2 << 9];
1501 let mut tmp_u16 = [0u16; 2 << 9];
1502 let mut tmp_flr = [flr::FLR::ZERO; 9 << 9];
1503 let mut sig = [0u8; SIGNATURE_SIZE_512];
1504
1505 #[cfg(not(feature = "small_context"))]
1506 let basis = {
1507 let mut basis = [flr::FLR::ZERO; 4 << 9];
1508 compute_basis_inner(9,
1509 &KAT_512_f, &KAT_512_g, &KAT_512_F, &KAT_512_G, &mut basis);
1510 basis
1511 };
1512
1513 sign_falcon_inner::<FakeCryptoRng, ChaCha20PRNG>(
1514 FalconProfile::TidecoinLegacyFalcon512, 9, &mut rng,
1515 &KAT_512_f, &KAT_512_g, &KAT_512_F, &KAT_512_G,
1516 &b"data1"[..],
1517 &mut sig,
1518 #[cfg(not(feature = "small_context"))]
1519 &basis,
1520 &mut tmp_i16, &mut tmp_u16, &mut tmp_flr)
1521 .unwrap();
1522
1523 assert!(sig[0] == 0x39);
1526 assert!(sig[1..41] == KAT_512_RND[0..40]);
1527 let mut sig_raw = [0i16; 512];
1528 assert!(codec::comp_decode(&sig[41..], &mut sig_raw[..]).is_ok());
1529 assert!(sig_raw == KAT_512_sig_raw);
1530 }
1531
1532 #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
1533 #[test]
1534 fn sign_avx2_512() {
1535 if !tide_fn_dsa_comm::has_avx2() {
1536 return;
1537 }
1538 let mut rng = FakeCryptoRng(0);
1540
1541 let mut tmp_i16 = [0i16; 2 << 9];
1543 let mut tmp_u16 = [0u16; 2 << 9];
1544 let mut tmp_flr = [flr::FLR::ZERO; 9 << 9];
1545 let mut sig = [0u8; SIGNATURE_SIZE_512];
1546
1547 #[cfg(not(feature = "small_context"))]
1548 let basis = {
1549 let mut basis = [flr::FLR::ZERO; 4 << 9];
1550 unsafe {
1551 sign_avx2::compute_basis_avx2_inner(9,
1552 &KAT_512_f, &KAT_512_g, &KAT_512_F, &KAT_512_G, &mut basis);
1553 }
1554 basis
1555 };
1556
1557 unsafe {
1558 sign_avx2::sign_falcon_avx2_inner::<FakeCryptoRng, ChaCha20PRNG>(
1559 FalconProfile::TidecoinLegacyFalcon512, 9, &mut rng,
1560 &KAT_512_f, &KAT_512_g, &KAT_512_F, &KAT_512_G,
1561 &b"data1"[..],
1562 &mut sig,
1563 #[cfg(not(feature = "small_context"))]
1564 &basis,
1565 &mut tmp_i16, &mut tmp_u16, &mut tmp_flr)
1566 .unwrap();
1567 }
1568
1569 assert!(sig[0] == 0x39);
1572 assert!(sig[1..41] == KAT_512_RND[0..40]);
1573 let mut sig_raw = [0i16; 512];
1574 assert!(codec::comp_decode(&sig[41..], &mut sig_raw[..]).is_ok());
1575 assert!(sig_raw == KAT_512_sig_raw);
1576 }
1577
1578 const KAT_512_f: [i8; 512] = [
1579 -4, -2, -5, -1, 4, -2, 0, -3, -1, 1, -2, -2, -6, -3, 3, -5, -1,
1580 4, -3, -8, 4, -1, 2, -1, -8, 5, -6, -3, 6, 0, -2, 4, 5, -6, 2,
1581 3, 6, 4, 2, 3, 3, 7, 0, 1, 5, -3, -1, -9, -1, 6, -2, -5, 4, 0,
1582 4, -2, 10, -4, -3, 4, -7, -1, -7, -2, -1, -6, 5, -1, -9, 3, 2,
1583 -5, 4, -2, 2, -4, 4, -3, -1, 0, 5, 2, 2, -1, -9, -7, -2, -1, 0,
1584 3, 1, 0, -1, -2, -5, 4, -1, -1, 3, -1, 1, 4, -3, 2, -5, -2, 2,
1585 -4, 3, 6, 3, 9, 1, -2, 4, -1, -1, -6, -2, -2, 4, 5, -1, 0, 10,
1586 -2, 1, -2, -3, 0, -4, -4, -1, 0, 1, -5, -3, -7, -2, -1, 2, -6,
1587 3, 0, 0, 4, -4, 0, 0, -5, -2, 5, -8, 8, 5, 4, 10, -4, 3, 8, 5,
1588 1, -7, 0, -5, 0, -4, 3, -4, -2, 2, -2, 6, 8, 2, -1, 4, -4, -2,
1589 1, 0, 3, 7, 0, 9, -3, 1, 4, -3, 2, -1, 5, -8, 4, -1, 1, -8, 2,
1590 4, -9, -3, 1, 3, -1, -7, 5, 5, 4, -3, 0, -7, -3, -1, -6, -7, 0,
1591 -3, 0, 3, -3, 0, -3, 1, 3, 4, -6, -6, -3, 6, 0, 2, -5, 1, -3,
1592 -6, -6, -1, -7, -2, -4, 3, 0, -4, -1, 2, 7, -7, -2, 4, 2, 0, 1,
1593 -1, -3, 2, 1, 8, -1, 1, -2, 1, -1, 1, 4, 0, -4, 4, 3, -2, 6, -3,
1594 -2, 1, 2, 3, 6, 5, -4, -7, -6, 4, 3, -4, 3, -3, 3, -3, 2, -1, 1,
1595 5, -2, 2, 1, 0, -7, 0, 0, -1, 4, -3, 2, 1, -3, 5, 4, -6, -1, -3,
1596 2, -1, -8, 4, 2, 4, 0, 1, -5, 8, 5, 4, -3, -1, -2, 4, 0, 2, -2,
1597 0, -2, -1, -7, 5, 0, 1, 2, 1, -2, 2, -1, 1, -4, 1, 0, 4, -4, 0,
1598 5, 1, 4, -5, -2, -3, -2, 1, 3, 1, 2, 5, 12, 0, -1, 4, -6, 1, -4,
1599 3, -5, -4, 4, 2, -2, -6, 1, 1, 3, -1, 0, -4, -4, -4, 6, -2, 4,
1600 -3, 0, -2, -1, 0, -6, -3, -2, 0, 6, 5, -5, -5, 3, 0, 3, -3, -2,
1601 5, 7, -3, 1, -1, 0, 3, 0, 3, -7, 2, -4, -4, 1, 1, 1, 0, -3, -8,
1602 3, 6, 1, -2, -7, 3, 3, 4, -1, -2, -5, 9, 7, 1, 2, -4, 4, 0, -11,
1603 3, 0, -3, -5, 5, -1, -1, 7, 6, -1, 6, 3, 9, 5, -2, -3, -3, 1,
1604 -2, 0, -1, 1, -2, 2, 0, -5, -1, -4, -2, 2, -1, -3, 0, -3, 0, 1,
1605 3, -3, 2, 5, 8, -2, 3, -4, -7, 0, 4, -8, 1, 8, -2, 1, -1, 2, 0,
1606 -2, 1, 3, 3, 4, -2, -4, 3, -4, 2, 3, -2, -4, 1, -4, 10, 2
1607 ];
1608 const KAT_512_g: [i8; 512] = [
1609 -1, 5, -7, -1, -4, 6, 4, -1, -4, -13, -1, -5, -2, -8, 2, 1, 4,
1610 2, 0, 0, 2, 0, -1, 2, 5, -5, -8, 8, 1, 11, 0, -8, -4, 1, 1, -6,
1611 -4, 1, -3, 0, -10, -4, -6, -3, -2, 1, 6, 2, 8, -2, 2, -2, 1, 3,
1612 -4, 2, -1, -1, -2, -2, -3, 0, -3, 2, -3, 2, -3, -4, 2, 3, 4, -5,
1613 6, -3, -2, -1, -1, -6, -2, 1, -4, -7, 8, 0, 2, -2, 2, 0, 1, 0,
1614 4, 9, 7, 0, -1, -1, 4, -3, -2, 6, 6, 0, 1, 7, -6, -5, 5, 1, 4,
1615 -1, 0, -2, 3, -4, 1, -1, -3, -2, 0, -1, -7, -8, -1, 2, 0, -5, 0,
1616 1, -4, 6, -5, 6, 4, 1, -4, -5, 8, -1, 1, -2, 1, 1, 1, 3, 0, -1,
1617 1, 1, -4, -5, -4, 2, -3, 2, -2, 3, 7, -4, 4, -1, -2, 4, -4, -5,
1618 2, 6, -7, 5, -1, 1, 3, 0, -5, -5, 3, -2, -3, -1, -6, 0, 2, 3, 2,
1619 7, -3, -2, -2, 1, -5, 3, 3, -7, 0, 4, 4, -1, 2, -3, 1, 3, -1,
1620 -1, 0, -7, -6, -3, 7, -3, 5, -5, 1, -2, 0, 9, -2, 3, -1, -5, -3,
1621 -5, 3, 1, -4, -3, 2, -2, 2, 8, -1, 0, 5, -3, -2, -6, 4, 0, 3,
1622 -3, -3, 4, -1, 0, 0, -2, -1, 3, 7, 4, 5, -1, 8, 0, -1, -6, -3,
1623 4, 3, -3, 5, 2, -1, -2, 1, -1, 3, -2, -6, 4, 0, 0, -4, 1, 6, 2,
1624 0, 10, 9, 2, -2, 0, 2, 1, -3, -1, -1, 3, 2, 1, 1, -3, -2, 7, 2,
1625 -1, 5, -3, -2, 1, -2, 2, -2, -4, 3, 2, 1, -4, 1, 4, 3, -7, -4,
1626 2, -5, -2, 5, -3, 1, -4, -5, 1, 0, 0, 0, 7, -5, -1, 2, 2, -3, 6,
1627 -6, 4, -3, -5, -6, -7, -4, 3, -2, -2, -10, -3, 2, -1, -6, -4, 1,
1628 2, 2, 1, 4, 1, -5, -10, -2, 2, -4, 4, 4, -2, 1, 4, -3, 0, -6,
1629 -3, 1, 5, -7, -6, -4, 8, -1, 0, -1, 6, -3, -2, -2, 6, 2, 3, -3,
1630 -3, 5, -2, 1, 1, -4, -4, 8, 0, 3, 2, 3, 7, 4, 3, 2, -6, -9, 0,
1631 -8, 11, -2, 2, -2, -2, 3, 0, -6, 2, -1, 4, 2, -2, 0, -3, -7, -1,
1632 -1, 0, -1, -4, -2, -5, 3, -4, 2, 2, -1, -1, 7, -1, 3, 6, -7, 1,
1633 -5, 0, -7, 4, 3, -5, -1, 0, 3, -4, 1, 2, -7, 1, -2, -8, -2, -5,
1634 -5, 1, -4, -4, 4, -3, -2, 2, -4, -8, -1, 0, -9, 5, -1, -2, 3, 2,
1635 6, -1, 1, -1, -5, 5, 9, 3, -6, -5, 1, -6, 0, 2, -4, 6, 2, 7, 2,
1636 15, 0, -2, 9, 0, 1, 6, 4, -1, -1, -6, -3, 3, 1, -6, -3, 2, 2, -2
1637 ];
1638 const KAT_512_F: [i8; 512] = [
1639 0, -25, -39, 21, 7, -5, -10, 4, -1, -38, -9, -1, 4, -23, 15, -1,
1640 8, 1, -38, 41, 29, 22, 9, 12, -46, 0, 9, -17, -19, 32, 38, -3,
1641 14, 6, 2, -6, -18, -1, 23, 80, -12, -20, 24, 22, -31, -38, -11,
1642 8, 17, 18, 19, -10, 0, -1, 28, -5, -28, -33, 4, -31, -33, -8,
1643 -9, -44, 46, -11, -5, -21, -22, -7, 1, -11, 33, -8, 12, -7, -6,
1644 63, 17, 12, -49, -11, -31, -8, 7, -28, 33, -28, -19, 8, 46, -73,
1645 9, 32, 18, 7, -43, 0, -6, -4, 8, -39, -17, 11, 15, -25, -9, -28,
1646 -2, 24, -23, 10, -15, 4, 41, 46, 18, 2, -3, -29, 11, -3, 20, 35,
1647 21, 23, 5, -8, -3, -27, -69, 0, 26, -29, -24, 8, 19, 6, -14,
1648 -18, 47, 5, 21, -50, 17, -44, -36, 24, 9, 16, -38, -5, -54, 34,
1649 13, 31, -2, 9, 8, -12, -14, -17, 28, -59, -20, 19, 31, 14, 14,
1650 7, -32, 37, 5, -3, -7, -6, 21, -29, -33, 23, -25, -23, 14, 38,
1651 -29, -33, -9, 23, -43, 18, -12, 2, 30, 32, -28, -21, 42, 1, 6,
1652 -6, 58, 34, -22, 1, 5, -2, -8, 14, -19, -4, -6, 10, -3, -3, 32,
1653 18, -19, -12, 49, 13, 4, -18, 57, 37, -19, 25, 14, 18, -51, 13,
1654 4, 4, 17, -37, -2, 1, 41, -36, -8, -13, 49, -6, 9, 46, -36, -6,
1655 -20, -18, -6, -29, -42, -21, -25, -29, 5, -41, 51, 49, -20, -22,
1656 -9, 3, -6, -52, 10, 41, 12, -27, -20, 31, -17, -23, -16, 3, 44,
1657 -3, -5, -2, 0, -22, 14, -30, -41, 3, -27, 3, 18, 38, 10, 49, 45,
1658 -13, -27, -4, -10, -67, -1, -17, -2, 72, 46, 20, 24, 22, 16, 25,
1659 6, -6, -31, 2, 0, -13, -14, 9, 4, 31, 18, 22, 12, 59, -1, -3,
1660 -24, -47, -10, 48, 37, -34, -32, -4, 18, -2, 52, -8, -7, 34,
1661 -44, -14, -21, -49, -35, 41, -4, 31, 3, 23, 9, 8, 0, -24, 38,
1662 -9, -9, 4, -10, -55, -19, 21, 27, 22, 41, 6, -23, 41, -2, 28,
1663 -46, 20, 52, 16, 20, 32, 18, 2, -3, 9, 16, 33, -18, 12, 6, -9,
1664 -19, 1, -5, -15, -17, 6, -3, 4, -22, 30, -34, 43, -4, 9, -3,
1665 -33, -43, -5, -13, -56, 38, 16, 11, -36, 11, -4, -56, 2, 0, -19,
1666 -45, -8, -34, 16, 31, -3, 16, 27, -16, -9, 8, 45, -51, -20, 62,
1667 -17, -4, 4, 17, -45, 4, -15, -19, 39, 39, 15, 17, -19, 2, 45,
1668 36, -22, 16, -23, 28, 34, 12, 5, 10, -7, 28, -35, 17, -37, -50,
1669 -28, 19, -25, 9, 45, -6, -7, -16, 57, 27, 50, -30, 2, -10, -1,
1670 -57, -49, -23, 0, -9, -36, -4, -3, 32, -6, -25, 67, -27, -19,
1671 25, -6, 1, -17, -14, 0, 29, 26, -12, -20, 44, 14, 10, 8, -11,
1672 -18, -53, 22, 25, 27, 35, 6, -16, 12, 71, -8
1673 ];
1674 const KAT_512_G: [i8; 512] = [
1675 27, 6, 12, -3, -31, -42, 27, 17, 11, 8, 34, 6, -3, 2, 11, -11,
1676 18, 48, 1, 21, -7, -6, 9, 33, -18, -40, -55, -9, -71, -50, 32,
1677 -36, 11, 4, 29, 33, 10, -19, -43, -10, 22, -36, -23, -21, -14,
1678 -47, 25, -4, -14, 30, 16, -18, -11, 6, -37, -27, -12, 6, 7, 33,
1679 -36, 33, -2, 12, -21, 1, 16, 49, -11, -16, -41, 15, 11, 8, 20,
1680 -15, 26, -8, 11, -43, -36, 28, 2, -47, -30, -47, -1, 1, 48, -6,
1681 -22, 24, -20, -3, -1, -15, -12, 62, 12, 7, -9, 15, -71, 49, 22,
1682 27, 20, -8, -28, -13, -31, 18, 28, 54, 29, 5, 0, 33, -5, -22,
1683 -21, -12, -14, -2, 11, -24, 32, -26, -71, 21, -15, -20, -12, 36,
1684 -5, 35, 46, 13, -34, -8, 10, -10, 10, 40, -52, 8, 0, 18, -33,
1685 -10, 8, 43, -8, -6, -31, -17, 19, 30, 12, -9, 8, -19, -32, -18,
1686 -1, -37, 4, 43, 27, 14, -6, -14, -44, -34, -8, 16, -39, 13, 6,
1687 -32, 8, 17, -12, 23, -44, -25, -66, -12, -31, 30, 14, -9, -5,
1688 -10, 44, -12, -2, -43, -22, -18, -7, -9, -15, -7, -21, -27, -5,
1689 1, -13, -10, 8, -8, 29, 21, 64, 47, -28, -9, -28, 25, -47, -34,
1690 -3, -14, -26, -12, -5, -10, -27, -9, -14, -23, -2, -31, 28, 17,
1691 -4, -30, 31, 3, -15, 25, 9, -32, 0, -6, -22, 20, -37, 3, 12,
1692 -19, -17, 13, 30, 11, -15, 15, 50, 66, -31, -31, 16, 2, 3, -8,
1693 40, -21, -31, -2, 41, -29, -12, 9, 14, -4, 9, 8, -20, 28, 12,
1694 20, -10, 5, -6, -33, 6, 21, 51, 30, 9, 3, 8, 7, 19, -53, 19, 15,
1695 4, -38, 19, 29, 18, 6, 19, 3, -17, -32, 16, 3, 46, -6, -3, 47,
1696 3, -66, 3, 25, -6, -6, 21, -24, -9, 28, -39, -42, 42, -6, -19,
1697 -14, 6, -8, 9, 28, -4, 23, 12, -17, -13, 3, 3, 6, 44, 6, -5, 38,
1698 -4, -16, 12, -15, 8, -11, 45, 1, -16, 37, -35, 20, 26, 9, 13,
1699 34, 25, -3, -10, -2, -42, -23, -22, -56, -56, 6, 17, -9, 0, 36,
1700 20, 6, -58, 12, 0, -3, -29, -49, -24, -12, -13, 5, -39, -8, 36,
1701 -9, 44, 35, -64, -22, -12, 26, -15, 41, 36, -19, -37, -20, 46,
1702 35, 9, 32, -5, 27, 21, -36, -51, 19, 10, -23, 28, 46, 28, 8, 22,
1703 -31, 18, 2, -16, -9, 1, -22, -22, 31, 14, 5, 44, -3, 38, 0, -12,
1704 50, -23, -19, 1, 42, 15, 1, 13, 32, 45, 37, 15, 11, -9, -23, -6,
1705 -23, 36, 4, -34, -14, -14, -37, -28, 19, 20, 14, 24, -48, -34,
1706 -27, -34, -12, 9, -20, -30, 25, 28, -51, -13, 11, -20, -1, -3,
1707 6, -38, -46, -15, 28, 10, -4, 3, -1, 4, -40, 16, 61, 31, 28, 8,
1708 -2, 21, -3, -25, -12, -32, -15, -38, 20, -7, -35, 28, 29, 9, -27
1709 ];
1710 #[allow(dead_code)]
1711 const KAT_512_VK: [u8; 897] = [
1712 0x09, 0x02, 0xCE, 0x21, 0x6B, 0xE4, 0x2C, 0xD0, 0x4F, 0xC8,
1713 0x4C, 0x24, 0xC7, 0x1D, 0x13, 0x07, 0x8E, 0xCA, 0x07, 0x97,
1714 0x6E, 0xE4, 0xAD, 0xBA, 0x2C, 0x98, 0x23, 0x46, 0xD8, 0x78,
1715 0xC0, 0x94, 0x76, 0x7F, 0xE2, 0x9C, 0x34, 0x5C, 0xE2, 0xFA,
1716 0x87, 0x4B, 0xEE, 0x23, 0x9E, 0xA6, 0x0B, 0xDF, 0xA7, 0x27,
1717 0xA5, 0x16, 0x82, 0xC3, 0xDF, 0x06, 0xA2, 0x68, 0x49, 0xC3,
1718 0xF7, 0x26, 0x46, 0x2A, 0x59, 0xE9, 0xC4, 0x16, 0x63, 0x87,
1719 0xBA, 0x89, 0x56, 0xDF, 0xC9, 0xFA, 0x62, 0x20, 0x95, 0x20,
1720 0xED, 0x65, 0x39, 0xCA, 0xDD, 0xA8, 0xF9, 0xE8, 0x11, 0xA6,
1721 0x8E, 0xD8, 0x69, 0x70, 0x13, 0x5A, 0xD5, 0x02, 0x6D, 0xBD,
1722 0x16, 0xF1, 0x59, 0x97, 0xA4, 0xBB, 0xBE, 0x35, 0x68, 0x38,
1723 0xD7, 0x5C, 0x7A, 0x91, 0x34, 0xED, 0xB8, 0xBF, 0x25, 0xBC,
1724 0xBA, 0x0A, 0x03, 0x13, 0x77, 0xEB, 0xF0, 0x11, 0x0D, 0x54,
1725 0x73, 0xC8, 0x46, 0x82, 0x7B, 0x25, 0x6B, 0x9A, 0xB4, 0xD0,
1726 0x26, 0x1E, 0x41, 0xC8, 0xDB, 0xF1, 0xA4, 0x24, 0xB6, 0xDA,
1727 0x1F, 0x21, 0xD0, 0xE2, 0x1A, 0x89, 0xBD, 0x29, 0x94, 0x07,
1728 0x4F, 0xA5, 0x36, 0x5E, 0xA7, 0x70, 0x0E, 0xEB, 0xD2, 0x26,
1729 0x94, 0x7C, 0xFA, 0x7B, 0xE1, 0xA7, 0x65, 0xF4, 0xD7, 0xF9,
1730 0x27, 0x50, 0x02, 0x3D, 0xF2, 0x68, 0x94, 0x51, 0x2E, 0x79,
1731 0x48, 0xC5, 0x64, 0x69, 0xE8, 0x81, 0xD1, 0x99, 0xDA, 0x81,
1732 0x35, 0xAF, 0xC1, 0x6E, 0x52, 0x3A, 0xF8, 0xA2, 0x3F, 0xD5,
1733 0x80, 0x22, 0xAE, 0x22, 0x9A, 0xC9, 0x5C, 0xFF, 0x09, 0x5D,
1734 0x6F, 0xF3, 0x2C, 0x89, 0x0D, 0xB2, 0x29, 0x41, 0x19, 0x21,
1735 0x90, 0x5B, 0x3B, 0xA5, 0x2D, 0x54, 0xB5, 0x0D, 0xEC, 0xB4,
1736 0x4D, 0xC3, 0xD7, 0xC8, 0x99, 0x66, 0x79, 0xE8, 0x28, 0xA4,
1737 0x3B, 0x8D, 0x06, 0x87, 0xE8, 0xBD, 0xE0, 0x60, 0xC5, 0x10,
1738 0x15, 0xAA, 0x9E, 0x00, 0x0C, 0x92, 0x59, 0x8F, 0x05, 0xB8,
1739 0x70, 0xA9, 0x4B, 0x29, 0x01, 0xA9, 0xE1, 0x2A, 0xE9, 0xAB,
1740 0xF2, 0x0A, 0x51, 0x71, 0x4A, 0x03, 0x6A, 0x85, 0x1C, 0xCE,
1741 0x89, 0x15, 0x42, 0xD1, 0xEB, 0x52, 0x7E, 0x73, 0x10, 0x76,
1742 0xD4, 0xFF, 0x2F, 0x09, 0xBA, 0x68, 0x94, 0xA2, 0x09, 0x03,
1743 0xCA, 0x6F, 0xA7, 0x6E, 0x13, 0xD1, 0x2D, 0xC0, 0xAB, 0xA6,
1744 0xB9, 0x26, 0xED, 0x6E, 0x89, 0x54, 0x84, 0x1D, 0xC0, 0x52,
1745 0x4A, 0x55, 0xE3, 0x65, 0x6C, 0x9C, 0x19, 0x88, 0x5E, 0xAB,
1746 0x65, 0x4D, 0x86, 0x94, 0x93, 0x51, 0xFB, 0x8B, 0x02, 0xEA,
1747 0x32, 0xAE, 0x71, 0x5F, 0x09, 0x8B, 0xE2, 0x4E, 0x83, 0xD2,
1748 0xE2, 0x71, 0xCC, 0x8C, 0x24, 0x14, 0x8E, 0x7B, 0xD5, 0x92,
1749 0x59, 0x28, 0x38, 0xFA, 0x55, 0xB8, 0x8A, 0xDB, 0x89, 0x7B,
1750 0xE5, 0xD9, 0x96, 0x97, 0xE3, 0xFC, 0xAC, 0xFA, 0xC0, 0x25,
1751 0xB4, 0x51, 0xF6, 0x2B, 0x6C, 0x35, 0x62, 0xC9, 0xEF, 0x90,
1752 0x71, 0x44, 0x57, 0xA2, 0xF6, 0x49, 0x22, 0x5F, 0x70, 0x20,
1753 0xE9, 0xAF, 0xDB, 0xB9, 0x2A, 0xE2, 0xBE, 0xDB, 0xA6, 0x19,
1754 0x33, 0xB9, 0x05, 0xCF, 0xD4, 0x1A, 0x03, 0x08, 0x2B, 0xD6,
1755 0xDF, 0x8B, 0x24, 0x27, 0xEC, 0x7B, 0xFC, 0xAB, 0x2A, 0xDE,
1756 0x16, 0x78, 0x9C, 0x09, 0x67, 0x45, 0x67, 0xDE, 0x11, 0x29,
1757 0xC1, 0xB2, 0xF6, 0x9E, 0x9C, 0x0F, 0x8F, 0xB2, 0x37, 0xC5,
1758 0x5D, 0x05, 0xCF, 0x8F, 0x69, 0xAD, 0x8B, 0xB7, 0x27, 0xA2,
1759 0x08, 0x9A, 0x43, 0x71, 0x1E, 0xC6, 0xCA, 0x54, 0xB6, 0x12,
1760 0xC1, 0xD7, 0x2F, 0xA0, 0x2B, 0x66, 0x40, 0x98, 0x78, 0x6D,
1761 0x08, 0x53, 0xD1, 0xBC, 0x98, 0xE1, 0x4A, 0x57, 0x90, 0xB2,
1762 0xCA, 0xC6, 0xC7, 0xD2, 0x48, 0x57, 0xD0, 0xFB, 0x44, 0xF5,
1763 0xD9, 0x5F, 0x34, 0x21, 0x33, 0x96, 0x86, 0xE8, 0xAF, 0xA5,
1764 0xBA, 0x92, 0x4B, 0xBA, 0x94, 0xF0, 0x73, 0xC9, 0x09, 0xE9,
1765 0xFB, 0x8A, 0xD0, 0xA4, 0x62, 0x24, 0xD6, 0xF8, 0x1B, 0x22,
1766 0xA2, 0x01, 0xAE, 0xDB, 0xA8, 0x94, 0xC2, 0xAA, 0x44, 0xBA,
1767 0xD6, 0x87, 0x4D, 0x6E, 0x24, 0xCE, 0x1B, 0xB8, 0x3F, 0x51,
1768 0xE6, 0x9F, 0x34, 0xA1, 0x40, 0xAD, 0x88, 0x55, 0x4F, 0x6C,
1769 0x47, 0x48, 0xFF, 0x9F, 0x64, 0x6F, 0x0D, 0xDB, 0xD3, 0xA4,
1770 0x85, 0xD0, 0xBA, 0xD8, 0x05, 0xFA, 0x29, 0xEB, 0x99, 0x68,
1771 0x18, 0x51, 0x71, 0x45, 0x05, 0xE3, 0x71, 0xA6, 0x4A, 0x7B,
1772 0xCF, 0x68, 0x97, 0x95, 0x81, 0x44, 0x91, 0xDC, 0x9D, 0xC5,
1773 0x27, 0x52, 0xE9, 0xA2, 0x7F, 0x96, 0xF4, 0x6C, 0xE8, 0xF8,
1774 0xA4, 0x27, 0x95, 0xC7, 0x10, 0x7E, 0xC1, 0x86, 0x78, 0x92,
1775 0x49, 0x6C, 0x91, 0xA1, 0x77, 0xFB, 0x80, 0x95, 0x0D, 0x69,
1776 0x3B, 0xD4, 0xAD, 0xDE, 0x30, 0x2E, 0x90, 0x3C, 0x41, 0x32,
1777 0xEC, 0x95, 0x38, 0x86, 0x8D, 0xE8, 0xCF, 0x80, 0x5F, 0x5A,
1778 0x21, 0x92, 0x96, 0x7F, 0xA6, 0xC3, 0x50, 0x6A, 0x1A, 0xAB,
1779 0x3C, 0x11, 0xA1, 0x5F, 0x1E, 0x47, 0xB3, 0xB4, 0x6E, 0x64,
1780 0x97, 0xB1, 0x5A, 0x88, 0x2E, 0x2C, 0xC8, 0x49, 0xA1, 0xB4,
1781 0x42, 0x49, 0xE9, 0x7F, 0x61, 0xF1, 0x6B, 0xD0, 0xEC, 0xEA,
1782 0xD5, 0x47, 0xDD, 0x71, 0xC5, 0xDD, 0xA5, 0xAA, 0x8A, 0x56,
1783 0xFE, 0x36, 0x31, 0x22, 0x15, 0x85, 0x2E, 0x78, 0xDA, 0x98,
1784 0x5D, 0x55, 0xA4, 0xA4, 0xD8, 0xF7, 0x14, 0x8E, 0x45, 0x67,
1785 0xD1, 0xE4, 0x67, 0x87, 0xC2, 0x23, 0x87, 0xCA, 0x4A, 0x85,
1786 0xF0, 0x11, 0xE3, 0x75, 0xC4, 0x5C, 0xCA, 0x0C, 0xE0, 0xA1,
1787 0x5B, 0xCD, 0x13, 0x37, 0xBD, 0xC9, 0x27, 0x1B, 0xFA, 0x84,
1788 0x73, 0xE1, 0x88, 0x2F, 0x33, 0x85, 0x58, 0x69, 0x7D, 0x9A,
1789 0xAF, 0x07, 0x5A, 0x90, 0x78, 0x33, 0x5A, 0x1F, 0xB8, 0xA1,
1790 0xB3, 0xB6, 0xE9, 0xD9, 0xCF, 0x43, 0x62, 0x84, 0x06, 0x7C,
1791 0x58, 0xC5, 0xA4, 0x8E, 0x04, 0x7A, 0x40, 0x08, 0xD0, 0x2B,
1792 0x7C, 0x85, 0x07, 0xC2, 0xEE, 0x6F, 0x88, 0xDA, 0x4C, 0x97,
1793 0xF6, 0x0F, 0x75, 0x44, 0x4C, 0x78, 0x84, 0x96, 0x67, 0x84,
1794 0x32, 0xC9, 0x5F, 0x3A, 0x92, 0x08, 0xB4, 0xA8, 0xC1, 0xCB,
1795 0xC6, 0xE2, 0xD4, 0xDA, 0x61, 0x25, 0x3D, 0xA0, 0x81, 0x27,
1796 0x5E, 0x8F, 0x34, 0xDB, 0xE4, 0xA1, 0xEC, 0xC2, 0x22, 0x24,
1797 0xC3, 0x08, 0x00, 0xA7, 0x75, 0x35, 0x74, 0xC8, 0x95, 0x86,
1798 0x95, 0x66, 0x6C, 0x28, 0x95, 0xB3, 0x5C, 0xCE, 0x07, 0x89,
1799 0x44, 0xA3, 0x10, 0x41, 0xA5, 0x23, 0x83, 0x7C, 0xED, 0x72,
1800 0x17, 0x69, 0x0F, 0xA1, 0x7C, 0x36, 0xCB, 0x45, 0x92, 0x63,
1801 0x35, 0xE6, 0x7B, 0x18, 0x04, 0x95, 0x9D,
1802 ];
1803
1804 const KAT_512_RND: [u8; 40 + 56] = [
1805 0x16, 0xC1, 0x25, 0x15, 0x25, 0x80, 0x93, 0x79, 0x99, 0x56,
1807 0x36, 0x8C, 0xDF, 0xC1, 0x82, 0xC1, 0xCA, 0x4A, 0x34, 0xF0,
1808 0x77, 0xE9, 0x24, 0x44, 0x16, 0xA8, 0xC4, 0xC1, 0x3F, 0xB0,
1809 0xCA, 0x24, 0x1E, 0x8B, 0x7A, 0xC1, 0x71, 0x2D, 0x28, 0xEB,
1810
1811 0xFF, 0xD8, 0x57, 0xF1, 0x49, 0x5C, 0xA5, 0x98, 0xDB, 0x2C,
1813 0x88, 0x64, 0xAF, 0x31, 0xFA, 0x8F, 0x37, 0xBC, 0x73, 0x8D,
1814 0xCD, 0xB6, 0xDD, 0xAA, 0xFD, 0x25, 0x4A, 0xBF, 0xE3, 0x01,
1815 0xB7, 0x91, 0x9B, 0x7E, 0x9B, 0x9F, 0xEC, 0xEA, 0x4E, 0xF0,
1816 0x01, 0xC9, 0x62, 0x9B, 0x96, 0x6B, 0x58, 0xD6, 0x81, 0x25,
1817 0x2F, 0xF3, 0x38, 0x9E, 0x81, 0x6B,
1818 ];
1819 const KAT_512_sig_raw: [i16; 512] = [
1820 11, 201, 176, -24, -141, -151, -63, -323, 154, -363, 168, -173,
1821 -29, -184, -142, 419, -48, 104, 103, -245, -374, 252, -59, 32,
1822 77, -237, 182, -9, 181, -54, -47, 52, -6, 81, 147, 113, -36, 28,
1823 -156, -261, -277, -431, 175, -182, 115, -273, 33, -76, -270,
1824 -124, -25, -61, -166, 65, -9, 34, 52, -104, 240, -81, 120, 55,
1825 9, 273, -13, -1, -193, 442, -43, -58, -86, -100, -14, -96, 245,
1826 -120, 10, 2, -40, 341, 8, 112, -260, 100, -24, -22, -181, -207,
1827 -123, -6, 108, -271, 194, 131, -60, 87, -66, 173, 44, 133, -270,
1828 -182, 176, 59, 289, 25, 98, -47, 153, -257, 160, -21, 73, 58,
1829 -4, -39, 79, -124, 31, 119, -175, -125, -222, -36, 71, 3, -153,
1830 -101, 20, 234, 235, 162, -147, -18, 155, -11, -90, -157, -18,
1831 -408, -18, -53, -16, 169, 104, -135, 303, -219, 572, 109, -235,
1832 -478, 114, 66, -17, 186, -13, -57, 31, -132, 73, 134, 35, -165,
1833 -279, 27, -360, -3, 44, -40, -262, 60, 100, 35, 78, -102, -281,
1834 -189, -66, 122, -65, -73, -287, -236, -131, -121, -24, 72, 68,
1835 -156, -69, 54, -127, -185, 154, 60, 144, -99, -81, 139, 80, 98,
1836 -93, 227, 170, -338, -15, 162, 149, -247, -89, 290, 36, -231,
1837 -77, 121, 205, -45, 140, 6, 45, -134, 248, -252, 58, 210, 204,
1838 272, 205, 282, 19, -15, 327, 70, 102, -36, 93, 67, -42, -243,
1839 106, 104, 47, -333, -139, 195, 49, -22, -138, 166, 308, 143, 57,
1840 -305, -26, -176, -46, -243, -130, 134, -176, -131, -277, 240,
1841 -228, -177, 142, -51, 84, 44, 187, 213, 24, 83, -134, -202, 286,
1842 48, 58, -199, 7, -18, 173, 113, 52, -190, 1, -117, -177, 122,
1843 -229, 83, -90, 46, 115, 63, -33, -4, 23, -51, 148, 97, 169,
1844 -183, -128, 37, 80, 61, 102, -28, 75, 142, 292, -89, -260, -47,
1845 62, 86, 184, 15, -258, -48, -47, -29, 211, -357, 228, -133,
1846 -144, 275, -110, -127, -83, -74, -89, 149, 9, -44, -208, -46,
1847 121, -157, 147, 216, 133, -96, 12, 247, 189, 100, -93, 135, -14,
1848 105, 175, -202, 37, 178, 141, 142, -140, -174, -60, -13, 95,
1849 -208, -84, -52, -144, -125, -2, 63, -436, -273, 47, 106, 122,
1850 -221, -180, 104, -4, -163, -121, 87, 405, 107, -229, 259, 118,
1851 -136, -313, -35, -84, 208, 128, -4, 13, 304, -40, 75, 165, 183,
1852 -196, 7, -48, -21, -250, 160, -280, 370, 91, 198, -228, -70, 30,
1853 -54, -263, -10, -125, -18, -231, -3, 287, -388, -10, 208, -358,
1854 -107, 148, -154, 31, -6, -119, -206, -37, -59, -30, -285, -13,
1855 69, -57, 153, -113, -108, 100, 58, -91, -239, -68, -181, 81, 43,
1856 18, -110, -59, -18, 97, -96, 27, 181, -62, -156, -19, -204, 343,
1857 66, -110, -52, 28, -188, -35, 49, -59, 38, -43, 64, -177, 171,
1858 132, -38, -120, 214, -42, 110, -324, -34, 158, -102, -4, -61,
1859 -117, -134, -310, -99, 79, -308, -306, -199, -126, -190, 27,
1860 -43, 120, 94, 340, -435, -99, 167, 210, -70, -84, 199
1861 ];
1862}