Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make verified ML-KEM available in libcrux-ml-kem #329

Merged
merged 62 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
7b5c5e4
Revert changes to Kyber (Round 3) for ML-KEM
jschneider-bensch Jun 18, 2024
5126d6a
Fix swapped private key decoding
jschneider-bensch Jun 18, 2024
11d7bb9
Pull out Kyber encaps
jschneider-bensch Jun 19, 2024
017ac5f
Make Kyber API available behind `kyber` feature
jschneider-bensch Jun 20, 2024
c7beed2
Format
jschneider-bensch Jun 20, 2024
0571d1f
Introduce `kyber` feature in `libcrux-kem`
jschneider-bensch Jun 20, 2024
283d99e
Format
jschneider-bensch Jun 20, 2024
4be326b
Include verified ML-KEM in `libcrux-ml-kem`
jschneider-bensch Jun 20, 2024
7f3e42e
WIP separation of verified API
jschneider-bensch Jun 20, 2024
66dca4d
Merge branch 'dev' into jonas/xyber768
franziskuskiefer Jun 21, 2024
e346e99
Integrating pre-verification and verified testing
jschneider-bensch Jun 21, 2024
cb11230
Integrating verified ML-KEM in `libcrux-kem`
jschneider-bensch Jun 21, 2024
688b7fb
Merge branch 'jonas/xyber768' into jonas/restore-verified-mlkem
jschneider-bensch Jun 21, 2024
cfaeac0
Format
jschneider-bensch Jun 21, 2024
d86006b
Test portable pre-verification ML-KEM 768
jschneider-bensch Jun 21, 2024
6b39b9e
Merge branch 'dev' into jonas/xyber768
franziskuskiefer Jun 24, 2024
8cdead9
fix C extraction
franziskuskiefer Jun 24, 2024
847136a
Fix typo
jschneider-bensch Jun 26, 2024
32af120
Give more accurate test names (`kyber...` to `mlkem...`)
jschneider-bensch Jun 26, 2024
11355da
Avoid unused warning when testing
jschneider-bensch Jun 26, 2024
0aa89eb
Use `Hasher` trait to select best KDF for Kyber
jschneider-bensch Jun 26, 2024
b4e4d13
Document differences between Kyber (Round 3) and ML-KEM
jschneider-bensch Jun 26, 2024
1d9e38d
Inline ML-KEM/Kyber variant differences
jschneider-bensch Jun 26, 2024
00e62c0
`kyber{512,768,1024}` top level modules
jschneider-bensch Jun 26, 2024
422bedb
Merge branch 'jonas/xyber768' of github.com:cryspen/libcrux into jona…
jschneider-bensch Jun 26, 2024
790eb06
Merge remote-tracking branch 'origin/jonas/xyber768-f' into jonas/xyb…
jschneider-bensch Jun 26, 2024
366c761
Fix `kyber` feature in `libcrux-kem`
jschneider-bensch Jun 26, 2024
d0740e3
Rename NIST KAT files for ML-KEM
jschneider-bensch Jun 26, 2024
2af99c3
Include NIST KATs for all Kyber parameter sets
jschneider-bensch Jun 26, 2024
e5b264c
Document single Kyber 768 KAT from boringssl
jschneider-bensch Jun 26, 2024
608fe19
Format
jschneider-bensch Jun 26, 2024
1233e95
Test Kyber on CI
jschneider-bensch Jun 26, 2024
7942c6f
Merge branch 'jonas/xyber768' into jonas/restore-verified-mlkem
jschneider-bensch Jun 26, 2024
f2f27e5
Fix insufficient feature gating
jschneider-bensch Jun 26, 2024
30cfb4c
Merge branch 'dev' into jonas/restore-verified-mlkem
jschneider-bensch Jun 26, 2024
a9e6489
Get rid of various warnings
jschneider-bensch Jun 26, 2024
956382d
Format
jschneider-bensch Jun 26, 2024
6d2fda3
Remove commented `use` declarations
jschneider-bensch Jun 26, 2024
936b0b9
Merge branch 'dev' into jonas/restore-verified-mlkem
jschneider-bensch Jun 27, 2024
906a298
Fix `unused_mut` warning
jschneider-bensch Jun 27, 2024
7f349f1
Feature gating helper macros
jschneider-bensch Jun 27, 2024
19040cd
Fix hax extraction
jschneider-bensch Jun 27, 2024
dbde61d
Feature flag documentation
jschneider-bensch Jun 27, 2024
24297ff
Fix mistaken feature guards
jschneider-bensch Jun 27, 2024
3877346
Remove commented code
jschneider-bensch Jun 27, 2024
5271f75
`size` -> `len`
jschneider-bensch Jun 27, 2024
96ab20d
Drop explicit dependency on `hax-lib-macros`
jschneider-bensch Jun 27, 2024
4b1d95a
Hide helper macro docs
jschneider-bensch Jun 27, 2024
bd14f8d
Formatting
jschneider-bensch Jun 27, 2024
c7ca638
Call out the `kyber` feature more prominently
jschneider-bensch Jun 27, 2024
12d7693
Feature gate tests etc so `--no-std-features` tests
jschneider-bensch Jun 27, 2024
c391c74
cleanup; make features work
franziskuskiefer Jun 28, 2024
fc84415
more cleanup and docs
franziskuskiefer Jun 28, 2024
193cc33
update hax extraction
franziskuskiefer Jun 28, 2024
d19b897
fixup x64 and hax extract
franziskuskiefer Jun 28, 2024
a3ce343
update C extraction
franziskuskiefer Jun 28, 2024
a576e70
update header only C code
franziskuskiefer Jun 28, 2024
9cd4bb5
Merge branch 'dev' into jonas/restore-verified-mlkem
franziskuskiefer Jun 28, 2024
65fd9fd
update C code
franziskuskiefer Jun 28, 2024
9c15eda
install cargo hack on ci
franziskuskiefer Jun 28, 2024
58c79cd
ci
franziskuskiefer Jun 28, 2024
43cab0a
more updates
franziskuskiefer Jun 28, 2024
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
18 changes: 18 additions & 0 deletions .github/workflows/mlkem.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,20 @@ jobs:

