Skip to main content

fn_dsa_sign/
lib.rs

1#![no_std]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4#![allow(clippy::too_many_arguments)]
5
6//! # FN-DSA signature generation
7//!
8//! This crate implements signature generation for FN-DSA. A `SigningKey`
9//! instance is created by decoding a signing key (from its encoded
10//! format). Signatures can be generated with the `sign()` method on the
11//! `SigningKey` instance. `sign()` uses the instance mutably because the
12//! process uses relatively large RAM buffers which are part of the
13//! instance (to avoid oversized stack allocation on embedded systems).
14//! The same `SigningKey` can be used for generating several signatures;
15//! this even allows CPU savings since some computations depend only on
16//! the key and can be reused for several signatures.
17//!
18//! The signature process uses a domain-separation context, which is an
19//! arbitrary binary strings (up to 255 bytes in length). If no such
20//! context is required in an application, use `DOMAIN_NONE` (the empty
21//! context).
22//!
23//! The message is supposed to be pre-hashed by the caller: the caller
24//! provides the hashed value, along with an identifier of the used hash
25//! function. The `HASH_ID_RAW` identifier can be used if the message is
26//! not actually pre-hashed, but is provided directly instead of a hash
27//! value.
28//!
29//! FN-DSA is parameterized by a degree, which is a power of two.
30//! Standard versions use degree 512 ("level I security") or 1024 ("level
31//! V security"); smaller degrees are deemed too weak for production use
32//! and meant only for research and testing. The degree is represented
33//! logarithmically as the `logn` value, such that the degree is `n =
34//! 2^logn` (thus, degrees 512 and 1024 correspond to `logn` values 9 and
35//! 10, respectively). The signature size is fixed for a given degree
36//! (see `signature_size()`).
37//!
38//! ## Standards alignment
39//!
40//! This crate targets **NIST FIPS 206** (FN-DSA). Key encodings, message
41//! pre-hashing, and domain separation follow the published standard. If NIST
42//! publishes errata or CAVP test-vector updates that affect wire
43//! interoperability, releases of this crate may adjust accordingly; consult
44//! release notes when upgrading.
45//!
46//! ## Example usage
47//!
48//! ```ignore
49//! use rand_core::OsRng;
50//! use fn_dsa_sign::{
51//!     sign_key_size, signature_size, FN_DSA_LOGN_512,
52//!     SigningKey, SigningKeyStandard,
53//!     DOMAIN_NONE, HASH_ID_RAW,
54//! };
55//!
56//! let mut sk = SigningKeyStandard::decode(encoded_signing_key)?;
57//! let mut sig = vec![0u8; signature_size(sk.get_logn())];
58//! sk.sign(&mut OsRng, &DOMAIN_NONE, &HASH_ID_RAW, b"message", &mut sig);
59//! ```
60
61mod flr;
62mod poly;
63mod sampler;
64
65// Re-export useful types, constants and functions.
66pub use fn_dsa_comm::{
67    CryptoRng,
68    DOMAIN_NONE,
69    DomainContext,
70    FN_DSA_LOGN_512,
71    FN_DSA_LOGN_1024,
72    HASH_ID_RAW,
73    HASH_ID_SHA3_256,
74    HASH_ID_SHA3_384,
75    HASH_ID_SHA3_512,
76    HASH_ID_SHA256,
77    HASH_ID_SHA384,
78    HASH_ID_SHA512,
79    HASH_ID_SHA512_256,
80    HASH_ID_SHAKE128,
81    HASH_ID_SHAKE256,
82    HashIdentifier,
83    Rng,
84    RngError,
85    sign_key_size,
86    signature_size,
87    vrfy_key_size,
88};
89use fn_dsa_comm::{
90    PRNG,
91    codec,
92    hash_to_point,
93    mq,
94    shake,
95};
96use zeroize::{
97    Zeroize,
98    ZeroizeOnDrop,
99};
100
101/// Signing key handler and temporary buffers.
102///
103/// Signature generation uses relatively large temporary buffers (about
104/// 42 or 84 kB, for the two standard degrees), which is why they are
105/// part of the `SigningKey` instance instead of being allocated on the
106/// stack. An instance can be used for several successive signature
107/// generations. Implementations of this trait are expected to handle
108/// automatic zeroization (overwrite of all contained secret values when
109/// the object is released).
110pub trait SigningKey: Sized {
111    /// Create the instance by decoding the signing key from its storage
112    /// format.
113    ///
114    /// If the source uses a degree not supported by this `SigningKey`
115    /// type, or does not have the exact length expected for the degree
116    /// it uses, or is otherwise invalidly encoded, then this function
117    /// returns `None`; otherwise, it returns the new instance.
118    fn decode(sec: &[u8]) -> Option<Self>;
119
120    /// Get the degree associated with this key.
121    ///
122    /// The degree is returned in a logarithmic scale (`logn`, value ranges
123    /// from 2 to 10).
124    fn get_logn(&self) -> u32;
125
126    /// Encode the public (verifying) key into the provided buffer.
127    ///
128    /// The output buffer must have the exact size of the verifying key.
129    fn to_verifying_key(&self, vrfy_key: &mut [u8]);
130
131    /// Generate a signature.
132    ///
133    /// Parameters:
134    ///
135    ///  - `rng`: a cryptographically secure random source
136    ///  - `ctx`: the domain separation context
137    ///  - `id`: the identifier for the pre-hash function
138    ///  - `hv`: the pre-hashed message (or the message itself, if `id`
139    ///    is `HASH_ID_RAW`)
140    ///  - `sig`: the output slice for the generated signature; its size
141    ///    MUST be exactly that expected for the key degree (see
142    ///    `signature_size()`).
143    fn sign<T: CryptoRng + Rng>(
144        &mut self,
145        rng: &mut T,
146        ctx: &DomainContext,
147        id: &HashIdentifier,
148        hv: &[u8],
149        sig: &mut [u8],
150    );
151}
152
153macro_rules! sign_key_impl {
154    ($typename:ident, $logn_min:expr, $logn_max:expr) => {
155        #[doc = concat!("Signature generator for degrees (`logn`) ",
156                                stringify!($logn_min), " to ", stringify!($logn_max), " only.")]
157        #[derive(Zeroize, ZeroizeOnDrop)]
158        pub struct $typename {
159            f: [i8; 1 << ($logn_max)],
160            g: [i8; 1 << ($logn_max)],
161            F: [i8; 1 << ($logn_max)],
162            G: [i8; 1 << ($logn_max)],
163            vrfy_key: [u8; vrfy_key_size($logn_max)],
164            hashed_vrfy_key: [u8; 64],
165            tmp_i16: [i16; 1 << ($logn_max)],
166            tmp_u16: [u16; 2 << ($logn_max)],
167            tmp_flr: [flr::Flr; 9 << ($logn_max)],
168
169            // Basis B = [[g, -f], [G, -F]], in FFT format.
170            #[cfg(not(feature = "small_context"))]
171            basis: [flr::Flr; 4 << ($logn_max)],
172
173            logn: u32,
174
175            // On x86_64, we use AVX2 if available, which is dynamically
176            // tested. We do not do that on plain x86, because plain x86 uses
177            // the emulated floating-point, not the native types (on 32-bit
178            // x86, native floating-point is x87, not SSE2).
179            #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
180            use_avx2: bool,
181        }
182
183        impl $typename {
184            fn decode_key(&mut self, src: &[u8]) -> Option<u32> {
185                #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
186                if self.use_avx2 {
187                    unsafe {
188                        return sign_avx2::decode_avx2_inner(
189                            $logn_min,
190                            $logn_max,
191                            &mut self.f[..],
192                            &mut self.g[..],
193                            &mut self.F[..],
194                            &mut self.G[..],
195                            &mut self.vrfy_key[..],
196                            &mut self.hashed_vrfy_key[..],
197                            &mut self.tmp_u16[..],
198                            src,
199                        );
200                    }
201                }
202
203                decode_inner(
204                    $logn_min,
205                    $logn_max,
206                    &mut self.f[..],
207                    &mut self.g[..],
208                    &mut self.F[..],
209                    &mut self.G[..],
210                    &mut self.vrfy_key[..],
211                    &mut self.hashed_vrfy_key[..],
212                    &mut self.tmp_u16[..],
213                    src,
214                )
215            }
216
217            #[cfg(not(feature = "small_context"))]
218            fn compute_basis(&mut self) {
219                let n = 1usize << self.logn;
220
221                #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
222                if self.use_avx2 {
223                    unsafe {
224                        sign_avx2::compute_basis_avx2_inner(
225                            self.logn,
226                            &self.f[..n],
227                            &self.g[..n],
228                            &self.F[..n],
229                            &self.G[..n],
230                            &mut self.basis[..(4 * n)],
231                        );
232                    }
233                    return;
234                }
235
236                compute_basis_inner(
237                    self.logn,
238                    &self.f[..n],
239                    &self.g[..n],
240                    &self.F[..n],
241                    &self.G[..n],
242                    &mut self.basis[..(4 * n)],
243                );
244            }
245        }
246
247        impl SigningKey for $typename {
248            fn decode(src: &[u8]) -> Option<Self> {
249                let f = [0i8; 1 << ($logn_max)];
250                let g = [0i8; 1 << ($logn_max)];
251                let F = [0i8; 1 << ($logn_max)];
252                let G = [0i8; 1 << ($logn_max)];
253                let vrfy_key = [0u8; vrfy_key_size($logn_max)];
254                let hashed_vrfy_key = [0u8; 64];
255                let tmp_i16 = [0i16; 1 << ($logn_max)];
256                let tmp_u16 = [0u16; 2 << ($logn_max)];
257                let tmp_flr = [flr::Flr::ZERO; 9 << ($logn_max)];
258
259                #[cfg(not(feature = "small_context"))]
260                let basis = [flr::Flr::ZERO; 4 << ($logn_max)];
261
262                let mut sk = Self {
263                    f,
264                    g,
265                    F,
266                    G,
267                    vrfy_key,
268                    hashed_vrfy_key,
269                    tmp_i16,
270                    tmp_u16,
271                    tmp_flr,
272                    #[cfg(not(feature = "small_context"))]
273                    basis,
274                    logn: 0,
275                    #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
276                    use_avx2: fn_dsa_comm::has_avx2(),
277                };
278                sk.logn = sk.decode_key(src)?;
279
280                #[cfg(not(feature = "small_context"))]
281                sk.compute_basis();
282
283                Some(sk)
284            }
285
286            fn get_logn(&self) -> u32 {
287                self.logn
288            }
289
290            fn to_verifying_key(&self, vrfy_key: &mut [u8]) {
291                let len = vrfy_key_size(self.logn);
292                assert!(vrfy_key.len() == len);
293                vrfy_key.copy_from_slice(&self.vrfy_key[..len]);
294            }
295
296            fn sign<T: CryptoRng + Rng>(
297                &mut self,
298                rng: &mut T,
299                ctx: &DomainContext,
300                id: &HashIdentifier,
301                hv: &[u8],
302                sig: &mut [u8],
303            ) {
304                let n = 1usize << self.logn;
305
306                #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
307                if self.use_avx2 {
308                    unsafe {
309                        #[cfg(feature = "shake256x4")]
310                        sign_avx2::sign_avx2_inner::<T, shake::SHAKE256x4>(
311                            self.logn,
312                            rng,
313                            &self.f[..n],
314                            &self.g[..n],
315                            &self.F[..n],
316                            &self.G[..n],
317                            &self.hashed_vrfy_key,
318                            ctx,
319                            id,
320                            hv,
321                            sig,
322                            #[cfg(not(feature = "small_context"))]
323                            &self.basis[..(4 * n)],
324                            &mut self.tmp_i16,
325                            &mut self.tmp_u16,
326                            &mut self.tmp_flr,
327                        );
328
329                        #[cfg(not(feature = "shake256x4"))]
330                        sign_avx2::sign_avx2_inner::<T, shake::SHAKE256_PRNG>(
331                            self.logn,
332                            rng,
333                            &self.f[..n],
334                            &self.g[..n],
335                            &self.F[..n],
336                            &self.G[..n],
337                            &self.hashed_vrfy_key,
338                            ctx,
339                            id,
340                            hv,
341                            sig,
342                            #[cfg(not(feature = "small_context"))]
343                            &self.basis[..(4 * n)],
344                            &mut self.tmp_i16,
345                            &mut self.tmp_u16,
346                            &mut self.tmp_flr,
347                        );
348                    }
349                    return;
350                }
351
352                #[cfg(feature = "shake256x4")]
353                sign_inner::<T, shake::SHAKE256x4>(
354                    self.logn,
355                    rng,
356                    &self.f[..n],
357                    &self.g[..n],
358                    &self.F[..n],
359                    &self.G[..n],
360                    &self.hashed_vrfy_key,
361                    ctx,
362                    id,
363                    hv,
364                    sig,
365                    #[cfg(not(feature = "small_context"))]
366                    &self.basis[..(4 * n)],
367                    &mut self.tmp_i16,
368                    &mut self.tmp_u16,
369                    &mut self.tmp_flr,
370                );
371
372                #[cfg(not(feature = "shake256x4"))]
373                sign_inner::<T, shake::SHAKE256_PRNG>(
374                    self.logn,
375                    rng,
376                    &self.f[..n],
377                    &self.g[..n],
378                    &self.F[..n],
379                    &self.G[..n],
380                    &self.hashed_vrfy_key,
381                    ctx,
382                    id,
383                    hv,
384                    sig,
385                    #[cfg(not(feature = "small_context"))]
386                    &self.basis[..(4 * n)],
387                    &mut self.tmp_i16,
388                    &mut self.tmp_u16,
389                    &mut self.tmp_flr,
390                );
391            }
392        }
393    };
394}
395
396// A SigningKey type that supports the standard degrees (512 and 1024).
397sign_key_impl!(SigningKeyStandard, 9, 10);
398
399// A SigningKey type that supports only degree 512. It uses less RAM than
400// SigningKeyStandard.
401sign_key_impl!(SigningKey512, 9, 9);
402
403// A SigningKey type that supports only degree 1024. It uses as much RAM as
404// SigningKeyStandard but enforces the level V security variant.
405sign_key_impl!(SigningKey1024, 10, 10);
406
407// A SigningKey type that supports only weak/toy degrees (4 to 256). It is
408// meant only for research and testing purposes.
409sign_key_impl!(SigningKeyWeak, 2, 8);
410
411#[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
412mod sign_avx2;
413
414// Decode a private key.
415fn decode_inner(
416    logn_min: u32,
417    logn_max: u32,
418    f: &mut [i8],
419    g: &mut [i8],
420    F: &mut [i8],
421    G: &mut [i8],
422    vrfy_key: &mut [u8],
423    hashed_vrfy_key: &mut [u8],
424    tmp_u16: &mut [u16],
425    src: &[u8],
426) -> Option<u32> {
427    if src.is_empty() {
428        return None;
429    }
430    let head = src[0];
431    if (head & 0xF0) != 0x50 {
432        return None;
433    }
434    let logn = (head & 0x0F) as u32;
435    if logn < logn_min || logn > logn_max {
436        return None;
437    }
438    if src.len() != sign_key_size(logn) {
439        return None;
440    }
441    let n = 1usize << logn;
442    assert!(f.len() >= n);
443    assert!(g.len() >= n);
444    assert!(F.len() >= n);
445    assert!(G.len() >= n);
446    assert!(vrfy_key.len() >= vrfy_key_size(logn));
447    assert!(hashed_vrfy_key.len() == 64);
448    let f = &mut f[..n];
449    let g = &mut g[..n];
450    let F = &mut F[..n];
451    let G = &mut G[..n];
452    let vk = &mut vrfy_key[..vrfy_key_size(logn)];
453
454    // Coefficients of (f,g) use a number of bits that depends on logn.
455    let nbits_fg = match logn {
456        2..=5 => 8,
457        6..=7 => 7,
458        8..=9 => 6,
459        _ => 5,
460    };
461    let j = 1 + codec::trim_i8_decode(&src[1..], f, nbits_fg)?;
462    let j = j + codec::trim_i8_decode(&src[j..], g, nbits_fg)?;
463    let j = j + codec::trim_i8_decode(&src[j..], F, 8)?;
464    // We already checked the length of src; any mismatch at this point
465    // is an implementation bug.
466    assert!(j == src.len());
467
468    // Compute G from f, g and F. This might fail if the decoded f turns
469    // out to be non-invertible modulo X^n+1 and q, or if the recomputed G
470    // is out of the allowed range (its coefficients should all be in
471    // the [-127,+127] range).
472    // Method:
473    //   f*G - g*F = q = 0 mod q
474    // thus:
475    //   G = g*F/f mod q
476    // We also compute the public key h = g/f mod q.
477    let (w0, w1) = tmp_u16.split_at_mut(n);
478
479    // w0 <- g/f  (NTT)
480    mq::mqpoly_small_to_int(logn, &*g, w0);
481    mq::mqpoly_small_to_int(logn, &*f, w1);
482    mq::mqpoly_int_to_NTT(logn, w0);
483    mq::mqpoly_int_to_NTT(logn, w1);
484    if !mq::mqpoly_div_ntt(logn, w0, w1) {
485        // f is not invertible
486        return None;
487    }
488
489    // w1 <- h*F = g*F/f = G  (NTT)
490    mq::mqpoly_small_to_int(logn, &*F, w1);
491    mq::mqpoly_int_to_NTT(logn, w1);
492    mq::mqpoly_mul_ntt(logn, w1, w0);
493
494    // Convert back h to external representation and encode it.
495    mq::mqpoly_NTT_to_int(logn, w0);
496    mq::mqpoly_int_to_ext(logn, w0);
497    vk[0] = logn as u8;
498    let j = 1 + codec::modq_encode(&w0[..n], &mut vk[1..]);
499    assert!(j == vk.len());
500    let mut sh = shake::SHAKE256::new();
501    sh.inject(vk);
502    sh.flip();
503    sh.extract(hashed_vrfy_key);
504
505    // Convert back G to external representation and check that all
506    // elements are small.
507    mq::mqpoly_NTT_to_int(logn, w1);
508    if !mq::mqpoly_int_to_small(logn, w1, G) {
509        return None;
510    }
511
512    // Decoding succeeded.
513    Some(logn)
514}
515
516fn compute_basis_inner(logn: u32, f: &[i8], g: &[i8], F: &[i8], G: &[i8], basis: &mut [flr::Flr]) {
517    let n = 1usize << logn;
518
519    // Lattice basis is B = [[g, -f], [G, -F]].
520    let (b00, work) = basis.split_at_mut(n);
521    let (b01, work) = work.split_at_mut(n);
522    let (b10, work) = work.split_at_mut(n);
523    let (b11, _) = work.split_at_mut(n);
524
525    poly::poly_set_small(logn, b01, f);
526    poly::poly_set_small(logn, b00, g);
527    poly::poly_set_small(logn, b11, F);
528    poly::poly_set_small(logn, b10, G);
529    poly::FFT(logn, b01);
530    poly::FFT(logn, b00);
531    poly::FFT(logn, b11);
532    poly::FFT(logn, b10);
533    poly::poly_neg(logn, b01);
534    poly::poly_neg(logn, b11);
535}
536
537// 1/12289
538const INV_Q: flr::Flr = flr::Flr::scaled(6004310871091074, -66);
539
540fn sign_inner<T: CryptoRng + Rng, P: PRNG>(
541    logn: u32,
542    rng: &mut T,
543    f: &[i8],
544    g: &[i8],
545    F: &[i8],
546    G: &[i8],
547    hashed_vrfy_key: &[u8],
548    ctx: &DomainContext,
549    id: &HashIdentifier,
550    hv: &[u8],
551    sig: &mut [u8],
552    #[cfg(not(feature = "small_context"))] basis: &[flr::Flr],
553    tmp_i16: &mut [i16],
554    tmp_u16: &mut [u16],
555    tmp_flr: &mut [flr::Flr],
556) {
557    let n = 1usize << logn;
558    assert!(f.len() == n);
559    assert!(g.len() == n);
560    assert!(F.len() == n);
561    assert!(G.len() == n);
562    assert!(sig.len() == signature_size(logn));
563
564    // Original Falcon support removed for security - always use proper FN-DSA
565
566    // Hash the message with a 40-byte random nonce, to produce the
567    // hashed message.
568    let mut nonce = [0u8; 40];
569    let mut first = true;
570
571    // Usually the signature generation works at the first attempt, but
572    // occasionally we need to try again because the obtained signature
573    // is not a short enough vector, or cannot be encoded in the target
574    // signature size.
575    loop {
576        let hm = &mut tmp_u16[0..n];
577        // We must generate a random 40-byte nonce, and hash the
578        // message to a polynomial hm[].
579        // In FN-DSA, message hashing is done at each loop restart for security
580        if first {
581            rng.fill_bytes(&mut nonce);
582            hash_to_point(&nonce, hashed_vrfy_key, ctx, id, hv, hm);
583            first = false;
584        }
585
586        // We initialize the PRNG with a 56-byte seed, to match the
587        // practice from the C code (it makes it simpler to reproduce
588        // test vectors). Any seed of at least 32 bytes would be fine.
589        let mut seed = [0u8; 56];
590        rng.fill_bytes(&mut seed);
591        let mut samp = sampler::Sampler::<P>::new(logn, &seed);
592
593        // Lattice basis is B = [[g, -f], [G, -F]]. We need it in FFT
594        // format, then we compute the Gram matrix G = B*adj(B).
595        // Formulas are:
596        //   g00 = b00*adj(b00) + b01*adj(b01)
597        //   g01 = b00*adj(b10) + b01*adj(b11)
598        //   g10 = b10*adj(b00) + b11*adj(b01)
599        //   g11 = b10*adj(b10) + b11*adj(b11)
600        //
601        // For historical reasons, this implementation uses g00,
602        // g01 and g11 (upper triangle), and omits g10, which is
603        // equal to adj(g01).
604        //
605        // We need the following in tmp_flr:
606        //   g00 g01 g11 b11 b01
607
608        #[cfg(feature = "small_context")]
609        {
610            // We do not have a precomputed basis, we recompute it.
611            compute_basis_inner(logn, f, g, F, G, tmp_flr);
612
613            let (b00, work) = tmp_flr.split_at_mut(n);
614            let (b01, work) = work.split_at_mut(n);
615            let (b10, work) = work.split_at_mut(n);
616            let (b11, work) = work.split_at_mut(n);
617            let (t0, work) = work.split_at_mut(n);
618            let (t1, _) = work.split_at_mut(n);
619
620            // t0 <- b01*adj(b01)
621            t0.copy_from_slice(&*b01);
622            poly::poly_mulownadj_fft(logn, t0);
623
624            // t1 <- b00*adj(b10)
625            t1.copy_from_slice(&*b00);
626            poly::poly_muladj_fft(logn, t1, b10);
627
628            // b00 <- b00*adj(b00)
629            poly::poly_mulownadj_fft(logn, b00);
630
631            // b00 <- g00
632            poly::poly_add(logn, b00, t0);
633
634            // Save b01 into t0.
635            t0.copy_from_slice(b01);
636
637            // b01 <- g01
638            poly::poly_muladj_fft(logn, b01, b11);
639            poly::poly_add(logn, b01, t1);
640
641            // b10 <- b10*adj(b10)
642            poly::poly_mulownadj_fft(logn, b10);
643
644            // b10 <- g11
645            t1.copy_from_slice(b11);
646            poly::poly_mulownadj_fft(logn, t1);
647            poly::poly_add(logn, b10, t1);
648        }
649
650        #[cfg(not(feature = "small_context"))]
651        {
652            // We have the precomputed basis B in FFT format.
653            let (b00, work) = basis.split_at(n);
654            let (b01, work) = work.split_at(n);
655            let (b10, work) = work.split_at(n);
656            let (b11, _) = work.split_at(n);
657
658            let (g00, work) = tmp_flr.split_at_mut(n);
659            let (g01, work) = work.split_at_mut(n);
660            let (g11, work) = work.split_at_mut(n);
661            let (t0, work) = work.split_at_mut(n);
662            let (t1, _) = work.split_at_mut(n);
663
664            g00.copy_from_slice(b00);
665            poly::poly_mulownadj_fft(logn, g00);
666            t0.copy_from_slice(b01);
667            poly::poly_mulownadj_fft(logn, t0);
668            poly::poly_add(logn, g00, t0);
669
670            g01.copy_from_slice(b00);
671            poly::poly_muladj_fft(logn, g01, b10);
672            t0.copy_from_slice(b01);
673            poly::poly_muladj_fft(logn, t0, b11);
674            poly::poly_add(logn, g01, t0);
675
676            g11.copy_from_slice(b10);
677            poly::poly_mulownadj_fft(logn, g11);
678            t0.copy_from_slice(b11);
679            poly::poly_mulownadj_fft(logn, t0);
680            poly::poly_add(logn, g11, t0);
681
682            t0.copy_from_slice(b11);
683            t1.copy_from_slice(b01);
684        }
685
686        // Memory layout at this point:
687        //   g00 g01 g11 b11 b01
688
689        {
690            let (_, work) = tmp_flr.split_at_mut(3 * n);
691            let (b11, work) = work.split_at_mut(n);
692            let (b01, work) = work.split_at_mut(n);
693            let (t0, work) = work.split_at_mut(n);
694            let (t1, _) = work.split_at_mut(n);
695
696            // Set the target (t0,t1) to [hm, 0].
697            // (t1 is not actually set; subsequent computations take into
698            // account that it is conceptually zero)
699            for i in 0..n {
700                t0[i] = flr::Flr::from_i32(hm[i] as i32);
701            }
702
703            // Apply the lattice basis to obtain the real target vector
704            // (after normalization with regard to the modulus).
705            poly::FFT(logn, t0);
706            t1.copy_from_slice(t0);
707            poly::poly_mul_fft(logn, t1, b01);
708            poly::poly_mulconst(logn, t1, -INV_Q);
709            poly::poly_mul_fft(logn, t0, b11);
710            poly::poly_mulconst(logn, t0, INV_Q);
711        }
712
713        // b01 and b11 can now be discarded; we move back (t0, t1).
714        tmp_flr.copy_within((5 * n)..(7 * n), 3 * n);
715
716        // Memory layout at this point:
717        //   g00 g01 g11 t0 t1
718
719        {
720            // Apply sampling.
721            let (g00, work) = tmp_flr.split_at_mut(n);
722            let (g01, work) = work.split_at_mut(n);
723            let (g11, work) = work.split_at_mut(n);
724            let (t0, work) = work.split_at_mut(n);
725            let (t1, work) = work.split_at_mut(n);
726            samp.ffsamp_fft(t0, t1, g00, g01, g11, work);
727        }
728
729        // Rearrange layout back to:
730        //   b00 b01 b10 b11 t0 t1
731        tmp_flr.copy_within((3 * n)..(5 * n), 4 * n);
732
733        #[cfg(feature = "small_context")]
734        compute_basis_inner(logn, f, g, F, G, tmp_flr);
735
736        #[cfg(not(feature = "small_context"))]
737        tmp_flr[..(4 * n)].copy_from_slice(&basis[..(4 * n)]);
738
739        let (b00, work) = tmp_flr.split_at_mut(n);
740        let (b01, work) = work.split_at_mut(n);
741        let (b10, work) = work.split_at_mut(n);
742        let (b11, work) = work.split_at_mut(n);
743        let (t0, work) = work.split_at_mut(n);
744        let (t1, work) = work.split_at_mut(n);
745        let (tx, work) = work.split_at_mut(n);
746        let (ty, _) = work.split_at_mut(n);
747
748        // Get the lattice point corresponding to the sampled vector.
749        tx.copy_from_slice(t0);
750        ty.copy_from_slice(t1);
751        poly::poly_mul_fft(logn, tx, b00);
752        poly::poly_mul_fft(logn, ty, b10);
753        poly::poly_add(logn, tx, ty);
754        ty.copy_from_slice(t0);
755        poly::poly_mul_fft(logn, ty, b01);
756        t0.copy_from_slice(tx);
757        poly::poly_mul_fft(logn, t1, b11);
758        poly::poly_add(logn, t1, ty);
759        poly::iFFT(logn, t0);
760        poly::iFFT(logn, t1);
761
762        // We compute s1, then s2 into buffer s2 (s1 is not retained).
763        // We accumulate their squared norm in sqn, with an "overflow"
764        // flag in ng. Since every value is coerced to the i16 type,
765        // a squared norm going over 2^31-1 necessarily implies at some
766        // point that the high bit of sqn is set, which will show up
767        // as the high bit of ng being set.
768        let mut sqn = 0u32;
769        let mut ng = 0;
770        for i in 0..n {
771            let z = (hm[i] as i32) - (t0[i].rint() as i32);
772            let z = (z as i16) as i32;
773            sqn = sqn.wrapping_add((z * z) as u32);
774            ng |= sqn;
775        }
776
777        // With standard degrees (512 and 1024), it is very improbable that
778        // the computed vector is not short enough; however, it may happen
779        // for smaller degrees in test/toy versions (e.g. degree 16). We
780        // need to loop in these cases.
781        let s2 = &mut tmp_i16[..n];
782        for i in 0..n {
783            let sz = (-t1[i].rint()) as i16;
784            let z = sz as i32;
785            sqn = sqn.wrapping_add((z * z) as u32);
786            ng |= sqn;
787            s2[i] = sz;
788        }
789
790        // If the squared norm exceeded 2^31-1 at some point, then the
791        // high bit of ng is set. We saturate sqn to 2^32-1 in that case
792        // (which will be enough to make the value too large, and force
793        // a new loop iteration).
794        sqn |= ((ng as i32) >> 31) as u32;
795        if sqn > mq::SQBETA[logn as usize] {
796            continue;
797        }
798
799        // We have a candidate signature; we must encode it. This may
800        // fail, since encoding is variable-size and might not fit in the
801        // target size.
802        if codec::comp_encode(s2, &mut sig[41..]) {
803            sig[0] = 0x30 + (logn as u8);
804            sig[1..41].copy_from_slice(&nonce);
805            return;
806        }
807    }
808}
809
810#[cfg(test)]
811pub(crate) mod tests {
812    #![allow(clippy::unwrap_used)]
813
814    use fn_dsa_comm::shake::SHAKE256;
815    // We need SHAKE256x4 for some tests (because test vectors were
816    // originally built with that PRNG). If we are not using it in
817    // the main code, then we must define a custom one here.
818    #[cfg(feature = "shake256x4")]
819    pub(crate) use fn_dsa_comm::shake::SHAKE256x4;
820    use fn_dsa_comm::{
821        Infallible,
822        TryCryptoRng,
823        TryRng,
824    };
825
826    use super::*;
827
828    #[cfg(not(feature = "shake256x4"))]
829    #[derive(Copy, Clone, Debug)]
830    pub(crate) struct SHAKE256x4 {
831        sh: [SHAKE256; 4],
832        buf: [u8; 4 * 136],
833        ptr: usize,
834    }
835
836    #[cfg(not(feature = "shake256x4"))]
837    impl SHAKE256x4 {
838        pub fn new(seed: &[u8]) -> Self {
839            let mut sh = [
840                SHAKE256::new(),
841                SHAKE256::new(),
842                SHAKE256::new(),
843                SHAKE256::new(),
844            ];
845            for (i, item) in sh.iter_mut().enumerate() {
846                item.inject(seed);
847                item.inject(&[i as u8]);
848                item.flip();
849            }
850            Self {
851                sh,
852                buf: [0u8; 4 * 136],
853                ptr: 4 * 136,
854            }
855        }
856
857        fn refill(&mut self) {
858            self.ptr = 0;
859            for i in 0..(4 * 136 / 32) {
860                for j in 0..4 {
861                    let k = 32 * i + 8 * j;
862                    self.sh[j].extract(&mut self.buf[k..(k + 8)]);
863                }
864            }
865        }
866
867        pub fn next_u8(&mut self) -> u8 {
868            if self.ptr >= 4 * 136 {
869                self.refill();
870            }
871            let x = self.buf[self.ptr];
872            self.ptr += 1;
873            x
874        }
875
876        pub fn next_u16(&mut self) -> u16 {
877            if self.ptr >= 4 * 136 - 1 {
878                self.refill();
879            }
880            let x = u16::from_le_bytes(
881                *<&[u8; 2]>::try_from(&self.buf[self.ptr..self.ptr + 2]).unwrap(),
882            );
883            self.ptr += 2;
884            x
885        }
886
887        pub fn next_u64(&mut self) -> u64 {
888            if self.ptr >= 4 * 136 - 7 {
889                self.refill();
890            }
891            let x = u64::from_le_bytes(
892                *<&[u8; 8]>::try_from(&self.buf[self.ptr..self.ptr + 8]).unwrap(),
893            );
894            self.ptr += 8;
895            x
896        }
897    }
898
899    #[cfg(not(feature = "shake256x4"))]
900    impl fn_dsa_comm::PRNG for SHAKE256x4 {
901        fn new(seed: &[u8]) -> Self {
902            SHAKE256x4::new(seed)
903        }
904
905        fn next_u8(&mut self) -> u8 {
906            SHAKE256x4::next_u8(self)
907        }
908
909        fn next_u16(&mut self) -> u16 {
910            SHAKE256x4::next_u16(self)
911        }
912
913        fn next_u64(&mut self) -> u64 {
914            SHAKE256x4::next_u64(self)
915        }
916    }
917
918    // PRNG implementation based on ChaCha20, used to mimic the reference
919    // C code to get reproducible behaviour. The seed MUST have length
920    // 56 bytes exactly (this is how it is used in sign_inner()).
921    #[derive(Clone, Copy, Debug)]
922    struct ChaCha20PRNG {
923        buf: [u8; 512],
924        state: [u8; 256],
925        ptr: usize,
926    }
927
928    const CW: [u32; 4] = [0x61707865, 0x3320646E, 0x79622D32, 0x6B206574];
929
930    impl ChaCha20PRNG {
931        fn refill(&mut self) {
932            let mut cc = u64::from_le_bytes(*<&[u8; 8]>::try_from(&self.state[48..56]).unwrap());
933            for i in 0..8 {
934                let mut state = [0u32; 16];
935                state[0..4].copy_from_slice(&CW);
936                for j in 0..12 {
937                    state[4 + j] = u32::from_le_bytes(
938                        *<&[u8; 4]>::try_from(&self.state[(4 * j)..(4 * j + 4)]).unwrap(),
939                    );
940                }
941                state[14] ^= cc as u32;
942                state[15] ^= (cc >> 32) as u32;
943                for _ in 0..10 {
944                    fn qround(st: &mut [u32; 16], a: usize, b: usize, c: usize, d: usize) {
945                        st[a] = st[a].wrapping_add(st[b]);
946                        st[d] ^= st[a];
947                        st[d] = st[d].rotate_left(16);
948                        st[c] = st[c].wrapping_add(st[d]);
949                        st[b] ^= st[c];
950                        st[b] = st[b].rotate_left(12);
951                        st[a] = st[a].wrapping_add(st[b]);
952                        st[d] ^= st[a];
953                        st[d] = st[d].rotate_left(8);
954                        st[c] = st[c].wrapping_add(st[d]);
955                        st[b] ^= st[c];
956                        st[b] = st[b].rotate_left(7);
957                    }
958                    qround(&mut state, 0, 4, 8, 12);
959                    qround(&mut state, 1, 5, 9, 13);
960                    qround(&mut state, 2, 6, 10, 14);
961                    qround(&mut state, 3, 7, 11, 15);
962                    qround(&mut state, 0, 5, 10, 15);
963                    qround(&mut state, 1, 6, 11, 12);
964                    qround(&mut state, 2, 7, 8, 13);
965                    qround(&mut state, 3, 4, 9, 14);
966                }
967
968                for j in 0..4 {
969                    state[j] = state[j].wrapping_add(CW[j]);
970                }
971                for j in 0..10 {
972                    state[4 + j] = state[4 + j].wrapping_add(u32::from_le_bytes(
973                        *<&[u8; 4]>::try_from(&self.state[(4 * j)..(4 * j + 4)]).unwrap(),
974                    ));
975                }
976                state[14] = state[14].wrapping_add(
977                    u32::from_le_bytes(*<&[u8; 4]>::try_from(&self.state[40..44]).unwrap()) ^
978                        (cc as u32),
979                );
980                state[15] = state[15].wrapping_add(
981                    u32::from_le_bytes(*<&[u8; 4]>::try_from(&self.state[44..48]).unwrap()) ^
982                        ((cc >> 32) as u32),
983                );
984                cc += 1;
985
986                for (j, item) in state.iter().enumerate() {
987                    let k = (j << 2) + (i << 6);
988                    self.buf[k..(k + 4)].copy_from_slice(&item.to_le_bytes());
989                }
990            }
991            self.state[48..56].copy_from_slice(&cc.to_le_bytes());
992            self.ptr = 0;
993        }
994    }
995
996    impl PRNG for ChaCha20PRNG {
997        fn new(seed: &[u8]) -> Self {
998            let mut p = Self {
999                buf: [0u8; 512],
1000                state: [0u8; 256],
1001                ptr: 0,
1002            };
1003            p.state[..56].copy_from_slice(seed);
1004            p.refill();
1005            p
1006        }
1007
1008        fn next_u8(&mut self) -> u8 {
1009            if self.ptr == self.buf.len() {
1010                self.refill();
1011            }
1012            let x = self.buf[self.ptr];
1013            self.ptr += 1;
1014            x
1015        }
1016
1017        fn next_u16(&mut self) -> u16 {
1018            let x0 = self.next_u8();
1019            let x1 = self.next_u8();
1020            (x0 as u16) | ((x1 as u16) << 1)
1021        }
1022
1023        fn next_u64(&mut self) -> u64 {
1024            let mut i = self.ptr;
1025            if i >= (self.buf.len() - 9) {
1026                self.refill();
1027                i = 0;
1028            }
1029            self.ptr = i + 8;
1030            u64::from_le_bytes(*<&[u8; 8]>::try_from(&self.buf[i..(i + 8)]).unwrap())
1031        }
1032    }
1033
1034    // Regenerated after ChaCha20PRNG buffer layout fix (sequential blocks).
1035    const KAT_RNG_1: [u64; 128] = [
1036        10118206865980352844,
1037        4186416994968924572,
1038        14407813434015218568,
1039        17999928204308794618,
1040        1281202863493570580,
1041        1215293592670952135,
1042        2662650687309711127,
1043        4950968403807295904,
1044        5162758428151459972,
1045        10844832002478462889,
1046        2152372350175039333,
1047        16663510599184623250,
1048        11748879267894739645,
1049        9315153642897576389,
1050        843976972260730699,
1051        1261701354592092221,
1052        8105821303884592444,
1053        7529634954489570079,
1054        575133564673458827,
1055        2093472206215043609,
1056        833393031138418875,
1057        7733850010291114247,
1058        13481871314116322223,
1059        11415547815848461648,
1060        2199402011451572558,
1061        8665283947099910497,
1062        8526838622528653153,
1063        9480927610656828044,
1064        2180302049036012308,
1065        12374959167662158686,
1066        12395725852717209259,
1067        2285950573032359990,
1068        3178894720812991391,
1069        13715355236500543103,
1070        13935188584178984125,
1071        9490268222115631411,
1072        15412630661220207885,
1073        9945702784445615473,
1074        17532343938726239310,
1075        8849181786919164502,
1076        14389227774839945492,
1077        11188424208367267411,
1078        8723730469410215675,
1079        6156120820198785454,
1080        5156565809544156914,
1081        2688897825680180598,
1082        15035334635217652153,
1083        17533008619055607030,
1084        8880420601663548525,
1085        1115094350924961784,
1086        2267453663324806620,
1087        8948565336726581792,
1088        9125975625518420122,
1089        15274140373700820667,
1090        7478801077138445484,
1091        1035450160594676773,
1092        11986213120279998009,
1093        17673958146477577562,
1094        12305459440141111064,
1095        14326368158202311078,
1096        1177814005100640761,
1097        8747661500288216167,
1098        2797765342783346840,
1099        4107359898270585920,
1100        11518238704365557048,
1101        6175352564507757509,
1102        4396475331278281679,
1103        3201421582953741656,
1104        11784142549909733272,
1105        5585412854666709543,
1106        2582853516077978199,
1107        9205210792867691364,
1108        12534618484258612970,
1109        7622943502960284153,
1110        11584269409789615882,
1111        8189573375121423581,
1112        9571905452515233284,
1113        716665414398392180,
1114        17528004569390045241,
1115        9235922718509541131,
1116        5829593106852634271,
1117        8814208540816662228,
1118        16133232462179240583,
1119        3305531072799582200,
1120        3517553763672608175,
1121        5072453735837072731,
1122        3087432279719960851,
1123        12018757166060582929,
1124        10295016195294092532,
1125        6915694762732032156,
1126        17598328482254484633,
1127        15636110532633868232,
1128        8803774359075619886,
1129        1830932215338098894,
1130        3962629290033382627,
1131        1916769747115319947,
1132        5482878565058858052,
1133        11823245115937445404,
1134        16582018945468735060,
1135        5447126734922287710,
1136        3807845955673994450,
1137        15934143589856303631,
1138        12266592860318918671,
1139        8383600949465076579,
1140        18303263099619098259,
1141        17645551392386460660,
1142        6749439027928258396,
1143        485438119962767056,
1144        3481957153076147354,
1145        3223851328808479444,
1146        8253146295282414289,
1147        4299195855338690944,
1148        6444506233343653792,
1149        9395364228380005075,
1150        11300796530137268589,
1151        10287453355807248725,
1152        14083145503895752763,
1153        17601794799780907610,
1154        3675357623818277351,
1155        5319896027624671966,
1156        5019668621475045549,
1157        3230679923130437320,
1158        3350076208214283281,
1159        3311388483548165406,
1160        14196905744269899417,
1161        12248417052101335070,
1162        14418418964481725733,
1163        9434739643424308990,
1164    ];
1165
1166    // Regenerated after ChaCha20PRNG buffer layout fix (sequential blocks).
1167    const KAT_RNG_2: [u8; 1024] = [
1168        7, 158, 53, 113, 114, 156, 140, 81, 188, 91, 102, 38, 11, 146, 21, 239, 105, 43, 133, 93,
1169        181, 57, 86, 237, 155, 76, 95, 232, 181, 119, 86, 59, 73, 176, 65, 210, 48, 182, 222, 115,
1170        240, 148, 33, 189, 23, 204, 251, 207, 46, 31, 53, 47, 64, 226, 127, 184, 198, 239, 254, 44,
1171        100, 83, 32, 160, 142, 35, 123, 157, 59, 227, 240, 49, 127, 125, 124, 149, 86, 69, 73, 148,
1172        35, 93, 16, 146, 43, 170, 83, 52, 5, 127, 120, 153, 185, 181, 61, 93, 41, 50, 156, 125,
1173        124, 4, 45, 182, 213, 9, 24, 120, 166, 207, 193, 50, 228, 122, 97, 154, 37, 139, 126, 146,
1174        212, 192, 4, 216, 143, 89, 178, 79, 35, 52, 122, 200, 17, 170, 89, 164, 93, 96, 224, 73,
1175        194, 208, 94, 149, 215, 220, 220, 248, 59, 176, 186, 31, 72, 58, 215, 203, 125, 43, 52,
1176        176, 112, 213, 61, 254, 223, 94, 76, 59, 124, 141, 30, 3, 62, 116, 12, 204, 163, 199, 39,
1177        135, 74, 140, 104, 27, 154, 81, 33, 205, 226, 90, 53, 136, 138, 23, 218, 123, 102, 172,
1178        170, 158, 21, 196, 86, 71, 196, 109, 0, 221, 96, 94, 237, 31, 188, 248, 88, 95, 150, 154,
1179        51, 151, 54, 45, 86, 233, 130, 39, 138, 56, 130, 246, 16, 228, 21, 177, 26, 232, 115, 178,
1180        190, 115, 201, 69, 188, 196, 119, 97, 30, 112, 91, 219, 159, 11, 57, 91, 108, 89, 162, 151,
1181        10, 120, 133, 217, 45, 173, 126, 141, 104, 60, 19, 147, 120, 194, 33, 178, 25, 39, 62, 208,
1182        77, 179, 98, 233, 189, 206, 36, 194, 90, 233, 25, 18, 20, 120, 148, 206, 144, 212, 114,
1183        183, 152, 95, 172, 142, 68, 81, 91, 103, 163, 37, 237, 194, 196, 165, 156, 71, 207, 232,
1184        89, 140, 16, 197, 43, 25, 173, 177, 202, 43, 105, 94, 84, 111, 32, 249, 133, 33, 93, 24,
1185        183, 183, 205, 73, 168, 94, 201, 184, 4, 114, 77, 133, 42, 248, 238, 131, 170, 42, 41, 226,
1186        35, 12, 189, 202, 35, 58, 145, 178, 69, 237, 246, 96, 151, 25, 100, 103, 223, 158, 118,
1187        237, 56, 107, 180, 148, 43, 243, 124, 73, 53, 189, 177, 231, 25, 159, 119, 21, 0, 67, 180,
1188        82, 146, 185, 72, 210, 152, 41, 144, 201, 210, 112, 211, 48, 103, 81, 105, 251, 116, 193,
1189        12, 128, 43, 187, 135, 79, 86, 183, 9, 108, 223, 253, 112, 105, 33, 61, 12, 227, 74, 152,
1190        212, 183, 73, 132, 61, 8, 220, 205, 154, 155, 253, 153, 12, 134, 116, 75, 130, 251, 67,
1191        240, 201, 159, 216, 70, 81, 252, 150, 69, 137, 13, 129, 205, 78, 68, 192, 60, 69, 137, 211,
1192        18, 188, 252, 173, 67, 92, 4, 122, 220, 192, 114, 172, 53, 168, 71, 196, 59, 250, 115, 62,
1193        27, 17, 85, 104, 26, 21, 151, 152, 91, 56, 122, 163, 200, 188, 30, 26, 132, 56, 27, 49, 33,
1194        56, 238, 194, 19, 105, 12, 2, 248, 252, 79, 97, 91, 69, 192, 66, 198, 133, 40, 184, 130,
1195        95, 121, 87, 88, 141, 47, 191, 67, 116, 35, 210, 30, 171, 235, 232, 111, 146, 119, 35, 29,
1196        61, 6, 147, 51, 138, 42, 128, 103, 35, 79, 7, 155, 2, 178, 21, 58, 198, 29, 116, 47, 116,
1197        51, 228, 228, 151, 250, 53, 205, 99, 2, 33, 208, 230, 242, 30, 47, 148, 66, 108, 27, 96,
1198        124, 97, 163, 12, 99, 130, 149, 87, 47, 40, 176, 61, 209, 182, 202, 78, 58, 120, 226, 52,
1199        173, 214, 42, 129, 196, 19, 130, 54, 61, 55, 245, 48, 61, 71, 137, 178, 37, 145, 25, 186,
1200        180, 224, 161, 130, 147, 145, 144, 196, 38, 112, 200, 161, 31, 123, 146, 118, 197, 250, 22,
1201        159, 250, 20, 47, 154, 23, 0, 203, 124, 185, 195, 161, 197, 177, 179, 140, 225, 40, 44, 71,
1202        89, 97, 79, 108, 255, 113, 67, 152, 253, 78, 34, 176, 156, 116, 5, 78, 207, 14, 239, 123,
1203        177, 176, 202, 40, 210, 87, 98, 182, 91, 158, 75, 165, 179, 125, 194, 190, 143, 252, 142,
1204        150, 108, 83, 213, 155, 96, 136, 16, 52, 39, 72, 48, 83, 244, 252, 241, 241, 152, 154, 2,
1205        62, 143, 127, 13, 160, 23, 207, 225, 146, 253, 237, 189, 133, 9, 41, 63, 206, 111, 204, 3,
1206        185, 47, 209, 165, 53, 57, 235, 124, 13, 113, 74, 78, 194, 230, 91, 51, 127, 90, 45, 206,
1207        5, 167, 63, 132, 62, 116, 29, 146, 25, 8, 2, 54, 178, 232, 211, 175, 172, 34, 113, 248,
1208        153, 116, 92, 221, 240, 91, 77, 221, 98, 111, 163, 161, 32, 202, 203, 17, 232, 54, 225,
1209        105, 255, 129, 232, 213, 214, 95, 121, 160, 28, 36, 244, 3, 213, 174, 150, 73, 126, 74,
1210        104, 84, 179, 1, 207, 204, 4, 61, 24, 213, 15, 152, 3, 49, 153, 109, 161, 234, 228, 157,
1211        103, 135, 77, 75, 75, 197, 172, 74, 50, 55, 150, 247, 115, 244, 114, 45, 176, 128, 50, 209,
1212        120, 206, 207, 7, 167, 174, 200, 87, 13, 246, 97, 21, 188, 219, 12, 108, 43, 109, 146, 112,
1213        39, 141, 8, 169, 216, 156, 13, 158, 151, 196, 19, 56, 13, 14, 106, 157, 73, 114, 203, 69,
1214        198, 228, 70, 46, 198, 158, 174, 105, 181, 233, 36, 207, 29, 115, 127, 188, 173, 178, 52,
1215        42, 225, 114, 104, 254, 174, 69, 140, 203, 178, 152, 235, 197, 42, 121, 128, 164, 215, 163,
1216        117, 71, 0, 130, 136, 182, 18, 234, 71, 252, 210, 1, 232, 84, 60, 76, 238, 129, 250, 3,
1217        174, 190, 112, 147, 186, 168, 113, 65, 225, 131, 66, 88, 4, 156, 3, 30, 41, 24, 124, 108,
1218        132, 252, 71, 99, 195, 91, 172, 115, 34, 215, 96, 220, 208, 152, 185, 69, 85, 220, 187, 10,
1219        91, 61, 180, 85, 50, 218, 127, 6, 117, 237, 23, 204, 42, 136, 111,
1220    ];
1221
1222    #[test]
1223    fn chacha20_prng() {
1224        let mut sh = SHAKE256::new();
1225        sh.inject(&b"rng"[..]);
1226        sh.flip();
1227        let mut seed = [0u8; 56];
1228        sh.extract(&mut seed);
1229        let mut p = ChaCha20PRNG::new(&seed);
1230
1231        #[allow(clippy::needless_range_loop)]
1232        for i in 0..KAT_RNG_1.len() {
1233            assert!(p.next_u64() == KAT_RNG_1[i]);
1234        }
1235        #[allow(clippy::needless_range_loop)]
1236        for i in 0..KAT_RNG_2.len() {
1237            assert!(p.next_u8() == KAT_RNG_2[i]);
1238        }
1239    }
1240
1241    // Fake CryptoRng that returns only predefined data, for test purposes.
1242    struct FakeCryptoRng(usize);
1243    impl TryRng for FakeCryptoRng {
1244        type Error = Infallible;
1245
1246        fn try_next_u32(&mut self) -> core::result::Result<u32, Self::Error> {
1247            let mut buf = [0u8; 4];
1248            buf.copy_from_slice(&KAT_512_RND[self.0..(self.0 + 4)]);
1249            self.0 += 4;
1250            Ok(u32::from_le_bytes(buf))
1251        }
1252        fn try_next_u64(&mut self) -> core::result::Result<u64, Self::Error> {
1253            let mut buf = [0u8; 8];
1254            buf.copy_from_slice(&KAT_512_RND[self.0..(self.0 + 8)]);
1255            self.0 += 8;
1256            Ok(u64::from_le_bytes(buf))
1257        }
1258        fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), Self::Error> {
1259            dest.copy_from_slice(&KAT_512_RND[self.0..(self.0 + dest.len())]);
1260            self.0 += dest.len();
1261            Ok(())
1262        }
1263    }
1264    impl TryCryptoRng for FakeCryptoRng {}
1265
1266    /// Verifies that Rng::fill_bytes() consumes bytes identically to direct
1267    /// try_fill_bytes for 40-byte and 56-byte buffers (nonce and seed sizes).
1268    #[test]
1269    fn test_fill_bytes_consumption_pattern() {
1270        use fn_dsa_comm::Rng;
1271        let mut rng = FakeCryptoRng(0);
1272        let mut nonce = [0u8; 40];
1273        rng.fill_bytes(&mut nonce);
1274        assert_eq!(
1275            nonce[..],
1276            KAT_512_RND[0..40],
1277            "nonce must match first 40 bytes"
1278        );
1279        let mut seed = [0u8; 56];
1280        rng.fill_bytes(&mut seed);
1281        assert_eq!(
1282            seed[..],
1283            KAT_512_RND[40..96],
1284            "seed must match bytes 40..96"
1285        );
1286    }
1287
1288    #[test]
1289    fn sign_512() {
1290        // We use a fake random source that returns some predefined bytes.
1291        let mut rng = FakeCryptoRng(0);
1292
1293        // Sign a specific message with the private key.
1294        let mut tmp_i16 = [0i16; 2 << 9];
1295        let mut tmp_u16 = [0u16; 2 << 9];
1296        let mut tmp_flr = [flr::Flr::ZERO; 9 << 9];
1297        let mut sig = [0u8; signature_size(9)];
1298
1299        // We are using the original Falcon rules; public key does not
1300        // actually matter.
1301        let mut hvk = [0u8; 64];
1302        let mut sh = shake::SHAKE256::new();
1303        sh.inject(&KAT_512_VK);
1304        sh.flip();
1305        sh.extract(&mut hvk);
1306
1307        #[cfg(not(feature = "small_context"))]
1308        let basis = {
1309            let mut basis = [flr::Flr::ZERO; 4 << 9];
1310            compute_basis_inner(
1311                9, &KAT_512_f, &KAT_512_g, &KAT_512_F, &KAT_512_G, &mut basis,
1312            );
1313            basis
1314        };
1315
1316        sign_inner::<FakeCryptoRng, ChaCha20PRNG>(
1317            9,
1318            &mut rng,
1319            &KAT_512_f,
1320            &KAT_512_g,
1321            &KAT_512_F,
1322            &KAT_512_G,
1323            &hvk,
1324            &DOMAIN_NONE,
1325            &HASH_ID_SHA3_256,
1326            &b"data1"[..],
1327            &mut sig,
1328            #[cfg(not(feature = "small_context"))]
1329            &basis,
1330            &mut tmp_i16,
1331            &mut tmp_u16,
1332            &mut tmp_flr,
1333        );
1334
1335        // Check that the signature value (s2) is exactly the one which
1336        // was expected.
1337        assert!(sig[0] == 0x39);
1338        assert!(sig[1..41] == KAT_512_RND[0..40]);
1339        let mut sig_raw = [0i16; 512];
1340        assert!(codec::comp_decode(&sig[41..], &mut sig_raw[..]));
1341        assert_eq!(sig_raw, KAT_512_sig_raw);
1342    }
1343
1344    #[cfg(all(not(feature = "no_avx2"), target_arch = "x86_64"))]
1345    #[test]
1346    fn sign_avx2_512() {
1347        if !fn_dsa_comm::has_avx2() {
1348            return;
1349        }
1350        // We use a fake random source that returns some predefined bytes.
1351        let mut rng = FakeCryptoRng(0);
1352
1353        // Sign a specific message with the private key.
1354        let mut tmp_i16 = [0i16; 2 << 9];
1355        let mut tmp_u16 = [0u16; 2 << 9];
1356        let mut tmp_flr = [flr::Flr::ZERO; 9 << 9];
1357        let mut sig = [0u8; signature_size(9)];
1358
1359        // We are using the original Falcon rules; public key does not
1360        // actually matter.
1361        let mut hvk = [0u8; 64];
1362        let mut sh = shake::SHAKE256::new();
1363        sh.inject(&KAT_512_VK);
1364        sh.flip();
1365        sh.extract(&mut hvk);
1366
1367        #[cfg(not(feature = "small_context"))]
1368        let basis = {
1369            let mut basis = [flr::Flr::ZERO; 4 << 9];
1370            unsafe {
1371                sign_avx2::compute_basis_avx2_inner(
1372                    9, &KAT_512_f, &KAT_512_g, &KAT_512_F, &KAT_512_G, &mut basis,
1373                );
1374            }
1375            basis
1376        };
1377
1378        unsafe {
1379            sign_avx2::sign_avx2_inner::<FakeCryptoRng, ChaCha20PRNG>(
1380                9,
1381                &mut rng,
1382                &KAT_512_f,
1383                &KAT_512_g,
1384                &KAT_512_F,
1385                &KAT_512_G,
1386                &hvk,
1387                &DOMAIN_NONE,
1388                &HASH_ID_SHA3_256,
1389                &b"data1"[..],
1390                &mut sig,
1391                #[cfg(not(feature = "small_context"))]
1392                &basis,
1393                &mut tmp_i16,
1394                &mut tmp_u16,
1395                &mut tmp_flr,
1396            );
1397        }
1398
1399        // Check that the signature value (s2) is exactly the one which
1400        // was expected.
1401        assert!(sig[0] == 0x39);
1402        assert!(sig[1..41] == KAT_512_RND[0..40]);
1403        let mut sig_raw = [0i16; 512];
1404        assert!(codec::comp_decode(&sig[41..], &mut sig_raw[..]));
1405        assert_eq!(sig_raw, KAT_512_sig_raw);
1406    }
1407
1408    const KAT_512_f: [i8; 512] = [
1409        -4, -2, -5, -1, 4, -2, 0, -3, -1, 1, -2, -2, -6, -3, 3, -5, -1, 4, -3, -8, 4, -1, 2, -1,
1410        -8, 5, -6, -3, 6, 0, -2, 4, 5, -6, 2, 3, 6, 4, 2, 3, 3, 7, 0, 1, 5, -3, -1, -9, -1, 6, -2,
1411        -5, 4, 0, 4, -2, 10, -4, -3, 4, -7, -1, -7, -2, -1, -6, 5, -1, -9, 3, 2, -5, 4, -2, 2, -4,
1412        4, -3, -1, 0, 5, 2, 2, -1, -9, -7, -2, -1, 0, 3, 1, 0, -1, -2, -5, 4, -1, -1, 3, -1, 1, 4,
1413        -3, 2, -5, -2, 2, -4, 3, 6, 3, 9, 1, -2, 4, -1, -1, -6, -2, -2, 4, 5, -1, 0, 10, -2, 1, -2,
1414        -3, 0, -4, -4, -1, 0, 1, -5, -3, -7, -2, -1, 2, -6, 3, 0, 0, 4, -4, 0, 0, -5, -2, 5, -8, 8,
1415        5, 4, 10, -4, 3, 8, 5, 1, -7, 0, -5, 0, -4, 3, -4, -2, 2, -2, 6, 8, 2, -1, 4, -4, -2, 1, 0,
1416        3, 7, 0, 9, -3, 1, 4, -3, 2, -1, 5, -8, 4, -1, 1, -8, 2, 4, -9, -3, 1, 3, -1, -7, 5, 5, 4,
1417        -3, 0, -7, -3, -1, -6, -7, 0, -3, 0, 3, -3, 0, -3, 1, 3, 4, -6, -6, -3, 6, 0, 2, -5, 1, -3,
1418        -6, -6, -1, -7, -2, -4, 3, 0, -4, -1, 2, 7, -7, -2, 4, 2, 0, 1, -1, -3, 2, 1, 8, -1, 1, -2,
1419        1, -1, 1, 4, 0, -4, 4, 3, -2, 6, -3, -2, 1, 2, 3, 6, 5, -4, -7, -6, 4, 3, -4, 3, -3, 3, -3,
1420        2, -1, 1, 5, -2, 2, 1, 0, -7, 0, 0, -1, 4, -3, 2, 1, -3, 5, 4, -6, -1, -3, 2, -1, -8, 4, 2,
1421        4, 0, 1, -5, 8, 5, 4, -3, -1, -2, 4, 0, 2, -2, 0, -2, -1, -7, 5, 0, 1, 2, 1, -2, 2, -1, 1,
1422        -4, 1, 0, 4, -4, 0, 5, 1, 4, -5, -2, -3, -2, 1, 3, 1, 2, 5, 12, 0, -1, 4, -6, 1, -4, 3, -5,
1423        -4, 4, 2, -2, -6, 1, 1, 3, -1, 0, -4, -4, -4, 6, -2, 4, -3, 0, -2, -1, 0, -6, -3, -2, 0, 6,
1424        5, -5, -5, 3, 0, 3, -3, -2, 5, 7, -3, 1, -1, 0, 3, 0, 3, -7, 2, -4, -4, 1, 1, 1, 0, -3, -8,
1425        3, 6, 1, -2, -7, 3, 3, 4, -1, -2, -5, 9, 7, 1, 2, -4, 4, 0, -11, 3, 0, -3, -5, 5, -1, -1,
1426        7, 6, -1, 6, 3, 9, 5, -2, -3, -3, 1, -2, 0, -1, 1, -2, 2, 0, -5, -1, -4, -2, 2, -1, -3, 0,
1427        -3, 0, 1, 3, -3, 2, 5, 8, -2, 3, -4, -7, 0, 4, -8, 1, 8, -2, 1, -1, 2, 0, -2, 1, 3, 3, 4,
1428        -2, -4, 3, -4, 2, 3, -2, -4, 1, -4, 10, 2,
1429    ];
1430    const KAT_512_g: [i8; 512] = [
1431        -1, 5, -7, -1, -4, 6, 4, -1, -4, -13, -1, -5, -2, -8, 2, 1, 4, 2, 0, 0, 2, 0, -1, 2, 5, -5,
1432        -8, 8, 1, 11, 0, -8, -4, 1, 1, -6, -4, 1, -3, 0, -10, -4, -6, -3, -2, 1, 6, 2, 8, -2, 2,
1433        -2, 1, 3, -4, 2, -1, -1, -2, -2, -3, 0, -3, 2, -3, 2, -3, -4, 2, 3, 4, -5, 6, -3, -2, -1,
1434        -1, -6, -2, 1, -4, -7, 8, 0, 2, -2, 2, 0, 1, 0, 4, 9, 7, 0, -1, -1, 4, -3, -2, 6, 6, 0, 1,
1435        7, -6, -5, 5, 1, 4, -1, 0, -2, 3, -4, 1, -1, -3, -2, 0, -1, -7, -8, -1, 2, 0, -5, 0, 1, -4,
1436        6, -5, 6, 4, 1, -4, -5, 8, -1, 1, -2, 1, 1, 1, 3, 0, -1, 1, 1, -4, -5, -4, 2, -3, 2, -2, 3,
1437        7, -4, 4, -1, -2, 4, -4, -5, 2, 6, -7, 5, -1, 1, 3, 0, -5, -5, 3, -2, -3, -1, -6, 0, 2, 3,
1438        2, 7, -3, -2, -2, 1, -5, 3, 3, -7, 0, 4, 4, -1, 2, -3, 1, 3, -1, -1, 0, -7, -6, -3, 7, -3,
1439        5, -5, 1, -2, 0, 9, -2, 3, -1, -5, -3, -5, 3, 1, -4, -3, 2, -2, 2, 8, -1, 0, 5, -3, -2, -6,
1440        4, 0, 3, -3, -3, 4, -1, 0, 0, -2, -1, 3, 7, 4, 5, -1, 8, 0, -1, -6, -3, 4, 3, -3, 5, 2, -1,
1441        -2, 1, -1, 3, -2, -6, 4, 0, 0, -4, 1, 6, 2, 0, 10, 9, 2, -2, 0, 2, 1, -3, -1, -1, 3, 2, 1,
1442        1, -3, -2, 7, 2, -1, 5, -3, -2, 1, -2, 2, -2, -4, 3, 2, 1, -4, 1, 4, 3, -7, -4, 2, -5, -2,
1443        5, -3, 1, -4, -5, 1, 0, 0, 0, 7, -5, -1, 2, 2, -3, 6, -6, 4, -3, -5, -6, -7, -4, 3, -2, -2,
1444        -10, -3, 2, -1, -6, -4, 1, 2, 2, 1, 4, 1, -5, -10, -2, 2, -4, 4, 4, -2, 1, 4, -3, 0, -6,
1445        -3, 1, 5, -7, -6, -4, 8, -1, 0, -1, 6, -3, -2, -2, 6, 2, 3, -3, -3, 5, -2, 1, 1, -4, -4, 8,
1446        0, 3, 2, 3, 7, 4, 3, 2, -6, -9, 0, -8, 11, -2, 2, -2, -2, 3, 0, -6, 2, -1, 4, 2, -2, 0, -3,
1447        -7, -1, -1, 0, -1, -4, -2, -5, 3, -4, 2, 2, -1, -1, 7, -1, 3, 6, -7, 1, -5, 0, -7, 4, 3,
1448        -5, -1, 0, 3, -4, 1, 2, -7, 1, -2, -8, -2, -5, -5, 1, -4, -4, 4, -3, -2, 2, -4, -8, -1, 0,
1449        -9, 5, -1, -2, 3, 2, 6, -1, 1, -1, -5, 5, 9, 3, -6, -5, 1, -6, 0, 2, -4, 6, 2, 7, 2, 15, 0,
1450        -2, 9, 0, 1, 6, 4, -1, -1, -6, -3, 3, 1, -6, -3, 2, 2, -2,
1451    ];
1452    const KAT_512_F: [i8; 512] = [
1453        0, -25, -39, 21, 7, -5, -10, 4, -1, -38, -9, -1, 4, -23, 15, -1, 8, 1, -38, 41, 29, 22, 9,
1454        12, -46, 0, 9, -17, -19, 32, 38, -3, 14, 6, 2, -6, -18, -1, 23, 80, -12, -20, 24, 22, -31,
1455        -38, -11, 8, 17, 18, 19, -10, 0, -1, 28, -5, -28, -33, 4, -31, -33, -8, -9, -44, 46, -11,
1456        -5, -21, -22, -7, 1, -11, 33, -8, 12, -7, -6, 63, 17, 12, -49, -11, -31, -8, 7, -28, 33,
1457        -28, -19, 8, 46, -73, 9, 32, 18, 7, -43, 0, -6, -4, 8, -39, -17, 11, 15, -25, -9, -28, -2,
1458        24, -23, 10, -15, 4, 41, 46, 18, 2, -3, -29, 11, -3, 20, 35, 21, 23, 5, -8, -3, -27, -69,
1459        0, 26, -29, -24, 8, 19, 6, -14, -18, 47, 5, 21, -50, 17, -44, -36, 24, 9, 16, -38, -5, -54,
1460        34, 13, 31, -2, 9, 8, -12, -14, -17, 28, -59, -20, 19, 31, 14, 14, 7, -32, 37, 5, -3, -7,
1461        -6, 21, -29, -33, 23, -25, -23, 14, 38, -29, -33, -9, 23, -43, 18, -12, 2, 30, 32, -28,
1462        -21, 42, 1, 6, -6, 58, 34, -22, 1, 5, -2, -8, 14, -19, -4, -6, 10, -3, -3, 32, 18, -19,
1463        -12, 49, 13, 4, -18, 57, 37, -19, 25, 14, 18, -51, 13, 4, 4, 17, -37, -2, 1, 41, -36, -8,
1464        -13, 49, -6, 9, 46, -36, -6, -20, -18, -6, -29, -42, -21, -25, -29, 5, -41, 51, 49, -20,
1465        -22, -9, 3, -6, -52, 10, 41, 12, -27, -20, 31, -17, -23, -16, 3, 44, -3, -5, -2, 0, -22,
1466        14, -30, -41, 3, -27, 3, 18, 38, 10, 49, 45, -13, -27, -4, -10, -67, -1, -17, -2, 72, 46,
1467        20, 24, 22, 16, 25, 6, -6, -31, 2, 0, -13, -14, 9, 4, 31, 18, 22, 12, 59, -1, -3, -24, -47,
1468        -10, 48, 37, -34, -32, -4, 18, -2, 52, -8, -7, 34, -44, -14, -21, -49, -35, 41, -4, 31, 3,
1469        23, 9, 8, 0, -24, 38, -9, -9, 4, -10, -55, -19, 21, 27, 22, 41, 6, -23, 41, -2, 28, -46,
1470        20, 52, 16, 20, 32, 18, 2, -3, 9, 16, 33, -18, 12, 6, -9, -19, 1, -5, -15, -17, 6, -3, 4,
1471        -22, 30, -34, 43, -4, 9, -3, -33, -43, -5, -13, -56, 38, 16, 11, -36, 11, -4, -56, 2, 0,
1472        -19, -45, -8, -34, 16, 31, -3, 16, 27, -16, -9, 8, 45, -51, -20, 62, -17, -4, 4, 17, -45,
1473        4, -15, -19, 39, 39, 15, 17, -19, 2, 45, 36, -22, 16, -23, 28, 34, 12, 5, 10, -7, 28, -35,
1474        17, -37, -50, -28, 19, -25, 9, 45, -6, -7, -16, 57, 27, 50, -30, 2, -10, -1, -57, -49, -23,
1475        0, -9, -36, -4, -3, 32, -6, -25, 67, -27, -19, 25, -6, 1, -17, -14, 0, 29, 26, -12, -20,
1476        44, 14, 10, 8, -11, -18, -53, 22, 25, 27, 35, 6, -16, 12, 71, -8,
1477    ];
1478    const KAT_512_G: [i8; 512] = [
1479        27, 6, 12, -3, -31, -42, 27, 17, 11, 8, 34, 6, -3, 2, 11, -11, 18, 48, 1, 21, -7, -6, 9,
1480        33, -18, -40, -55, -9, -71, -50, 32, -36, 11, 4, 29, 33, 10, -19, -43, -10, 22, -36, -23,
1481        -21, -14, -47, 25, -4, -14, 30, 16, -18, -11, 6, -37, -27, -12, 6, 7, 33, -36, 33, -2, 12,
1482        -21, 1, 16, 49, -11, -16, -41, 15, 11, 8, 20, -15, 26, -8, 11, -43, -36, 28, 2, -47, -30,
1483        -47, -1, 1, 48, -6, -22, 24, -20, -3, -1, -15, -12, 62, 12, 7, -9, 15, -71, 49, 22, 27, 20,
1484        -8, -28, -13, -31, 18, 28, 54, 29, 5, 0, 33, -5, -22, -21, -12, -14, -2, 11, -24, 32, -26,
1485        -71, 21, -15, -20, -12, 36, -5, 35, 46, 13, -34, -8, 10, -10, 10, 40, -52, 8, 0, 18, -33,
1486        -10, 8, 43, -8, -6, -31, -17, 19, 30, 12, -9, 8, -19, -32, -18, -1, -37, 4, 43, 27, 14, -6,
1487        -14, -44, -34, -8, 16, -39, 13, 6, -32, 8, 17, -12, 23, -44, -25, -66, -12, -31, 30, 14,
1488        -9, -5, -10, 44, -12, -2, -43, -22, -18, -7, -9, -15, -7, -21, -27, -5, 1, -13, -10, 8, -8,
1489        29, 21, 64, 47, -28, -9, -28, 25, -47, -34, -3, -14, -26, -12, -5, -10, -27, -9, -14, -23,
1490        -2, -31, 28, 17, -4, -30, 31, 3, -15, 25, 9, -32, 0, -6, -22, 20, -37, 3, 12, -19, -17, 13,
1491        30, 11, -15, 15, 50, 66, -31, -31, 16, 2, 3, -8, 40, -21, -31, -2, 41, -29, -12, 9, 14, -4,
1492        9, 8, -20, 28, 12, 20, -10, 5, -6, -33, 6, 21, 51, 30, 9, 3, 8, 7, 19, -53, 19, 15, 4, -38,
1493        19, 29, 18, 6, 19, 3, -17, -32, 16, 3, 46, -6, -3, 47, 3, -66, 3, 25, -6, -6, 21, -24, -9,
1494        28, -39, -42, 42, -6, -19, -14, 6, -8, 9, 28, -4, 23, 12, -17, -13, 3, 3, 6, 44, 6, -5, 38,
1495        -4, -16, 12, -15, 8, -11, 45, 1, -16, 37, -35, 20, 26, 9, 13, 34, 25, -3, -10, -2, -42,
1496        -23, -22, -56, -56, 6, 17, -9, 0, 36, 20, 6, -58, 12, 0, -3, -29, -49, -24, -12, -13, 5,
1497        -39, -8, 36, -9, 44, 35, -64, -22, -12, 26, -15, 41, 36, -19, -37, -20, 46, 35, 9, 32, -5,
1498        27, 21, -36, -51, 19, 10, -23, 28, 46, 28, 8, 22, -31, 18, 2, -16, -9, 1, -22, -22, 31, 14,
1499        5, 44, -3, 38, 0, -12, 50, -23, -19, 1, 42, 15, 1, 13, 32, 45, 37, 15, 11, -9, -23, -6,
1500        -23, 36, 4, -34, -14, -14, -37, -28, 19, 20, 14, 24, -48, -34, -27, -34, -12, 9, -20, -30,
1501        25, 28, -51, -13, 11, -20, -1, -3, 6, -38, -46, -15, 28, 10, -4, 3, -1, 4, -40, 16, 61, 31,
1502        28, 8, -2, 21, -3, -25, -12, -32, -15, -38, 20, -7, -35, 28, 29, 9, -27,
1503    ];
1504    const KAT_512_VK: [u8; 897] = [
1505        0x09, 0x02, 0xCE, 0x21, 0x6B, 0xE4, 0x2C, 0xD0, 0x4F, 0xC8, 0x4C, 0x24, 0xC7, 0x1D, 0x13,
1506        0x07, 0x8E, 0xCA, 0x07, 0x97, 0x6E, 0xE4, 0xAD, 0xBA, 0x2C, 0x98, 0x23, 0x46, 0xD8, 0x78,
1507        0xC0, 0x94, 0x76, 0x7F, 0xE2, 0x9C, 0x34, 0x5C, 0xE2, 0xFA, 0x87, 0x4B, 0xEE, 0x23, 0x9E,
1508        0xA6, 0x0B, 0xDF, 0xA7, 0x27, 0xA5, 0x16, 0x82, 0xC3, 0xDF, 0x06, 0xA2, 0x68, 0x49, 0xC3,
1509        0xF7, 0x26, 0x46, 0x2A, 0x59, 0xE9, 0xC4, 0x16, 0x63, 0x87, 0xBA, 0x89, 0x56, 0xDF, 0xC9,
1510        0xFA, 0x62, 0x20, 0x95, 0x20, 0xED, 0x65, 0x39, 0xCA, 0xDD, 0xA8, 0xF9, 0xE8, 0x11, 0xA6,
1511        0x8E, 0xD8, 0x69, 0x70, 0x13, 0x5A, 0xD5, 0x02, 0x6D, 0xBD, 0x16, 0xF1, 0x59, 0x97, 0xA4,
1512        0xBB, 0xBE, 0x35, 0x68, 0x38, 0xD7, 0x5C, 0x7A, 0x91, 0x34, 0xED, 0xB8, 0xBF, 0x25, 0xBC,
1513        0xBA, 0x0A, 0x03, 0x13, 0x77, 0xEB, 0xF0, 0x11, 0x0D, 0x54, 0x73, 0xC8, 0x46, 0x82, 0x7B,
1514        0x25, 0x6B, 0x9A, 0xB4, 0xD0, 0x26, 0x1E, 0x41, 0xC8, 0xDB, 0xF1, 0xA4, 0x24, 0xB6, 0xDA,
1515        0x1F, 0x21, 0xD0, 0xE2, 0x1A, 0x89, 0xBD, 0x29, 0x94, 0x07, 0x4F, 0xA5, 0x36, 0x5E, 0xA7,
1516        0x70, 0x0E, 0xEB, 0xD2, 0x26, 0x94, 0x7C, 0xFA, 0x7B, 0xE1, 0xA7, 0x65, 0xF4, 0xD7, 0xF9,
1517        0x27, 0x50, 0x02, 0x3D, 0xF2, 0x68, 0x94, 0x51, 0x2E, 0x79, 0x48, 0xC5, 0x64, 0x69, 0xE8,
1518        0x81, 0xD1, 0x99, 0xDA, 0x81, 0x35, 0xAF, 0xC1, 0x6E, 0x52, 0x3A, 0xF8, 0xA2, 0x3F, 0xD5,
1519        0x80, 0x22, 0xAE, 0x22, 0x9A, 0xC9, 0x5C, 0xFF, 0x09, 0x5D, 0x6F, 0xF3, 0x2C, 0x89, 0x0D,
1520        0xB2, 0x29, 0x41, 0x19, 0x21, 0x90, 0x5B, 0x3B, 0xA5, 0x2D, 0x54, 0xB5, 0x0D, 0xEC, 0xB4,
1521        0x4D, 0xC3, 0xD7, 0xC8, 0x99, 0x66, 0x79, 0xE8, 0x28, 0xA4, 0x3B, 0x8D, 0x06, 0x87, 0xE8,
1522        0xBD, 0xE0, 0x60, 0xC5, 0x10, 0x15, 0xAA, 0x9E, 0x00, 0x0C, 0x92, 0x59, 0x8F, 0x05, 0xB8,
1523        0x70, 0xA9, 0x4B, 0x29, 0x01, 0xA9, 0xE1, 0x2A, 0xE9, 0xAB, 0xF2, 0x0A, 0x51, 0x71, 0x4A,
1524        0x03, 0x6A, 0x85, 0x1C, 0xCE, 0x89, 0x15, 0x42, 0xD1, 0xEB, 0x52, 0x7E, 0x73, 0x10, 0x76,
1525        0xD4, 0xFF, 0x2F, 0x09, 0xBA, 0x68, 0x94, 0xA2, 0x09, 0x03, 0xCA, 0x6F, 0xA7, 0x6E, 0x13,
1526        0xD1, 0x2D, 0xC0, 0xAB, 0xA6, 0xB9, 0x26, 0xED, 0x6E, 0x89, 0x54, 0x84, 0x1D, 0xC0, 0x52,
1527        0x4A, 0x55, 0xE3, 0x65, 0x6C, 0x9C, 0x19, 0x88, 0x5E, 0xAB, 0x65, 0x4D, 0x86, 0x94, 0x93,
1528        0x51, 0xFB, 0x8B, 0x02, 0xEA, 0x32, 0xAE, 0x71, 0x5F, 0x09, 0x8B, 0xE2, 0x4E, 0x83, 0xD2,
1529        0xE2, 0x71, 0xCC, 0x8C, 0x24, 0x14, 0x8E, 0x7B, 0xD5, 0x92, 0x59, 0x28, 0x38, 0xFA, 0x55,
1530        0xB8, 0x8A, 0xDB, 0x89, 0x7B, 0xE5, 0xD9, 0x96, 0x97, 0xE3, 0xFC, 0xAC, 0xFA, 0xC0, 0x25,
1531        0xB4, 0x51, 0xF6, 0x2B, 0x6C, 0x35, 0x62, 0xC9, 0xEF, 0x90, 0x71, 0x44, 0x57, 0xA2, 0xF6,
1532        0x49, 0x22, 0x5F, 0x70, 0x20, 0xE9, 0xAF, 0xDB, 0xB9, 0x2A, 0xE2, 0xBE, 0xDB, 0xA6, 0x19,
1533        0x33, 0xB9, 0x05, 0xCF, 0xD4, 0x1A, 0x03, 0x08, 0x2B, 0xD6, 0xDF, 0x8B, 0x24, 0x27, 0xEC,
1534        0x7B, 0xFC, 0xAB, 0x2A, 0xDE, 0x16, 0x78, 0x9C, 0x09, 0x67, 0x45, 0x67, 0xDE, 0x11, 0x29,
1535        0xC1, 0xB2, 0xF6, 0x9E, 0x9C, 0x0F, 0x8F, 0xB2, 0x37, 0xC5, 0x5D, 0x05, 0xCF, 0x8F, 0x69,
1536        0xAD, 0x8B, 0xB7, 0x27, 0xA2, 0x08, 0x9A, 0x43, 0x71, 0x1E, 0xC6, 0xCA, 0x54, 0xB6, 0x12,
1537        0xC1, 0xD7, 0x2F, 0xA0, 0x2B, 0x66, 0x40, 0x98, 0x78, 0x6D, 0x08, 0x53, 0xD1, 0xBC, 0x98,
1538        0xE1, 0x4A, 0x57, 0x90, 0xB2, 0xCA, 0xC6, 0xC7, 0xD2, 0x48, 0x57, 0xD0, 0xFB, 0x44, 0xF5,
1539        0xD9, 0x5F, 0x34, 0x21, 0x33, 0x96, 0x86, 0xE8, 0xAF, 0xA5, 0xBA, 0x92, 0x4B, 0xBA, 0x94,
1540        0xF0, 0x73, 0xC9, 0x09, 0xE9, 0xFB, 0x8A, 0xD0, 0xA4, 0x62, 0x24, 0xD6, 0xF8, 0x1B, 0x22,
1541        0xA2, 0x01, 0xAE, 0xDB, 0xA8, 0x94, 0xC2, 0xAA, 0x44, 0xBA, 0xD6, 0x87, 0x4D, 0x6E, 0x24,
1542        0xCE, 0x1B, 0xB8, 0x3F, 0x51, 0xE6, 0x9F, 0x34, 0xA1, 0x40, 0xAD, 0x88, 0x55, 0x4F, 0x6C,
1543        0x47, 0x48, 0xFF, 0x9F, 0x64, 0x6F, 0x0D, 0xDB, 0xD3, 0xA4, 0x85, 0xD0, 0xBA, 0xD8, 0x05,
1544        0xFA, 0x29, 0xEB, 0x99, 0x68, 0x18, 0x51, 0x71, 0x45, 0x05, 0xE3, 0x71, 0xA6, 0x4A, 0x7B,
1545        0xCF, 0x68, 0x97, 0x95, 0x81, 0x44, 0x91, 0xDC, 0x9D, 0xC5, 0x27, 0x52, 0xE9, 0xA2, 0x7F,
1546        0x96, 0xF4, 0x6C, 0xE8, 0xF8, 0xA4, 0x27, 0x95, 0xC7, 0x10, 0x7E, 0xC1, 0x86, 0x78, 0x92,
1547        0x49, 0x6C, 0x91, 0xA1, 0x77, 0xFB, 0x80, 0x95, 0x0D, 0x69, 0x3B, 0xD4, 0xAD, 0xDE, 0x30,
1548        0x2E, 0x90, 0x3C, 0x41, 0x32, 0xEC, 0x95, 0x38, 0x86, 0x8D, 0xE8, 0xCF, 0x80, 0x5F, 0x5A,
1549        0x21, 0x92, 0x96, 0x7F, 0xA6, 0xC3, 0x50, 0x6A, 0x1A, 0xAB, 0x3C, 0x11, 0xA1, 0x5F, 0x1E,
1550        0x47, 0xB3, 0xB4, 0x6E, 0x64, 0x97, 0xB1, 0x5A, 0x88, 0x2E, 0x2C, 0xC8, 0x49, 0xA1, 0xB4,
1551        0x42, 0x49, 0xE9, 0x7F, 0x61, 0xF1, 0x6B, 0xD0, 0xEC, 0xEA, 0xD5, 0x47, 0xDD, 0x71, 0xC5,
1552        0xDD, 0xA5, 0xAA, 0x8A, 0x56, 0xFE, 0x36, 0x31, 0x22, 0x15, 0x85, 0x2E, 0x78, 0xDA, 0x98,
1553        0x5D, 0x55, 0xA4, 0xA4, 0xD8, 0xF7, 0x14, 0x8E, 0x45, 0x67, 0xD1, 0xE4, 0x67, 0x87, 0xC2,
1554        0x23, 0x87, 0xCA, 0x4A, 0x85, 0xF0, 0x11, 0xE3, 0x75, 0xC4, 0x5C, 0xCA, 0x0C, 0xE0, 0xA1,
1555        0x5B, 0xCD, 0x13, 0x37, 0xBD, 0xC9, 0x27, 0x1B, 0xFA, 0x84, 0x73, 0xE1, 0x88, 0x2F, 0x33,
1556        0x85, 0x58, 0x69, 0x7D, 0x9A, 0xAF, 0x07, 0x5A, 0x90, 0x78, 0x33, 0x5A, 0x1F, 0xB8, 0xA1,
1557        0xB3, 0xB6, 0xE9, 0xD9, 0xCF, 0x43, 0x62, 0x84, 0x06, 0x7C, 0x58, 0xC5, 0xA4, 0x8E, 0x04,
1558        0x7A, 0x40, 0x08, 0xD0, 0x2B, 0x7C, 0x85, 0x07, 0xC2, 0xEE, 0x6F, 0x88, 0xDA, 0x4C, 0x97,
1559        0xF6, 0x0F, 0x75, 0x44, 0x4C, 0x78, 0x84, 0x96, 0x67, 0x84, 0x32, 0xC9, 0x5F, 0x3A, 0x92,
1560        0x08, 0xB4, 0xA8, 0xC1, 0xCB, 0xC6, 0xE2, 0xD4, 0xDA, 0x61, 0x25, 0x3D, 0xA0, 0x81, 0x27,
1561        0x5E, 0x8F, 0x34, 0xDB, 0xE4, 0xA1, 0xEC, 0xC2, 0x22, 0x24, 0xC3, 0x08, 0x00, 0xA7, 0x75,
1562        0x35, 0x74, 0xC8, 0x95, 0x86, 0x95, 0x66, 0x6C, 0x28, 0x95, 0xB3, 0x5C, 0xCE, 0x07, 0x89,
1563        0x44, 0xA3, 0x10, 0x41, 0xA5, 0x23, 0x83, 0x7C, 0xED, 0x72, 0x17, 0x69, 0x0F, 0xA1, 0x7C,
1564        0x36, 0xCB, 0x45, 0x92, 0x63, 0x35, 0xE6, 0x7B, 0x18, 0x04, 0x95, 0x9D,
1565    ];
1566
1567    const KAT_512_RND: [u8; 40 + 56] = [
1568        // nonce: 40 bytes
1569        0x16, 0xC1, 0x25, 0x15, 0x25, 0x80, 0x93, 0x79, 0x99, 0x56, 0x36, 0x8C, 0xDF, 0xC1, 0x82,
1570        0xC1, 0xCA, 0x4A, 0x34, 0xF0, 0x77, 0xE9, 0x24, 0x44, 0x16, 0xA8, 0xC4, 0xC1, 0x3F, 0xB0,
1571        0xCA, 0x24, 0x1E, 0x8B, 0x7A, 0xC1, 0x71, 0x2D, 0x28, 0xEB,
1572        // seed for the ChaCha20 PRNG: 56 bytes
1573        0xFF, 0xD8, 0x57, 0xF1, 0x49, 0x5C, 0xA5, 0x98, 0xDB, 0x2C, 0x88, 0x64, 0xAF, 0x31, 0xFA,
1574        0x8F, 0x37, 0xBC, 0x73, 0x8D, 0xCD, 0xB6, 0xDD, 0xAA, 0xFD, 0x25, 0x4A, 0xBF, 0xE3, 0x01,
1575        0xB7, 0x91, 0x9B, 0x7E, 0x9B, 0x9F, 0xEC, 0xEA, 0x4E, 0xF0, 0x01, 0xC9, 0x62, 0x9B, 0x96,
1576        0x6B, 0x58, 0xD6, 0x81, 0x25, 0x2F, 0xF3, 0x38, 0x9E, 0x81, 0x6B,
1577    ];
1578    // KAT vectors regenerated after fixing ChaCha20PRNG buffer layout to sequential
1579    // (j<<2)+(i<<6) for correct little-endian block output; matches rand_core 0.10 behavior.
1580    const KAT_512_sig_raw: [i16; 512] = [
1581        -26, 98, -55, 235, 202, 440, 43, 53, -313, -11, 25, -155, -45, -34, 28, 136, -47, 68, 176,
1582        -165, 174, -196, -133, -74, 85, -5, -166, -15, 249, -125, 120, -62, 155, -153, 79, -82,
1583        -318, 63, -311, 69, 292, 40, 43, -164, 122, -91, 92, -11, 18, -7, 184, 10, -304, 364, 9,
1584        324, -374, -7, -85, 30, -36, 24, -106, -160, 71, -24, 78, 155, -281, 378, -64, -37, -122,
1585        2, 28, -26, -36, 98, -331, 110, -250, 51, 98, -6, -188, 223, -144, 200, -71, -5, -36, -53,
1586        -44, -11, -340, -2, -7, 136, -301, -3, -198, 308, -169, -33, 31, 43, -345, 145, 66, 97, 71,
1587        185, 99, -79, 261, -19, -146, -89, -85, 41, 164, -78, -18, 19, 74, 210, -113, 373, 1, 237,
1588        -255, 216, -25, 37, 278, -195, -2, 57, 137, 183, 28, -170, 57, -5, -28, 98, 17, 5, 60,
1589        -203, -122, 113, -274, 7, -30, -139, 76, 32, -103, -30, 205, 37, -98, -111, -44, -54, 75,
1590        -121, -344, 99, 374, -41, 189, -141, 10, -2, -329, -147, 4, -155, 255, 100, 71, -235, -421,
1591        169, 239, -113, 30, 138, 62, -242, 49, 1, 56, -147, 24, 88, -93, -344, -9, 328, -131, -218,
1592        44, -197, -12, -172, -273, 13, -102, -146, -8, 259, 193, -172, -11, -99, -232, -167, 140,
1593        125, 27, 31, -63, 126, -113, -222, 213, -164, -171, 150, -214, -191, -10, -77, -280, -39,
1594        -178, 136, -46, 170, -104, 167, -102, 89, 1, -94, 97, 36, 287, 222, 49, -106, 191, 3, 108,
1595        204, -385, -106, -101, 70, 178, -45, 381, -285, -254, -31, 77, 7, -12, 182, -206, 80, -93,
1596        -3, 85, 95, 112, 147, -141, 53, -30, 269, 172, 56, -143, -173, -139, 298, -242, 58, 136,
1597        -49, -269, 151, -64, 273, -139, 32, 179, -387, -249, 157, -92, -128, 109, -126, -51, -150,
1598        140, -117, -52, 306, -367, -117, -342, 141, 86, -303, 55, -296, 270, 44, 186, -30, -78,
1599        -69, 43, -173, -100, -61, -6, 136, 331, 188, 41, 121, -169, -250, 91, 112, -77, -153, -194,
1600        -237, -42, 118, -238, 14, 61, -90, 9, 208, -9, -24, 168, -123, 211, 124, 211, -103, 196, 1,
1601        70, -42, 223, 11, 81, 79, 112, -19, 45, 199, -50, 187, -88, 99, -56, -250, -72, 43, 103,
1602        -174, 208, 148, -138, 7, 3, -3, 471, 32, 260, -28, 172, 204, 23, -181, -196, 47, -57, 20,
1603        228, 212, -160, -345, -106, 138, 217, 52, 425, 319, 68, -170, 58, 203, 233, 90, 12, -36,
1604        -1, 46, -166, 207, 101, -177, 63, -83, 10, -45, -125, -66, -142, 165, -46, 51, 38, 17, 61,
1605        421, 5, -59, 89, -147, 169, 295, 48, 147, -162, 159, -136, 103, 107, -187, 39, 103, 267,
1606        -346, 12, 95, 98, -122, 115, 320, -122, 87, -19, 49, -143, -56, -45, 224, 314, 167, 14,
1607        -168, -11, -89, -47, -190, 188, 196, 62, 130, 6, 98, -18, 331, -65, 144, -195, -310, 238,
1608        186, 55, 186, 108, -49, -66, -3, -286, 143, 333, -242, -187, 161, 411, -136, 186, 107, 136,
1609        -201,
1610    ];
1611}