Skip to main content

tide_fn_dsa_sign/
lib.rs

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
13//! # FN-DSA signature generation
14//!
15//! This crate implements signature generation for FN-DSA. A `SigningKey`
16//! instance is created by decoding a signing key (from its encoded
17//! format). Signatures can be generated with the `sign()` method on the
18//! `SigningKey` instance. `sign()` uses the instance mutably because the
19//! process uses relatively large RAM buffers which are part of the
20//! instance (to avoid oversized stack allocation on embedded systems).
21//! The same `SigningKey` can be used for generating several signatures;
22//! this even allows CPU savings since some computations depend only on
23//! the key and can be reused for several signatures.
24//!
25//! The signature process uses a domain-separation context, which is an
26//! arbitrary binary strings (up to 255 bytes in length). If no such
27//! context is required in an application, use `DOMAIN_NONE` (the empty
28//! context).
29//!
30//! The message is supposed to be pre-hashed by the caller: the caller
31//! provides the hashed value, along with an identifier of the used hash
32//! function. The `HASH_ID_RAW` identifier can be used if the message is
33//! not actually pre-hashed, but is provided directly instead of a hash
34//! value.
35//!
36//! FN-DSA is parameterized by a degree, which is a power of two.
37//! Standard versions use degree 512 ("level I security") or 1024 ("level
38//! V security"); smaller degrees are deemed too weak for production use
39//! and meant only for research and testing. The degree is represented
40//! logarithmically as the `logn` value, such that the degree is `n =
41//! 2^logn` (thus, degrees 512 and 1024 correspond to `logn` values 9 and
42//! 10, respectively). The signature size is fixed for a given degree
43//! (see `signature_size()`).
44//!
45//! ## WARNING
46//!
47//! **The FN-DSA standard is currently being drafted, but no version has
48//! been published yet. When published, it may differ from the exact
49//! scheme implemented in this crate, in particular with regard to key
50//! encodings, message pre-hashing, and domain separation. Key pairs
51//! generated with this crate MAY fail to be interoperable with the final
52//! FN-DSA standard. This implementation is expected to be adjusted to
53//! the FN-DSA standard when published (before the 1.0 version release).**
54//!
55//! ## Example usage
56//!
57//! ```no_run
58//! use tide_fn_dsa_sign::{
59//!     SIGN_KEY_SIZE_512, SIGNATURE_SIZE_512, FN_DSA_LOGN_512,
60//!     SigningKey, SigningKeyStandard,
61//!     DOMAIN_NONE, HASH_ID_RAW, CryptoRng, RngCore, RngError,
62//! };
63//! #
64//! # struct DemoRng(u64);
65//! # impl CryptoRng for DemoRng {}
66//! # impl RngCore for DemoRng {
67//! #     fn next_u32(&mut self) -> u32 {
68//! #         let x = self.0 as u32;
69//! #         self.0 = self.0.wrapping_mul(6364136223846793005).wrapping_add(1);
70//! #         x
71//! #     }
72//! #     fn next_u64(&mut self) -> u64 {
73//! #         let x = self.0;
74//! #         self.0 = self.0.wrapping_mul(6364136223846793005).wrapping_add(1);
75//! #         x
76//! #     }
77//! #     fn fill_bytes(&mut self, dest: &mut [u8]) {
78//! #         for chunk in dest.chunks_mut(8) {
79//! #             let bytes = self.next_u64().to_le_bytes();
80//! #             let len = chunk.len();
81//! #             chunk.copy_from_slice(&bytes[..len]);
82//! #         }
83//! #     }
84//! #     fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), RngError> {
85//! #         self.fill_bytes(dest);
86//! #         Ok(())
87//! #     }
88//! # }
89//! 
90//! // Load a valid encoded signing key from storage or key generation.
91//! # let encoded_signing_key: [u8; SIGN_KEY_SIZE_512] = todo!();
92//! let mut sk = SigningKeyStandard::decode(&encoded_signing_key)
93//!     .expect("valid signing key bytes");
94//! let mut sig = [0u8; SIGNATURE_SIZE_512];
95//! let mut rng = DemoRng(1);
96//! sk.sign(&mut rng, &DOMAIN_NONE, &HASH_ID_RAW, b"message", &mut sig)
97//!     .unwrap();
98//! ```
99
100mod 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
108// Re-export useful types, constants and functions.
109pub 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/// Error type for signing-key operations with caller-supplied buffers.
135#[derive(Copy, Clone, Debug, Eq, PartialEq)]
136pub enum SigningKeyError {
137    /// The destination buffer for the verifying key has the wrong size.
138    InvalidVerifyingKeyBufferLen { expected: usize, actual: usize },
139
140    /// The destination buffer for the signature has the wrong size.
141    InvalidSignatureBufferLen { expected: usize, actual: usize },
142
143    /// The destination buffer for a variable-length Falcon signature is too short.
144    InvalidSignatureBufferLenAtLeast { min: usize, actual: usize },
145
146    /// The selected Falcon profile does not support the key degree.
147    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
173/// Signing key handler and temporary buffers.
174///
175/// Signature generation uses relatively large temporary buffers (about
176/// 42 or 84 kB, for the two standard degrees), which is why they are
177/// part of the `SigningKey` instance instead of being allocated on the
178/// stack. An instance can be used for several successive signature
179/// generations. Implementations of this trait are expected to handle
180/// automatic zeroization (overwrite of all contained secret values when
181/// the object is released).
182pub trait SigningKey: Sized {
183
184    /// Create the instance by decoding the signing key from its storage
185    /// format.
186    ///
187    /// If the source uses a degree not supported by this `SigningKey`
188    /// type, or does not have the exact length expected for the degree
189    /// it uses, or is otherwise invalidly encoded, then this function
190    /// returns `None`; otherwise, it returns the new instance.
191    fn decode(sec: &[u8]) -> Option<Self>;
192
193    /// Get the degree associated with this key.
194    ///
195    /// The degree is returned in a logarithmic scale (`logn`, value ranges
196    /// from 2 to 10).
197    fn get_logn(&self) -> u32;
198
199    /// Encode the public (verifying) key into the provided buffer.
200    ///
201    /// The output buffer must have the exact size of the verifying key.
202    fn to_verifying_key(&self, vrfy_key: &mut [u8])
203        -> Result<(), SigningKeyError>;
204
205    /// Generate a signature.
206    ///
207    /// Parameters:
208    ///
209    ///  - `rng`: a cryptographically secure random source
210    ///  - `ctx`: the domain separation context
211    ///  - `id`: the identifier for the pre-hash function
212    ///  - `hv`: the pre-hashed message (or the message itself, if `id`
213    ///    is `HASH_ID_RAW`)
214    ///  - `sig`: the output slice for the generated signature; its size
215    ///    MUST be exactly that expected for the key degree (see
216    ///    `signature_size()`).
217    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    /// Generate a raw-message Falcon-compatible signature.
222    ///
223    /// The returned value is the number of bytes written to `sig`.
224    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        // Basis B = [[g, -f], [G, -F]], in FFT format.
247        #[cfg(not(feature = "small_context"))]
248        basis: [flr::FLR; 4 << ($logn_max)],
249
250        logn: u32,
251
252        // On x86_64, we use AVX2 if available, which is dynamically
253        // tested. We do not do that on plain x86, because plain x86 uses
254        // the emulated floating-point, not the native types (on 32-bit
255        // x86, native floating-point is x87, not SSE2).
256        #[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
466// A SigningKey type that supports the standard degrees (512 and 1024).
467sign_key_impl!(SigningKeyStandard, 9, 10);
468
469// A SigningKey type that supports only degree 512. It uses less RAM than
470// SigningKeyStandard.
471sign_key_impl!(SigningKey512, 9, 9);
472
473// A SigningKey type that supports only degree 1024. It uses as much RAM as
474// SigningKeyStandard but enforces the level V security variant.
475sign_key_impl!(SigningKey1024, 10, 10);
476
477// A SigningKey type that supports only weak/toy degrees (4 to 256). It is
478// meant only for research and testing purposes.
479sign_key_impl!(SigningKeyWeak, 2, 8);
480
481#[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
482mod sign_avx2;
483
484// Decode a private key.
485fn 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    // Coefficients of (f,g) use a number of bits that depends on logn.
518    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    // We already checked the length of src; any mismatch at this point
528    // is an implementation bug.
529    assert!(j == src.len());
530
531    // Compute G from f, g and F. This might fail if the decoded f turns
532    // out to be non-invertible modulo X^n+1 and q, or if the recomputed G
533    // is out of the allowed range (its coefficients should all be in
534    // the [-127,+127] range).
535    // Method:
536    //   f*G - g*F = q = 0 mod q
537    // thus:
538    //   G = g*F/f mod q
539    // We also compute the public key h = g/f mod q.
540    let (w0, w1) = tmp_u16.split_at_mut(n);
541
542    // w0 <- g/f  (NTT)
543    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        // f is not invertible
549        return None;
550    }
551
552    // w1 <- h*F = g*F/f = G  (NTT)
553    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    // Convert back h to external representation and encode it.
558    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    // Convert back G to external representation and check that all
569    // elements are small.
570    mq::mqpoly_NTT_to_int(logn, w1);
571    if !mq::mqpoly_int_to_small(logn, w1, G) {
572        return None;
573    }
574
575    // Decoding succeeded.
576    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    // Lattice basis is B = [[g, -f], [G, -F]].
585    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
602// 1/12289
603const 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    // Hash the message with a 40-byte random nonce, to produce the
645    // hashed message.
646    let mut nonce = [0u8; 40];
647
648    // Usually the signature generation works at the first attempt, but
649    // occasionally we need to try again because the obtained signature
650    // is not a short enough vector, or cannot be encoded in the target
651    // signature size.
652    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        // We initialize the PRNG with a 56-byte seed, to match the
660        // practice from the C code (it makes it simpler to reproduce
661        // test vectors). Any seed of at least 32 bytes would be fine.
662        let mut seed = [0u8; 56];
663        rng.fill_bytes(&mut seed);
664        let mut samp = sampler::Sampler::<P>::new(logn, &seed);
665
666        // Lattice basis is B = [[g, -f], [G, -F]]. We need it in FFT
667        // format, then we compute the Gram matrix G = B*adj(B).
668        // Formulas are:
669        //   g00 = b00*adj(b00) + b01*adj(b01)
670        //   g01 = b00*adj(b10) + b01*adj(b11)
671        //   g10 = b10*adj(b00) + b11*adj(b01)
672        //   g11 = b10*adj(b10) + b11*adj(b11)
673        //
674        // For historical reasons, this implementation uses g00,
675        // g01 and g11 (upper triangle), and omits g10, which is
676        // equal to adj(g01).
677        //
678        // We need the following in tmp_flr:
679        //   g00 g01 g11 b11 b01
680
681        #[cfg(feature = "small_context")]
682        {
683            // We do not have a precomputed basis, we recompute it.
684            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 <- b01*adj(b01)
694            t0.copy_from_slice(&*b01);
695            poly::poly_mulownadj_fft(logn, t0);
696
697            // t1 <- b00*adj(b10)
698            t1.copy_from_slice(&*b00);
699            poly::poly_muladj_fft(logn, t1, b10);
700
701            // b00 <- b00*adj(b00)
702            poly::poly_mulownadj_fft(logn, b00);
703
704            // b00 <- g00
705            poly::poly_add(logn, b00, t0);
706
707            // Save b01 into t0.
708            t0.copy_from_slice(b01);
709
710            // b01 <- g01
711            poly::poly_muladj_fft(logn, b01, b11);
712            poly::poly_add(logn, b01, t1);
713
714            // b10 <- b10*adj(b10)
715            poly::poly_mulownadj_fft(logn, b10);
716
717            // b10 <- g11
718            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            // We have the precomputed basis B in FFT format.
726            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        // Memory layout at this point:
760        //   g00 g01 g11 b11 b01
761
762        {
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            // Set the target (t0,t1) to [hm, 0].
770            // (t1 is not actually set; subsequent computations take into
771            // account that it is conceptually zero)
772            for i in 0..n {
773                t0[i] = flr::FLR::from_i32(hm[i] as i32);
774            }
775
776            // Apply the lattice basis to obtain the real target vector
777            // (after normalization with regard to the modulus).
778            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        // b01 and b11 can now be discarded; we move back (t0, t1).
787        tmp_flr.copy_within((5 * n)..(7 * n), 3 * n);
788
789        // Memory layout at this point:
790        //   g00 g01 g11 t0 t1
791
792        {
793            // Apply sampling.
794            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        // Rearrange layout back to:
803        //   b00 b01 b10 b11 t0 t1
804        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        // Get the lattice point corresponding to the sampled vector.
822        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        // We compute s1, then s2 into buffer s2 (s1 is not retained).
836        // We accumulate their squared norm in sqn, with an "overflow"
837        // flag in ng. Since every value is coerced to the i16 type,
838        // a squared norm going over 2^31-1 necessarily implies at some
839        // point that the high bit of sqn is set, which will show up
840        // as the high bit of ng being set.
841        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        // With standard degrees (512 and 1024), it is very improbable that
851        // the computed vector is not short enough; however, it may happen
852        // for smaller degrees in test/toy versions (e.g. degree 16). We
853        // need to loop in these cases.
854        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        // If the squared norm exceeded 2^31-1 at some point, then the
864        // high bit of ng is set. We saturate sqn to 2^32-1 in that case
865        // (which will be enough to make the value too large, and force
866        // a new loop iteration).
867        sqn |= ((ng as i32) >> 31) as u32;
868        if sqn > mq::SQBETA[logn as usize] {
869            continue;
870        }
871
872        // We have a candidate signature; we must encode it. This may
873        // fail, since encoding is variable-size and might not fit in the
874        // target size.
875        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    // We need SHAKE256x4 for some tests (because test vectors were
1088    // originally built with that PRNG). If we are not using it in
1089    // the main code, then we must define a custom one here.
1090    #[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    // PRNG implementation based on ChaCha20, used to mimic the reference
1183    // C code to get reproducible behaviour. The seed MUST have length
1184    // 56 bytes exactly (this is how it is used in sign_inner()).
1185    #[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    // Fake CryptoRng that returns only predefined data, for test purposes.
1475    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        // We use a fake random source that returns some predefined bytes.
1497        let mut rng = FakeCryptoRng(0);
1498
1499        // Sign a specific message with the private key.
1500        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        // Check that the signature value (s2) is exactly the one which
1524        // was expected.
1525        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        // We use a fake random source that returns some predefined bytes.
1539        let mut rng = FakeCryptoRng(0);
1540
1541        // Sign a specific message with the private key.
1542        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        // Check that the signature value (s2) is exactly the one which
1570        // was expected.
1571        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        // nonce: 40 bytes
1806        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        // seed for the ChaCha20 PRNG: 56 bytes
1812        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}