steps:
- uses: actions/checkout@v4
- uses: taiki-e/install-action@cargo-hack

- name: Update dependencies
run: cargo update

- run: echo "RUST_TARGET_FLAG=" > $GITHUB_ENV
if: ${{ matrix.bits == 64 }}

- run: echo 'EXCLUDE_FEATURES=--exclude-features simd256' > $GITHUB_ENV
if: ${{ matrix.os == 'macos-latest' }}

- run: echo 'EXCLUDE_FEATURES=--exclude-features simd128' > $GITHUB_ENV
if: ${{ matrix.os != 'macos-latest' }}

- name: 🛠️ Setup Rust Nightly
run: rustup toolchain install nightly

Expand Down Expand Up @@ -150,6 +157,17 @@ jobs:
cargo clean
cargo test --features kyber --verbose $RUST_TARGET_FLAG

- name: 🏃🏻‍♀️ Cargo Check Features
if: ${{ matrix.bits == 64 }}
run: |
cargo clean
cargo hack check --feature-powerset $EXCLUDE_FEATURES --verbose --no-dev-deps $RUST_TARGET_FLAG

- name: 🏃🏻‍♀️ Cargo Test Features
if: ${{ matrix.bits == 64 }}
run: |
cargo clean
cargo hack test --each-feature $EXCLUDE_FEATURES --verbose $RUST_TARGET_FLAG

benchmarks:
strategy:
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ members = [
"libcrux-kem",
"libcrux-hmac",
"libcrux-hkdf",
"libcrux-ecdh", "libcrux-psq",
"libcrux-ecdh",
"libcrux-psq",
]

[workspace.package]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ module Libcrux_intrinsics.Avx2
open Core
open FStar.Mul

unfold
let t_Vec128 = Core.Core_arch.X86.t____m128i

unfold
let t_Vec256 = Core.Core_arch.X86.t____m256i

val mm256_add_epi16 (lhs rhs: Core.Core_arch.X86.t____m256i)
: Prims.Pure Core.Core_arch.X86.t____m256i Prims.l_True (fun _ -> Prims.l_True)

Expand Down
4 changes: 2 additions & 2 deletions libcrux-kem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ libcrux-sha3 = { version = "0.0.2-pre.2", path = "../libcrux-sha3" }
libcrux-ecdh = { version = "0.0.2-pre.2", path = "../libcrux-ecdh" }
rand = { version = "0.8" }


[features]
tests = [] # Expose functions for testing.
tests = [] # Expose functions for testing.
kyber = ["libcrux-ml-kem/kyber"]
pre-verification = ["libcrux-ml-kem/pre-verification"]

