Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/workspace-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ concurrency:
cancel-in-progress: true

jobs:
check:
if: ${{ github.event_name != 'merge_group' }}
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v5

- name: 🧐 Cargo check
env:
RUSTFLAGS: "-D missing_docs"
run: cargo check --workspace

fmt:
if: ${{ github.event_name != 'merge_group' }}
runs-on: ubuntu-latest
Expand All @@ -28,7 +40,7 @@ jobs:

fmt-status:
if: ${{ always() }}
needs: [fmt]
needs: [fmt, check]
runs-on: ubuntu-latest
steps:
- name: Successful
Expand Down
4 changes: 4 additions & 0 deletions benchmarks/build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
//! Build script for benchmarks crate.
//!
//! This script configures linking to lib25519 if available for benchmark comparisons.

use std::{env, path::Path};

fn main() {
Expand Down
9 changes: 9 additions & 0 deletions benchmarks/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
//! Benchmark utilities for libcrux performance testing.
//!
//! This crate provides utility functions for benchmarking cryptographic operations.

/// Utility functions for benchmarking
pub mod util {
/// Generate random bytes for testing
pub fn randombytes(n: usize) -> Vec<u8> {
use rand::rngs::OsRng;
use rand::TryRngCore;
Expand All @@ -8,12 +14,14 @@ pub mod util {
bytes
}

/// Format byte count with appropriate units (KB, MB, GB)
pub fn fmt(x: usize) -> String {
let base = (x as f64).log(1024f64).floor() as usize;
let suffix = ["", "KB", "MB", "GB"];
format!("{} {}", x >> (10 * base), suffix[base])
}

/// Convert hex string to byte vector
pub fn hex_str_to_bytes(val: &str) -> Vec<u8> {
let b: Result<Vec<u8>, std::num::ParseIntError> = (0..val.len())
.step_by(2)
Expand All @@ -22,6 +30,7 @@ pub mod util {
b.expect("Error parsing hex string")
}

/// Convert hex string to fixed-size array
pub fn hex_str_to_array<A>(val: &str) -> A
where
A: Default + AsMut<[u8]>,
Expand Down
1 change: 1 addition & 0 deletions blake2/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![cfg_attr(not(feature = "std"), no_std)]

#[allow(missing_docs)]
mod hacl {
//! This module contains generated hacl code.

Expand Down
14 changes: 14 additions & 0 deletions cavp/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//! CAVP (Cryptographic Algorithm Validation Program) test vector parser.
//!
//! This crate provides functionality to read and parse CAVP test vectors
//! for various cryptographic algorithms including SHA3 and SHAKE.

use core::fmt;
use std::{
fs::File,
Expand All @@ -19,14 +24,18 @@ pub fn read_string<Ty: Tv>(tv: &str) -> Result<TestVector<Ty>, Error> {
/// Errors
#[derive(Debug, Clone, Copy)]
pub enum Error {
/// Failed to open the test vector file
FileOpen,
/// Failed to read or parse test vector data
Read,
}

/// A CAVP test vector.
#[derive(Debug, Clone, Default)]
pub struct TestVector<TestType: Tv> {
/// Header information for the test vector
pub header: TestType::H,
/// Collection of individual test cases
pub tests: Vec<TestType::T>,
}

Expand Down Expand Up @@ -123,14 +132,17 @@ use helper::*;
pub struct Sha3Test {
/// Note that `msg_length` is not necessary the same as `msg.len()`
pub msg_length: usize,
/// Input message bytes
pub msg: Vec<u8>,
/// Expected SHA3 digest output
pub digest: Vec<u8>,
}

/// Empty SHA3 header.
#[derive(Debug, Clone, Default)]
pub struct Sha3Header {}

/// SHA3 test vector type
#[derive(Debug, Clone, Default)]
pub struct Sha3 {}
impl Tv for Sha3 {
Expand Down Expand Up @@ -181,7 +193,9 @@ impl Test for Sha3Test {
pub struct ShakeMsgTest {
/// Note that `msg_length` is not necessary the same as `msg.len()`
pub msg_length: usize,
/// Input message bytes
pub msg: Vec<u8>,
/// Expected SHAKE digest output
pub digest: Vec<u8>,
}

Expand Down
6 changes: 6 additions & 0 deletions fstar-helpers/core-models/src/abstractions/bit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
/// Represent a bit: `0` or `1`.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Bit {
/// Represents the bit value `0`.
Zero,
/// Represents the bit value `1`.
One,
}

Expand Down Expand Up @@ -111,6 +113,10 @@ impl Bit {
}
}

/// Extracts the `nth` bit from the given integer `x`.
///
/// This function treats the integer as a two's complement representation
/// and returns the bit at position `nth` (0-indexed from the least significant bit).
pub fn of_int<T: Into<i128> + MachineInteger>(x: T, nth: u32) -> Bit {
let x: i128 = x.into();
if x >= 0 {
Expand Down
10 changes: 10 additions & 0 deletions fstar-helpers/core-models/src/abstractions/bitvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ const _: () = ();
macro_rules! impl_pointwise {
($n:literal, $($i:literal)*) => {
impl BitVec<$n> {
/// Creates a pointwise copy of the bit vector elements.
///
/// This method reconstructs the bit vector by applying an identity function
/// to each bit, effectively creating a new bit vector with the same values.
pub fn pointwise(self) -> Self {
Self::from_fn(|i| match i {
$($i => self[$i],)*
Expand Down Expand Up @@ -241,6 +245,10 @@ pub fn bitvec_postprocess_norm() {}

#[hax_lib::attributes]
impl<const N: u64> BitVec<N> {
/// Performs chunked shift operations on the bit vector.
///
/// Divides the bit vector into chunks of size `CHUNK` and applies shift operations
/// specified in the `shl` array to each chunk.
#[hax_lib::requires(CHUNK > 0 && CHUNK.to_int() * SHIFTS.to_int() == N.to_int())]
pub fn chunked_shift<const CHUNK: u64, const SHIFTS: u64>(
self,
Expand Down Expand Up @@ -355,6 +363,7 @@ pub mod int_vec_interp {
u32x4 [u32; 4], u64x2 [u64; 2], u16x8 [u16; 8]);

impl i64x4 {
/// Converts an `i64x4` into an `i32x8` by splitting each 64-bit integer into two 32-bit integers.
pub fn into_i32x8(self) -> i32x8 {
i32x8::from_fn(|i| {
let value = *self.get(i / 2);
Expand All @@ -364,6 +373,7 @@ pub mod int_vec_interp {
}

impl i32x8 {
/// Converts an `i32x8` into an `i64x4` by combining pairs of 32-bit integers into 64-bit integers.
pub fn into_i64x4(self) -> i64x4 {
i64x4::from_fn(|i| {
let low = *self.get(2 * i) as u32 as u64;
Expand Down
4 changes: 4 additions & 0 deletions fstar-helpers/core-models/src/abstractions/funarr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ impl<const N: u64, T> FunArray<N, T> {
macro_rules! impl_pointwise {
($n:literal, $($i:literal)*) => {
impl<T: Copy> FunArray<$n, T> {
/// Creates a pointwise copy of the array elements.
///
/// This method reconstructs the array by applying an identity function
/// to each element, effectively creating a new array with the same values.
pub fn pointwise(self) -> Self {
Self::from_fn(|i| match i {
$($i => self[$i],)*
Expand Down
1 change: 1 addition & 0 deletions fstar-helpers/core-models/src/abstractions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@

pub mod bit;
pub mod bitvec;
/// Functional array abstraction with fixed-size arrays and F* integration.
pub mod funarr;
22 changes: 22 additions & 0 deletions fstar-helpers/core-models/src/core_arch/x86.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
//!
#![allow(clippy::too_many_arguments)]

/// Interpretations and additional models for x86 SIMD operations.
pub mod interpretations;
use crate::abstractions::{bit::*, bitvec::*, funarr::*};

Expand Down Expand Up @@ -171,15 +172,18 @@ pub type __m128i = BitVec<128>;
pub type __m256 = __m256i;

pub use ssse3::*;
/// SSSE3 (Supplemental Streaming SIMD Extensions 3) instruction models.
pub mod ssse3 {
use super::*;
/// Shuffle bytes in a 128-bit vector according to control bytes in indexes.
#[hax_lib::opaque]
pub fn _mm_shuffle_epi8(vector: __m128i, indexes: __m128i) -> __m128i {
let indexes = indexes.to_vec().try_into().unwrap();
extra::mm_shuffle_epi8_u8_array(vector, indexes)
}
}
pub use sse2::*;
/// SSE2 (Streaming SIMD Extensions 2) instruction models.
pub mod sse2 {
/// This intrinsics is not extracted via hax currently since it cannot hanlde raw pointers.
/// [Intel Documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_loadu_si128&ig_expand=4106)
Expand All @@ -195,6 +199,7 @@ pub mod sse2 {
}

use super::*;
/// Set packed 8-bit integers in a 128-bit vector with the supplied values.
#[hax_lib::opaque]
pub fn _mm_set_epi8(
_e15: i8,
Expand Down Expand Up @@ -263,6 +268,7 @@ pub mod sse2 {
}

pub use avx::*;
/// AVX (Advanced Vector Extensions) instruction models.
pub mod avx {
/// This intrinsics is not extracted via hax currently since it cannot hanlde raw pointers.
/// [Intel Documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_storeu_si256)
Expand Down Expand Up @@ -332,6 +338,7 @@ pub mod avx {
}

pub use super::*;
/// Cast a 256-bit integer vector to a 128-bit integer vector, extracting the lower 128 bits.
pub fn _mm256_castsi256_si128(vector: __m256i) -> __m128i {
BitVec::from_fn(|i| vector[i])
}
Expand Down Expand Up @@ -429,6 +436,7 @@ pub mod avx {
}
}
pub use avx2::*;
/// AVX2 (Advanced Vector Extensions 2) instruction models.
pub mod avx2 {
use super::*;

Expand Down Expand Up @@ -925,16 +933,19 @@ let ${_rw_mm256_mullo_epi16_shifts} = e___e_rw_mm256_mullo_epi16_shifts'
}
};

/// Extra helper functions for SIMD operations not directly corresponding to intrinsics.
pub mod extra {
use super::*;

/// Variable left shift packed 32-bit integers in a 256-bit vector using counts from an array.
pub fn mm256_sllv_epi32_u32_array(
vector: BitVec<256>,
counts: FunArray<8, u32>,
) -> BitVec<256> {
vector.chunked_shift::<32, 8>(FunArray::from_fn(|i| counts[i] as i128))
}

/// Variable left shift packed 32-bit integers in a 256-bit vector using individual shift counts.
pub fn mm256_sllv_epi32_u32(
vector: BitVec<256>,
b7: u32,
Expand Down Expand Up @@ -962,13 +973,15 @@ pub mod extra {
)
}

/// Variable right shift packed 32-bit integers in a 256-bit vector using counts from an array.
pub fn mm256_srlv_epi32_u32_array(
vector: BitVec<256>,
counts: FunArray<8, u32>,
) -> BitVec<256> {
vector.chunked_shift::<32, 8>(FunArray::from_fn(|i| -(counts[i] as i128)))
}

/// Variable right shift packed 32-bit integers in a 256-bit vector using individual shift counts.
pub fn mm256_srlv_epi32_u32(
vector: BitVec<256>,
b7: u32,
Expand Down Expand Up @@ -996,6 +1009,7 @@ pub mod extra {
)
}

/// Permute packed 32-bit integers in a 256-bit vector using indices from an array.
pub fn mm256_permutevar8x32_epi32_u32_array(
a: BitVec<256>,
b: FunArray<8, u32>,
Expand All @@ -1007,6 +1021,7 @@ pub mod extra {
})
}

/// Permute packed 32-bit integers in a 256-bit vector using individual indices.
pub fn mm256_permutevar8x32_epi32_u32(
vector: BitVec<256>,
b7: u32,
Expand Down Expand Up @@ -1034,6 +1049,7 @@ pub mod extra {
)
}

/// Shuffle bytes in a 128-bit vector using indices from an array.
pub fn mm_shuffle_epi8_u8_array(vector: BitVec<128>, indexes: FunArray<16, u8>) -> BitVec<128> {
BitVec::from_fn(|i| {
let nth = i / 8;
Expand All @@ -1047,6 +1063,7 @@ pub mod extra {
})
}

/// Shuffle bytes in a 128-bit vector using individual byte indices.
pub fn mm_shuffle_epi8_u8(
vector: BitVec<128>,
b15: u8,
Expand Down Expand Up @@ -1088,6 +1105,7 @@ pub mod extra {
mm_shuffle_epi8_u8_array(vector, indexes)
}

/// Shuffle bytes in a 256-bit vector using indices from an array.
pub fn mm256_shuffle_epi8_i8_array(
vector: BitVec<256>,
indexes: FunArray<32, i8>,
Expand All @@ -1104,6 +1122,7 @@ pub mod extra {
})
}

/// Shuffle bytes in a 256-bit vector using individual byte indices.
pub fn mm256_shuffle_epi8_i8(
vector: BitVec<256>,
byte31: i8,
Expand Down Expand Up @@ -1177,6 +1196,7 @@ pub mod extra {
mm256_shuffle_epi8_i8_array(vector, indexes)
}

/// Multiply packed 16-bit integers and shift left by individual shift amounts.
pub fn mm256_mullo_epi16_shifts(
vector: __m256i,
s15: u8,
Expand Down Expand Up @@ -1217,6 +1237,7 @@ pub mod extra {
});
mm256_mullo_epi16_shifts_array(vector, shifts)
}
/// Multiply packed 16-bit integers and shift left by shift amounts from an array.
pub fn mm256_mullo_epi16_shifts_array(vector: __m256i, shifts: FunArray<16, u8>) -> __m256i {
BitVec::from_fn(|i| {
let nth_bit = i % 16;
Expand All @@ -1232,6 +1253,7 @@ pub mod extra {
})
}

/// Store 128-bit integer vector to unaligned byte array.
#[hax_lib::exclude]
pub fn mm_storeu_bytes_si128(output: &mut [u8], vector: BitVec<128>) {
output.copy_from_slice(&vector.to_vec()[..]);
Expand Down
Loading