## KAT for FIPS-203 Compliant with FIPS-203, published on August 13, 2024. ## File format: | Field | Meaning | |-----------|--------------------------------------------------------| | ``count`` | Test number | | ``z`` | Random 32-bytes ``z`` (Algorithm 15) | | ``d`` | Random 32-bytes ``d`` (Algorithm 12) | | ``msg`` | Random 32-bytes ``m`` (Algorithm 16) | | ``seed`` | AES-CTR-drbg seed | | ``pk`` | Resulting public key | | ``sk`` | Resulting secret key | | ``ct`` | Resulting KEM ciphertext | | ``ss`` | Resulting KEM shared secret | | ``ct_n`` | Invalid KEM ciphertext | | ``ss_n`` | Shared secret resulting from decapsulation of ``ct_n`` | ## Differences with the FIPS-203 - No tests for key validation ## How it was generated We use DRBG based on based on AES-CTR (see [SP800-90A](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf)) for generating random bytes. For each KAT vector, the DRBG is seeded with the ``seed`` value (personalisation string is not used). The test first generates a secret and public key. Then it encapsulates and decapsulates the shared secret. The pseudocode below may make it clearer ``` use aes_ctr_drbg::DrbgCtx; // aes_ctr_drbg = "0.0.2" crate fn main() { // Initialize DRBG with the magic value let Ok(mut entropy) = hex::decode("60496cd0a12512800a79161189b055ac3996ad24e578d3c5fc57c1e60fa2eb4e550d08e51e9db7b67f1a616681d9182d") else { ... blah ... } let mut drbg: DrbgCtx = DrbgCtx::new(); drbg.init(&entropy, Vec::new()); for i in 0..100 { drbg.get_random(&mut entropy); kem::kem(i, &entropy); } } pub fn kem(count: usize, entropy: &[u8]) { let mut buf = Vec::new(); let mut drbg: DrbgCtx = DrbgCtx::new(); drbg.init(&entropy.clone(), Vec::new()); println!("count = {}", count); // The code generates random strings in the following order: z,d,msg // z buf.resize(32, 0); drbg.get_random(&mut buf); println!("z = {}", hex::encode(&buf)); // d drbg.get_random(&mut buf); println!("d = {}", hex::encode(&buf)); // msg drbg.get_random(&mut buf); println!("msg = {}", hex::encode(&buf)); // Re-init drbg.init(&entropy.clone(), Vec::new()); // Generate keys kyber_keygen(&mut pk, &mut sk); // Encapsulate kyber_encaps(&pk, &mut ct, &mut ss); // Decapsulate kyber_decaps(&sk, &ct, &mut ss); println!("seed = {}", hex::encode(&entropy)); println!("pk = {}", hex::encode(&pk)); println!("sk = {}", hex::encode(&sk)); println!("ct = {}", hex::encode(&ct)); println!("ss = {}", hex::encode(&ss1)); ```