|
1 | 1 | [//]: # (SPDX-License-Identifier: CC-BY-4.0)
|
2 |
| -[//]: # (TODO Customize project readme) |
3 | 2 |
|
4 |
| -# template-code |
| 3 | +# mlkem-rust-libcrux |
| 4 | +`mlkem-rust-libcrux` is a portable Rust implementation of ML-KEM which |
| 5 | +optionally supports optimizations for AVX2 and NEON platforms. |
| 6 | + |
| 7 | +It originates in the `libcrux` library of formally verified |
| 8 | +cryptographic algorithm in Rust. |
| 9 | + |
| 10 | +## Getting Started |
| 11 | +To use this implementation of ML-KEM in your Rust project, run |
| 12 | + |
| 13 | +``` |
| 14 | +cargo add libcrux-ml-kem |
| 15 | +``` |
| 16 | +in your project directory, or add |
| 17 | + |
| 18 | +``` |
| 19 | +libcrux-ml-kem = "0.0.3" |
| 20 | +``` |
| 21 | +to your `Cargo.toml`. |
| 22 | + |
| 23 | + |
| 24 | +## Status |
| 25 | +The modules |
| 26 | +- `mlkem512` |
| 27 | +- `mlkem768` |
| 28 | +- `mlkem1024` |
| 29 | +implement the three parameter sets for ML-KEM defined in FIPS 203. |
| 30 | + |
| 31 | +Each module provides the following API: |
| 32 | +- `generate_key_pair`: to generate an ML-KEM key pair, |
| 33 | +- `encapsulate`: to encapsulate a shared secret towards a given ML-KEM public key, |
| 34 | +- `decapsulate`: to decapsulate a shared secret from a ciphertext using an ML-KEM private key, |
| 35 | +- `validate_public_key`: to perform validation of public keys as required by FIPS 203 prior to encapsulation, |
| 36 | +- `validate_private_key`: to perform validation of private keys and ciphertexts as required by FIPS 203 prior to decapsulation. |
| 37 | + |
| 38 | +For detailed documentation, please refer to |
| 39 | +[docs.rs](https://docs.rs/libcrux-ml-kem/latest/libcrux_ml_kem/). |
| 40 | + |
| 41 | +### Portable and Optimized Implementations |
| 42 | +The crate provides portable, as well as AVX2- and NEON-optimized |
| 43 | +implementations of the above API. By defautl, the crate's `build.rs` |
| 44 | +will include the portable implementation and one of the optimized |
| 45 | +implementations in the build, according to the value of |
| 46 | +`CARGO_CFG_TARGET_ARCH`. |
| 47 | + |
| 48 | +In addition, the above functions perform CPU feature detection at |
| 49 | +runtime to ensure the most efficient implementation for the given |
| 50 | +platform is selected. |
| 51 | + |
| 52 | +It is recommended to rely on the automatic feature detection, but specific |
| 53 | +builds can be forced by setting environment variables, |
| 54 | +`LIBCRUX_ENABLE_SIMD128=1` or `LIBCRUX_ENABLE_SIMD256=1`. |
| 55 | + |
| 56 | +### Unpacked APIs |
| 57 | +The default KEM API described above operates on serialized keys, |
| 58 | +i.e. `encapsulate` will take a serialized ML-KEM public key as input |
| 59 | +and `decapsulate` will take a serialized ML-KEM private key as input, |
| 60 | +and these must be validated before use with `validate_public_key` |
| 61 | +and `validate_private_key` for FIPS 203 compliance. |
| 62 | + |
| 63 | +In addition, in each parameter set module, (e.g. `mlkem768`) the crate |
| 64 | +provides an API for working with "unpacked" keys, which have already |
| 65 | +been deserialized. For some applications it may thus be advantageous |
| 66 | +to validate key material once, then deserialized into unpacked |
| 67 | +representation once, and to use the the already validated and |
| 68 | +deserialized form from then on. |
| 69 | + |
| 70 | +The unpacked APIs are platform dependent, so they can be found in |
| 71 | +submodules `mlkem768::portable::unpacked`, `mlkem768::avx2::unpacked`, |
| 72 | +`mlkem768::neon::unpacked`, depending on which of these platform |
| 73 | +specific modules are part of the build in question. |
| 74 | + |
| 75 | +### Common APIs |
| 76 | +The implementation of common APIs across PQCP implementations is |
| 77 | +work-in-progress. Progress for this implementation is tracked in issue |
| 78 | +[`cryspen/libcrux#894`](https://github.com/cryspen/libcrux/issues/894). |
| 79 | + |
| 80 | +### Crate Features |
| 81 | +The crate provides the following features. |
| 82 | + |
| 83 | +Default features: |
| 84 | +- `mlkem512`, `mlkem768` & `mlkem1024`: These can be used to select |
| 85 | + individual parameter sets. By default, all parameter sets are |
| 86 | + included. |
| 87 | +- `rand`: Whereas the default APIs for `generate_key_pair` and |
| 88 | + `encapsulate` expect external provision of random bytes, this |
| 89 | + feature enables randomized versions of these APIs (in submodules |
| 90 | + `mlkem512::rand`, `mlkem768::rand`, `mlkem1024::rand`) which take an |
| 91 | + `&mut impl rand_core::CryptoRng` argument to generate the required |
| 92 | + randomness internally. |
| 93 | +- `default-no-std` & `std`: Disabling default feature `std` provides |
| 94 | + `no_std` support. For convenience `default-no-std` collects all default |
| 95 | + features except `std`. |
| 96 | + |
| 97 | +Additional features: |
| 98 | +- `kyber`: Provides access to an, as yet, unverified implementation of |
| 99 | + Kyber as submitted in Round 3 of the NIST PQ competition. The Kyber |
| 100 | + APIs follow the general structure of the ML-KEM APIs. |
| 101 | +- `check-secret-independence`: All operations on ring elements in the |
| 102 | + portable implementation use the integer types of the |
| 103 | + [`libcrux-secrets`](https://crates.io/crates/libcrux-secrets) crate under the hood. That crate allows checking a |
| 104 | + program operating on these types for secret independence at compile |
| 105 | + time. Enabling the `check-secret-independence` feature switches on |
| 106 | + this compile-time checking of secret independence. By default, the |
| 107 | + integer types of `libcrux-secrets` transparently fall back on Rust's |
| 108 | + standard integer types. |
| 109 | +- `simd128`, `simd256`: These features force a compilation for NEON or |
| 110 | + AVX2 targets, respectively, as discussed above. |
| 111 | +- `incremental`: An experimental API, which allows for incremental |
| 112 | + encapsulation. |
| 113 | + |
| 114 | +## Security |
| 115 | +As outlined in the description of the `check-secret-independence` |
| 116 | +feature above, we leverage the Rust type system to ensure that secret |
| 117 | +values are not used in operations that are known to have |
| 118 | +data-dependent execution time. While the implementation of constant time |
| 119 | +operations is best-effort, as there are no guarantees from the |
| 120 | +compiler, we follow established constant-time patterns and validate |
| 121 | +constant-time code via inspection of the generated assembly |
| 122 | +instructions. |
| 123 | + |
| 124 | +## Verification Status |
| 125 | +The portable and AVX2 code for field arithmetic, NTT polynomial |
| 126 | +arithmetic, serialization, and the generic code for high-level |
| 127 | +algorithms is formally verified using [hax](https://hax.cryspen.com) and [F*](https://fstar-lang.org). |
| 128 | + |
| 129 | +Please refer to [this |
| 130 | +file](https://github.com/cryspen/libcrux/blob/f9d1802c06ffe1dec900367e12b00edb1e7f9963/libcrux-ml-kem/proofs/verification_status.md) |
| 131 | +in the `libcrux-ml-kem` repository for details on the verification of |
| 132 | +this crate. |
| 133 | + |
| 134 | +## Performance |
| 135 | +We provide a dashboard of benchmark results for the main key |
| 136 | +generation, encapsulation and decapsulation APIs across different |
| 137 | +platforms and operating systems at |
| 138 | +[libcrux.cryspen.com](https://libcrux.cryspen.com). |
| 139 | + |
| 140 | +If you wish to run the benchmarks yourself, you can do so by running |
| 141 | +``` |
| 142 | +cargo bench |
| 143 | +``` |
| 144 | +from the crate root of the `libcrux-ml-kem` crate. |
5 | 145 |
|
6 |
| -Template for creating code repositories, with basic file setup included |
|
0 commit comments