-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'dev' into franziskus/mlkem-c
- Loading branch information
Showing
27 changed files
with
7,235 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
name: ML-DSA | ||
|
||
on: | ||
push: | ||
branches: ["main", "dev"] | ||
pull_request: | ||
branches: ["main", "dev", "*"] | ||
workflow_dispatch: | ||
merge_group: | ||
|
||
env: | ||
CARGO_TERM_COLOR: always | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
build: | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
bits: [32, 64] | ||
os: | ||
- macos-13 # Intel mac | ||
- macos-latest # macos-14 m1 | ||
- ubuntu-latest | ||
- windows-latest | ||
exclude: | ||
- bits: 32 | ||
os: "macos-latest" | ||
- bits: 32 | ||
os: "macos-13" | ||
|
||
runs-on: ${{ matrix.os }} | ||
defaults: | ||
run: | ||
shell: bash | ||
working-directory: libcrux-ml-dsa | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- run: echo "RUST_TARGET_FLAG=" > $GITHUB_ENV | ||
if: ${{ matrix.bits == 64 }} | ||
|
||
- name: 🛠️ Setup Rust Nightly | ||
run: rustup toolchain install nightly | ||
|
||
- name: 🛠️ Setup Ubuntu x86 | ||
if: ${{ matrix.bits == 32 && matrix.os == 'ubuntu-latest' }} | ||
run: | | ||
rustup target add i686-unknown-linux-gnu | ||
sudo apt-get update | ||
sudo apt-get install -y gcc-multilib g++-multilib | ||
- name: 🛠️ Setup Ubuntu x64 | ||
if: ${{ matrix.bits == 64 && matrix.os == 'ubuntu-latest' }} | ||
run: | | ||
rustup target add aarch64-unknown-linux-gnu | ||
# Set up 32 bit systems | ||
|
||
- name: 🛠️ Config Windows x86 | ||
run: echo "RUST_TARGET_FLAG=--target=i686-pc-windows-msvc" > $GITHUB_ENV | ||
if: ${{ matrix.bits == 32 && matrix.os == 'windows-latest' }} | ||
|
||
- name: 🛠️ Config Linux x86 | ||
run: | | ||
echo "RUST_TARGET_FLAG=--target=i686-unknown-linux-gnu" > $GITHUB_ENV | ||
if: ${{ matrix.bits == 32 && matrix.os == 'ubuntu-latest' }} | ||
|
||
# Build ... | ||
|
||
- name: 🔨 Build | ||
run: | | ||
rustc --print=cfg | ||
cargo build --verbose $RUST_TARGET_FLAG | ||
- name: 🔨 Build Release | ||
run: cargo build --verbose --release $RUST_TARGET_FLAG | ||
|
||
- name: 🏃🏻 Asan MacOS | ||
if: ${{ matrix.os == 'macos-latest' }} | ||
run: RUSTDOCFLAGS=-Zsanitizer=address RUSTFLAGS=-Zsanitizer=address cargo +nightly test --release --target aarch64-apple-darwin | ||
|
||
# Test ML-DSA | ||
|
||
- name: 🏃🏻♀️ Test | ||
run: | | ||
cargo clean | ||
cargo test --verbose $RUST_TARGET_FLAG | ||
- name: 🏃🏻♀️ Test Release | ||
run: | | ||
cargo clean | ||
cargo test --verbose --release $RUST_TARGET_FLAG |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
use crate::constants::{BITS_IN_LOWER_PART_OF_T, COEFFICIENTS_IN_RING_ELEMENT, FIELD_MODULUS}; | ||
|
||
/// Values having this type hold a representative 'x' of the ML-DSA field. | ||
pub(crate) type FieldElement = i32; | ||
|
||
#[derive(Clone, Copy)] | ||
pub struct PolynomialRingElement { | ||
pub(crate) coefficients: [FieldElement; COEFFICIENTS_IN_RING_ELEMENT], | ||
} | ||
|
||
impl PolynomialRingElement { | ||
pub const ZERO: Self = Self { | ||
// FIXME: hax issue, 256 is COEFFICIENTS_IN_RING_ELEMENT | ||
coefficients: [0i32; 256], | ||
}; | ||
} | ||
|
||
// Splits 0 ≤ t < Q into t0 and t1 with a = t1*2ᴰ + t0 | ||
// and -2ᴰ⁻¹ < t0 < 2ᴰ⁻¹. Returns t0 and t1 computed as. | ||
// | ||
// - t0 = t mod± 2ᵈ | ||
// - t1 = (t - t0) / 2ᵈ. | ||
// | ||
// This approach has been taken from: | ||
// https://github.com/cloudflare/circl/blob/main/sign/dilithium/internal/common/field.go#L35 | ||
pub(crate) fn power2round(t: i32) -> (i32, i32) { | ||
debug_assert!(t >= 0 && t < FIELD_MODULUS); | ||
|
||
// Compute t mod 2ᵈ | ||
// t0 is now one of 0, 1, ..., 2ᵈ⁻¹-1, 2ᵈ⁻¹, 2ᵈ⁻¹+1, ..., 2ᵈ-1 | ||
let mut t0 = t & ((1 << BITS_IN_LOWER_PART_OF_T) - 1); | ||
|
||
// now t0 is -2ᵈ⁻¹-1, -2ᵈ⁻¹, ..., -2, -1, 0, ..., 2ᵈ⁻¹-2 | ||
t0 -= (1 << (BITS_IN_LOWER_PART_OF_T - 1)) + 1; | ||
|
||
// Next, we add 2ᴰ to those t0 that are negative | ||
// now a0 is 2ᵈ⁻¹-1, 2ᵈ⁻¹, ..., 2ᵈ-2, 2ᵈ-1, 0, ..., 2ᵈ⁻¹-2 | ||
t0 += (t0 >> 31) & (1 << BITS_IN_LOWER_PART_OF_T); | ||
|
||
// now t0 is 0, 1, 2, ..., 2ᵈ⁻¹-1, 2ᵈ⁻¹-1, -2ᵈ⁻¹-1, ... | ||
// which is what we want. | ||
t0 -= (1 << (BITS_IN_LOWER_PART_OF_T - 1)) - 1; | ||
|
||
let t1 = (t - t0) >> BITS_IN_LOWER_PART_OF_T; | ||
|
||
(t0, t1) | ||
} | ||
|
||
pub(crate) fn t0_to_unsigned_representative(t0: i32) -> i32 { | ||
(1 << (BITS_IN_LOWER_PART_OF_T - 1)) - t0 | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_power2round() { | ||
assert_eq!(power2round(2898283), (-1685, 354)); | ||
assert_eq!(power2round(3821421), (3949, 466)); | ||
assert_eq!(power2round(2577417), (-3063, 315)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,14 @@ | ||
pub(crate) const FIELD_MODULUS: i32 = 8_380_417; | ||
|
||
pub(crate) const COEFFICIENTS_IN_RING_ELEMENT: usize = 256; | ||
|
||
pub(crate) const FIELD_MODULUS_MINUS_ONE_BIT_LENGTH: usize = 23; | ||
|
||
pub(crate) const DROPPED_BITS_FROM_T: usize = 13; | ||
pub(crate) const BITS_IN_LOWER_PART_OF_T: usize = 13; | ||
|
||
pub(crate) const BITS_IN_UPPER_PART_OF_T: usize = | ||
FIELD_MODULUS_MINUS_ONE_BIT_LENGTH - BITS_IN_LOWER_PART_OF_T; | ||
|
||
pub(crate) const SEED_FOR_A_SIZE: usize = 32; | ||
pub(crate) const HASH_OF_PUBLIC_KEY_SIZE: usize = 64; | ||
pub(crate) const SEED_FOR_SIGNING_SIZE: usize = 32; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#![allow(non_snake_case)] | ||
pub(crate) fn H<const OUTPUT_LENGTH: usize>(input: &[u8]) -> [u8; OUTPUT_LENGTH] { | ||
let mut out = [0u8; OUTPUT_LENGTH]; | ||
libcrux_sha3::portable::shake256(&mut out, input); | ||
|
||
out | ||
} | ||
|
||
pub(crate) mod H_128 { | ||
use libcrux_sha3::portable::{incremental, KeccakState1}; | ||
|
||
const BLOCK_SIZE: usize = 168; | ||
const FIVE_BLOCKS_SIZE: usize = BLOCK_SIZE * 5; | ||
|
||
#[inline(always)] | ||
pub(crate) fn new(seed: [u8; 34]) -> KeccakState1 { | ||
let mut state = incremental::shake128_init(); | ||
incremental::shake128_absorb_final(&mut state, &seed); | ||
|
||
state | ||
} | ||
|
||
pub(crate) fn squeeze_first_five_blocks(state: &mut KeccakState1) -> [u8; FIVE_BLOCKS_SIZE] { | ||
let mut out = [0u8; FIVE_BLOCKS_SIZE]; | ||
incremental::shake128_squeeze_first_five_blocks(state, &mut out); | ||
|
||
out | ||
} | ||
|
||
pub(crate) fn squeeze_next_block(state: &mut KeccakState1) -> [u8; BLOCK_SIZE] { | ||
let mut out = [0u8; BLOCK_SIZE]; | ||
incremental::shake128_squeeze_next_block(state, &mut out); | ||
|
||
out | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,11 @@ | ||
mod arithmetic; | ||
mod constants; | ||
mod hash_functions; | ||
mod matrix; | ||
mod sample; | ||
mod serialize; | ||
mod utils; | ||
|
||
mod ml_dsa_generic; | ||
|
||
pub mod ml_dsa_65; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
use crate::{arithmetic::PolynomialRingElement, sample::sample_ring_element_uniform}; | ||
|
||
#[allow(non_snake_case)] | ||
#[inline(always)] | ||
pub(crate) fn expand_to_A<const ROWS_IN_A: usize, const COLUMNS_IN_A: usize>( | ||
mut seed: [u8; 34], | ||
transposed: bool, | ||
) -> [[PolynomialRingElement; COLUMNS_IN_A]; ROWS_IN_A] { | ||
let mut A = [[PolynomialRingElement::ZERO; COLUMNS_IN_A]; ROWS_IN_A]; | ||
|
||
for i in 0..ROWS_IN_A { | ||
for j in 0..COLUMNS_IN_A { | ||
seed[32] = i as u8; | ||
seed[33] = j as u8; | ||
|
||
let sampled = sample_ring_element_uniform(seed); | ||
|
||
if transposed { | ||
A[j][i] = sampled; | ||
} else { | ||
A[i][j] = sampled; | ||
} | ||
} | ||
} | ||
|
||
A | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,19 @@ | ||
pub(crate) fn generate_key_pair<const SECRET_KEY_SIZE: usize, const PUBLIC_KEY_SIZE: usize>( | ||
use crate::{hash_functions::H, matrix::expand_to_A, utils::into_padded_array}; | ||
|
||
#[allow(non_snake_case)] | ||
pub(crate) fn generate_key_pair< | ||
const ROWS_IN_A: usize, | ||
const COLUMNS_IN_A: usize, | ||
const SIGNING_KEY_SIZE: usize, | ||
const VERIFICATION_KEY_SIZE: usize, | ||
>( | ||
randomness: [u8; 32], | ||
) -> ([u8; SECRET_KEY_SIZE], [u8; PUBLIC_KEY_SIZE]) { | ||
let _ = randomness; | ||
) -> ([u8; SIGNING_KEY_SIZE], [u8; VERIFICATION_KEY_SIZE]) { | ||
let seed_expanded = H::<1024>(&randomness); | ||
let (seed_for_A, seed_expanded) = seed_expanded.split_at(32); | ||
let (_seed_for_short_vectors, _random_seed_for_signing) = seed_expanded.split_at(64); | ||
|
||
let _A_hat = expand_to_A::<ROWS_IN_A, COLUMNS_IN_A>(into_padded_array(seed_for_A), false); | ||
|
||
todo!(); | ||
} |
Oops, something went wrong.