Skip to content

Commit

Permalink
action
Browse files Browse the repository at this point in the history
  • Loading branch information
eschorn1 committed Oct 29, 2023
1 parent 2b235de commit 17ee437
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 162 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ jobs:
rust:
- 1.72.0 # MSRV
- stable
#target:
# - thumbv7em-none-eabi
# - wasm32-unknown-unknown
target:
- thumbv7em-none-eabi
- wasm32-unknown-unknown
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
#targets: ${{ matrix.target }}
targets: ${{ matrix.target }}
- run: cargo build --target ${{ matrix.target }} --release

#benches:
Expand Down
12 changes: 10 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,18 @@ exclude = [".idea/*"]


[dependencies]
zeroize = {version = "1.6.0", features = ["zeroize_derive"]}
zeroize = { version = "1.6.0", features = ["zeroize_derive"] }
sha3 = "0.10.8"
rand = "0.8.5"
getrandom = { version = "0.2", features = ["js"] }


[features]
default = ["ml_kem_512", "ml_kem_768", "ml_kem_1024"]
ml_kem_512 = []
ml_kem_768 = []
ml_kem_1024 = []


[dev-dependencies]
rand_chacha = "0.3.1"
rand_chacha = "0.3.1"
21 changes: 11 additions & 10 deletions src/byte_fns.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::{k_pke::Z256, Q};
use crate::Q;
use crate::types::Z256;

