Skip to content

Commit

Permalink
rustfmt
Browse files Browse the repository at this point in the history
  • Loading branch information
integritychain committed Feb 20, 2024
1 parent 53d0cba commit 37969be
Show file tree
Hide file tree
Showing 15 changed files with 66 additions and 64 deletions.
12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ keywords = ["FIPS", "FIPS203", "lattice", "key", "encapsulation"]
rust-version = "1.72"


[dependencies]
zeroize = { version = "1.6.0", default-features = false, features = ["zeroize_derive"] }
rand_core = { version = "0.6.4", default-features = false }
sha3 = { version = "0.10.2", default-features = false }


[features]
default = ["default-rng", "ml-kem-512", "ml-kem-768", "ml-kem-1024"]
default-rng = ["rand_core/getrandom"]
Expand All @@ -28,6 +22,12 @@ ml-kem-768 = []
ml-kem-1024 = []


[dependencies]
zeroize = { version = "1.6.0", default-features = false, features = ["zeroize_derive"] }
rand_core = { version = "0.6.4", default-features = false }
sha3 = { version = "0.10.2", default-features = false }


[dev-dependencies]
rand = "0.8.5"
regex = "1.10.2"
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ The Rust [Documentation][docs-link] lives under each **Module** corresponding to
## Notes

* This crate is fully functional and corresponds to the first initial public draft of FIPS 203.
* Constant-time assurances target the source-code level only, and are a work in progress.
* Constant-time ambitions target the source-code level only, and are a work in progress (thus the API
suffix of `_vt`).
* Note that FIPS 203 places specific requirements on randomness per section 3.3, hence the exposed `RNG`.
* Requires Rust **1.72** or higher. The minimum supported Rust version may be changed in the future, but
it will be done with a minor version bump.
Expand Down
4 changes: 2 additions & 2 deletions benches/benchmark.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use criterion::{Criterion, criterion_group, criterion_main};
use criterion::{criterion_group, criterion_main, Criterion};

use fips203::{ml_kem_1024, ml_kem_512, ml_kem_768};
use fips203::traits::{Decaps, Encaps, KeyGen};
use fips203::{ml_kem_1024, ml_kem_512, ml_kem_768};