[dev-dependencies]
libcrux-kem = { version = "0.0.2-pre.2", path = "./", features = ["tests"] }
Expand Down
20 changes: 20 additions & 0 deletions libcrux-kem/src/kem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,26 @@ impl Ct {
ct_x.try_into().map_err(|_| Error::InvalidCiphertext)?,
))
}
#[cfg(feature = "kyber")]
Algorithm::X25519Kyber768Draft00 => {
let key: [u8; MlKem768Ciphertext::len() + 32] =
bytes.try_into().map_err(|_| Error::InvalidCiphertext)?;
let (xct, kct) = key.split_at(32);
Ok(Self::X25519Kyber768Draft00(
kct.try_into().map_err(|_| Error::InvalidCiphertext)?,
xct.try_into().map_err(|_| Error::InvalidCiphertext)?,
))
}
#[cfg(feature = "kyber")]
Algorithm::XWingKyberDraft02 => {
let key: [u8; MlKem768Ciphertext::len() + 32] =
bytes.try_into().map_err(|_| Error::InvalidCiphertext)?;
let (ct_m, ct_x) = key.split_at(MlKem768Ciphertext::len());
Ok(Self::XWingKyberDraft02(
ct_m.try_into().map_err(|_| Error::InvalidCiphertext)?,
ct_x.try_into().map_err(|_| Error::InvalidCiphertext)?,
))
}
Algorithm::MlKem1024 => bytes
.try_into()
.map_err(|_| Error::InvalidCiphertext)
Expand Down
8 changes: 4 additions & 4 deletions libcrux-ml-dsa/src/hash_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,29 @@ pub(crate) fn H<const OUTPUT_LENGTH: usize>(input: &[u8]) -> [u8; OUTPUT_LENGTH]
}

pub(crate) mod H_128 {
use libcrux_sha3::portable::{incremental, KeccakState1};
use libcrux_sha3::portable::{incremental, KeccakState};

const BLOCK_SIZE: usize = 168;
const FIVE_BLOCKS_SIZE: usize = BLOCK_SIZE * 5;

#[inline(always)]
pub(crate) fn new(seed: [u8; 34]) -> KeccakState1 {
pub(crate) fn new(seed: [u8; 34]) -> KeccakState {
let mut state = incremental::shake128_init();
incremental::shake128_absorb_final(&mut state, &seed);

state
}

#[inline(always)]
pub(crate) fn squeeze_first_five_blocks(state: &mut KeccakState1) -> [u8; FIVE_BLOCKS_SIZE] {
pub(crate) fn squeeze_first_five_blocks(state: &mut KeccakState) -> [u8; FIVE_BLOCKS_SIZE] {
let mut out = [0u8; FIVE_BLOCKS_SIZE];
incremental::shake128_squeeze_first_five_blocks(state, &mut out);

out
}

#[inline(always)]
pub(crate) fn squeeze_next_block(state: &mut KeccakState1) -> [u8; BLOCK_SIZE] {
pub(crate) fn squeeze_next_block(state: &mut KeccakState) -> [u8; BLOCK_SIZE] {
let mut out = [0u8; BLOCK_SIZE];
incremental::shake128_squeeze_next_block(state, &mut out);

Expand Down
38 changes: 37 additions & 1 deletion libcrux-ml-kem/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,28 @@ libcrux-intrinsics = { version = "0.0.2-pre.2", path = "../libcrux-intrinsics" }
hax-lib = { version = "0.1.0-pre.1", git = "https://github.com/hacspec/hax/" }

[features]
# By default all variants and std are enabled.
default = ["std", "mlkem512", "mlkem768", "mlkem1024"]

# Hardware features can be force enabled.
# It is not recommended to use these. This crate performs CPU feature detection
# and enables the features when they are available.
simd128 = ["libcrux-sha3/simd128"]
simd256 = ["libcrux-sha3/simd256"]

# Features for the different key sizes of ML-KEM
mlkem512 = []
mlkem768 = []
mlkem1024 = []
std = []

# Enable Round 3 Kyber in addition to ML-KEM
kyber = []

# Code that is not yet verified
pre-verification = []

std = []

[dev-dependencies]
rand = { version = "0.8" }
serde_json = { version = "1.0" }
Expand All @@ -48,3 +61,26 @@ criterion = "0.5"
[[bench]]
name = "ml-kem"
harness = false

[[example]]
name = "encapsulate"
required-features = ["mlkem768"]

[[example]]
name = "decapsulate"
required-features = ["mlkem768"]

[[example]]
name = "keygen"
required-features = ["mlkem768"]

[package.metadata."docs.rs"]
features = ["pre-verification", "kyber"]
rustdoc-args = ["--cfg", "doc_cfg"]

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(hax)',
'cfg(eurydice)',
'cfg(doc_cfg)',
] }
20 changes: 15 additions & 5 deletions libcrux-ml-kem/c.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ clean=0
config=c.yaml
out=c
glue=$EURYDICE_HOME/include/eurydice_glue.h
features=
features="--cargo-arg=--features=pre-verification"
eurydice_glue=1
unrolling=16

# Parse command line arguments.
all_args=("$@")
Expand All @@ -32,7 +34,9 @@ while [ $# -gt 0 ]; do
--config) config="$2"; shift ;;
--out) out="$2"; shift ;;
--glue) glue="$2"; shift ;;
--mlkem768) features="--cargo-arg=--no-default-features --cargo-arg=--features=mlkem768" ;;
--mlkem768) features="${features} --cargo-arg=--no-default-features --cargo-arg=--features=mlkem768" ;;
--no-glue) eurydice_glue=0 ;;
--no-unrolling) unrolling=0 ;;
esac
shift
done
Expand Down Expand Up @@ -70,8 +74,10 @@ if [[ "$clean" = 1 ]]; then
fi