// Algorithm 2 `BitsToBytes(b)` on page 17.
// Converts a bit string (of length a multiple of eight) into an array of bytes.
/// Algorithm 2 `BitsToBytes(b)` on page 17.
/// Converts a bit string (of length a multiple of eight) into an array of bytes.
pub(crate) fn bits_to_bytes(bits: &[u8], bytes: &mut [u8]) {
// Input: bit array b ∈ {0,1}^{8·ℓ}
// Output: byte array B ∈ B^ℓ
Expand All @@ -18,8 +19,8 @@ pub(crate) fn bits_to_bytes(bits: &[u8], bytes: &mut [u8]) {
} // 5: return B


// Algorithm 3 `BytesToBits(B)` on page 18.
// Performs the inverse of `BitsToBytes`, converting a byte array into a bit array.
/// Algorithm 3 `BytesToBits(B)` on page 18.
/// Performs the inverse of `BitsToBytes`, converting a byte array into a bit array.
pub(crate) fn bytes_to_bits(bytes: &[u8], bits: &mut [u8]) {
// Input: byte array B ∈ B^ℓ
// Output: bit array b ∈ {0,1}^{8·ℓ}
Expand All @@ -42,8 +43,8 @@ pub(crate) fn bytes_to_bits(bytes: &[u8], bits: &mut [u8]) {
} // 7: return b


// Algorithm 4 `ByteEncode<d>(F)` on page 19.
// Encodes an array of d-bit integers into a byte array, for 1 ≤ d ≤ 12.
/// Algorithm 4 `ByteEncode<d>(F)` on page 19.
/// Encodes an array of d-bit integers into a byte array, for 1 ≤ d ≤ 12.
pub(crate) fn byte_encode<const D: usize, const D_256: usize>(
integers_f: &[Z256; 256], bytes_b: &mut [u8],
) {
Expand Down Expand Up @@ -80,8 +81,8 @@ pub(crate) fn byte_encode<const D: usize, const D_256: usize>(
} // 9: return B


// Algorithm 5 `ByteDecode<d>(B)` on page 19.
// Decodes a byte array into an array of d-bit integers, for 1 ≤ d ≤ 12.
/// Algorithm 5 `ByteDecode<d>(B)` on page 19.
/// Decodes a byte array into an array of d-bit integers, for 1 ≤ d ≤ 12.
pub(crate) fn byte_decode<const D: usize, const D_256: usize>(
bytes_b: &[u8], integers_f: &mut [Z256; 256],
) {
Expand Down Expand Up @@ -123,7 +124,7 @@ mod tests {
use rand::{Rng, SeedableRng};

use crate::byte_fns::{bits_to_bytes, byte_decode, byte_encode, bytes_to_bits};
use crate::k_pke::Z256;
use crate::types::Z256;

#[test]
fn test_bytes_and_bits() {
Expand Down
36 changes: 18 additions & 18 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ use sha3::{Digest, Sha3_256, Sha3_512, Shake128, Shake256};
use sha3::digest::{ExtendableOutput, XofReader};
use sha3::digest::Update;

use crate::k_pke::Z256;
use crate::ntt::multiply_ntts;
use crate::Q;
use crate::types::Z256;

// Vector addition; See bottom of page 9, second row: z_hat = u_hat + v_hat
/// Vector addition; See bottom of page 9, second row: z_hat = u_hat + v_hat
#[must_use]
pub(crate) fn vec_add<const K: usize>(
vec_a: &[[Z256; 256]; K], vec_b: &[[Z256; 256]; K],
) -> [[Z256; 256]; K] {
// TODO: remove K(?)
let mut result = [[Z256(0); 256]; K];
for i in 0..vec_a.len() {
for j in 0..vec_a[i].len() {
Expand All @@ -22,7 +21,7 @@ pub(crate) fn vec_add<const K: usize>(
}


// Matrix by vector multiplication; See top of page 10, first row: w_hat = A_hat mul u_hat
/// Matrix by vector multiplication; See top of page 10, first row: w_hat = A_hat mul u_hat
#[must_use]
pub(crate) fn mat_vec_mul<const K: usize>(
a_hat: &[[[Z256; 256]; K]; K], u_hat: &[[Z256; 256]; K],
Expand All @@ -42,7 +41,7 @@ pub(crate) fn mat_vec_mul<const K: usize>(
}


// Matrix transpose by vector multiplication; See top of page 10, second row: y_hat = A_hatT mul u_hat
/// Matrix transpose by vector multiplication; See top of page 10, second row: y_hat = A_hatT mul u_hat
#[must_use]
pub(crate) fn mat_t_vec_mul<const K: usize>(
a_hat: &[[[Z256; 256]; K]; K], u_hat: &[[Z256; 256]; K],
Expand Down Expand Up @@ -77,7 +76,7 @@ pub(crate) fn dot_t_prod<const K: usize>(
}


// Function PRF on page 16 (4.1).
/// Function PRF on page 16 (4.1).
#[must_use]
pub(crate) fn prf<const ETA_64: usize>(s: &[u8; 32], b: u8) -> [u8; ETA_64] {
let mut hasher = Shake256::default();
Expand All @@ -90,7 +89,7 @@ pub(crate) fn prf<const ETA_64: usize>(s: &[u8; 32], b: u8) -> [u8; ETA_64] {
}


// Function XOF on page 16 (4.2).
/// Function XOF on page 16 (4.2).
#[must_use]
pub(crate) fn xof(rho: &[u8; 32], i: u8, j: u8) -> impl XofReader {
let mut hasher = Shake128::default();
Expand All @@ -101,7 +100,7 @@ pub(crate) fn xof(rho: &[u8; 32], i: u8, j: u8) -> impl XofReader {
}


// Function G on page 17 (4.4).
/// Function G on page 17 (4.4).
pub(crate) fn g(bytes: &[u8]) -> ([u8; 32], [u8; 32]) {
let mut hasher = Sha3_512::new();
Digest::update(&mut hasher, bytes);
Expand All @@ -114,7 +113,7 @@ pub(crate) fn g(bytes: &[u8]) -> ([u8; 32], [u8; 32]) {
}


// Function H on page 17 (4.3).
/// Function H on page 17 (4.3).
#[must_use]
pub(crate) fn h(bytes: &[u8]) -> [u8; 32] {
let mut hasher = Sha3_256::new();
Expand All @@ -124,7 +123,7 @@ pub(crate) fn h(bytes: &[u8]) -> [u8; 32] {
}


// Function J n page 17 (4.4).
/// Function J n page 17 (4.4).
#[must_use]
pub(crate) fn j(bytes: &[u8]) -> [u8; 32] {
let mut hasher = Shake256::default();
Expand All @@ -136,9 +135,9 @@ pub(crate) fn j(bytes: &[u8]) -> [u8; 32] {
}


// BitRev7(i) from page 21 line 839-840.
// Returns the integer represented by bit-reversing the unsigned 7-bit value that
// corresponds to the input integer i ∈ {0, . . . , 127}.
/// BitRev7(i) from page 21 line 839-840.
/// Returns the integer represented by bit-reversing the unsigned 7-bit value that
/// corresponds to the input integer i ∈ {0, . . . , 127}.
#[must_use]
pub(crate) fn bit_rev_7(a: u8) -> u8 {
((a >> 6) & 1)
Expand All @@ -151,7 +150,7 @@ pub(crate) fn bit_rev_7(a: u8) -> u8 {
}


// HAC Algorithm 14.76 Right-to-left binary exponentiation mod Q.
/// HAC Algorithm 14.76 Right-to-left binary exponentiation mod Q.
#[must_use]
pub(crate) fn pow_mod_q(g: u32, e: u8) -> u32 {
let mut result = 1;
Expand All @@ -170,6 +169,7 @@ pub(crate) fn pow_mod_q(g: u32, e: u8) -> u32 {
}


/// Round to nearest
fn nearest(numerator: u32, denominator: u32) -> u16 {
let remainder = numerator % denominator;
let quotient = u16::try_from(numerator / denominator).unwrap();
Expand All @@ -181,17 +181,17 @@ fn nearest(numerator: u32, denominator: u32) -> u16 {
}


// Compress<d> from page 18 (4.5).
// x → ⌈(2^d/q) · x⌋
/// Compress<d> from page 18 (4.5).
/// x → ⌈(2^d/q) · x⌋
pub(crate) fn compress<const D: usize>(inout: &mut [Z256]) {
for x_ref in &mut *inout {
x_ref.0 = nearest(2u32.pow(u32::try_from(D).unwrap()) * u32::from(x_ref.0), Q);
}
}


// Decompress<d> from page 18 (4.6).
// y → ⌈(q/2^d) · y⌋ .
/// Decompress<d> from page 18 (4.6).
/// y → ⌈(q/2^d) · y⌋ .
pub(crate) fn decompress<const D: usize>(inout: &mut [Z256]) {
for y_ref in &mut *inout {
y_ref.0 = nearest(Q * u32::from(y_ref.0), 2u32.pow(u32::try_from(D).unwrap()));
Expand Down
40 changes: 8 additions & 32 deletions src/k_pke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,10 @@ use crate::helpers::{
use crate::ntt::{ntt, ntt_inv};
use crate::Q;
use crate::sampling::{sample_ntt, sample_poly_cbd};
use crate::types::Z256;

// Stored as u16, but arithmetic as u32 (so we can multiply/reduce/etc)
#[derive(Clone, Copy)]
pub struct Z256(pub u16);

impl Z256 {
pub fn get_u32(self) -> u32 { u32::from(self.0) }

pub fn get_u16(self) -> u16 { self.0 }

pub fn set_u16(&mut self, a: u32) {
//debug_assert!(a < Q); //u32::from(u16::MAX));
self.0 = u16::try_from(a % Q).unwrap(); // TODO: Revisit
}

#[allow(dead_code)] // stitch in when we get overall correct
pub fn mul(self, other: Self) -> Self {
let prod = u64::from(self.0) * u64::from(other.0);
let div = prod * (2u64.pow(24) / (u64::from(Q)));
let (diff, borrow) = div.overflowing_sub(u64::from(Q));
let result = if borrow { div } else { diff }; // TODO: CT MUX
Self(u16::try_from(result).unwrap()) // TODO: Revisit
}
}


// Algorithm 12 `K-PKE.KeyGen()` on page 26.
// Generates an encryption key and a corresponding decryption key.
/// Algorithm 12 `K-PKE.KeyGen()` on page 26.
/// Generates an encryption key and a corresponding decryption key.
#[allow(clippy::similar_names, clippy::module_name_repetitions)]
pub fn k_pke_key_gen<
const K: usize,
Expand Down Expand Up @@ -124,8 +100,8 @@ pub fn k_pke_key_gen<
}


// Algorithm 13 `K-PKE.Encrypt(ekPKE , m, r)` on page 27.
// Uses the encryption key to encrypt a plaintext message using the randomness r.
/// Algorithm 13 `K-PKE.Encrypt(ekPKE , m, r)` on page 27.
/// Uses the encryption key to encrypt a plaintext message using the randomness r.
#[allow(clippy::many_single_char_names)]
pub(crate) fn k_pke_encrypt<
const K: usize,
Expand Down Expand Up @@ -245,8 +221,8 @@ pub(crate) fn k_pke_encrypt<
}


// Algorithm 14 `K-PKE.Decrypt(dkPKE, c)` on page 28.
// Uses the decryption key to decrypt a ciphertext.
/// Algorithm 14 `K-PKE.Decrypt(dkPKE, c)` on page 28.
/// Uses the decryption key to decrypt a ciphertext.
pub(crate) fn k_pke_decrypt<
const K: usize,
const DU: usize,
Expand Down Expand Up @@ -283,7 +259,7 @@ pub(crate) fn k_pke_decrypt<
decompress::<DV>(&mut v);

// 5: s_hat ← ByteDecode_{12}(dk_{PKE{)
let mut s_hat = [[Z256(0); 256]; K]; // TODO: recheck the dimensions of s_hat
let mut s_hat = [[Z256(0); 256]; K];
for i in 0..K {
byte_decode::<12, { 12 * 256 }>(&dk[384 * i..384 * (i + 1)], &mut s_hat[i]);
}
Expand Down
Loading

0 comments on commit 17ee437

Please sign in to comment.