#[allow(clippy::redundant_closure)]
pub fn criterion_benchmark(c: &mut Criterion) {
Expand Down
11 changes: 5 additions & 6 deletions src/byte_fns.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
use crate::helpers::ensure;
use crate::Q;
use crate::types::Z;
use crate::Q;

// Note: Algorithm 2 and 3 have been "optimized away" as they had a lot of overhead
// and made memory management tricky. The headers are left here for reference.

// Note: Algorithm 2 and 3 have been "optimized away" as they had a lot of overhead
// and made memory allocations tricky. The definitions are left here for reference.

// /// Algorithm 2 `BitsToBytes(b)` on page 17.
// /// Converts a bit string (of length a multiple of eight) into an array of bytes.
// ///
// /// Input: bit array b ∈ {0,1}^{8·ℓ} <br>
// /// Output: byte array B ∈ B^ℓ


// /// Algorithm 3 `BytesToBits(B)` on page 18.
// /// Performs the inverse of `BitsToBytes`, converting a byte array into a bit array.
// ///
Expand Down Expand Up @@ -51,7 +50,7 @@ pub(crate) fn byte_encode(
bit_index += d as usize;

// While we have enough bits to drop a byte, do so
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_truncation)] // Intentional truncation
while bit_index > 7 {
//
// Drop the byte
Expand Down Expand Up @@ -91,7 +90,7 @@ pub(crate) fn byte_decode(
bit_index += 8;

// If we have enough bits to drop an int, do so
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_truncation)] // Intentional truncation
while bit_index >= d {
//
// Mask off the upport portion and drop it in
Expand Down
13 changes: 6 additions & 7 deletions src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use sha3::{Digest, Sha3_256, Sha3_512, Shake128, Shake256};
use sha3::digest::{ExtendableOutput, XofReader};
use sha3::digest::Update;
use sha3::digest::{ExtendableOutput, XofReader};
use sha3::{Digest, Sha3_256, Sha3_512, Shake128, Shake256};

use crate::ntt::multiply_ntts;
use crate::Q;
use crate::types::Z;
use crate::Q;


/// If the condition is not met, return an error message. Borrowed from the `anyhow` crate.
macro_rules! ensure {
Expand Down Expand Up @@ -115,7 +116,6 @@ pub(crate) fn xof(rho: &[u8; 32], i: u8, j: u8) -> impl XofReader {
pub(crate) fn g(bytes: &[&[u8]]) -> ([u8; 32], [u8; 32]) {
let mut hasher = Sha3_512::new();
bytes.iter().for_each(|b| Digest::update(&mut hasher, b));
//Digest::update(&mut hasher, bytes);
let digest = hasher.finalize();
let mut a = [0u8; 32];
let mut b = [0u8; 32];
Expand Down Expand Up @@ -160,11 +160,10 @@ pub(crate) fn compress(d: u32, inout: &mut [Z]) {
// Barrett division, quotient could be too small by one
let top = u64::from(x_ref.get_u32()) << d;
let quot = (top * m) >> k;
let bump = (top - quot * q64) > u64::from(Q);
let (_diff, bump) = u64::from(Q).overflowing_sub(top - quot * q64);
let quot = quot + (u64::from(bump).wrapping_neg() & 1);
// Round to nearest
let rem = top - quot * q64;
let bump = rem > (q64 >> 1);
let (_diff, bump) = u64::from(Q >> 1).overflowing_sub(top - quot * q64);
let result = quot + (u64::from(bump).wrapping_neg() & 1);
x_ref.set_u16(result as u16);
}
Expand Down
4 changes: 1 addition & 3 deletions src/k_pke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::ntt::{ntt, ntt_inv};
use crate::sampling::{sample_ntt, sample_poly_cbd};
use crate::types::Z;


/// Algorithm 12 `K-PKE.KeyGen()` on page 26.
/// Generates an encryption key and a corresponding decryption key.
///
Expand Down Expand Up @@ -309,7 +310,6 @@ mod tests {
let m = [0u8; 32];
let r = [0u8; 32];


let pkg = k_pke_key_gen::<K, ETA1_64>;
let res = pkg(&mut rng, ETA1, &mut ek, &mut dk[0..384 * K]);
assert!(res.is_ok());
Expand All @@ -322,7 +322,6 @@ mod tests {
let res = pkg(&mut rng, ETA1, &mut ek, &mut bad_dk);
assert!(res.is_err());


let pke = k_pke_encrypt::<K, ETA1_64, ETA2_64>;
let res = pke(DU, DV, ETA1, ETA2, &ek, &m, &r, &mut ct);
assert!(res.is_ok());
Expand All @@ -348,7 +347,6 @@ mod tests {
let res = pke(DU, DV, ETA1, ETA2 + 2, &ek, &m, &r, &mut ct);
assert!(res.is_err());


let pkd = k_pke_decrypt::<K>;
let res = pkd(DU, DV, &dk[0..384 * K], &ct);
assert!(res.is_ok());
Expand Down
35 changes: 21 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
#![deny(missing_docs)]
#![doc = include_str!("../README.md")]

// Implements FIPS 203 draft Module-Lattice-based Key-Encapsulation Mechanism Standard.
// See <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.ipd.pdf>

///
/// Implements FIPS 203 draft Module-Lattice-based Key-Encapsulation Mechanism Standard.
/// See <https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.ipd.pdf>
//
// Supports automatically clearing sensitive data on drop
use zeroize::{Zeroize, ZeroizeOnDrop};

Expand Down Expand Up @@ -38,7 +36,8 @@ use crate::traits::SerDes;
//
// The three parameter sets are modules in this file with injected macro code
// that connects them into the functionality in ml_kem.rs. Some of the 'obtuse'
// coding style is driven by clippy pedantic.
// coding style is driven by `clippy pedantic`.


mod byte_fns;
mod helpers;
Expand All @@ -51,32 +50,35 @@ mod types;
/// All functionality is covered by traits, such that consumers can utilize trait objects as desired.
pub mod traits;


// Relevant to all parameter sets
const _N: u32 = 256;
const Q: u32 = 3329;
const ZETA: u32 = 17;

/// Shared Secret Key Length for all ML-KEM variants (in bytes)

/// Shared Secret Key length for all ML-KEM variants (in bytes)
pub const SSK_LEN: usize = 32;

/// The (opaque) secret key that can be de/serialized by each party.
#[derive(Clone, Debug, Zeroize, ZeroizeOnDrop)]
pub struct SharedSecretKey([u8; SSK_LEN]);


impl SerDes for SharedSecretKey {
type ByteArray = [u8; SSK_LEN];

fn into_bytes(self) -> Self::ByteArray { self.0 }

fn try_from_bytes(ssk: Self::ByteArray) -> Result<Self, &'static str> {
// Not really needed but provided for symmetry.
// No opportunity for validation, but using a Result for a future possibility
// The `try_from` is not really needed but provided for symmetry, e.g., there
// is no opportunity for validation, but using a Result for the future possibility
Ok(SharedSecretKey(ssk))
}
}


// Conservative (constant-time) paranoia...
// Conservative (constant-time) ambitions...
impl PartialEq for SharedSecretKey {
fn eq(&self, other: &Self) -> bool {
let mut result = true;
Expand All @@ -103,6 +105,7 @@ macro_rules! functionality {
use crate::SharedSecretKey;
use rand_core::CryptoRngCore;


/// Correctly sized encapsulation key specific to the target security parameter set.
pub type EncapsKey = crate::types::EncapsKey<EK_LEN>;

Expand All @@ -115,6 +118,7 @@ macro_rules! functionality {
/// Supports the `KeyGen` trait, allowing for keypair generation
pub struct KG();


impl KeyGen for KG {
type DecapsByteArray = [u8; DK_LEN];
type DecapsKey = DecapsKey;
Expand All @@ -126,7 +130,7 @@ macro_rules! functionality {
) -> Result<(EncapsKey, DecapsKey), &'static str> {
let (mut ek, mut dk) = ([0u8; EK_LEN], [0u8; DK_LEN]);
ml_kem_key_gen::<K, ETA1_64>(rng, ETA1, &mut ek, &mut dk)?;
Ok((EncapsKey{0: ek}, DecapsKey{0: dk}))
Ok((EncapsKey { 0: ek }, DecapsKey { 0: dk }))
}

fn validate_keypair_vt(ek: &Self::EncapsByteArray, dk: &Self::DecapsByteArray) -> bool {
Expand All @@ -139,6 +143,7 @@ macro_rules! functionality {
}
}


impl Encaps for EncapsKey {
type CipherText = CipherText;
type SharedSecretKey = SharedSecretKey;
Expand All @@ -150,10 +155,11 @@ macro_rules! functionality {
let ssk = ml_kem_encaps::<K, ETA1_64, ETA2_64>(
rng, DU, DV, ETA1, ETA2, &self.0, &mut ct,
)?;
Ok((ssk, CipherText{0: ct}))
Ok((ssk, CipherText { 0: ct }))
}
}


impl Decaps for DecapsKey {
type CipherText = CipherText;
type SharedSecretKey = SharedSecretKey;
Expand Down Expand Up @@ -181,7 +187,7 @@ macro_rules! functionality {
for i in 0..K {
byte_decode(12, &ek[384 * i..384 * (i + 1)], &mut ek_hat)?;
}
Ok(EncapsKey{0: ek})
Ok(EncapsKey { 0: ek })
}
}

Expand All @@ -195,10 +201,11 @@ macro_rules! functionality {
// Validation per pg 31. Note that the two checks specify fixed sizes, and these
// functions take only byte arrays of correct size. Nonetheless, we use a Result
// here in case future opportunities for validation arise.
Ok(DecapsKey{0: dk})
Ok(DecapsKey { 0: dk })
}
}


impl SerDes for CipherText {
type ByteArray = [u8; CT_LEN];

Expand All @@ -208,7 +215,7 @@ macro_rules! functionality {
// Validation per pg 31. Note that the two checks specify fixed sizes, and these
// functions take only byte arrays of correct size. Nonetheless, we use a Result
// here in case future opportunities for validation arise.
Ok(CipherText{0: ct})
Ok(CipherText { 0: ct })
}
}
};
Expand Down
6 changes: 2 additions & 4 deletions src/ml_kem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ use rand_core::CryptoRngCore;
use crate::byte_fns::{byte_decode, byte_encode};
use crate::helpers::{ensure, g, h, j};
use crate::k_pke::{k_pke_decrypt, k_pke_encrypt, k_pke_key_gen};
use crate::SharedSecretKey;
use crate::types::Z;
use crate::SharedSecretKey;


/// Algorithm 15 `ML-KEM.KeyGen()` on page 29.
/// Generates an encapsulation key and a corresponding decapsulation key.
Expand Down Expand Up @@ -175,7 +176,6 @@ mod tests {
let mut dk = [0u8; DK_LEN];
let mut ct = [0u8; CT_LEN];


let mkg = ml_kem_key_gen::<K, ETA1_64>;
let res = mkg(&mut rng, ETA1, &mut ek, &mut dk);
assert!(res.is_ok());
Expand All @@ -188,7 +188,6 @@ mod tests {
let res = mkg(&mut rng, ETA1, &mut ek, &mut bad_dk);
assert!(res.is_err());


let mke = ml_kem_encaps::<K, ETA1_64, ETA2_64>;
let res = mke(&mut rng, DU, DV, ETA1, ETA2, &ek, &mut ct);
assert!(res.is_ok());
Expand All @@ -200,7 +199,6 @@ mod tests {
let res = mke(&mut rng, DU, DV, ETA1, ETA2, &ff_ek, &mut ct);
assert!(res.is_err());


let mkd = ml_kem_decaps::<K, ETA1_64, ETA2_64, J_LEN, CT_LEN>;
let res = mkd(DU, DV, ETA1, ETA2, &dk, &ct);
assert!(res.is_ok());
Expand Down
10 changes: 5 additions & 5 deletions src/ntt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{Q, ZETA};
use crate::types::Z;
use crate::{Q, ZETA};


/// Algorithm 8 `NTT(f)` on page 22.
/// Computes the NTT representation `f_hat` of the given polynomial f ∈ `R_q`.
Expand Down Expand Up @@ -165,10 +166,9 @@ pub fn base_case_multiply(a0: Z, a1: Z, b0: Z, b1: Z, gamma: Z) -> (Z, Z) {
// ----------
// The functionality below calculates the Zeta array at compile-time. Thus, not particularly optimal or CT.


/// HAC Algorithm 14.76 Right-to-left binary exponentiation mod Q.
#[must_use]
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_truncation)] // on result
const fn pow_mod_q(g: u32, e: u8) -> u16 {
let g = g as u64;
let mut result = 1;
Expand All @@ -187,7 +187,7 @@ const fn pow_mod_q(g: u32, e: u8) -> u16 {
}


#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_truncation)] // i as u8
const fn gen_zeta_table() -> [u16; 256] {
let mut result = [0u16; 256];
let mut i = 0;
Expand All @@ -205,8 +205,8 @@ pub(crate) static ZETA_TABLE: [u16; 256] = gen_zeta_table();
#[cfg(test)]
mod tests {
use crate::ntt::{gen_zeta_table, pow_mod_q};
use crate::SharedSecretKey;
use crate::traits::SerDes;
use crate::SharedSecretKey;

#[test]
fn test_zeta_misc() {
Expand Down
3 changes: 2 additions & 1 deletion src/sampling.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use sha3::digest::XofReader;

use crate::Q;
use crate::types::Z;
use crate::Q;


/// Algorithm 6 `SampleNTT(B)` on page 20.
/// If the input is a stream of uniformly random bytes, the output is a uniformly random element of `T_q`.
Expand Down
Loading

0 comments on commit 37969be

Please sign in to comment.