echo "Running eurydice ..."
$EURYDICE_HOME/eurydice --config ../$config ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc
cp $EURYDICE_HOME/include/eurydice_glue.h .
$EURYDICE_HOME/eurydice --config ../$config -funroll-loops $unrolling ../../libcrux_ml_kem.llbc ../../libcrux_sha3.llbc
if [[ "$eurydice_glue" = 1 ]]; then
cp $EURYDICE_HOME/include/eurydice_glue.h .
fi

clang-format --style=Google -i *.c *.h
clang-format --style=Google -i internal/*.h
Expand All @@ -81,7 +87,11 @@ clang-format --style=Google -i intrinsics/*.h
[[ -z "$CHARON_REV" && -d $CHARON_HOME/.git ]] && export CHARON_REV=$(git -C $CHARON_HOME rev-parse HEAD)
[[ -z "$EURYDICE_REV" && -d $EURYDICE_HOME/.git ]] && export EURYDICE_REV=$(git -C $EURYDICE_HOME rev-parse HEAD)
[[ -z "$KRML_REV" && -d $KRML_HOME/.git ]] && export KRML_REV=$(git -C $KRML_HOME rev-parse HEAD)
[[ -z "$FSTAR_REV" && -d $FSTAR_HOME/.git ]] && export FSTAR_REV=$(git -C $FSTAR_HOME rev-parse HEAD)
if [[ -z "$FSTAR_REV" && -d $FSTAR_HOME/.git ]]; then
export FSTAR_REV=$(git -C $FSTAR_HOME rev-parse HEAD)
else
export FSTAR_REV=$(fstar.exe --version | grep commit | sed 's/commit=\(.*\)/\1/')
fi
rm -f code_gen.txt
echo "This code was generated with the following tools:" >> code_gen.txt
echo -n "Charon: " >> code_gen.txt
Expand Down
4 changes: 2 additions & 2 deletions libcrux-ml-kem/c/benches/sha3.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ shake128_34_504(benchmark::State &state)

Eurydice_slice last[4] = {EURYDICE_SLICE(input, 0, 34), EURYDICE_SLICE(input, 0, 34), EURYDICE_SLICE(input, 0, 34), EURYDICE_SLICE(input, 0, 34)};
Eurydice_slice out[4] = {EURYDICE_SLICE(digest0, 0, 504), EURYDICE_SLICE(digest1, 0, 504), EURYDICE_SLICE(digest2, 0, 504), EURYDICE_SLICE(digest3, 0, 504)};
libcrux_sha3_avx2_x4_incremental_KeccakState4 st = libcrux_sha3_avx2_x4_incremental_shake128_init();
libcrux_sha3_avx2_x4_incremental_KeccakState st = libcrux_sha3_avx2_x4_incremental_shake128_init();
libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_168size_t_31uint8_t(&st, last);
libcrux_sha3_generic_keccak_squeeze_first_three_blocks__core_core_arch_x86___m256i_4size_t_168size_t(&st, out);

for (auto _ : state)
{
libcrux_sha3_avx2_x4_incremental_KeccakState4 st = libcrux_sha3_avx2_x4_incremental_shake128_init();
libcrux_sha3_avx2_x4_incremental_KeccakState st = libcrux_sha3_avx2_x4_incremental_shake128_init();
libcrux_sha3_generic_keccak_absorb_final__core_core_arch_x86___m256i_4size_t_168size_t_31uint8_t(&st, last);
libcrux_sha3_generic_keccak_squeeze_first_three_blocks__core_core_arch_x86___m256i_4size_t_168size_t(&st, out);
}
Expand Down
6 changes: 3 additions & 3 deletions libcrux-ml-kem/c/code_gen.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
This code was generated with the following tools:
Charon: ae55966c01a1a4b185a1a34da7861ba5db74c8ad
Eurydice: bbfd102bbfbc3e4c362953f093dbfd65e2fbc10c
Charon: 23f20c184e51015582b7918ea4f1eb063b28daba
Eurydice: 30fdb50add4dabaee90051878c166bac8c5ac26a
Karamel: 42a431696cd32d41155d7e484720eb71fd5dc7b1
F*: f09228ef9a64ac4ef383ee0e10656ccb612db2ee
F*: a32b316e521fa4f239b610ec8f1d15e78d62cbe8-dirty
41 changes: 34 additions & 7 deletions libcrux-ml-kem/c/eurydice_glue.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ typedef struct {

#define Eurydice_array_eq(sz, a1, a2, t, _, _ret_t) \
(memcmp(a1, a2, sz * sizeof(t)) == 0)
#define core_array_equality___core__cmp__PartialEq__Array_B__N___for__Array_A__N____eq \
#define core_array_equality___core__cmp__PartialEq__Array_U__N___for__Array_T__N____eq \
Eurydice_array_eq

#define core_slice___Slice_T___split_at(slice, mid, element_type, ret_t) \
Expand Down Expand Up @@ -135,6 +135,21 @@ core_convert_num___core__convert__From_i32__for_i64__59__from(int32_t x) {
return x;
}

static inline uint64_t
core_convert_num___core__convert__From_u8__for_u64__66__from(uint8_t x) {
return x;
}

static inline uint64_t
core_convert_num___core__convert__From_u16__for_u64__70__from(uint16_t x) {
return x;
}

static inline size_t
core_convert_num___core__convert__From_u16__for_usize__96__from(uint16_t x) {
return x;
}

static inline uint32_t core_num__u8_6__count_ones(uint8_t x0) {
#ifdef _MSC_VER
return __popcnt(x0);
Expand Down Expand Up @@ -163,9 +178,14 @@ static inline uint8_t Eurydice_shr_pv_u8(uint8_t *p, int32_t v) {
return (*p) >> v;
}

// ITERATORS
#define core_num_nonzero_private_NonZeroUsizeInner size_t
static inline core_num_nonzero_private_NonZeroUsizeInner
core_num_nonzero_private___core__clone__Clone_for_core__num__nonzero__private__NonZeroUsizeInner__26__clone(
core_num_nonzero_private_NonZeroUsizeInner *x0) {
return *x0;
}

#define core_num_nonzero_NonZeroUsize size_t
// ITERATORS
#define Eurydice_range_iter_next(iter_ptr, t, ret_t) \
(((iter_ptr)->start == (iter_ptr)->end) \
? (CLITERAL(ret_t){.tag = core_option_None}) \
Expand All @@ -183,6 +203,9 @@ static inline uint8_t Eurydice_shr_pv_u8(uint8_t *p, int32_t v) {
#define Eurydice_into_iter(x, t, _ret_t) (x)
#define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I___into_iter \
Eurydice_into_iter
// This name changed on 20240627
#define core_iter_traits_collect___core__iter__traits__collect__IntoIterator_for_I__1__into_iter \
Eurydice_into_iter

typedef struct {
Eurydice_slice slice;
Expand Down Expand Up @@ -214,11 +237,15 @@ static inline Eurydice_slice chunk_next(Eurydice_chunks *chunks,
.chunk_size = sz_})
#define core_slice_iter_Chunks Eurydice_chunks
#define core_slice_iter_ChunksExact Eurydice_chunks
#define core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___70__next( \
iter, t, ret_t) \
(((iter)->slice.len == 0) ? ((ret_t){.tag = core_option_None}) \
: ((ret_t){.tag = core_option_Some, \
#define Eurydice_chunks_next(iter, t, ret_t) \
(((iter)->slice.len == 0) ? ((ret_t){.tag = core_option_None}) \
: ((ret_t){.tag = core_option_Some, \
.f0 = chunk_next(iter, sizeof(t))}))
#define core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___70__next \
Eurydice_chunks_next
// This name changed on 20240627
#define core_slice_iter___core__iter__traits__iterator__Iterator_for_core__slice__iter__Chunks__a__T___71__next \
Eurydice_chunks_next
#define core_slice_iter__core__slice__iter__ChunksExact__a__T__89__next( \
iter, t, _ret_t) \
core_slice_iter__core__slice__iter__Chunks__a__T__70__next(iter, t)
Expand Down
Loading
Loading