From 6d13a32a514f22cc8b845dc7744e8617f7259cc0 Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Thu, 9 May 2024 08:15:16 +0100 Subject: [PATCH 1/9] v0.0.5 --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 30 ++++++++++++------------------ TEMPLATE.md | 27 +-------------------------- rustfmt.toml | 4 ++++ 5 files changed, 19 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d924a4..75b8c1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -440,7 +440,7 @@ dependencies = [ [[package]] name = "kyberlib" -version = "0.0.4" +version = "0.0.5" dependencies = [ "aes", "cc", diff --git a/Cargo.toml b/Cargo.toml index 3cce4d7..18a31ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ license = "MIT OR Apache-2.0" name = "kyberlib" readme = "README.md" repository = "https://github.com/sebastienrousseau/kyberlib" -version = "0.0.4" +version = "0.0.5" [dependencies] aes = { version = "0.8.4", optional = true } diff --git a/README.md b/README.md index b5dfe83..4cd2be2 100644 --- a/README.md +++ b/README.md @@ -18,17 +18,9 @@ A Robust Rust Library for CRYSTALS-Kyber Post-Quantum Cryptography.
-[![Made With Rust][made-with-rust-badge]][05] -[![Crates.io][crates-badge]][07] -[![Lib.rs][libs-badge]][09] -[![Docs.rs][docs-badge]][08] -[![License][license-badge]][02] - -• [Website][00] -• [Documentation][08] -• [Report Bug][03] -• [Request Feature][03] -• [Contributing Guidelines][04] +[![Made With Love][made-with-rust]][05] [![Crates.io][crates-badge]][07] [![Lib.rs][libs-badge]][09] [![Docs.rs][docs-badge]][08] [![License][license-badge]][02] [![Codecov][codecov-badge]][15] + +• [Website][00] • [Documentation][08] • [Report Bug][03] • [Request Feature][03] • [Contributing Guidelines][04]
@@ -73,7 +65,7 @@ It takes just a few minutes to get up and running with `kyberlib`. ### Requirements The minimum supported Rust toolchain version is currently Rust -**1.56.0** or later (stable). +**1.60** or later (stable). ### Installation @@ -95,7 +87,7 @@ To use the `kyberlib` library in your project, add the following to your ```toml [dependencies] -kyberlib = "0.0.4" +kyberlib = "0.0.5" ``` Add the following to your `main.rs` file: @@ -303,10 +295,12 @@ providing a lot of useful suggestions on how to improve this project. [12]: https://www.reddit.com/r/rust/ "Reddit" [13]: https://www.rust-lang.org/learn/get-started "Rust" [14]: https://github.com/Argyle-Software/kyber "Kyber from Argyle-Software" +[15]: https://codecov.io/gh/sebastienrousseau/kyberlib "Codecov" -[crates-badge]: https://img.shields.io/crates/v/kyberlib.svg?style=for-the-badge 'Crates.io badge' +[crates-badge]: https://img.shields.io/crates/v/kyberlib.svg?style=for-the-badge 'Crates.io' +[codecov-badge]: https://img.shields.io/codecov/c/github/sebastienrousseau/kyberlib?style=for-the-badge&token=oEisyTucB5 'Codecov' [divider]: https://kura.pro/common/images/elements/divider.svg "divider" -[docs-badge]: https://img.shields.io/docsrs/kyberlib.svg?style=for-the-badge 'Docs.rs badge' -[libs-badge]: https://img.shields.io/badge/lib.rs-v0.0.1-orange.svg?style=for-the-badge 'Lib.rs badge' -[license-badge]: https://img.shields.io/crates/l/kyberlib.svg?style=for-the-badge 'License badge' -[made-with-rust-badge]: https://img.shields.io/badge/rust-f04041?style=for-the-badge&labelColor=c0282d&logo=rust 'Made With Rust badge' +[docs-badge]: https://img.shields.io/docsrs/kyberlib.svg?style=for-the-badge 'Docs.rs' +[libs-badge]: https://img.shields.io/badge/lib.rs-v0.0.5-orange.svg?style=for-the-badge 'Lib.rs' +[license-badge]: https://img.shields.io/crates/l/kyberlib.svg?style=for-the-badge 'License' +[made-with-rust]: https://img.shields.io/badge/rust-f04041?style=for-the-badge&labelColor=c0282d&logo=rust 'Made With Rust' diff --git a/TEMPLATE.md b/TEMPLATE.md index 7e5eb57..e753090 100644 --- a/TEMPLATE.md +++ b/TEMPLATE.md @@ -40,30 +40,6 @@ A Robust Rust Library for CRYSTALS-Kyber Post-Quantum Cryptography A Robust Rust Library for CRYSTALS-Kyber Post-Quantum Cryptography -## Features ✨ - -### Core Features - -- **`no_std` compatible**: No dependence on the Rust standard library -- **Avoid allocations**: Uses stack-based data structures only -- **Configurable**: Features to enable different parameter sets -- **Optimised x86_64**: Uses assembly for performance-critical code, including an optimised AVX2 version by default. -- **Safe code**: Reference implementations have no `unsafe` blocks -- **WebAssembly Support**: Can be compiled to WASM using wasm-bindgen. - -### Advanced Features - -- **Allocation-free Guarantee**: KyberLib guarantees all its core cryptography operations are free of heap allocations. -- **Assembly Optimizations**: The x86_64 assembly implementations use AVX2 instructions for high performance. -- **Security**: KyberLib contains no unsafe code in its public API surface. - -## Functionality 📚 - -- **Key Generation**: Create public/private key pairs -- **Encapsulation**: Encapsulate a shared secret with a public key -- **Decapsulation**: Decapsulate a shared secret with a private key -- **Key Exchange**: Perform authenticated key exchanges - [0]: https://kyberlib.com/ [2]: http://opensource.org/licenses/MIT [3]: https://github.com/sebastienrousseau/kyberlib/kyberlib/issues @@ -73,11 +49,10 @@ A Robust Rust Library for CRYSTALS-Kyber Post-Quantum Cryptography [8]: https://docs.rs/kyberlib [9]: https://lib.rs/crates/kyberlib -[banner]: https://via.placeholder.com/1500x500.png/000000/FFFFFF?text=kyberlib "kyberlib's banner" [crates-badge]: https://img.shields.io/crates/v/kyberlib.svg?style=for-the-badge 'Crates.io badge' [divider]: https://via.placeholder.com/1024x1.png/d8dee4/FFFFFF?text=− "kyberlib's divider" [docs-badge]: https://img.shields.io/docsrs/kyberlib.svg?style=for-the-badge 'Docs.rs badge' -[libs-badge]: https://img.shields.io/badge/lib.rs-v0.0.1-orange.svg?style=for-the-badge 'Lib.rs badge' +[libs-badge]: https://img.shields.io/badge/lib.rs-v0.0.5-orange.svg?style=for-the-badge 'Lib.rs badge' [license-badge]: https://img.shields.io/crates/l/kyberlib.svg?style=for-the-badge 'License badge' [made-with-rust-badge]: https://img.shields.io/badge/rust-f04041?style=for-the-badge&labelColor=c0282d&logo=rust 'Made With Rust badge' diff --git a/rustfmt.toml b/rustfmt.toml index e69de29..76f30d8 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -0,0 +1,4 @@ +edition = "2018" +max_width = 72 +tab_spaces = 4 +use_field_init_shorthand = true \ No newline at end of file From c32f576d8ca22bbe94621f64a618ad60e7aa821e Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Thu, 9 May 2024 13:55:36 +0100 Subject: [PATCH 2/9] style(kyberlib): :art: fix Rustfmt warnings --- Cargo.lock | 31 ++++++++ Cargo.toml | 2 + benches/api.rs | 33 ++++++-- examples/ake.rs | 8 +- examples/kem.rs | 6 +- examples/uake.rs | 3 +- src/api.rs | 41 ++++++++-- src/avx2/aes256ctr.rs | 85 ++++++++++++++++---- src/avx2/align.rs | 21 +++-- src/avx2/cbd.rs | 8 +- src/avx2/consts.rs | 112 +++++++++++++++----------- src/avx2/fips202.rs | 81 ++++++++++++++++--- src/avx2/fips202x4.rs | 56 +++++++++++-- src/avx2/indcpa.rs | 80 ++++++++++++++----- src/avx2/keccak4x.rs | 16 +++- src/avx2/poly.rs | 59 ++++++++++---- src/avx2/polyvec.rs | 53 +++++++++---- src/avx2/rejsample.rs | 39 ++++++--- src/avx2/verify.rs | 21 +++-- src/kem.rs | 17 ++-- src/kex.rs | 44 +++++++++-- src/lib.rs | 11 ++- src/macros.rs | 10 ++- src/params.rs | 38 +++++---- src/reference/aes256ctr.rs | 97 ++++++++++++++++++++--- src/reference/fips202.rs | 81 ++++++++++++++++--- src/reference/indcpa.rs | 52 +++++++++--- src/reference/ntt.rs | 20 +++-- src/reference/poly.rs | 39 ++++++--- src/reference/polyvec.rs | 67 +++++++++++----- src/rng.rs | 6 +- src/symmetric.rs | 36 +++++++-- src/wasm.rs | 9 ++- tests/test_api.rs | 48 +++++++++--- tests/test_error.rs | 10 ++- tests/test_kat.rs | 14 +++- tests/test_kem.rs | 28 +++++-- tests/test_kex.rs | 89 ++++++++++++++++----- tests/test_lib.rs | 157 ++++++++++++++++++++++++++++--------- tests/test_macros.rs | 91 ++++++++++++++++----- tests/test_params.rs | 14 +++- tests/test_symmetric.rs | 8 +- tests/test_wasm.rs | 18 +++-- 43 files changed, 1345 insertions(+), 414 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75b8c1b..51404cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -447,6 +447,7 @@ dependencies = [ "criterion", "ctr", "nasm-rs", + "pqc_core", "rand", "rand_core", "rlg 0.0.4", @@ -454,6 +455,7 @@ dependencies = [ "tokio", "wasm-bindgen", "wasm-bindgen-test", + "zeroize", ] [[package]] @@ -631,6 +633,15 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "pqc_core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f480b84be33bffb34e615ae7a350602d9caa77a9450d6b9488d6fb3d5fd4cc1" +dependencies = [ + "zeroize", +] + [[package]] name = "proc-macro2" version = "1.0.82" @@ -1303,3 +1314,23 @@ name = "windows_x86_64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 18a31ea..d9fd415 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,12 +35,14 @@ version = "0.0.5" [dependencies] aes = { version = "0.8.4", optional = true } ctr = { version = "0.9.2", optional = true } +pqc_core = { version = "0.3.0", features = ["zero"]} rand = { version = "0.8.5", default-features = false, features = ["getrandom"] } rand_core = { version = "0.6.4", default-features = false } rlg = "0.0.4" sha2 = { version = "0.10.8", optional = true } tokio = { version = "1.37.0", optional = true } wasm-bindgen = "0.2.92" +zeroize = { version = "1.7.0", features = ["derive"] } [dev-dependencies] criterion = "0.5.1" diff --git a/benches/api.rs b/benches/api.rs index 1c3783c..726d124 100644 --- a/benches/api.rs +++ b/benches/api.rs @@ -13,7 +13,8 @@ pub fn keypair(c: &mut Criterion) { let bufs = Some(([1u8; 32].as_slice(), [255u8; 32].as_slice())); c.bench_function("Keypair Generation", |b| { b.iter(|| { - generate_key_pair(&mut pk, &mut sk, &mut _rng, bufs).unwrap(); + generate_key_pair(&mut pk, &mut sk, &mut _rng, bufs) + .unwrap(); }) }); } @@ -27,7 +28,10 @@ pub fn encap(c: &mut Criterion) { let encap_buf = Some([255u8; 32].as_slice()); c.bench_function("Encapsulate", |b| { b.iter(|| { - encrypt_message(&mut ct, &mut ss, &pk, &mut _rng, encap_buf).unwrap(); + encrypt_message( + &mut ct, &mut ss, &pk, &mut _rng, encap_buf, + ) + .unwrap(); }) }); } @@ -58,7 +62,10 @@ pub fn decap_fail(c: &mut Criterion) { pub fn decode_hex(s: &str) -> Vec { (0..s.len()) .step_by(2) - .map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("Hex string decoding")) + .map(|i| { + u8::from_str_radix(&s[i..i + 2], 16) + .expect("Hex string decoding") + }) .collect::>() } @@ -105,13 +112,25 @@ const BAD_SK: &str = "062396f6b21ff625b96b4b1f5c3a38b3c80708f33bcc1784bedb48bee0 const CT: &str = "ac5913d6b37c9b3168ad3db9c839053b5bf491a4a17d17d685384baceede11efc0de58c0a6c5e4a58bd930ea71082a4db72f15a931bfd77bbf4c9b3debd580d79010c2f09f2e73b92051408f076b1d34c521f5f25fbe8ec7519d07fa83df3e5e90a5c8d6c190d594b3ad7184c2b8ada4c8328be534603fbe99fd0b7b6e4b24d08d91bb0aae6317ece1b1706c565641f53dd29d6111a53995fe67d5064c7b18d92cd3aa25223ab1b3c9e8a8248661162cf56bc2c5e1a40f126d8518fe5fe5e2941576e070bbdb3d2ff3df094c2fccc3181fd2ef85887ba98a7a419fbb704ed64b1236a874e4e34561ff490436a8222a6508d3349cb124a95f79f8f4dc5fa64703ba8d3876184a42431fd94ee114c6f4108b0c4ccd735d40936be66198a60f46817276b56d6607473a58d91148c87fe4da071397a1621548d213d05033250a99924023069b5785aba24e444d82befa2cdbdcd1cbaef8cb64d416d795de48d1c3507ac5dcf5ee984a7ee46991dd145dbe503b7c7d6fb6ccebd02bb1c00c5a5158d98dd81ad492ac0b9ad65e5ff3b74209ccf0437169b06ffd80c99af7820c4e34796c627110a32535b11773a9f40f88df20b35be11da2c8c2e79b36db8cf39754846f97e369b93b68af2ff9ed1eae15a09bdcb1c633dc5c05a1b3e8f9f29c437e431e6b9c4f6c0d4b284d585ee7e5787a0cc966ec86758f6ed33f2632615b2ba57745e0d1f8404a2bd3e240591ffc775dfc5c9f60b207713b7c09c89e57023d48abd551083a1c9421b712292452e6837d3a3e232e3277cde8f41f8915dfc96c48603e5862bb2549e0228a2256e58397dd2195a95213d3050f4f43dc72a8c0a10b75c5a0185771e7ba9fc342ddbfc17d0a3b5552c8eaf8a386780ddc48a79b3da8d71f487d813799c49cf01367abc343ff3f1cccbcd8d14ffd096a3c9b53dacda41c1b4824fd7634d02affafc8f5c9919c6f8297fe343a8ee09eb16785b41d3e19f677e9b459ec1d90dbde9f195b324ce872d5fa263a6b5dcd7dba43ca7ccafdb8a0c1e2cc79d54eb87049b69920aeffe2eb8135512dbcfc6dc686e96c7c9f105177aaec6515d348eb32ec579f32731e12cb56931bcff2dd888876629b98b75b12e855cdee47860b5bc8f1fb0c00c9cb6fd091fb7cddbfeaddd7940304a8ab1baa3b8fc1ac66eea138ac8884dbba112885de5e39fb19eea8fe5444d34248cdf6b02cbbe458a6d1c6d09b2f3a51052f57d2822890d28dd4391f4c0b3f1ea189a0912464cbd41fd566c48a9a6454c2dca57f28c21e70fe56de08317e674c8ff1d9f3e225ccc5bd1fc9faa58c9bab9d54900e6d71cbd14265645a779a4856c9c26903357f95ec632c4de088b247cd821af63abd9a247591e0d0d710234db269a665c376f974edbd5e6cac5ba7d1f19e2e4d6caa3fbd4dd3c37702c8d00300051c16bf0ba0fa9dd0a730922eee0ff7e3ae817f5cba734f2a28105790db3d1ab02e9acc763e5fd2bc0447ac32e11fa02612e6f987e5f777ca2e7ac36551cf62649c29483c"; // tvecs768-90s -#[cfg(all(not(any(feature = "kyber512", feature = "kyber1024")), feature = "90s"))] +#[cfg(all( + not(any(feature = "kyber512", feature = "kyber1024")), + feature = "90s" +))] const PK: &str = "33cb9679095aeb053e69351ed1c3363a344c090801d0500951d743ac51518dd51a14168be2661edce32585c875f05c0c01181a7bf9804b66034e93122cf52ba2ea8e7e6a8860b2be5c602725891f55ec47092a96c5267d86b38c0d92a27b959e1b96a921733c3ca28f09d2c7b7b18b8423491bb1201463b2c12b52f9f3ab8fa8242e7400f8e00b56f70805295e10a964a85377952785e35aa055f2080e59bfa3cc0b12e127feda068cc3867ce31f714cbd5e9b292ee81c295718b16346d43b409112474af110f0641d3c2967616a9fc64364b141c55fe8357f85114ed1876e644c7775af9a952bf5a5bf3da717c9a3187fa41f551919c5e240ad7c04f1b4ce33804a45a6b45489c59e6225ea6a8099a22d221b1f8b2100d269b68884564fa31fe9ac7c0ed00fb0d909f40345a83554c97cc6e4625f696b44b7303639379c494a964d5b2b01b5157cd70168ba5bfd9c9ad620848d608298fa4a7be6b5dc703dc3222ec8bc21cd0737b89005c4e0b32522a9de0cc7dc804facca327647b8a3c309c55366f6b4758d017370c77ab2950ae215975a74af7567b008f1862b381d875520f2ec9b7f280c727ab451fc4b428602df48949e4a8b74baa263d74edef8c055233aef4a7f3e95afac9575c2ac86f0365fea0824d53a8b40b1bd18e600c4c442ed601cb0334f28da06a2f4738a40a95b21b38c4c5ff7d27c29f1cbc506ad7ef392c29002667513ef002cfad9518f4acd6fc0a90202a8d534052e097a5ee6450c242beb8c122c2044a4025792974112c41b2efc062591180f69961f98648f2362ff1789f56605060c47f091aa6687c0ef6bb744755adadb67bc1b896a8bcff25a594b865c6c2abe68c5058b7c4c10cbcaa4f438d9350b7ef9520367b42c5581472823f6ca188eb24a60bb169998a00fcbc6e34368d4420eb7897d1d98a27520bdc6f48dc019bfd1ba3d9ea461737046dae8b2e1151ce734b4e952a119d6a601893c5c951b20eb56b12ac03395a497fb689b189b4f7ac84457463eca471d41883b49b02ed99f3358a2201461464b0c0e511f47656c0cb90c018a27457a1bdf2a1897e17fe77a70d58b4297ab9b68dbc796477477085c6f1272e62911a3bccfb469495ceb4843363652603b6059372fac140723a5dd4c6d2edac516563d4b846e9a8ab30f60c46153173c3b8d8746801d12a1a1919c0bd59f907c93c66c8760f3296fa6bc358c557f1ccc6efa66ef3bb2c14c4aafd56ddc4413859963bcabc0dc170117a11623635669e975d73c3ce9559642495bb9386ac049cfc40a39b1b56522b4540acbbad9b046cc990d192c2e2cf49422b60b763282cfa32dacf82cb4169c74e42368b962a30912cbc76c23bb49cfdb4f477b4ee4e651c0c80f38b5b06deb18833292c201a69c22a4ec43a8fec5ca04869f6dba8263e6acca761dcf2cc1bb65cefc902a4a123285f53f8c4283f1342c119b6ce0616776b6cb5607446f4948e0e5023d593c0ed585ea1a44a85c691ab49750222ac7775bf559bfebda3f8b3baedc4b1c6498a1328a73e7aa9370653cbc502e620aaf112718fdc002b9dc60cf3c250da55f8237b034acb7408347db34a436d492cd8629014230502294e6611e5f7f5c2504f59871b3e7da307fe5e3e4123fb2896e20c45ddaf9cdc54a592f8d"; -#[cfg(all(not(any(feature = "kyber512", feature = "kyber1024")), feature = "90s"))] +#[cfg(all( + not(any(feature = "kyber512", feature = "kyber1024")), + feature = "90s" +))] const SK: &str = "910c5a48053837472f7dcacc4e74709f3a29e7177e83198ee8228390d43d164a2d3526a72aec993fc5642023b0cb08a5c4b05d3e7baa3b27943b1b1ca6589aa565344c5c63a6b6c3dd5b53ffac269478958776127c1520f9dab47cc24a9c5b1e0125a7db596213c0526877b829b6484cc21f4d0397a3d39fc328af7dd1ce39d1291ba628d9189b69291659229021173f0b8b0bb09c56f52c566979a6603c19ac4453b6862aae8ba96983ac0d8a674af237397b369d1050f9a441d6c3c336fc5b22e62421723bdfc04eb074075f2b3b61c0268614744675ab30f2cede9c4989d922d8c3c740189aa7b65dca9a1892d998fa66a6cf37186a983151f065ba42cdd0dcbc08ecc6ac544aa8178e383940dc328d199a3e749c00d796841f64a5872ab74cec8b0ecbbc2db58e462ccd87e385be11a0948c19de9581d7d682c5b73ee3a868fdb0a61c82cce47a7615319397b13e64438b67b5747e6bad05f81f5b08ae9071a7d9106cfff80c39879e75879f06231ecf0495a896ab11727e97b1c638bc28893a948567bd0e98749604b0ec8587d0e49a38663fc1d33dd632162ed17a3f320a12e1c56c040418b25c5f478b62539a8bd765edb203da9c0a871b59a5e60c51f9295f263373999c96ac4f32684a52649fd109bbc256acec86c4c1c24dcce386414c692e4aa4e4496b87080fb9438e82468f95862441970ba79120c6f446ba6228c5719d19cc2d7fc8ac7de73a0d2ac7151480ae183d78fb7f1d3053b5a82f75131d702a1ae4c8c3028c5d1a2968e58726410b5b7be6888633cd3952024ef953809b69095a0aacba00e837a77e262b1ca9cca263328a74a789f01d8d25aeaa50c24e654d8fd42126ec0a6ec8462c8865ea01960e5b822ba9452f5542047804c190cbe8787256c80248a52e326c1a6c4465d4437323b25d86d46d366a200298a30d71ac1ba2c2ee6a31a3509eb46200f2aa4fa55b386a7087468b41df5236e8034bf059b5a5cb7d439a6ef5bb1704550c559c9b6428c87df1195c595ebd93ada3096796c15300fd86f18b55ee844b175b70dc0bb4e11376e7a81df433add04553d687ced41805f69a3a3f760aa476bfc0a04392387a3598824af2c2373762d1274e300c452118880542a50e1671ff778bb36390459b6477312b012c93ea43c45bdc3931d8ceb6949970e899ca09206f0841ee7961106b94f8831cfbfc3d856a9bc0b403c9f362d6556ffd97746eb896a0e44d1fabaebda13c39d1c00274cc77981ef26016ec89aa002c7d57f20b32ac5a9456bb2ea6a0fb1a517f9043fd31582e07a70b34380a324e2b52b366a2aa2f36c01d40560e9215f2a06ca6a2c147830e7fb8a1b959783f57c6a54963c42881dab7a96770a44df945fac73731a29e770129652211fe23cdf1fb7d565c23183258f0d43c3503093fc1b918b84353825eede34a77c7aeb9e78e0bf218498610f51067449137d925a9c3e4b5a7a031804a9e4b847f8478561e8c8756024032a661db899742203fbf233594823db7187d71659c34b61fc9a3881a4129c552b70ebc41a463a5446ccce536960cd86ed57b892f2b64580b636e69060b33681bb09dfbe31f9ad761d6074e8f628406a8994f829333cb9679095aeb053e69351ed1c3363a344c090801d0500951d743ac51518dd51a14168be2661edce32585c875f05c0c01181a7bf9804b66034e93122cf52ba2ea8e7e6a8860b2be5c602725891f55ec47092a96c5267d86b38c0d92a27b959e1b96a921733c3ca28f09d2c7b7b18b8423491bb1201463b2c12b52f9f3ab8fa8242e7400f8e00b56f70805295e10a964a85377952785e35aa055f2080e59bfa3cc0b12e127feda068cc3867ce31f714cbd5e9b292ee81c295718b16346d43b409112474af110f0641d3c2967616a9fc64364b141c55fe8357f85114ed1876e644c7775af9a952bf5a5bf3da717c9a3187fa41f551919c5e240ad7c04f1b4ce33804a45a6b45489c59e6225ea6a8099a22d221b1f8b2100d269b68884564fa31fe9ac7c0ed00fb0d909f40345a83554c97cc6e4625f696b44b7303639379c494a964d5b2b01b5157cd70168ba5bfd9c9ad620848d608298fa4a7be6b5dc703dc3222ec8bc21cd0737b89005c4e0b32522a9de0cc7dc804facca327647b8a3c309c55366f6b4758d017370c77ab2950ae215975a74af7567b008f1862b381d875520f2ec9b7f280c727ab451fc4b428602df48949e4a8b74baa263d74edef8c055233aef4a7f3e95afac9575c2ac86f0365fea0824d53a8b40b1bd18e600c4c442ed601cb0334f28da06a2f4738a40a95b21b38c4c5ff7d27c29f1cbc506ad7ef392c29002667513ef002cfad9518f4acd6fc0a90202a8d534052e097a5ee6450c242beb8c122c2044a4025792974112c41b2efc062591180f69961f98648f2362ff1789f56605060c47f091aa6687c0ef6bb744755adadb67bc1b896a8bcff25a594b865c6c2abe68c5058b7c4c10cbcaa4f438d9350b7ef9520367b42c5581472823f6ca188eb24a60bb169998a00fcbc6e34368d4420eb7897d1d98a27520bdc6f48dc019bfd1ba3d9ea461737046dae8b2e1151ce734b4e952a119d6a601893c5c951b20eb56b12ac03395a497fb689b189b4f7ac84457463eca471d41883b49b02ed99f3358a2201461464b0c0e511f47656c0cb90c018a27457a1bdf2a1897e17fe77a70d58b4297ab9b68dbc796477477085c6f1272e62911a3bccfb469495ceb4843363652603b6059372fac140723a5dd4c6d2edac516563d4b846e9a8ab30f60c46153173c3b8d8746801d12a1a1919c0bd59f907c93c66c8760f3296fa6bc358c557f1ccc6efa66ef3bb2c14c4aafd56ddc4413859963bcabc0dc170117a11623635669e975d73c3ce9559642495bb9386ac049cfc40a39b1b56522b4540acbbad9b046cc990d192c2e2cf49422b60b763282cfa32dacf82cb4169c74e42368b962a30912cbc76c23bb49cfdb4f477b4ee4e651c0c80f38b5b06deb18833292c201a69c22a4ec43a8fec5ca04869f6dba8263e6acca761dcf2cc1bb65cefc902a4a123285f53f8c4283f1342c119b6ce0616776b6cb5607446f4948e0e5023d593c0ed585ea1a44a85c691ab49750222ac7775bf559bfebda3f8b3baedc4b1c6498a1328a73e7aa9370653cbc502e620aaf112718fdc002b9dc60cf3c250da55f8237b034acb7408347db34a436d492cd8629014230502294e6611e5f7f5c2504f59871b3e7da307fe5e3e4123fb2896e20c45ddaf9cdc54a592f8d4fb89130551689123ba3c6ed310295dea662cdbee35fd1162c8d26f3a18458d73e2a2ea6c9c476fc4937b013c993a793d6c0ab9960695ba838f649da539ca3d0"; -#[cfg(all(not(any(feature = "kyber512", feature = "kyber1024")), feature = "90s"))] +#[cfg(all( + not(any(feature = "kyber512", feature = "kyber1024")), + feature = "90s" +))] const BAD_SK: &str = "010c5a48053837472f7dcacc4e74709f3a29e7177e83198ee8228390d43d164a2d3526a72aec993fc5642023b0cb08a5c4b05d3e7baa3b27943b1b1ca6589aa565344c5c63a6b6c3dd5b53ffac269478958776127c1520f9dab47cc24a9c5b1e0125a7db596213c0526877b829b6484cc21f4d0397a3d39fc328af7dd1ce39d1291ba628d9189b69291659229021173f0b8b0bb09c56f52c566979a6603c19ac4453b6862aae8ba96983ac0d8a674af237397b369d1050f9a441d6c3c336fc5b22e62421723bdfc04eb074075f2b3b61c0268614744675ab30f2cede9c4989d922d8c3c740189aa7b65dca9a1892d998fa66a6cf37186a983151f065ba42cdd0dcbc08ecc6ac544aa8178e383940dc328d199a3e749c00d796841f64a5872ab74cec8b0ecbbc2db58e462ccd87e385be11a0948c19de9581d7d682c5b73ee3a868fdb0a61c82cce47a7615319397b13e64438b67b5747e6bad05f81f5b08ae9071a7d9106cfff80c39879e75879f06231ecf0495a896ab11727e97b1c638bc28893a948567bd0e98749604b0ec8587d0e49a38663fc1d33dd632162ed17a3f320a12e1c56c040418b25c5f478b62539a8bd765edb203da9c0a871b59a5e60c51f9295f263373999c96ac4f32684a52649fd109bbc256acec86c4c1c24dcce386414c692e4aa4e4496b87080fb9438e82468f95862441970ba79120c6f446ba6228c5719d19cc2d7fc8ac7de73a0d2ac7151480ae183d78fb7f1d3053b5a82f75131d702a1ae4c8c3028c5d1a2968e58726410b5b7be6888633cd3952024ef953809b69095a0aacba00e837a77e262b1ca9cca263328a74a789f01d8d25aeaa50c24e654d8fd42126ec0a6ec8462c8865ea01960e5b822ba9452f5542047804c190cbe8787256c80248a52e326c1a6c4465d4437323b25d86d46d366a200298a30d71ac1ba2c2ee6a31a3509eb46200f2aa4fa55b386a7087468b41df5236e8034bf059b5a5cb7d439a6ef5bb1704550c559c9b6428c87df1195c595ebd93ada3096796c15300fd86f18b55ee844b175b70dc0bb4e11376e7a81df433add04553d687ced41805f69a3a3f760aa476bfc0a04392387a3598824af2c2373762d1274e300c452118880542a50e1671ff778bb36390459b6477312b012c93ea43c45bdc3931d8ceb6949970e899ca09206f0841ee7961106b94f8831cfbfc3d856a9bc0b403c9f362d6556ffd97746eb896a0e44d1fabaebda13c39d1c00274cc77981ef26016ec89aa002c7d57f20b32ac5a9456bb2ea6a0fb1a517f9043fd31582e07a70b34380a324e2b52b366a2aa2f36c01d40560e9215f2a06ca6a2c147830e7fb8a1b959783f57c6a54963c42881dab7a96770a44df945fac73731a29e770129652211fe23cdf1fb7d565c23183258f0d43c3503093fc1b918b84353825eede34a77c7aeb9e78e0bf218498610f51067449137d925a9c3e4b5a7a031804a9e4b847f8478561e8c8756024032a661db899742203fbf233594823db7187d71659c34b61fc9a3881a4129c552b70ebc41a463a5446ccce536960cd86ed57b892f2b64580b636e69060b33681bb09dfbe31f9ad761d6074e8f628406a8994f829333cb9679095aeb053e69351ed1c3363a344c090801d0500951d743ac51518dd51a14168be2661edce32585c875f05c0c01181a7bf9804b66034e93122cf52ba2ea8e7e6a8860b2be5c602725891f55ec47092a96c5267d86b38c0d92a27b959e1b96a921733c3ca28f09d2c7b7b18b8423491bb1201463b2c12b52f9f3ab8fa8242e7400f8e00b56f70805295e10a964a85377952785e35aa055f2080e59bfa3cc0b12e127feda068cc3867ce31f714cbd5e9b292ee81c295718b16346d43b409112474af110f0641d3c2967616a9fc64364b141c55fe8357f85114ed1876e644c7775af9a952bf5a5bf3da717c9a3187fa41f551919c5e240ad7c04f1b4ce33804a45a6b45489c59e6225ea6a8099a22d221b1f8b2100d269b68884564fa31fe9ac7c0ed00fb0d909f40345a83554c97cc6e4625f696b44b7303639379c494a964d5b2b01b5157cd70168ba5bfd9c9ad620848d608298fa4a7be6b5dc703dc3222ec8bc21cd0737b89005c4e0b32522a9de0cc7dc804facca327647b8a3c309c55366f6b4758d017370c77ab2950ae215975a74af7567b008f1862b381d875520f2ec9b7f280c727ab451fc4b428602df48949e4a8b74baa263d74edef8c055233aef4a7f3e95afac9575c2ac86f0365fea0824d53a8b40b1bd18e600c4c442ed601cb0334f28da06a2f4738a40a95b21b38c4c5ff7d27c29f1cbc506ad7ef392c29002667513ef002cfad9518f4acd6fc0a90202a8d534052e097a5ee6450c242beb8c122c2044a4025792974112c41b2efc062591180f69961f98648f2362ff1789f56605060c47f091aa6687c0ef6bb744755adadb67bc1b896a8bcff25a594b865c6c2abe68c5058b7c4c10cbcaa4f438d9350b7ef9520367b42c5581472823f6ca188eb24a60bb169998a00fcbc6e34368d4420eb7897d1d98a27520bdc6f48dc019bfd1ba3d9ea461737046dae8b2e1151ce734b4e952a119d6a601893c5c951b20eb56b12ac03395a497fb689b189b4f7ac84457463eca471d41883b49b02ed99f3358a2201461464b0c0e511f47656c0cb90c018a27457a1bdf2a1897e17fe77a70d58b4297ab9b68dbc796477477085c6f1272e62911a3bccfb469495ceb4843363652603b6059372fac140723a5dd4c6d2edac516563d4b846e9a8ab30f60c46153173c3b8d8746801d12a1a1919c0bd59f907c93c66c8760f3296fa6bc358c557f1ccc6efa66ef3bb2c14c4aafd56ddc4413859963bcabc0dc170117a11623635669e975d73c3ce9559642495bb9386ac049cfc40a39b1b56522b4540acbbad9b046cc990d192c2e2cf49422b60b763282cfa32dacf82cb4169c74e42368b962a30912cbc76c23bb49cfdb4f477b4ee4e651c0c80f38b5b06deb18833292c201a69c22a4ec43a8fec5ca04869f6dba8263e6acca761dcf2cc1bb65cefc902a4a123285f53f8c4283f1342c119b6ce0616776b6cb5607446f4948e0e5023d593c0ed585ea1a44a85c691ab49750222ac7775bf559bfebda3f8b3baedc4b1c6498a1328a73e7aa9370653cbc502e620aaf112718fdc002b9dc60cf3c250da55f8237b034acb7408347db34a436d492cd8629014230502294e6611e5f7f5c2504f59871b3e7da307fe5e3e4123fb2896e20c45ddaf9cdc54a592f8d4fb89130551689123ba3c6ed310295dea662cdbee35fd1162c8d26f3a18458d73e2a2ea6c9c476fc4937b013c993a793d6c0ab9960695ba838f649da539ca3d0"; -#[cfg(all(not(any(feature = "kyber512", feature = "kyber1024")), feature = "90s"))] +#[cfg(all( + not(any(feature = "kyber512", feature = "kyber1024")), + feature = "90s" +))] const CT: &str = "769bba9ca387e4547a85272b32a51ebdb331176a71637fbb7071bf91462aa4eb160131625ab37b0f7aad7a2ee470ec33ba6907c311d722ecdb98bdfa2db93dc9bb3ea2e542c1fedbd8973bc424bdb617534a83aa7931cf3b9d8a5c29609851cf9f9b2f4e810bc382cf5a3b88e8c6e4efae09e9dd22a7dc665d9cac37c0d9b9f977a3c273704dccdebf294c4b4836cffc32ddd6a09978602a1fe45269d3850a01c79a02c719823233fada96d0a286e1170717ab8b8c868edd9f1a7f1eb7883585d9d3b0d7183a5d8d8d9bde501075d13212299d74af356133fcdb6823c68525b368302a06ec647c25b2192647fd32c7da807a30862bd6fea6bc9c2b7f159f35539e655a36611831845f6d29bcc2dbcd889fdddbaaee11a4ed1eda9749f9a08efd2b707a05e2166cdd037e7fcb28451216bfcf71022f504b3e4705b0447d61c4207a12b6913003b39bcbfa6796ad128f6dbcc6a6346addd2c136a7f90d55787af060229c94f6cac497efeac2a625feb1804d46b12b4869bf6af30f75401cb721077cacec47c119995df8258f676ebd8f2199a4354466b52332b90e7fffd181d82b059a2468d06384470967475ba340401364a6831f7b52d010ad5ede2345f8a9bbb9327350b9563ad4eec2565198dbd23d32ca9374df78af100c2f1c27ccbd35083bf2515a956108f20291dc9c2954b8865994e40addb6ae358992503755306fd86793e822565b02bc73ef7b47b4a0e99d6bc65e0d0ac1cf1a6adbc24e5b9516733da4a99a1913edf15f7188be52856424eda5c994e333a738a8af3bfa680fb67df329fdfe7cce6786a7217dd1aa74dcbac13e4357e79db1ae5b7f57c7e8bd42829949c455f248193eefeb183ea7fa2e36884610b3e8c611a5079307148c7a4b3273c69c9d9b7fc1201d649888803463470c596a8e75cd8f96fa3d2b1eb45e257fbc04596453615d54be9f411ade2dd129386e4bf54e111b79ef0ebcb7dcb202f02bcb2e5734bd8393e9b1f36067e50b18bead1333728f4f171c6590e365c391acbde3dd75432f8ec846e86d4249c9982fbcaf8717be029a8f2387b6b1f835ee3a48b4161c1cd73cadd42bced3d5a2b0c68b9963e0af500f156e22bb09a097d9f502ccf8cd8ece80e28e423ceb4d1993cb4257b65a73040671a125294d2c77687e7b096e54044382c6eb916609be778f96054680c1da5f4c81c54755d26cdf0adbcc68d22e796cb8c41f19568e9e36c9d9fcdc14c52a11d21f15f628650512022e543160ebcce5ddf282f3307799addef28cce458a53debc70e2376972b328205b94e3abd786a08aec8239b60fab8ae06e58e6863585f4591659d2317b1fb7b5d2a9e1e28f5d87a3e927260fc620fca5fa29e5327f3ed18d96e74fefe0c9f70fbc26bf5a425eedc0bed0e7859fe63f7c6ed79ceab1fef92b7897fce490367df2e27bcf8794c937f2c3913657be8cd8229ea42ce4cdb1ab6f33f2f915043042e88fcda4a01f83d95e3ce5632be90e4fdb619ce323f4904d370a8983d1592dd065b0"; // tvecs1024 diff --git a/examples/ake.rs b/examples/ake.rs index c9185d9..ccd9fda 100644 --- a/examples/ake.rs +++ b/examples/ake.rs @@ -36,8 +36,12 @@ fn main() -> Result<(), KyberLibError> { // Bob receives the request and authenticates Alice, sends // encapsulated shared secret back - let server_send = - bob.server_receive(client_send, &alice_keys.public, &bob_keys.secret, &mut rng)?; + let server_send = bob.server_receive( + client_send, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + )?; // Alice authenticates and decapsulates alice.client_confirm(server_send, &alice_keys.secret)?; diff --git a/examples/kem.rs b/examples/kem.rs index ee5a47e..2e852c4 100644 --- a/examples/kem.rs +++ b/examples/kem.rs @@ -30,10 +30,12 @@ fn main() -> Result<(), KyberLibError> { let alice_keys = keypair(&mut rng)?; // Bob encapsulates a shared secret - let (ciphertext, shared_secret_bob) = encapsulate(&alice_keys.public, &mut rng)?; + let (ciphertext, shared_secret_bob) = + encapsulate(&alice_keys.public, &mut rng)?; // Alice decapsulates the shared secret - let shared_secret_alice = decapsulate(&ciphertext, &alice_keys.secret)?; + let shared_secret_alice = + decapsulate(&ciphertext, &alice_keys.secret)?; // Both can now communicate symmetrically assert_eq!(shared_secret_alice, shared_secret_bob); diff --git a/examples/uake.rs b/examples/uake.rs index 3929fba..bd01d88 100644 --- a/examples/uake.rs +++ b/examples/uake.rs @@ -36,7 +36,8 @@ fn main() -> Result<(), KyberLibError> { // Bob receives the request and authenticates Alice, sends // encapsulated shared secret back - let server_send = bob.server_receive(client_send, &bob_keys.secret, &mut rng)?; + let server_send = + bob.server_receive(client_send, &bob_keys.secret, &mut rng)?; // Alice authenticates and decapsulates alice.client_confirm(server_send)?; diff --git a/src/api.rs b/src/api.rs index 405b230..c3f4f69 100644 --- a/src/api.rs +++ b/src/api.rs @@ -8,6 +8,7 @@ use crate::{ params::*, CryptoRng, RngCore, }; +use pqc_core::zero; #[cfg(feature = "zeroize")] use zeroize::{Zeroize, ZeroizeOnDrop}; @@ -38,7 +39,9 @@ where let mut public = [0u8; KYBER_PUBLIC_KEY_BYTES]; let mut secret = [0u8; KYBER_SECRET_KEY_BYTES]; generate_key_pair(&mut public, &mut secret, rng, None)?; - Ok(Keypair { public, secret }) + let keys = Keypair { public, secret }; + zero!(secret); + Ok(keys) } /// Verify that given secret and public key matches and put them in @@ -62,7 +65,7 @@ pub fn keypairfrom( where R: RngCore + CryptoRng, { - //Try to encapsulate and decapsule to verify secret key matches public key + //Try to encapsulate and decapsulate to verify secret key matches public key let (ciphertext, shared_secret) = encapsulate(public, rng)?; let expected_shared_secret = decapsulate(&ciphertext, secret)?; //If it does match, return a KeyPair @@ -142,12 +145,14 @@ where /// let mut rng = rand::thread_rng(); /// let keys = keypair(&mut rng)?; /// let (ct, ss1) = encapsulate(&keys.public, &mut rng)?; -/// let ss2 = decapsulate(&ct, &keys.secret)?; +/// let ss2 = decapsulate(&ct, keys.expose_secret())?; /// assert_eq!(ss1, ss2); /// # Ok(())} /// ``` pub fn decapsulate(ct: &[u8], sk: &[u8]) -> Decapsulated { - if ct.len() != KYBER_CIPHERTEXT_BYTES || sk.len() != KYBER_SECRET_KEY_BYTES { + if ct.len() != KYBER_CIPHERTEXT_BYTES + || sk.len() != KYBER_SECRET_KEY_BYTES + { return Err(KyberLibError::InvalidInput); } let mut ss = [0u8; KYBER_SHARED_SECRET_BYTES]; @@ -188,10 +193,27 @@ impl Keypair { /// # assert!(empty_keys != keys); /// # Ok(()) } /// ``` - pub fn generate(rng: &mut R) -> Result { + pub fn generate( + rng: &mut R, + ) -> Result { keypair(rng) } + /// Explicitly exposes the secret key + ///``` + /// use kyberlib::*; + /// + /// let mut rng = rand::thread_rng(); + /// let keys = Keypair::generate(&mut rng); + /// let binding = keys.expect("Exposed secret key"); + /// let secret = binding.expose_secret(); + /// assert!(secret.len() == KYBER_SECRET_KEY_BYTES); + /// assert!(secret.len() != 0); + /// ``` + pub fn expose_secret(&self) -> &SecretKey { + &self.secret + } + /// Imports a keypair from existing public and secret key arrays. /// /// This function imports a keypair from existing public and secret key arrays and returns it as a `Keypair` struct. @@ -237,7 +259,10 @@ impl RngCore for DummyRng { panic!() } - fn try_fill_bytes(&mut self, _dest: &mut [u8]) -> Result<(), rand_core::Error> { + fn try_fill_bytes( + &mut self, + _dest: &mut [u8], + ) -> Result<(), rand_core::Error> { panic!() } @@ -287,7 +312,9 @@ pub fn derive(seed: &[u8]) -> Result { pub fn public(sk: &[u8]) -> PublicKey { let mut pk = [0u8; KYBER_INDCPA_PUBLICKEYBYTES]; pk.copy_from_slice( - &sk[KYBER_INDCPA_SECRETKEYBYTES..KYBER_INDCPA_SECRETKEYBYTES + KYBER_INDCPA_PUBLICKEYBYTES], + &sk[KYBER_INDCPA_SECRETKEYBYTES + ..KYBER_INDCPA_SECRETKEYBYTES + + KYBER_INDCPA_PUBLICKEYBYTES], ); pk } diff --git a/src/avx2/aes256ctr.rs b/src/avx2/aes256ctr.rs index 7f5e566..3bda063 100644 --- a/src/avx2/aes256ctr.rs +++ b/src/avx2/aes256ctr.rs @@ -24,20 +24,33 @@ impl Aes256CtrCtx { } } -unsafe fn aesni_encrypt4(out: &mut [u8], n: &mut __m128i, rkeys: &[__m128i; 16]) { - let idx: __m128i = _mm_set_epi8(8, 9, 10, 11, 12, 13, 14, 15, 7, 6, 5, 4, 3, 2, 1, 0); +unsafe fn aesni_encrypt4( + out: &mut [u8], + n: &mut __m128i, + rkeys: &[__m128i; 16], +) { + let idx: __m128i = _mm_set_epi8( + 8, 9, 10, 11, 12, 13, 14, 15, 7, 6, 5, 4, 3, 2, 1, 0, + ); // Load current counter value let mut f = _mm_load_si128(n); // Increase counter in 4 consecutive blocks - let mut f0 = _mm_shuffle_epi8(_mm_add_epi64(f, _mm_set_epi64x(0, 0)), idx); - let mut f1 = _mm_shuffle_epi8(_mm_add_epi64(f, _mm_set_epi64x(1, 0)), idx); - let mut f2 = _mm_shuffle_epi8(_mm_add_epi64(f, _mm_set_epi64x(2, 0)), idx); - let mut f3 = _mm_shuffle_epi8(_mm_add_epi64(f, _mm_set_epi64x(3, 0)), idx); + let mut f0 = + _mm_shuffle_epi8(_mm_add_epi64(f, _mm_set_epi64x(0, 0)), idx); + let mut f1 = + _mm_shuffle_epi8(_mm_add_epi64(f, _mm_set_epi64x(1, 0)), idx); + let mut f2 = + _mm_shuffle_epi8(_mm_add_epi64(f, _mm_set_epi64x(2, 0)), idx); + let mut f3 = + _mm_shuffle_epi8(_mm_add_epi64(f, _mm_set_epi64x(3, 0)), idx); // Write counter for next iteration, increased by 4 - _mm_store_si128(n as *mut __m128i, _mm_add_epi64(f, _mm_set_epi64x(4, 0))); + _mm_store_si128( + n as *mut __m128i, + _mm_add_epi64(f, _mm_set_epi64x(4, 0)), + ); // Actual AES encryption, 4x interleaved4 f = _mm_load_si128(&rkeys[0]); @@ -76,11 +89,16 @@ unsafe fn cast_128(x: __m128i) -> __m128 { _mm_castsi128_ps(x) } -pub fn aes256ctr_init(state: &mut Aes256CtrCtx, key: &[u8], nonce: [u8; 12]) { +pub fn aes256ctr_init( + state: &mut Aes256CtrCtx, + key: &[u8], + nonce: [u8; 12], +) { unsafe { let mut idx = 0; let key0 = _mm_loadu_si128(key.as_ptr() as *const __m128i); - let key1 = _mm_loadu_si128(key[16..].as_ptr() as *const __m128i); + let key1 = + _mm_loadu_si128(key[16..].as_ptr() as *const __m128i); state.n = _mm_loadl_epi64(nonce[..].as_ptr() as *const __m128i); state.rkeys[idx] = key0; @@ -95,11 +113,23 @@ pub fn aes256ctr_init(state: &mut Aes256CtrCtx, key: &[u8], nonce: [u8; 12]) { temp1 = _mm_aeskeygenassist_si128(temp2, $imm); state.rkeys[idx] = temp2; idx += 1; - temp4 = cast_128i(_mm_shuffle_ps(cast_128(temp4), cast_128(temp0), 0x10)); + temp4 = cast_128i(_mm_shuffle_ps( + cast_128(temp4), + cast_128(temp0), + 0x10, + )); temp0 = _mm_xor_si128(temp0, temp4); - temp4 = cast_128i(_mm_shuffle_ps(cast_128(temp4), cast_128(temp0), 0x8c)); + temp4 = cast_128i(_mm_shuffle_ps( + cast_128(temp4), + cast_128(temp0), + 0x8c, + )); temp0 = _mm_xor_si128(temp0, temp4); - temp1 = cast_128i(_mm_shuffle_ps(cast_128(temp1), cast_128(temp1), 0xff)); + temp1 = cast_128i(_mm_shuffle_ps( + cast_128(temp1), + cast_128(temp1), + 0xff, + )); temp0 = _mm_xor_si128(temp0, temp1) }; } @@ -109,11 +139,23 @@ pub fn aes256ctr_init(state: &mut Aes256CtrCtx, key: &[u8], nonce: [u8; 12]) { temp1 = _mm_aeskeygenassist_si128(temp0, $imm); state.rkeys[idx] = temp0; idx += 1; - temp4 = cast_128i(_mm_shuffle_ps(cast_128(temp4), cast_128(temp2), 0x10)); + temp4 = cast_128i(_mm_shuffle_ps( + cast_128(temp4), + cast_128(temp2), + 0x10, + )); temp2 = _mm_xor_si128(temp2, temp4); - temp4 = cast_128i(_mm_shuffle_ps(cast_128(temp4), cast_128(temp2), 0x8c)); + temp4 = cast_128i(_mm_shuffle_ps( + cast_128(temp4), + cast_128(temp2), + 0x8c, + )); temp2 = _mm_xor_si128(temp2, temp4); - temp1 = cast_128i(_mm_shuffle_ps(cast_128(temp1), cast_128(temp1), 0xaa)); + temp1 = cast_128i(_mm_shuffle_ps( + cast_128(temp1), + cast_128(temp1), + 0xaa, + )); temp2 = _mm_xor_si128(temp2, temp1) }; } @@ -138,7 +180,11 @@ pub fn aes256ctr_init(state: &mut Aes256CtrCtx, key: &[u8], nonce: [u8; 12]) { } } -pub fn aes256ctr_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut Aes256CtrCtx) { +pub fn aes256ctr_squeezeblocks( + out: &mut [u8], + nblocks: usize, + state: &mut Aes256CtrCtx, +) { let mut idx = 0; for _ in 0..nblocks { unsafe { @@ -149,7 +195,12 @@ pub fn aes256ctr_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut Aes25 } #[cfg(feature = "90s")] -pub fn aes256ctr_prf(out: &mut [u8], mut outlen: usize, seed: &[u8], nonce: u8) { +pub fn aes256ctr_prf( + out: &mut [u8], + mut outlen: usize, + seed: &[u8], + nonce: u8, +) { let mut buf = [0u8; 64]; let mut idx = 0; let mut pad_nonce = [0u8; 12]; diff --git a/src/avx2/align.rs b/src/avx2/align.rs index f801772..ae245bb 100644 --- a/src/avx2/align.rs +++ b/src/avx2/align.rs @@ -11,7 +11,8 @@ use core::arch::x86_64::*; #[repr(C, align(32))] pub union GenMatrixBuf { pub coeffs: [u8; REJ_UNIFORM_AVX_NBLOCKS * SHAKE128_RATE], - pub vec: [__m256i; (REJ_UNIFORM_AVX_NBLOCKS * SHAKE128_RATE + 31) / 32], + pub vec: + [__m256i; (REJ_UNIFORM_AVX_NBLOCKS * SHAKE128_RATE + 31) / 32], } impl GenMatrixBuf { @@ -26,7 +27,8 @@ impl GenMatrixBuf { #[repr(C)] pub union GenMatrixBuf90s { pub coeffs: [u8; REJ_UNIFORM_AVX_NBLOCKS * XOF_BLOCKBYTES], - pub vec: [__m256i; (REJ_UNIFORM_AVX_NBLOCKS * XOF_BLOCKBYTES + 31) / 32], + pub vec: + [__m256i; (REJ_UNIFORM_AVX_NBLOCKS * XOF_BLOCKBYTES + 31) / 32], } #[cfg(feature = "90s")] @@ -51,15 +53,22 @@ impl GenMatrixBuf90s { #[repr(C)] pub union IndcpaBuf { - pub coeffs: [u8; (KYBER_ETA1 * KYBER_N / 4) / XOF_BLOCKBYTES * XOF_BLOCKBYTES + 32], - pub vec: - [__m256i; ((KYBER_ETA1 * KYBER_N / 4) / XOF_BLOCKBYTES * XOF_BLOCKBYTES + 32 + 31) / 32], + pub coeffs: [u8; (KYBER_ETA1 * KYBER_N / 4) / XOF_BLOCKBYTES + * XOF_BLOCKBYTES + + 32], + pub vec: [__m256i; + ((KYBER_ETA1 * KYBER_N / 4) / XOF_BLOCKBYTES * XOF_BLOCKBYTES + + 32 + + 31) + / 32], } impl IndcpaBuf { pub fn new() -> Self { Self { - coeffs: [0u8; (KYBER_ETA1 * KYBER_N / 4) / XOF_BLOCKBYTES * XOF_BLOCKBYTES + 32], + coeffs: [0u8; (KYBER_ETA1 * KYBER_N / 4) / XOF_BLOCKBYTES + * XOF_BLOCKBYTES + + 32], } } } diff --git a/src/avx2/cbd.rs b/src/avx2/cbd.rs index 257cde6..7d38dac 100644 --- a/src/avx2/cbd.rs +++ b/src/avx2/cbd.rs @@ -58,12 +58,14 @@ fn cbd3(r: &mut Poly, buf: &[u8]) { let mask70: __m256i = _mm256_set1_epi32(7 << 16); let mask: __m256i = _mm256_set1_epi16(3); let shufbidx: __m256i = _mm256_set_epi8( - -1, 15, 14, 13, -1, 12, 11, 10, -1, 9, 8, 7, -1, 6, 5, 4, -1, 11, 10, 9, -1, 8, 7, 6, - -1, 5, 4, 3, -1, 2, 1, 0, + -1, 15, 14, 13, -1, 12, 11, 10, -1, 9, 8, 7, -1, 6, 5, 4, + -1, 11, 10, 9, -1, 8, 7, 6, -1, 5, 4, 3, -1, 2, 1, 0, ); for i in 0..(KYBER_N / 32) { - f0 = _mm256_loadu_si256(buf[24 * i..].as_ptr() as *const __m256i); + f0 = _mm256_loadu_si256( + buf[24 * i..].as_ptr() as *const __m256i + ); f0 = _mm256_permute4x64_epi64(f0, 0x94); f0 = _mm256_shuffle_epi8(f0, shufbidx); diff --git a/src/avx2/consts.rs b/src/avx2/consts.rs index d537da0..3abdc3f 100644 --- a/src/avx2/consts.rs +++ b/src/avx2/consts.rs @@ -32,51 +32,71 @@ pub union Qdata { pub const QDATA: Qdata = Qdata { coeffs: [ - Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, QINV, QINV, QINV, QINV, QINV, QINV, QINV, - QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, V, V, V, V, V, V, V, V, V, V, V, V, - V, V, V, V, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, - FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, MONTSQLO, - MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, - MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQHI, MONTSQHI, MONTSQHI, - MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, - MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, - MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, 3854, 3340, 2826, 2312, 1798, 1284, 770, - 256, 3854, 3340, 2826, 2312, 1798, 1284, 770, 256, 7, 0, 6, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1, - 0, 0, 0, 31498, 31498, 31498, 31498, -758, -758, -758, -758, 5237, 5237, 5237, 5237, 1397, - 1397, 1397, 1397, 14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745, - 14745, 14745, 14745, 14745, 14745, 14745, -359, -359, -359, -359, -359, -359, -359, -359, - -359, -359, -359, -359, -359, -359, -359, -359, 13525, 13525, 13525, 13525, 13525, 13525, - 13525, 13525, -12402, -12402, -12402, -12402, -12402, -12402, -12402, -12402, 1493, 1493, - 1493, 1493, 1493, 1493, 1493, 1493, 1422, 1422, 1422, 1422, 1422, 1422, 1422, 1422, -20907, - -20907, -20907, -20907, 27758, 27758, 27758, 27758, -3799, -3799, -3799, -3799, -15690, - -15690, -15690, -15690, -171, -171, -171, -171, 622, 622, 622, 622, 1577, 1577, 1577, 1577, - 182, 182, 182, 182, -5827, -5827, 17363, 17363, -26360, -26360, -29057, -29057, 5571, 5571, - -1102, -1102, 21438, 21438, -26242, -26242, 573, 573, -1325, -1325, 264, 264, 383, 383, - -829, -829, 1458, 1458, -1602, -1602, -130, -130, -5689, -6516, 1496, 30967, -23565, 20179, - 20710, 25080, -12796, 26616, 16064, -12442, 9134, -650, -25986, 27837, 1223, 652, -552, - 1015, -1293, 1491, -282, -1544, 516, -8, -320, -666, -1618, -1162, 126, 1469, -335, -11477, - -32227, 20494, -27738, 945, -14883, 6182, 32010, 10631, 29175, -28762, -18486, 17560, - -14430, -5276, -1103, 555, -1251, 1550, 422, 177, -291, 1574, -246, 1159, -777, -602, - -1590, -872, 418, -156, 11182, 13387, -14233, -21655, 13131, -4587, 23092, 5493, -32502, - 30317, -18741, 12639, 20100, 18525, 19529, -12619, 430, 843, 871, 105, 587, -235, -460, - 1653, 778, -147, 1483, 1119, 644, 349, 329, -75, 787, 787, 787, 787, 787, 787, 787, 787, - 787, 787, 787, 787, 787, 787, 787, 787, -1517, -1517, -1517, -1517, -1517, -1517, -1517, - -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, 28191, 28191, 28191, 28191, - 28191, 28191, 28191, 28191, -16694, -16694, -16694, -16694, -16694, -16694, -16694, -16694, - 287, 287, 287, 287, 287, 287, 287, 287, 202, 202, 202, 202, 202, 202, 202, 202, 10690, - 10690, 10690, 10690, 1358, 1358, 1358, 1358, -11202, -11202, -11202, -11202, 31164, 31164, - 31164, 31164, 962, 962, 962, 962, -1202, -1202, -1202, -1202, -1474, -1474, -1474, -1474, - 1468, 1468, 1468, 1468, -28073, -28073, 24313, 24313, -10532, -10532, 8800, 8800, 18426, - 18426, 8859, 8859, 26675, 26675, -16163, -16163, -681, -681, 1017, 1017, 732, 732, 608, - 608, -1542, -1542, 411, 411, -205, -205, -1571, -1571, 19883, -28250, -15887, -8898, - -28309, 9075, -30199, 18249, 13426, 14017, -29156, -12757, 16832, 4311, -24155, -17915, - -853, -90, -271, 830, 107, -1421, -247, -951, -398, 961, -1508, -725, 448, -1065, 677, - -1275, -31183, 25435, -7382, 24391, -20927, 10946, 24214, 16989, 10335, -7934, -22502, - 10906, 31636, 28644, 23998, -17422, 817, 603, 1322, -1465, -1215, 1218, -874, -1187, -1185, - -1278, -1510, -870, -108, 996, 958, 1522, 20297, 2146, 15355, -32384, -6280, -14903, - -11044, 14469, -21498, -20198, 23210, -17442, -23860, -20257, 7756, 23132, 1097, 610, - -1285, 384, -136, -1335, 220, -1659, -1530, 794, -854, 478, -308, 991, -1460, 1628, SHIFT, - SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, - SHIFT, SHIFT, + Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, QINV, QINV, + QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, QINV, + QINV, QINV, QINV, QINV, V, V, V, V, V, V, V, V, V, V, V, V, V, + V, V, V, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, FLO, + FLO, FLO, FLO, FLO, FLO, FHI, FHI, FHI, FHI, FHI, FHI, FHI, + FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, FHI, MONTSQLO, + MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, + MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, MONTSQLO, + MONTSQLO, MONTSQLO, MONTSQLO, MONTSQHI, MONTSQHI, MONTSQHI, + MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, + MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, MONTSQHI, + MONTSQHI, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, MASK, + MASK, MASK, MASK, MASK, MASK, MASK, MASK, 3854, 3340, 2826, + 2312, 1798, 1284, 770, 256, 3854, 3340, 2826, 2312, 1798, 1284, + 770, 256, 7, 0, 6, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1, 0, 0, 0, + 31498, 31498, 31498, 31498, -758, -758, -758, -758, 5237, 5237, + 5237, 5237, 1397, 1397, 1397, 1397, 14745, 14745, 14745, 14745, + 14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745, 14745, + 14745, 14745, 14745, -359, -359, -359, -359, -359, -359, -359, + -359, -359, -359, -359, -359, -359, -359, -359, -359, 13525, + 13525, 13525, 13525, 13525, 13525, 13525, 13525, -12402, + -12402, -12402, -12402, -12402, -12402, -12402, -12402, 1493, + 1493, 1493, 1493, 1493, 1493, 1493, 1493, 1422, 1422, 1422, + 1422, 1422, 1422, 1422, 1422, -20907, -20907, -20907, -20907, + 27758, 27758, 27758, 27758, -3799, -3799, -3799, -3799, -15690, + -15690, -15690, -15690, -171, -171, -171, -171, 622, 622, 622, + 622, 1577, 1577, 1577, 1577, 182, 182, 182, 182, -5827, -5827, + 17363, 17363, -26360, -26360, -29057, -29057, 5571, 5571, + -1102, -1102, 21438, 21438, -26242, -26242, 573, 573, -1325, + -1325, 264, 264, 383, 383, -829, -829, 1458, 1458, -1602, + -1602, -130, -130, -5689, -6516, 1496, 30967, -23565, 20179, + 20710, 25080, -12796, 26616, 16064, -12442, 9134, -650, -25986, + 27837, 1223, 652, -552, 1015, -1293, 1491, -282, -1544, 516, + -8, -320, -666, -1618, -1162, 126, 1469, -335, -11477, -32227, + 20494, -27738, 945, -14883, 6182, 32010, 10631, 29175, -28762, + -18486, 17560, -14430, -5276, -1103, 555, -1251, 1550, 422, + 177, -291, 1574, -246, 1159, -777, -602, -1590, -872, 418, + -156, 11182, 13387, -14233, -21655, 13131, -4587, 23092, 5493, + -32502, 30317, -18741, 12639, 20100, 18525, 19529, -12619, 430, + 843, 871, 105, 587, -235, -460, 1653, 778, -147, 1483, 1119, + 644, 349, 329, -75, 787, 787, 787, 787, 787, 787, 787, 787, + 787, 787, 787, 787, 787, 787, 787, 787, -1517, -1517, -1517, + -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, -1517, + -1517, -1517, -1517, -1517, 28191, 28191, 28191, 28191, 28191, + 28191, 28191, 28191, -16694, -16694, -16694, -16694, -16694, + -16694, -16694, -16694, 287, 287, 287, 287, 287, 287, 287, 287, + 202, 202, 202, 202, 202, 202, 202, 202, 10690, 10690, 10690, + 10690, 1358, 1358, 1358, 1358, -11202, -11202, -11202, -11202, + 31164, 31164, 31164, 31164, 962, 962, 962, 962, -1202, -1202, + -1202, -1202, -1474, -1474, -1474, -1474, 1468, 1468, 1468, + 1468, -28073, -28073, 24313, 24313, -10532, -10532, 8800, 8800, + 18426, 18426, 8859, 8859, 26675, 26675, -16163, -16163, -681, + -681, 1017, 1017, 732, 732, 608, 608, -1542, -1542, 411, 411, + -205, -205, -1571, -1571, 19883, -28250, -15887, -8898, -28309, + 9075, -30199, 18249, 13426, 14017, -29156, -12757, 16832, 4311, + -24155, -17915, -853, -90, -271, 830, 107, -1421, -247, -951, + -398, 961, -1508, -725, 448, -1065, 677, -1275, -31183, 25435, + -7382, 24391, -20927, 10946, 24214, 16989, 10335, -7934, + -22502, 10906, 31636, 28644, 23998, -17422, 817, 603, 1322, + -1465, -1215, 1218, -874, -1187, -1185, -1278, -1510, -870, + -108, 996, 958, 1522, 20297, 2146, 15355, -32384, -6280, + -14903, -11044, 14469, -21498, -20198, 23210, -17442, -23860, + -20257, 7756, 23132, 1097, 610, -1285, 384, -136, -1335, 220, + -1659, -1530, 794, -854, 478, -308, 991, -1460, 1628, SHIFT, + SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, + SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, ], }; diff --git a/src/avx2/fips202.rs b/src/avx2/fips202.rs index 4828cc2..3999a83 100644 --- a/src/avx2/fips202.rs +++ b/src/avx2/fips202.rs @@ -329,7 +329,12 @@ pub fn keccakf1600_statepermute(state: &mut [u64]) { /// - u64 nblocks: number of blocks to be squeezed (written to h) /// - u64 *s: in/output Keccak state /// - usize r: rate in bytes (e.g., 168 for SHAKE128) -pub fn keccak_squeezeblocks(h: &mut [u8], mut nblocks: usize, s: &mut [u64], r: usize) { +pub fn keccak_squeezeblocks( + h: &mut [u8], + mut nblocks: usize, + s: &mut [u64], + r: usize, +) { let mut idx = 0usize; while nblocks > 0 { keccakf1600_statepermute(s); @@ -351,7 +356,11 @@ pub fn keccak_squeezeblocks(h: &mut [u8], mut nblocks: usize, s: &mut [u64], r: /// Arguments: - [u8] out: pointer to output blocks /// - u64 nblocks: number of blocks to be squeezed (written to output) /// - KeccakState state: pointer to input/output Keccak state -pub fn shake128_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut KeccakState) { +pub fn shake128_squeezeblocks( + out: &mut [u8], + nblocks: usize, + state: &mut KeccakState, +) { keccak_squeezeblocks(out, nblocks, &mut state.s, SHAKE128_RATE); } @@ -363,7 +372,12 @@ pub fn shake128_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut Keccak /// - usize outlen: requested output length in bytes /// - [u8] input: input /// - usize inlen: length of input in bytes -pub fn shake256(out: &mut [u8], mut outlen: usize, input: &[u8], inlen: usize) { +pub fn shake256( + out: &mut [u8], + mut outlen: usize, + input: &[u8], + inlen: usize, +) { let mut state = KeccakState::new(); let mut idx = 0; shake256_absorb_once(&mut state, input, inlen); @@ -429,7 +443,13 @@ fn keccak_finalize(s: &mut [u64], pos: usize, r: usize, p: u8) { /// - const [u8] input: input to be absorbed into s /// - u64 mlen: length of input in bytes /// - [u8] p: domain-separation byte for different Keccak-derived functions -pub fn keccak_absorb_once(s: &mut [u64], r: usize, input: &[u8], mut inlen: usize, p: u8) { +pub fn keccak_absorb_once( + s: &mut [u64], + r: usize, + input: &[u8], + mut inlen: usize, + p: u8, +) { /// Zero State for i in s.iter_mut() { *i = 0; @@ -516,8 +536,18 @@ fn shake128_finalize(state: &mut KeccakState) { /// Arguments: - [u8] out: pointer to output blocks /// - usize outlen : number of bytes to be squeezed (written to output) /// - keccak_state s: pointer to input/output Keccak state -fn shake128_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) { - state.pos = keccak_squeeze(out, outlen, &mut state.s, state.pos, SHAKE128_RATE); +fn shake128_squeeze( + out: &mut [u8], + outlen: usize, + state: &mut KeccakState, +) { + state.pos = keccak_squeeze( + out, + outlen, + &mut state.s, + state.pos, + SHAKE128_RATE, + ); } /// Name: shake128_absorb_once @@ -527,7 +557,11 @@ fn shake128_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) { /// Arguments: - keccak_state state: pointer to (uninitialized) output Keccak state /// - const [u8] in: input to be absorbed into s /// - usize inlen: length of input in bytes -pub fn shake128_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize) { +pub fn shake128_absorb_once( + state: &mut KeccakState, + input: &[u8], + inlen: usize, +) { keccak_absorb_once(&mut state.s, SHAKE128_RATE, input, inlen, 0x1F); state.pos = SHAKE128_RATE; } @@ -541,20 +575,43 @@ fn shake256_finalize(state: &mut KeccakState) { state.pos = SHAKE256_RATE; } -fn shake256_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) { - state.pos = keccak_squeeze(out, outlen, &mut state.s, state.pos, SHAKE256_RATE); +fn shake256_squeeze( + out: &mut [u8], + outlen: usize, + state: &mut KeccakState, +) { + state.pos = keccak_squeeze( + out, + outlen, + &mut state.s, + state.pos, + SHAKE256_RATE, + ); } -pub fn shake256_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize) { +pub fn shake256_absorb_once( + state: &mut KeccakState, + input: &[u8], + inlen: usize, +) { keccak_absorb_once(&mut state.s, SHAKE256_RATE, input, inlen, 0x1F); state.pos = SHAKE256_RATE; } -fn shake256_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut KeccakState) { +fn shake256_squeezeblocks( + out: &mut [u8], + nblocks: usize, + state: &mut KeccakState, +) { keccak_squeezeblocks(out, nblocks, &mut state.s, SHAKE256_RATE); } -fn shake128(out: &mut [u8], mut outlen: usize, input: &[u8], inlen: usize) { +fn shake128( + out: &mut [u8], + mut outlen: usize, + input: &[u8], + inlen: usize, +) { let mut state = KeccakState::new(); let mut idx = 0; shake128_absorb_once(&mut state, input, inlen); diff --git a/src/avx2/fips202x4.rs b/src/avx2/fips202x4.rs index 0bfa5b4..92d7b50 100644 --- a/src/avx2/fips202x4.rs +++ b/src/avx2/fips202x4.rs @@ -111,11 +111,23 @@ pub unsafe fn keccakx4_squeezeblocks256( f1600_x4(s); for i in 0..(r / 8) { t = _mm_castsi128_pd(_mm256_castsi256_si128(s[i])); - _mm_storel_pd(out[0].coeffs[idx + 8 * i..].as_mut_ptr() as *mut f64, t); - _mm_storeh_pd(out[1].coeffs[idx + 8 * i..].as_mut_ptr() as *mut f64, t); + _mm_storel_pd( + out[0].coeffs[idx + 8 * i..].as_mut_ptr() as *mut f64, + t, + ); + _mm_storeh_pd( + out[1].coeffs[idx + 8 * i..].as_mut_ptr() as *mut f64, + t, + ); t = _mm_castsi128_pd(_mm256_extracti128_si256(s[i], 1)); - _mm_storel_pd(out[2].coeffs[idx + 8 * i..].as_mut_ptr() as *mut f64, t); - _mm_storeh_pd(out[3].coeffs[idx + 8 * i..].as_mut_ptr() as *mut f64, t); + _mm_storel_pd( + out[2].coeffs[idx + 8 * i..].as_mut_ptr() as *mut f64, + t, + ); + _mm_storeh_pd( + out[3].coeffs[idx + 8 * i..].as_mut_ptr() as *mut f64, + t, + ); } idx += r; nblocks -= 1; @@ -130,7 +142,16 @@ pub unsafe fn shake128x4_absorb_once( in3: &[u8], inlen: usize, ) { - keccakx4_absorb_once(&mut state.s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F) + keccakx4_absorb_once( + &mut state.s, + SHAKE128_RATE, + in0, + in1, + in2, + in3, + inlen, + 0x1F, + ) } pub unsafe fn shake128x4_squeezeblocks( @@ -138,7 +159,12 @@ pub unsafe fn shake128x4_squeezeblocks( nblocks: usize, state: &mut Keccakx4State, ) { - keccakx4_squeezeblocks128(out, nblocks, SHAKE128_RATE, &mut state.s); + keccakx4_squeezeblocks128( + out, + nblocks, + SHAKE128_RATE, + &mut state.s, + ); } pub unsafe fn shake256x4_absorb_once( @@ -149,7 +175,16 @@ pub unsafe fn shake256x4_absorb_once( in3: &[u8], inlen: usize, ) { - keccakx4_absorb_once(&mut state.s, SHAKE256_RATE, in0, in1, in2, in3, inlen, 0x1F) + keccakx4_absorb_once( + &mut state.s, + SHAKE256_RATE, + in0, + in1, + in2, + in3, + inlen, + 0x1F, + ) } pub unsafe fn shake256x4_squeezeblocks( @@ -157,5 +192,10 @@ pub unsafe fn shake256x4_squeezeblocks( nblocks: usize, state: &mut Keccakx4State, ) { - keccakx4_squeezeblocks256(out, nblocks, SHAKE256_RATE, &mut state.s); + keccakx4_squeezeblocks256( + out, + nblocks, + SHAKE256_RATE, + &mut state.s, + ); } diff --git a/src/avx2/indcpa.rs b/src/avx2/indcpa.rs index 19497da..14d5cbd 100644 --- a/src/avx2/indcpa.rs +++ b/src/avx2/indcpa.rs @@ -1,5 +1,8 @@ use crate::rng::randombytes; -use crate::{params::*, poly::*, polyvec::*, symmetric::*, CryptoRng, KyberLibError, RngCore}; +use crate::{ + params::*, poly::*, polyvec::*, symmetric::*, CryptoRng, + KyberLibError, RngCore, +}; /// Name: pack_pk /// @@ -13,7 +16,8 @@ use crate::{params::*, poly::*, polyvec::*, symmetric::*, CryptoRng, KyberLibErr fn pack_pk(r: &mut [u8], pk: &mut Polyvec, seed: &[u8]) { const END: usize = KYBER_SYM_BYTES + KYBER_POLYVECBYTES; polyvec_tobytes(r, pk); - r[KYBER_POLYVECBYTES..END].copy_from_slice(&seed[..KYBER_SYM_BYTES]); + r[KYBER_POLYVECBYTES..END] + .copy_from_slice(&seed[..KYBER_SYM_BYTES]); } /// Name: unpack_pk @@ -27,7 +31,8 @@ fn pack_pk(r: &mut [u8], pk: &mut Polyvec, seed: &[u8]) { fn unpack_pk(pk: &mut Polyvec, seed: &mut [u8], packedpk: &[u8]) { const END: usize = KYBER_SYM_BYTES + KYBER_POLYVECBYTES; polyvec_frombytes(pk, packedpk); - seed[..KYBER_SYM_BYTES].copy_from_slice(&packedpk[KYBER_POLYVECBYTES..END]); + seed[..KYBER_SYM_BYTES] + .copy_from_slice(&packedpk[KYBER_POLYVECBYTES..END]); } /// Name: pack_sk @@ -88,13 +93,20 @@ fn unpack_ciphertext(b: &mut Polyvec, v: &mut Poly, c: &[u8]) { /// - usize buflen: length of input buffer in bytes /// /// Returns number of sampled 16-bit integers (at most len) -fn rej_uniform(r: &mut [i16], len: usize, buf: &[u8], buflen: usize) -> usize { +fn rej_uniform( + r: &mut [i16], + len: usize, + buf: &[u8], + buflen: usize, +) -> usize { let (mut ctr, mut pos) = (0usize, 0usize); let (mut val0, mut val1); while ctr < len && pos + 3 <= buflen { val0 = ((buf[pos]) as u16 | (buf[pos + 1] as u16) << 8) & 0xFFF; - val1 = ((buf[pos + 1] >> 4) as u16 | (buf[pos + 2] as u16) << 4) & 0xFFF; + val1 = ((buf[pos + 1] >> 4) as u16 + | (buf[pos + 2] as u16) << 4) + & 0xFFF; pos += 3; if val0 < KYBER_Q as u16 { @@ -130,13 +142,16 @@ fn gen_at(a: &mut [Polyvec], b: &[u8]) { fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) { let mut ctr; const GEN_MATRIX_NBLOCKS: usize = - (12 * KYBER_N / 8 * (1 << 12) / KYBER_Q + XOF_BLOCKBYTES) / XOF_BLOCKBYTES; + (12 * KYBER_N / 8 * (1 << 12) / KYBER_Q + XOF_BLOCKBYTES) + / XOF_BLOCKBYTES; let mut buf = [0u8; GEN_MATRIX_NBLOCKS * XOF_BLOCKBYTES + 2]; let mut buflen: usize; let mut off: usize; let mut state = XofState::new(); - for (i, item) in a.iter_mut().enumerate().take(KYBER_SECURITY_PARAMETER) { + for (i, item) in + a.iter_mut().enumerate().take(KYBER_SECURITY_PARAMETER) + { for j in 0..KYBER_SECURITY_PARAMETER { if transposed { xof_absorb(&mut state, seed, i as u8, j as u8); @@ -145,7 +160,12 @@ fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) { } xof_squeezeblocks(&mut buf, GEN_MATRIX_NBLOCKS, &mut state); buflen = GEN_MATRIX_NBLOCKS * XOF_BLOCKBYTES; - ctr = rej_uniform(&mut item.vec[j].coeffs, KYBER_N, &buf, buflen); + ctr = rej_uniform( + &mut item.vec[j].coeffs, + KYBER_N, + &buf, + buflen, + ); while ctr < KYBER_N { off = buflen % 3; @@ -154,7 +174,12 @@ fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) { } xof_squeezeblocks(&mut buf[off..], 1, &mut state); buflen = off + XOF_BLOCKBYTES; - ctr += rej_uniform(&mut item.vec[j].coeffs[ctr..], KYBER_N - ctr, &buf, buflen); + ctr += rej_uniform( + &mut item.vec[j].coeffs[ctr..], + KYBER_N - ctr, + &buf, + buflen, + ); } } } @@ -177,7 +202,8 @@ where R: CryptoRng + RngCore, { let mut a = [Polyvec::new(); KYBER_SECURITY_PARAMETER]; - let (mut e, mut pkpv, mut skpv) = (Polyvec::new(), Polyvec::new(), Polyvec::new()); + let (mut e, mut pkpv, mut skpv) = + (Polyvec::new(), Polyvec::new(), Polyvec::new()); let mut nonce = 0u8; let mut buf = [0u8; 2 * KYBER_SYM_BYTES]; let mut randbuf = [0u8; 2 * KYBER_SYM_BYTES]; @@ -193,11 +219,15 @@ where let (publicseed, noiseseed) = buf.split_at(KYBER_SYM_BYTES); gen_a(&mut a, publicseed); - for (i, _item) in a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) { + for (i, _item) in + a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) + { poly_getnoise_eta1(&mut skpv.vec[i], noiseseed, nonce); nonce += 1; } - for (i, _item) in a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) { + for (i, _item) in + a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) + { poly_getnoise_eta1(&mut e.vec[i], noiseseed, nonce); nonce += 1; } @@ -206,7 +236,9 @@ where polyvec_ntt(&mut e); // matrix-vector multiplication - for (i, _item) in a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) { + for (i, _item) in + a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) + { polyvec_basemul_acc_montgomery(&mut pkpv.vec[i], &a[i], &skpv); poly_tomont(&mut pkpv.vec[i]); } @@ -228,7 +260,12 @@ where /// - const [u8] pk: input public key (length KYBER_INDCPA_PUBLICKEYBYTES) /// - const [u8] coin: input random coins used as seed (length KYBER_SYM_BYTES) /// to deterministically generate all randomness -pub(crate) fn indcpa_enc(c: &mut [u8], m: &[u8], pk: &[u8], coins: &[u8]) { +pub(crate) fn indcpa_enc( + c: &mut [u8], + m: &[u8], + pk: &[u8], + coins: &[u8], +) { let mut at = [Polyvec::new(); KYBER_SECURITY_PARAMETER]; let (mut sp, mut pkpv, mut ep, mut b) = ( Polyvec::new(), @@ -236,7 +273,8 @@ pub(crate) fn indcpa_enc(c: &mut [u8], m: &[u8], pk: &[u8], coins: &[u8]) { Polyvec::new(), Polyvec::new(), ); - let (mut v, mut k, mut epp) = (Poly::new(), Poly::new(), Poly::new()); + let (mut v, mut k, mut epp) = + (Poly::new(), Poly::new(), Poly::new()); let mut seed = [0u8; KYBER_SYM_BYTES]; let mut nonce = 0u8; @@ -244,11 +282,15 @@ pub(crate) fn indcpa_enc(c: &mut [u8], m: &[u8], pk: &[u8], coins: &[u8]) { poly_frommsg(&mut k, m); gen_at(&mut at, &seed); - for (i, _item) in a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) { + for (i, _item) in + a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) + { poly_getnoise_eta1(&mut sp.vec[i], coins, nonce); nonce += 1; } - for (i, _item) in a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) { + for (i, _item) in + a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) + { poly_getnoise_eta2(&mut ep.vec[i], coins, nonce); nonce += 1; } @@ -257,7 +299,9 @@ pub(crate) fn indcpa_enc(c: &mut [u8], m: &[u8], pk: &[u8], coins: &[u8]) { polyvec_ntt(&mut sp); // matrix-vector multiplication - for (i, _item) in a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) { + for (i, _item) in + a.iter().enumerate().take(KYBER_SECURITY_PARAMETER) + { polyvec_basemul_acc_montgomery(&mut b.vec[i], &at[i], &sp); } diff --git a/src/avx2/keccak4x.rs b/src/avx2/keccak4x.rs index f82c56e..953027b 100644 --- a/src/avx2/keccak4x.rs +++ b/src/avx2/keccak4x.rs @@ -27,11 +27,13 @@ union Temp { } const RHO: [u32; 24] = [ - 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, + 62, 18, 39, 61, 20, 44, ]; const PI: [usize; 24] = [ - 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, + 20, 14, 22, 9, 6, 1, ]; // Set __mm256i constants with a union @@ -280,7 +282,10 @@ pub fn f1600_x4(a: &mut [__m256i]) { for i in 0..4 { t2.u[i] = t2.u[i].rotate_left(1); } - a[5 * y + x] = _mm256_xor_si256(a[5 * y + x], _mm256_xor_si256(t1, t2.vec)); + a[5 * y + x] = _mm256_xor_si256( + a[5 * y + x], + _mm256_xor_si256(t1, t2.vec), + ); }); }); @@ -307,7 +312,10 @@ pub fn f1600_x4(a: &mut [__m256i]) { unroll5!(x, { let t1 = array[(x + 1) % 5]; let t2 = array[(x + 2) % 5]; - let tmp = _mm256_xor_si256(array[x], _mm256_andnot_si256(t1, t2)); + let tmp = _mm256_xor_si256( + array[x], + _mm256_andnot_si256(t1, t2), + ); a[y + x] = tmp; }); }); diff --git a/src/avx2/poly.rs b/src/avx2/poly.rs index ceaab0b..79a289f 100644 --- a/src/avx2/poly.rs +++ b/src/avx2/poly.rs @@ -1,8 +1,12 @@ #![allow(unused_imports)] -use crate::{align::*, cbd::*, consts::*, fips202::*, fips202x4::*, params::*, symmetric::*}; +use crate::{ + align::*, cbd::*, consts::*, fips202::*, fips202x4::*, params::*, + symmetric::*, +}; use core::arch::x86_64::*; -pub const NOISE_NBLOCKS: usize = (KYBER_ETA1 * KYBER_N / 4 + SHAKE256_RATE - 1) / SHAKE256_RATE; +pub const NOISE_NBLOCKS: usize = + (KYBER_ETA1 * KYBER_N / 4 + SHAKE256_RATE - 1) / SHAKE256_RATE; #[derive(Clone)] #[repr(C)] @@ -33,14 +37,19 @@ extern "C" { ); fn tomont_avx(r: &mut [i16; KYBER_N], q_data: &[i16; 640]); fn reduce_avx(r: &mut [i16; KYBER_N], q_data: &[i16; 640]); - fn ntttobytes_avx(r: *mut u8, a: &[i16; KYBER_N], q_data: &[i16; 640]); + fn ntttobytes_avx( + r: *mut u8, + a: &[i16; KYBER_N], + q_data: &[i16; 640], + ); fn nttfrombytes_avx(r: *mut i16, a: *const u8, q_data: &[i16; 640]); } #[cfg(any(feature = "kyber512", not(feature = "kyber1024")))] pub unsafe fn poly_compress(r: &mut [u8], a: Poly) { let (mut f0, mut f1, mut f2, mut f3); - let v: __m256i = _mm256_load_si256(QDATA.vec[_16XV / 16..].as_ptr()); + let v: __m256i = + _mm256_load_si256(QDATA.vec[_16XV / 16..].as_ptr()); let shift1: __m256i = _mm256_set1_epi16(1 << 9); let mask: __m256i = _mm256_set1_epi16(15); let shift2: __m256i = _mm256_set1_epi16((16 << 8) + 1); @@ -69,17 +78,21 @@ pub unsafe fn poly_compress(r: &mut [u8], a: Poly) { f2 = _mm256_maddubs_epi16(f2, shift2); f0 = _mm256_packus_epi16(f0, f2); f0 = _mm256_permutevar8x32_epi32(f0, permdidx); - _mm256_storeu_si256(r[32 * i..].as_mut_ptr() as *mut __m256i, f0); + _mm256_storeu_si256( + r[32 * i..].as_mut_ptr() as *mut __m256i, + f0, + ); } } #[cfg(any(feature = "kyber512", not(feature = "kyber1024")))] pub unsafe fn poly_decompress(r: &mut Poly, a: &[u8]) { let (mut t, mut f); - let q: __m256i = _mm256_load_si256(QDATA.vec[_16XQ / 16..].as_ptr()); + let q: __m256i = + _mm256_load_si256(QDATA.vec[_16XQ / 16..].as_ptr()); let shufbidx: __m256i = _mm256_set_epi8( - 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, - 0, 0, + 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 3, 2, + 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, ); let mask: __m256i = _mm256_set1_epi32(0x00F0000F); let shift: __m256i = _mm256_set1_epi32((128 << 16) + 2048); @@ -107,8 +120,8 @@ pub unsafe fn poly_compress(r: &mut [u8], a: Poly) { let shift3: __m256i = _mm256_set1_epi32((1024 << 16) + 1); let sllvdidx: __m256i = _mm256_set1_epi64x(12); let shufbidx: __m256i = _mm256_set_epi8( - 8, -1, -1, -1, -1, -1, 4, 3, 2, 1, 0, -1, 12, 11, 10, 9, -1, 12, 11, 10, 9, 8, -1, -1, -1, - -1, -1, 4, 3, 2, 1, 0, + 8, -1, -1, -1, -1, -1, 4, 3, 2, 1, 0, -1, 12, 11, 10, 9, -1, + 12, 11, 10, 9, 8, -1, -1, -1, -1, -1, 4, 3, 2, 1, 0, ); for i in 0..(KYBER_N / 32) { @@ -129,7 +142,10 @@ pub unsafe fn poly_compress(r: &mut [u8], a: Poly) { t0 = _mm256_castsi256_si128(f0); t1 = _mm256_extracti128_si256(f0, 1); t0 = _mm_blendv_epi8(t0, t1, _mm256_castsi256_si128(shufbidx)); - _mm_storeu_si128(r[20 * i + 0..].as_mut_ptr() as *mut __m128i, t0); + _mm_storeu_si128( + r[20 * i + 0..].as_mut_ptr() as *mut __m128i, + t0, + ); tmp = _mm_cvtsi128_si32(t1); r[20 * i + 16..20 * i + 20].copy_from_slice(&tmp.to_le_bytes()); } @@ -141,14 +157,16 @@ pub unsafe fn poly_decompress(r: &mut Poly, a: &[u8]) { let q = _mm256_load_si256(&QDATA.vec[_16XQ / 16]); let shufbidx = _mm256_set_epi8( - 9, 9, 9, 8, 8, 8, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 0, - 0, 0, + 9, 9, 9, 8, 8, 8, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, + 3, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, ); let mask = _mm256_set_epi16( - 248, 1984, 62, 496, 3968, 124, 992, 31, 248, 1984, 62, 496, 3968, 124, 992, 31, + 248, 1984, 62, 496, 3968, 124, 992, 31, 248, 1984, 62, 496, + 3968, 124, 992, 31, ); let shift = _mm256_set_epi16( - 128, 16, 512, 64, 8, 256, 32, 1024, 128, 16, 512, 64, 8, 256, 32, 1024, + 128, 16, 512, 64, 8, 256, 32, 1024, 128, 16, 512, 64, 8, 256, + 32, 1024, ); for i in 0..KYBER_N / 16 { @@ -166,7 +184,11 @@ pub unsafe fn poly_decompress(r: &mut Poly, a: &[u8]) { pub fn poly_frombytes(r: &mut Poly, a: &[u8]) { unsafe { - nttfrombytes_avx(r.coeffs.as_mut_ptr(), a.as_ptr(), &QDATA.coeffs); + nttfrombytes_avx( + r.coeffs.as_mut_ptr(), + a.as_ptr(), + &QDATA.coeffs, + ); } } @@ -246,7 +268,10 @@ pub fn poly_tomsg(msg: &mut [u8], a: Poly) { } } -#[cfg(all(any(feature = "kyber1024", feature = "kyber512"), not(feature = "90s")))] +#[cfg(all( + any(feature = "kyber1024", feature = "kyber512"), + not(feature = "90s") +))] pub fn poly_getnoise_eta2(r: &mut Poly, seed: &[u8], nonce: u8) { let mut buf = Eta2Buf::new(); unsafe { diff --git a/src/avx2/polyvec.rs b/src/avx2/polyvec.rs index 009e6b4..227ed1d 100644 --- a/src/avx2/polyvec.rs +++ b/src/avx2/polyvec.rs @@ -25,11 +25,13 @@ pub unsafe fn poly_compress10(r: &mut [u8], a: &Poly) { let off = _mm256_set1_epi16(15); let shift1 = _mm256_set1_epi16(1 << 12); let mask = _mm256_set1_epi16(1023); - let shift2 = _mm256_set1_epi64x(((1024u64 << 48) + (1u64 << 32) + (1024 << 16) + 1) as i64); + let shift2 = _mm256_set1_epi64x( + ((1024u64 << 48) + (1u64 << 32) + (1024 << 16) + 1) as i64, + ); let sllvdidx = _mm256_set1_epi64x(12); let shufbidx = _mm256_set_epi8( - 8, 4, 3, 2, 1, 0, -1, -1, -1, -1, -1, -1, 12, 11, 10, 9, -1, -1, -1, -1, -1, -1, 12, 11, - 10, 9, 8, 4, 3, 2, 1, 0, + 8, 4, 3, 2, 1, 0, -1, -1, -1, -1, -1, -1, 12, 11, 10, 9, -1, + -1, -1, -1, -1, -1, 12, 11, 10, 9, 8, 4, 3, 2, 1, 0, ); for i in 0..(KYBER_N / 16) { @@ -52,16 +54,21 @@ pub unsafe fn poly_compress10(r: &mut [u8], a: &Poly) { t1 = _mm256_extracti128_si256(f0, 1); t0 = _mm_blend_epi16(t0, t1, 0xE0); _mm_storeu_si128(r[20 * i..].as_mut_ptr() as *mut __m128i, t0); - _mm_storeu_si128(r[20 * i + 16..].as_mut_ptr() as *mut __m128i, t1); + _mm_storeu_si128( + r[20 * i + 16..].as_mut_ptr() as *mut __m128i, + t1, + ); } } pub unsafe fn poly_decompress10(r: &mut Poly, a: &[u8]) { let mut f; - let q = _mm256_set1_epi32(((KYBER_Q as i32) << 16) + 4 * KYBER_Q as i32); + let q = _mm256_set1_epi32( + ((KYBER_Q as i32) << 16) + 4 * KYBER_Q as i32, + ); let shufbidx = _mm256_set_epi8( - 11, 10, 10, 9, 9, 8, 8, 7, 6, 5, 5, 4, 4, 3, 3, 2, 9, 8, 8, 7, 7, 6, 6, 5, 4, 3, 3, 2, 2, - 1, 1, 0, + 11, 10, 10, 9, 9, 8, 8, 7, 6, 5, 5, 4, 4, 3, 3, 2, 9, 8, 8, 7, + 7, 6, 6, 5, 4, 3, 3, 2, 2, 1, 1, 0, ); let sllvdidx = _mm256_set1_epi64x(4); let mask = _mm256_set1_epi32((32736 << 16) + 8184); @@ -85,12 +92,14 @@ pub unsafe fn poly_compress11(r: &mut [u8], a: &Poly) { let off = _mm256_set1_epi16(36); let shift1 = _mm256_set1_epi16(1 << 13); let mask = _mm256_set1_epi16(2047); - let shift2 = _mm256_set1_epi64x(((2048u64 << 48) + (1u64 << 32) + (2048 << 16) + 1) as i64); + let shift2 = _mm256_set1_epi64x( + ((2048u64 << 48) + (1u64 << 32) + (2048 << 16) + 1) as i64, + ); let sllvdidx = _mm256_set1_epi64x(10); let srlvqidx = _mm256_set_epi64x(30, 10, 30, 10); let shufbidx = _mm256_set_epi8( - 4, 3, 2, 1, 0, 0, -1, -1, -1, -1, 10, 9, 8, 7, 6, 5, -1, -1, -1, -1, -1, 10, 9, 8, 7, 6, 5, - 4, 3, 2, 1, 0, + 4, 3, 2, 1, 0, 0, -1, -1, -1, -1, 10, 9, 8, 7, 6, 5, -1, -1, + -1, -1, -1, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, ); for i in 0..KYBER_N / 16 { @@ -115,8 +124,14 @@ pub unsafe fn poly_compress11(r: &mut [u8], a: &Poly) { t0 = _mm256_castsi256_si128(f0); t1 = _mm256_extracti128_si256(f0, 1); t0 = _mm_blendv_epi8(t0, t1, _mm256_castsi256_si128(shufbidx)); - _mm_storeu_si128(r[22 * i + 0..].as_mut_ptr() as *mut __m128i, t0); - _mm_storel_epi64(r[22 * i + 16..].as_mut_ptr() as *mut __m128i, t1); + _mm_storeu_si128( + r[22 * i + 0..].as_mut_ptr() as *mut __m128i, + t0, + ); + _mm_storel_epi64( + r[22 * i + 16..].as_mut_ptr() as *mut __m128i, + t1, + ); } } @@ -125,12 +140,14 @@ pub unsafe fn poly_decompress11(r: &mut Poly, a: &[u8]) { let q = _mm256_load_si256(QDATA.vec[_16XQ / 16..].as_ptr()); let shufbidx = _mm256_set_epi8( - 13, 12, 12, 11, 10, 9, 9, 8, 8, 7, 6, 5, 5, 4, 4, 3, 10, 9, 9, 8, 7, 6, 6, 5, 5, 4, 3, 2, - 2, 1, 1, 0, + 13, 12, 12, 11, 10, 9, 9, 8, 8, 7, 6, 5, 5, 4, 4, 3, 10, 9, 9, + 8, 7, 6, 6, 5, 5, 4, 3, 2, 2, 1, 1, 0, ); let srlvdidx = _mm256_set_epi32(0, 0, 1, 0, 0, 0, 1, 0); let srlvqidx = _mm256_set_epi64x(2, 0, 2, 0); - let shift = _mm256_set_epi16(4, 32, 1, 8, 32, 1, 4, 32, 4, 32, 1, 8, 32, 1, 4, 32); + let shift = _mm256_set_epi16( + 4, 32, 1, 8, 32, 1, 4, 32, 4, 32, 1, 8, 32, 1, 4, 32, + ); let mask = _mm256_set1_epi16(32752); for i in 0..(KYBER_N / 16) { @@ -212,7 +229,11 @@ pub fn polyvec_invntt_tomont(r: &mut Polyvec) { /// Arguments: - poly *r: output polynomial /// - const Polyvec a: first input vector of polynomials /// - const Polyvec b: second input vector of polynomials -pub fn polyvec_basemul_acc_montgomery(r: &mut Poly, a: &Polyvec, b: &Polyvec) { +pub fn polyvec_basemul_acc_montgomery( + r: &mut Poly, + a: &Polyvec, + b: &Polyvec, +) { let mut t = Poly::new(); poly_basemul(r, &a.vec[0], &b.vec[0]); for i in 1..KYBER_SECURITY_PARAMETER { diff --git a/src/avx2/rejsample.rs b/src/avx2/rejsample.rs index 3e6f094..2352220 100644 --- a/src/avx2/rejsample.rs +++ b/src/avx2/rejsample.rs @@ -2,8 +2,10 @@ use crate::{consts::*, params::*, symmetric::*}; use core::arch::x86_64::*; pub const REJ_UNIFORM_AVX_NBLOCKS: usize = - (12 * KYBER_N / 8 * (1 << 12) / KYBER_Q + XOF_BLOCKBYTES) / XOF_BLOCKBYTES; -const REJ_UNIFORM_AVX_BUFLEN: usize = REJ_UNIFORM_AVX_NBLOCKS * XOF_BLOCKBYTES; + (12 * KYBER_N / 8 * (1 << 12) / KYBER_Q + XOF_BLOCKBYTES) + / XOF_BLOCKBYTES; +const REJ_UNIFORM_AVX_BUFLEN: usize = + REJ_UNIFORM_AVX_NBLOCKS * XOF_BLOCKBYTES; pub unsafe fn _mm256_cmpge_epu16(a: __m256i, b: __m256i) -> __m256i { _mm256_cmpeq_epi16(_mm256_max_epu16(a, b), a) @@ -25,12 +27,14 @@ pub unsafe fn rej_uniform_avx(r: &mut [i16], buf: &[u8]) -> usize { let ones = _mm256_set1_epi8(1); let mask = _mm256_set1_epi16(0xFFF); let idx8 = _mm256_set_epi8( - 15, 14, 14, 13, 12, 11, 11, 10, 9, 8, 8, 7, 6, 5, 5, 4, 11, 10, 10, 9, 8, 7, 7, 6, 5, 4, 4, - 3, 2, 1, 1, 0, + 15, 14, 14, 13, 12, 11, 11, 10, 9, 8, 8, 7, 6, 5, 5, 4, 11, 10, + 10, 9, 8, 7, 7, 6, 5, 4, 4, 3, 2, 1, 1, 0, ); while ctr <= KYBER_N - 32 && pos <= REJ_UNIFORM_AVX_BUFLEN - 48 { f0 = _mm256_loadu_si256(buf[pos..].as_ptr() as *const __m256i); - f1 = _mm256_loadu_si256(buf[pos + 24..].as_ptr() as *const __m256i); + f1 = _mm256_loadu_si256( + buf[pos + 24..].as_ptr() as *const __m256i + ); f0 = _mm256_permute4x64_epi64(f0, 0x94); f1 = _mm256_permute4x64_epi64(f1, 0x94); f0 = _mm256_shuffle_epi8(f0, idx8); @@ -49,14 +53,22 @@ pub unsafe fn rej_uniform_avx(r: &mut [i16], buf: &[u8]) -> usize { g0 = _mm256_packs_epi16(g0, g1); good = _mm256_movemask_epi8(g0) as usize; - let mut l0 = _mm_loadl_epi64(IDX[(good >> 0) & 0xFF].as_ptr() as *const __m128i); + let mut l0 = _mm_loadl_epi64( + IDX[(good >> 0) & 0xFF].as_ptr() as *const __m128i + ); g0 = _mm256_castsi128_si256(l0); - let mut l1 = _mm_loadl_epi64(IDX[(good >> 8) & 0xFF].as_ptr() as *const __m128i); + let mut l1 = _mm_loadl_epi64( + IDX[(good >> 8) & 0xFF].as_ptr() as *const __m128i + ); g1 = _mm256_castsi128_si256(l1); - l0 = _mm_loadl_epi64(IDX[(good >> 16) & 0xFF].as_ptr() as *const __m128i); + l0 = _mm_loadl_epi64( + IDX[(good >> 16) & 0xFF].as_ptr() as *const __m128i + ); g0 = _mm256_inserti128_si256(g0, l0, 1); - l1 = _mm_loadl_epi64(IDX[(good >> 24) & 0xFF].as_ptr() as *const __m128i); + l1 = _mm_loadl_epi64( + IDX[(good >> 24) & 0xFF].as_ptr() as *const __m128i + ); g1 = _mm256_inserti128_si256(g1, l1, 1); g2 = _mm256_add_epi8(g0, ones); @@ -101,7 +113,8 @@ pub unsafe fn rej_uniform_avx(r: &mut [i16], buf: &[u8]) -> usize { good = _mm_movemask_epi8(t) as usize; let good = _pext_u32(good as u32, 0x5555) as usize; - pilo = _mm_loadl_epi64(IDX[good][..].as_ptr() as *const __m128i); + pilo = + _mm_loadl_epi64(IDX[good][..].as_ptr() as *const __m128i); pihi = _mm_add_epi8(pilo, _mm256_castsi256_si128(ones)); pilo = _mm_unpacklo_epi8(pilo, pihi); f = _mm_shuffle_epi8(f, pilo); @@ -110,8 +123,10 @@ pub unsafe fn rej_uniform_avx(r: &mut [i16], buf: &[u8]) -> usize { } while ctr < KYBER_N && pos <= REJ_UNIFORM_AVX_BUFLEN - 3 { - val0 = (buf[pos + 0] >> 0) as u16 | ((buf[pos + 1] as u16) << 8) & 0xFFF; - val1 = (buf[pos + 1] >> 4) as u16 | ((buf[pos + 2] as u16) << 4); + val0 = (buf[pos + 0] >> 0) as u16 + | ((buf[pos + 1] as u16) << 8) & 0xFFF; + val1 = + (buf[pos + 1] >> 4) as u16 | ((buf[pos + 2] as u16) << 4); pos += 3; if (val0 as usize) < KYBER_Q { diff --git a/src/avx2/verify.rs b/src/avx2/verify.rs index af87fa9..36356ae 100644 --- a/src/avx2/verify.rs +++ b/src/avx2/verify.rs @@ -6,8 +6,12 @@ pub fn verify(a: &[u8], b: &[u8], mut len: usize) -> u8 { unsafe { let mut h = _mm256_setzero_si256(); for i in 0..(len / 32) { - f = _mm256_loadu_si256(a[32 * i..].as_ptr() as *const __m256i); - g = _mm256_loadu_si256(b[32 * i..].as_ptr() as *const __m256i); + f = _mm256_loadu_si256( + a[32 * i..].as_ptr() as *const __m256i + ); + g = _mm256_loadu_si256( + b[32 * i..].as_ptr() as *const __m256i + ); f = _mm256_xor_si256(f, g); h = _mm256_or_si256(h, f); } @@ -26,10 +30,17 @@ pub fn cmov(r: &mut [u8], x: &[u8], mut len: usize, mut b: u8) { unsafe { let bvec = _mm256_set1_epi64x(b as i64); for i in 0..(len / 32) { - rvec = _mm256_loadu_si256(r[32 * i..].as_ptr() as *const __m256i); - xvec = _mm256_loadu_si256(x[32 * i..].as_ptr() as *const __m256i); + rvec = _mm256_loadu_si256( + r[32 * i..].as_ptr() as *const __m256i + ); + xvec = _mm256_loadu_si256( + x[32 * i..].as_ptr() as *const __m256i + ); rvec = _mm256_blendv_epi8(rvec, xvec, bvec); - _mm256_storeu_si256(r[32 * i..].as_mut_ptr() as *mut __m256i, rvec); + _mm256_storeu_si256( + r[32 * i..].as_mut_ptr() as *mut __m256i, + rvec, + ); } } let idx = 32 * (len / 32); diff --git a/src/kem.rs b/src/kem.rs index be56c35..c1193ef 100644 --- a/src/kem.rs +++ b/src/kem.rs @@ -2,7 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT use crate::{ - error::KyberLibError, indcpa::*, params::*, rng::randombytes, symmetric::*, verify::*, + error::KyberLibError, indcpa::*, params::*, rng::randombytes, + symmetric::*, verify::*, }; use rand_core::{CryptoRng, RngCore}; @@ -27,13 +28,16 @@ pub fn generate_key_pair( where R: RngCore + CryptoRng, { - const PK_START: usize = KYBER_SECRET_KEY_BYTES - (2 * KYBER_SYM_BYTES); + const PK_START: usize = + KYBER_SECRET_KEY_BYTES - (2 * KYBER_SYM_BYTES); const SK_START: usize = KYBER_SECRET_KEY_BYTES - KYBER_SYM_BYTES; - const END: usize = KYBER_INDCPA_PUBLICKEYBYTES + KYBER_INDCPA_SECRETKEYBYTES; + const END: usize = + KYBER_INDCPA_PUBLICKEYBYTES + KYBER_INDCPA_SECRETKEYBYTES; indcpa_keypair(pk, sk, _seed, _rng)?; - sk[KYBER_INDCPA_SECRETKEYBYTES..END].copy_from_slice(&pk[..KYBER_INDCPA_PUBLICKEYBYTES]); + sk[KYBER_INDCPA_SECRETKEYBYTES..END] + .copy_from_slice(&pk[..KYBER_INDCPA_PUBLICKEYBYTES]); hash_h(&mut sk[PK_START..], pk, KYBER_PUBLIC_KEY_BYTES); if let Some(s) = _seed { @@ -113,7 +117,10 @@ pub fn decrypt_message(ss: &mut [u8], ct: &[u8], sk: &[u8]) { let mut cmp = [0u8; KYBER_CIPHERTEXT_BYTES]; let mut pk = [0u8; KYBER_INDCPA_PUBLICKEYBYTES]; - pk.copy_from_slice(&sk[KYBER_INDCPA_SECRETKEYBYTES..][..KYBER_INDCPA_PUBLICKEYBYTES]); + pk.copy_from_slice( + &sk[KYBER_INDCPA_SECRETKEYBYTES..] + [..KYBER_INDCPA_PUBLICKEYBYTES], + ); indcpa_dec(&mut buf, ct, sk); diff --git a/src/kex.rs b/src/kex.rs index 8d209ea..ae98581 100644 --- a/src/kex.rs +++ b/src/kex.rs @@ -5,11 +5,13 @@ use crate::{kem::*, params::*, symmetric::kdf, KyberLibError}; use rand_core::{CryptoRng, RngCore}; /// Unilateral Key Exchange Initiation Byte Length -pub const UAKE_INIT_BYTES: usize = KYBER_PUBLIC_KEY_BYTES + KYBER_CIPHERTEXT_BYTES; +pub const UAKE_INIT_BYTES: usize = + KYBER_PUBLIC_KEY_BYTES + KYBER_CIPHERTEXT_BYTES; /// Unilateral Key Exchange Response Byte Length pub const UAKE_RESPONSE_BYTES: usize = KYBER_CIPHERTEXT_BYTES; /// Mutual Key Exchange Initiation Byte Length -pub const AKE_INIT_BYTES: usize = KYBER_PUBLIC_KEY_BYTES + KYBER_CIPHERTEXT_BYTES; +pub const AKE_INIT_BYTES: usize = + KYBER_PUBLIC_KEY_BYTES + KYBER_CIPHERTEXT_BYTES; /// Mutual Key Exchange Response Byte Length pub const AKE_RESPONSE_BYTES: usize = 2 * KYBER_CIPHERTEXT_BYTES; @@ -22,7 +24,8 @@ pub type Encapsulated = Result< KyberLibError, >; /// Decapsulated ciphertext -pub type Decapsulated = Result<[u8; KYBER_SHARED_SECRET_BYTES], KyberLibError>; +pub type Decapsulated = + Result<[u8; KYBER_SHARED_SECRET_BYTES], KyberLibError>; /// Kyber public key pub type PublicKey = [u8; KYBER_PUBLIC_KEY_BYTES]; /// Kyber secret key @@ -177,8 +180,16 @@ impl Uake { /// let client_confirm = alice.client_confirm(server_send)?; /// assert_eq!(alice.shared_secret, bob.shared_secret); /// # Ok(()) } - pub fn client_confirm(&mut self, send_b: UakeSendResponse) -> Result<(), KyberLibError> { - uake_shared_a(&mut self.shared_secret, &send_b, &self.temp_key, &self.eska)?; + pub fn client_confirm( + &mut self, + send_b: UakeSendResponse, + ) -> Result<(), KyberLibError> { + uake_shared_a( + &mut self.shared_secret, + &send_b, + &self.temp_key, + &self.eska, + )?; Ok(()) } } @@ -352,7 +363,13 @@ where R: CryptoRng + RngCore, { generate_key_pair(send, sk, rng, None)?; - encrypt_message(&mut send[KYBER_PUBLIC_KEY_BYTES..], tk, pkb, rng, None)?; + encrypt_message( + &mut send[KYBER_PUBLIC_KEY_BYTES..], + tk, + pkb, + rng, + None, + )?; Ok(()) } @@ -379,7 +396,12 @@ where } // Unilaterally authenticated key exchange computation by Alice -fn uake_shared_a(k: &mut [u8], recv: &[u8], tk: &[u8], sk: &[u8]) -> Result<(), KyberLibError> { +fn uake_shared_a( + k: &mut [u8], + recv: &[u8], + tk: &[u8], + sk: &[u8], +) -> Result<(), KyberLibError> { let mut buf = [0u8; 2 * KYBER_SYM_BYTES]; decrypt_message(&mut buf, recv, sk); buf[KYBER_SYM_BYTES..].copy_from_slice(tk); @@ -399,7 +421,13 @@ where R: CryptoRng + RngCore, { generate_key_pair(send, sk, rng, None)?; - encrypt_message(&mut send[KYBER_PUBLIC_KEY_BYTES..], tk, pkb, rng, None)?; + encrypt_message( + &mut send[KYBER_PUBLIC_KEY_BYTES..], + tk, + pkb, + rng, + None, + )?; Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 527e6be..d8fc0e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -202,13 +202,18 @@ pub use api::*; pub use error::KyberLibError; pub use kex::*; pub use params::{ - KYBER_90S, KYBER_CIPHERTEXT_BYTES, KYBER_PUBLIC_KEY_BYTES, KYBER_SECRET_KEY_BYTES, - KYBER_SECURITY_PARAMETER, KYBER_SHARED_SECRET_BYTES, KYBER_SYM_BYTES, + KYBER_90S, KYBER_CIPHERTEXT_BYTES, KYBER_PUBLIC_KEY_BYTES, + KYBER_SECRET_KEY_BYTES, KYBER_SECURITY_PARAMETER, + KYBER_SHARED_SECRET_BYTES, KYBER_SYM_BYTES, }; pub use rand_core::{CryptoRng, RngCore}; // Feature hack to expose private functions for the Known Answer Tests // and fuzzing. Will fail to compile if used outside `cargo test` or // the fuzz binaries. -#[cfg(any(KYBER_SECURITY_PARAMETERat, fuzzing, feature = "benchmarking"))] +#[cfg(any( + KYBER_SECURITY_PARAMETERat, + fuzzing, + feature = "benchmarking" +))] pub use kem::*; diff --git a/src/macros.rs b/src/macros.rs index bf97456..56cc50f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -151,7 +151,8 @@ macro_rules! kyberlib_uake_client_init { #[doc = "Macro to handle the output of a Unilaterally Authenticated Key Exchange."] macro_rules! kyberlib_uake_server_receive { ($send_a:expr, $secretkey:expr, $rng:expr) => { - kyberlib::kex::Uake::new().server_receive($send_a, $secretkey, $rng) + kyberlib::kex::Uake::new() + .server_receive($send_a, $secretkey, $rng) }; } @@ -207,7 +208,12 @@ macro_rules! kyberlib_ake_client_init { #[doc = "Macro to handle the output of a Mutually Authenticated Key Exchange."] macro_rules! kyberlib_ake_server_receive { ($ake_send_a:expr, $pubkey:expr, $secretkey:expr, $rng:expr) => { - kyberlib::kex::Ake::new().server_receive($ake_send_a, $pubkey, $secretkey, $rng) + kyberlib::kex::Ake::new().server_receive( + $ake_send_a, + $pubkey, + $secretkey, + $rng, + ) }; } diff --git a/src/params.rs b/src/params.rs index a1d6b82..c9db827 100644 --- a/src/params.rs +++ b/src/params.rs @@ -15,7 +15,8 @@ pub const KYBER_90S: bool = cfg!(feature = "90s"); /// /// - Determines the distribution of the noise in the cryptographic algorithm. /// - The value is set to 3 for Kyber512 and 2 for other variants. -pub const KYBER_ETA1: usize = if cfg!(feature = "kyber512") { 3 } else { 2 }; +pub const KYBER_ETA1: usize = + if cfg!(feature = "kyber512") { 3 } else { 2 }; /// The noise parameter eta2, universally used across different Kyber variants. /// @@ -37,13 +38,15 @@ pub const KYBER_POLYBYTES: usize = 384; pub const KYBER_POLYCOMPRESSEDBYTES: usize = 128; /// The byte size of the vector of polynomials in Kyber, calculated from the security parameter and KYBER_POLYBYTES. -pub const KYBER_POLYVECBYTES: usize = KYBER_SECURITY_PARAMETER * KYBER_POLYBYTES; +pub const KYBER_POLYVECBYTES: usize = + KYBER_SECURITY_PARAMETER * KYBER_POLYBYTES; /// Compressed byte size of the polynomial vector for Kyber variants except Kyber1024. /// /// - This setting affects data compression in non-Kyber1024 configurations. #[cfg(not(feature = "kyber1024"))] -pub const KYBER_POLYVECCOMPRESSEDBYTES: usize = KYBER_SECURITY_PARAMETER * 320; +pub const KYBER_POLYVECCOMPRESSEDBYTES: usize = + KYBER_SECURITY_PARAMETER * 320; /// The modulus Q used in the Kyber scheme. /// @@ -54,8 +57,9 @@ pub const KYBER_Q: usize = 3329; /// /// - It is computed as the sum of IND-CPA secret key and public key sizes, along with twice the size of symmetric keys. /// - This size is crucial for memory allocation during key generation and storage. -pub const KYBER_SECRET_KEY_BYTES: usize = - KYBER_INDCPA_SECRETKEYBYTES + KYBER_INDCPA_PUBLICKEYBYTES + 2 * KYBER_SYM_BYTES; +pub const KYBER_SECRET_KEY_BYTES: usize = KYBER_INDCPA_SECRETKEYBYTES + + KYBER_INDCPA_PUBLICKEYBYTES + + 2 * KYBER_SYM_BYTES; /// The security parameter for Kyber, affecting the overall security level. /// @@ -66,13 +70,14 @@ pub const KYBER_SECRET_KEY_BYTES: usize = /// - Kyber-768 for AES-192 equivalent security (value = 3, default). /// - Kyber-1024 for AES-256 equivalent security (value = 4). /// For more details, refer to the Kyber documentation: -pub const KYBER_SECURITY_PARAMETER: usize = if cfg!(feature = "kyber512") { - 2 -} else if cfg!(feature = "kyber1024") { - 4 -} else { - 3 -}; +pub const KYBER_SECURITY_PARAMETER: usize = + if cfg!(feature = "kyber512") { + 2 + } else if cfg!(feature = "kyber1024") { + 4 + } else { + 3 + }; /// Size in bytes of shared secrets generated by Kyber KEM. /// @@ -94,12 +99,14 @@ pub const KYBER_POLYCOMPRESSEDBYTES: usize = 160; /// /// - Affects how polynomial vector data is compressed in the Kyber1024 variant. #[cfg(feature = "kyber1024")] -pub const KYBER_POLYVECCOMPRESSEDBYTES: usize = KYBER_SECURITY_PARAMETER * 352; +pub const KYBER_POLYVECCOMPRESSEDBYTES: usize = + KYBER_SECURITY_PARAMETER * 352; /// Byte size of the IND-CPA public key in Kyber. /// /// - This constant is used to allocate memory for storing and transmitting public keys. -pub const KYBER_INDCPA_PUBLICKEYBYTES: usize = KYBER_POLYVECBYTES + KYBER_SYM_BYTES; +pub const KYBER_INDCPA_PUBLICKEYBYTES: usize = + KYBER_POLYVECBYTES + KYBER_SYM_BYTES; /// Byte size of the IND-CPA secret key in Kyber. /// @@ -109,7 +116,8 @@ pub const KYBER_INDCPA_SECRETKEYBYTES: usize = KYBER_POLYVECBYTES; /// Total byte size of the IND-CPA data in Kyber. /// /// - It includes the sizes of compressed polynomial vectors and compressed polynomials. -pub const KYBER_INDCPA_BYTES: usize = KYBER_POLYVECCOMPRESSEDBYTES + KYBER_POLYCOMPRESSEDBYTES; +pub const KYBER_INDCPA_BYTES: usize = + KYBER_POLYVECCOMPRESSEDBYTES + KYBER_POLYCOMPRESSEDBYTES; /// Size in bytes of a public key in Kyber KEM. /// diff --git a/src/reference/aes256ctr.rs b/src/reference/aes256ctr.rs index 927d10b..7381c4a 100644 --- a/src/reference/aes256ctr.rs +++ b/src/reference/aes256ctr.rs @@ -48,7 +48,10 @@ impl Default for Aes256CtrCtx { } fn br_dec32le(src: &[u8]) -> u32 { - src[0] as u32 | (src[1] as u32) << 8 | (src[2] as u32) << 16 | (src[3] as u32) << 24 + src[0] as u32 + | (src[1] as u32) << 8 + | (src[2] as u32) << 16 + | (src[3] as u32) << 24 } fn br_range_dec32le(v: &mut [u32], mut num: usize, src: &[u8]) { @@ -92,8 +95,27 @@ fn br_aes_ct64_bitslice_sbox(q: &mut [u64]) { // to cryptology" (https://eprint.iacr.org/2009/191.pdf). // Note that variables x(input) and s(output) are numbered // in "reverse" order (x0 is the high bit, x7 is the low bit). - let (x0, x1, x2, x3, x4, x5, x6, x7): (u64, u64, u64, u64, u64, u64, u64, u64); - let (y1, y2, y3, y4, y5, y6, y7, y8, y9): (u64, u64, u64, u64, u64, u64, u64, u64, u64); + let (x0, x1, x2, x3, x4, x5, x6, x7): ( + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + ); + let (y1, y2, y3, y4, y5, y6, y7, y8, y9): ( + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + ); let (y10, y11, y12, y13, y14, y15, y16, y17, y18, y19): ( u64, u64, @@ -119,7 +141,16 @@ fn br_aes_ct64_bitslice_sbox(q: &mut [u64]) { u64, u64, ); - let (z10, z11, z12, z13, z14, z15, z16, z17): (u64, u64, u64, u64, u64, u64, u64, u64); + let (z10, z11, z12, z13, z14, z15, z16, z17): ( + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + ); let (t0, t1, t2, t3, t4, t5, t6, t7, t8, t9): ( u64, u64, @@ -192,8 +223,26 @@ fn br_aes_ct64_bitslice_sbox(q: &mut [u64]) { u64, u64, ); - let (t60, t61, t62, t63, t64, t65, t66, t67): (u64, u64, u64, u64, u64, u64, u64, u64); - let (s0, s1, s2, s3, s4, s5, s6, s7): (u64, u64, u64, u64, u64, u64, u64, u64); + let (t60, t61, t62, t63, t64, t65, t66, t67): ( + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + ); + let (s0, s1, s2, s3, s4, s5, s6, s7): ( + u64, + u64, + u64, + u64, + u64, + u64, + u64, + u64, + ); x0 = q[7]; x1 = q[6]; @@ -430,7 +479,8 @@ fn sub_word(x: u32) -> u32 { q[0] as u32 } -const RCON: [u32; 10] = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36]; +const RCON: [u32; 10] = + [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36]; fn br_aes_ct64_keysched(comp_skey: &mut [u64], key: &[u8]) { let (mut j, mut k) = (0usize, 0usize); @@ -578,7 +628,11 @@ fn aes_ctr4x(out: &mut [u8], ivw: &mut [u32], sk_exp: &[u64]) { let mut q = [0u64; 8]; let (q0, q1) = q.split_at_mut(4); for i in 0..4 { - br_aes_ct64_interleave_in(&mut q0[i], &mut q1[i], &w[(i << 2)..]); + br_aes_ct64_interleave_in( + &mut q0[i], + &mut q1[i], + &w[(i << 2)..], + ); } br_aes_ct64_ortho(&mut q); @@ -613,7 +667,13 @@ fn br_aes_ct64_ctr_init(sk_exp: &mut [u64], key: &[u8]) { } #[cfg(not(feature = "90s-fixslice"))] -fn br_aes_ct64_ctr_run(sk_exp: &mut [u64], iv: &[u8], cc: u32, data: &mut [u8], mut len: usize) { +fn br_aes_ct64_ctr_run( + sk_exp: &mut [u64], + iv: &[u8], + cc: u32, + data: &mut [u8], + mut len: usize, +) { let mut ivw = [0u32; 16]; br_range_dec32le(&mut ivw, 3, iv); let mut slice = [0u32; 3]; @@ -649,7 +709,12 @@ fn br_aes_ct64_ctr_run(sk_exp: &mut [u64], iv: &[u8], cc: u32, data: &mut [u8], /// - const [u8] key: 32-byte key /// - const u8 nonce: 1-byte nonce (will be zero-padded to 12 bytes) #[cfg(not(feature = "90s-fixslice"))] -pub(crate) fn aes256ctr_prf(output: &mut [u8], outlen: usize, key: &[u8], nonce: u8) { +pub(crate) fn aes256ctr_prf( + output: &mut [u8], + outlen: usize, + key: &[u8], + nonce: u8, +) { let mut sk_exp = [0u64; 120]; let mut pad_nonce = [0u8; 12]; pad_nonce[0] = nonce; @@ -666,7 +731,11 @@ pub(crate) fn aes256ctr_prf(output: &mut [u8], outlen: usize, key: &[u8], nonce: /// Arguments: - aes256xof_ctx *s: state to "absorb" key and IV into /// - const [u8] key: 32-byte key /// - [u8] nonce: additional bytes to "absorb" -pub(crate) fn aes256ctr_init(s: &mut Aes256CtrCtx, key: &[u8], nonce: [u8; 12]) { +pub(crate) fn aes256ctr_init( + s: &mut Aes256CtrCtx, + key: &[u8], + nonce: [u8; 12], +) { br_aes_ct64_ctr_init(&mut s.sk_exp, key); br_range_dec32le(&mut s.ivw, 3, &nonce); @@ -681,7 +750,11 @@ pub(crate) fn aes256ctr_init(s: &mut Aes256CtrCtx, key: &[u8], nonce: [u8; 12]) s.ivw[15] = br_swap32(3); } -pub(crate) fn aes256ctr_squeezeblocks(out: &mut [u8], mut nblocks: usize, s: &mut Aes256CtrCtx) { +pub(crate) fn aes256ctr_squeezeblocks( + out: &mut [u8], + mut nblocks: usize, + s: &mut Aes256CtrCtx, +) { let mut idx = 0; while nblocks > 0 { aes_ctr4x(&mut out[idx..], &mut s.ivw, &s.sk_exp); diff --git a/src/reference/fips202.rs b/src/reference/fips202.rs index 62cdc04..cde2370 100644 --- a/src/reference/fips202.rs +++ b/src/reference/fips202.rs @@ -330,7 +330,12 @@ pub(crate) fn keccakf1600_statepermute(state: &mut [u64]) { /// - u64 nblocks: number of blocks to be squeezed (written to h) /// - u64 *s: in/output Keccak state /// - usize r: rate in bytes (e.g., 168 for SHAKE128) -pub(crate) fn keccak_squeezeblocks(h: &mut [u8], mut nblocks: usize, s: &mut [u64], r: usize) { +pub(crate) fn keccak_squeezeblocks( + h: &mut [u8], + mut nblocks: usize, + s: &mut [u64], + r: usize, +) { let mut idx = 0usize; while nblocks > 0 { keccakf1600_statepermute(s); @@ -352,7 +357,11 @@ pub(crate) fn keccak_squeezeblocks(h: &mut [u8], mut nblocks: usize, s: &mut [u6 /// Arguments: - [u8] out: pointer to output blocks /// - u64 nblocks: number of blocks to be squeezed (written to output) /// - KeccakState state: pointer to input/output Keccak state -pub(crate) fn shake128_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut KeccakState) { +pub(crate) fn shake128_squeezeblocks( + out: &mut [u8], + nblocks: usize, + state: &mut KeccakState, +) { keccak_squeezeblocks(out, nblocks, &mut state.s, SHAKE128_RATE); } @@ -364,7 +373,12 @@ pub(crate) fn shake128_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut /// - usize outlen: requested output length in bytes /// - [u8] input: input /// - usize inlen: length of input in bytes -pub(crate) fn shake256(out: &mut [u8], mut outlen: usize, input: &[u8], inlen: usize) { +pub(crate) fn shake256( + out: &mut [u8], + mut outlen: usize, + input: &[u8], + inlen: usize, +) { let mut state = KeccakState::new(); let mut idx = 0; shake256_absorb_once(&mut state, input, inlen); @@ -430,7 +444,13 @@ fn keccak_finalize(s: &mut [u64], pos: usize, r: usize, p: u8) { /// - const [u8] input: input to be absorbed into s /// - u64 mlen: length of input in bytes /// - [u8] p: domain-separation byte for different Keccak-derived functions -pub(crate) fn keccak_absorb_once(s: &mut [u64], r: usize, input: &[u8], mut inlen: usize, p: u8) { +pub(crate) fn keccak_absorb_once( + s: &mut [u64], + r: usize, + input: &[u8], + mut inlen: usize, + p: u8, +) { // Zero State s.fill(0); @@ -517,8 +537,18 @@ fn shake128_finalize(state: &mut KeccakState) { /// Arguments: - [u8] out: pointer to output blocks /// - usize outlen : number of bytes to be squeezed (written to output) /// - keccak_state s: pointer to input/output Keccak state -fn shake128_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) { - state.pos = keccak_squeeze(out, outlen, &mut state.s, state.pos, SHAKE128_RATE); +fn shake128_squeeze( + out: &mut [u8], + outlen: usize, + state: &mut KeccakState, +) { + state.pos = keccak_squeeze( + out, + outlen, + &mut state.s, + state.pos, + SHAKE128_RATE, + ); } /// Name: shake128_absorb_once @@ -528,7 +558,11 @@ fn shake128_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) { /// Arguments: - keccak_state state: pointer to (uninitialized) output Keccak state /// - const [u8] in: input to be absorbed into s /// - usize inlen: length of input in bytes -pub(crate) fn shake128_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize) { +pub(crate) fn shake128_absorb_once( + state: &mut KeccakState, + input: &[u8], + inlen: usize, +) { keccak_absorb_once(&mut state.s, SHAKE128_RATE, input, inlen, 0x1F); state.pos = SHAKE128_RATE; } @@ -542,20 +576,43 @@ fn shake256_finalize(state: &mut KeccakState) { state.pos = SHAKE256_RATE; } -fn shake256_squeeze(out: &mut [u8], outlen: usize, state: &mut KeccakState) { - state.pos = keccak_squeeze(out, outlen, &mut state.s, state.pos, SHAKE256_RATE); +fn shake256_squeeze( + out: &mut [u8], + outlen: usize, + state: &mut KeccakState, +) { + state.pos = keccak_squeeze( + out, + outlen, + &mut state.s, + state.pos, + SHAKE256_RATE, + ); } -fn shake256_absorb_once(state: &mut KeccakState, input: &[u8], inlen: usize) { +fn shake256_absorb_once( + state: &mut KeccakState, + input: &[u8], + inlen: usize, +) { keccak_absorb_once(&mut state.s, SHAKE256_RATE, input, inlen, 0x1F); state.pos = SHAKE256_RATE; } -fn shake256_squeezeblocks(out: &mut [u8], nblocks: usize, state: &mut KeccakState) { +fn shake256_squeezeblocks( + out: &mut [u8], + nblocks: usize, + state: &mut KeccakState, +) { keccak_squeezeblocks(out, nblocks, &mut state.s, SHAKE256_RATE); } -fn shake128(out: &mut [u8], mut outlen: usize, input: &[u8], inlen: usize) { +fn shake128( + out: &mut [u8], + mut outlen: usize, + input: &[u8], + inlen: usize, +) { let mut state = KeccakState::new(); let mut idx = 0; shake128_absorb_once(&mut state, input, inlen); diff --git a/src/reference/indcpa.rs b/src/reference/indcpa.rs index 5e4c33f..4a6939c 100644 --- a/src/reference/indcpa.rs +++ b/src/reference/indcpa.rs @@ -1,5 +1,8 @@ use crate::rng::randombytes; -use crate::{params::*, poly::*, polyvec::*, symmetric::*, CryptoRng, KyberLibError, RngCore}; +use crate::{ + params::*, poly::*, polyvec::*, symmetric::*, CryptoRng, + KyberLibError, RngCore, +}; /// Name: pack_pk /// @@ -13,7 +16,8 @@ use crate::{params::*, poly::*, polyvec::*, symmetric::*, CryptoRng, KyberLibErr fn pack_pk(r: &mut [u8], pk: &mut Polyvec, seed: &[u8]) { const END: usize = KYBER_SYM_BYTES + KYBER_POLYVECBYTES; polyvec_tobytes(r, pk); - r[KYBER_POLYVECBYTES..END].copy_from_slice(&seed[..KYBER_SYM_BYTES]); + r[KYBER_POLYVECBYTES..END] + .copy_from_slice(&seed[..KYBER_SYM_BYTES]); } /// Name: unpack_pk @@ -27,7 +31,8 @@ fn pack_pk(r: &mut [u8], pk: &mut Polyvec, seed: &[u8]) { fn unpack_pk(pk: &mut Polyvec, seed: &mut [u8], packedpk: &[u8]) { const END: usize = KYBER_SYM_BYTES + KYBER_POLYVECBYTES; polyvec_frombytes(pk, packedpk); - seed[..KYBER_SYM_BYTES].copy_from_slice(&packedpk[KYBER_POLYVECBYTES..END]); + seed[..KYBER_SYM_BYTES] + .copy_from_slice(&packedpk[KYBER_POLYVECBYTES..END]); } /// Name: pack_sk @@ -88,13 +93,20 @@ fn unpack_ciphertext(b: &mut Polyvec, v: &mut Poly, c: &[u8]) { /// - usize buflen: length of input buffer in bytes /// /// Returns number of sampled 16-bit integers (at most len) -fn rej_uniform(r: &mut [i16], len: usize, buf: &[u8], buflen: usize) -> usize { +fn rej_uniform( + r: &mut [i16], + len: usize, + buf: &[u8], + buflen: usize, +) -> usize { let (mut ctr, mut pos) = (0usize, 0usize); let (mut val0, mut val1); while ctr < len && pos + 3 <= buflen { val0 = (buf[pos] as u16 | (buf[pos + 1] as u16) << 8) & 0xFFF; - val1 = ((buf[pos + 1] >> 4) as u16 | (buf[pos + 2] as u16) << 4) & 0xFFF; + val1 = ((buf[pos + 1] >> 4) as u16 + | (buf[pos + 2] as u16) << 4) + & 0xFFF; pos += 3; if val0 < KYBER_Q as u16 { @@ -131,7 +143,8 @@ fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) { let mut ctr; // 530 is expected number of required bytes const GEN_MATRIX_NBLOCKS: usize = - (12 * KYBER_N / 8 * (1 << 12) / KYBER_Q + XOF_BLOCKBYTES) / XOF_BLOCKBYTES; + (12 * KYBER_N / 8 * (1 << 12) / KYBER_Q + XOF_BLOCKBYTES) + / XOF_BLOCKBYTES; let mut buf = [0u8; GEN_MATRIX_NBLOCKS * XOF_BLOCKBYTES + 2]; let mut buflen: usize; let mut off: usize; @@ -147,7 +160,12 @@ fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) { } xof_squeezeblocks(&mut buf, GEN_MATRIX_NBLOCKS, &mut state); buflen = GEN_MATRIX_NBLOCKS * XOF_BLOCKBYTES; - ctr = rej_uniform(&mut a[i].vec[j].coeffs, KYBER_N, &buf, buflen); + ctr = rej_uniform( + &mut a[i].vec[j].coeffs, + KYBER_N, + &buf, + buflen, + ); while ctr < KYBER_N { off = buflen % 3; @@ -156,7 +174,12 @@ fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) { } xof_squeezeblocks(&mut buf[off..], 1, &mut state); buflen = off + XOF_BLOCKBYTES; - ctr += rej_uniform(&mut a[i].vec[j].coeffs[ctr..], KYBER_N - ctr, &buf, buflen); + ctr += rej_uniform( + &mut a[i].vec[j].coeffs[ctr..], + KYBER_N - ctr, + &buf, + buflen, + ); } } } @@ -179,7 +202,8 @@ where R: CryptoRng + RngCore, { let mut a = [Polyvec::new(); KYBER_SECURITY_PARAMETER]; - let (mut e, mut pkpv, mut skpv) = (Polyvec::new(), Polyvec::new(), Polyvec::new()); + let (mut e, mut pkpv, mut skpv) = + (Polyvec::new(), Polyvec::new(), Polyvec::new()); let mut nonce = 0u8; let mut buf = [0u8; 2 * KYBER_SYM_BYTES]; let mut randbuf = [0u8; 2 * KYBER_SYM_BYTES]; @@ -231,7 +255,12 @@ where /// - const [u8] pk: input public key (length KYBER_INDCPA_PUBLICKEYBYTES) /// - const [u8] coin: input random coins used as seed (length KYBER_SYM_BYTES) /// to deterministically generate all randomness -pub(crate) fn indcpa_enc(c: &mut [u8], m: &[u8], pk: &[u8], coins: &[u8]) { +pub(crate) fn indcpa_enc( + c: &mut [u8], + m: &[u8], + pk: &[u8], + coins: &[u8], +) { let mut at = [Polyvec::new(); KYBER_SECURITY_PARAMETER]; let (mut sp, mut pkpv, mut ep, mut b) = ( Polyvec::new(), @@ -239,7 +268,8 @@ pub(crate) fn indcpa_enc(c: &mut [u8], m: &[u8], pk: &[u8], coins: &[u8]) { Polyvec::new(), Polyvec::new(), ); - let (mut v, mut k, mut epp) = (Poly::new(), Poly::new(), Poly::new()); + let (mut v, mut k, mut epp) = + (Poly::new(), Poly::new(), Poly::new()); let mut seed = [0u8; KYBER_SYM_BYTES]; let mut nonce = 0u8; diff --git a/src/reference/ntt.rs b/src/reference/ntt.rs index 440dc2d..2ed0bef 100644 --- a/src/reference/ntt.rs +++ b/src/reference/ntt.rs @@ -37,14 +37,18 @@ use crate::reduce::*; //} pub(crate) const ZETAS: [i16; 128] = [ - -1044, -758, -359, -1517, 1493, 1422, 287, 202, -171, 622, 1577, 182, 962, -1202, -1474, 1468, - 573, -1325, 264, 383, -829, 1458, -1602, -130, -681, 1017, 732, 608, -1542, 411, -205, -1571, - 1223, 652, -552, 1015, -1293, 1491, -282, -1544, 516, -8, -320, -666, -1618, -1162, 126, 1469, - -853, -90, -271, 830, 107, -1421, -247, -951, -398, 961, -1508, -725, 448, -1065, 677, -1275, - -1103, 430, 555, 843, -1251, 871, 1550, 105, 422, 587, 177, -235, -291, -460, 1574, 1653, -246, - 778, 1159, -147, -777, 1483, -602, 1119, -1590, 644, -872, 349, 418, 329, -156, -75, 817, 1097, - 603, 610, 1322, -1285, -1465, 384, -1215, -136, 1218, -1335, -874, 220, -1187, -1659, -1185, - -1530, -1278, 794, -1510, -854, -870, 478, -108, -308, 996, 991, 958, -1460, 1522, 1628, + -1044, -758, -359, -1517, 1493, 1422, 287, 202, -171, 622, 1577, + 182, 962, -1202, -1474, 1468, 573, -1325, 264, 383, -829, 1458, + -1602, -130, -681, 1017, 732, 608, -1542, 411, -205, -1571, 1223, + 652, -552, 1015, -1293, 1491, -282, -1544, 516, -8, -320, -666, + -1618, -1162, 126, 1469, -853, -90, -271, 830, 107, -1421, -247, + -951, -398, 961, -1508, -725, 448, -1065, 677, -1275, -1103, 430, + 555, 843, -1251, 871, 1550, 105, 422, 587, 177, -235, -291, -460, + 1574, 1653, -246, 778, 1159, -147, -777, 1483, -602, 1119, -1590, + 644, -872, 349, 418, 329, -156, -75, 817, 1097, 603, 610, 1322, + -1285, -1465, 384, -1215, -136, 1218, -1335, -874, 220, -1187, + -1659, -1185, -1530, -1278, 794, -1510, -854, -870, 478, -108, + -308, 996, 991, 958, -1460, 1522, 1628, ]; /// Name: fqmul diff --git a/src/reference/poly.rs b/src/reference/poly.rs index fce1069..a150c8f 100644 --- a/src/reference/poly.rs +++ b/src/reference/poly.rs @@ -41,7 +41,9 @@ pub(crate) fn poly_compress(r: &mut [u8], a: Poly) { // map to positive standard representatives u = a.coeffs[8 * i + j]; u += (u >> 15) & KYBER_Q as i16; - t[j] = (((((u as u16) << 4) + KYBER_Q as u16 / 2) / KYBER_Q as u16) & 15) as u8; + t[j] = (((((u as u16) << 4) + KYBER_Q as u16 / 2) + / KYBER_Q as u16) + & 15) as u8; } r[k] = t[0] | (t[1] << 4); r[k + 1] = t[2] | (t[3] << 4); @@ -57,7 +59,9 @@ pub(crate) fn poly_compress(r: &mut [u8], a: Poly) { // map to positive standard representatives u = a.coeffs[8 * i + j]; u += (u >> 15) & KYBER_Q as i16; - t[j] = (((((u as u32) << 5) + KYBER_Q as u32 / 2) / KYBER_Q as u32) & 31) as u8; + t[j] = (((((u as u32) << 5) + KYBER_Q as u32 / 2) + / KYBER_Q as u32) + & 31) as u8; } r[k] = t[0] | (t[1] << 5); r[k + 1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); @@ -67,7 +71,9 @@ pub(crate) fn poly_compress(r: &mut [u8], a: Poly) { k += 5; } } - _ => panic!("KYBER_POLYCOMPRESSEDBYTES needs to be one of (128, 160)"), + _ => panic!( + "KYBER_POLYCOMPRESSEDBYTES needs to be one of (128, 160)" + ), } } @@ -82,8 +88,12 @@ pub(crate) fn poly_decompress(r: &mut Poly, a: &[u8]) { match KYBER_POLYCOMPRESSEDBYTES { 128 => { for (idx, i) in (0..KYBER_N / 2).enumerate() { - r.coeffs[2 * i] = ((((a[idx] & 15) as usize * KYBER_Q) + 8) >> 4) as i16; - r.coeffs[2 * i + 1] = ((((a[idx] >> 4) as usize * KYBER_Q) + 8) >> 4) as i16; + r.coeffs[2 * i] = ((((a[idx] & 15) as usize * KYBER_Q) + + 8) + >> 4) as i16; + r.coeffs[2 * i + 1] = + ((((a[idx] >> 4) as usize * KYBER_Q) + 8) >> 4) + as i16; } } 160 => { @@ -102,11 +112,14 @@ pub(crate) fn poly_decompress(r: &mut Poly, a: &[u8]) { idx += 5; for j in 0..8 { r.coeffs[8 * i + j] = - ((((t[j] as u32) & 31) * KYBER_Q as u32 + 16) >> 5) as i16; + ((((t[j] as u32) & 31) * KYBER_Q as u32 + 16) + >> 5) as i16; } } } - _ => panic!("KYBER_POLYCOMPRESSEDBYTES needs to be either (128, 160)"), + _ => panic!( + "KYBER_POLYCOMPRESSEDBYTES needs to be either (128, 160)" + ), } } @@ -140,9 +153,12 @@ pub(crate) fn poly_tobytes(r: &mut [u8], a: Poly) { /// - const [u8] a: input byte array (of KYBER_POLYBYTES bytes) pub(crate) fn poly_frombytes(r: &mut Poly, a: &[u8]) { for i in 0..(KYBER_N / 2) { - r.coeffs[2 * i] = ((a[3 * i]) as u16 | ((a[3 * i + 1] as u16) << 8) & 0xFFF) as i16; - r.coeffs[2 * i + 1] = - ((a[3 * i + 1] >> 4) as u16 | ((a[3 * i + 2] as u16) << 4) & 0xFFF) as i16; + r.coeffs[2 * i] = ((a[3 * i]) as u16 + | ((a[3 * i + 1] as u16) << 8) & 0xFFF) + as i16; + r.coeffs[2 * i + 1] = ((a[3 * i + 1] >> 4) as u16 + | ((a[3 * i + 2] as u16) << 4) & 0xFFF) + as i16; } } @@ -294,7 +310,8 @@ pub(crate) fn poly_frommsg(r: &mut Poly, msg: &[u8]) { for i in 0..KYBER_N / 8 { for j in 0..8 { mask = ((msg[i] as u16 >> j) & 1).wrapping_neg(); - r.coeffs[8 * i + j] = (mask & ((KYBER_Q + 1) / 2) as u16) as i16; + r.coeffs[8 * i + j] = + (mask & ((KYBER_Q + 1) / 2) as u16) as i16; } } } diff --git a/src/reference/polyvec.rs b/src/reference/polyvec.rs index 9e15939..8b90618 100644 --- a/src/reference/polyvec.rs +++ b/src/reference/polyvec.rs @@ -31,9 +31,13 @@ pub(crate) fn polyvec_compress(r: &mut [u8], a: Polyvec) { for j in 0..KYBER_N / 8 { for k in 0..8 { t[k] = a.vec[i].coeffs[8 * j + k] as u16; - t[k] = t[k].wrapping_add((((t[k] as i16) >> 15) & KYBER_Q as i16) as u16); - t[k] = (((((t[k] as u32) << 11) + KYBER_Q as u32 / 2) / KYBER_Q as u32) & 0x7ff) - as u16; + t[k] = t[k].wrapping_add( + (((t[k] as i16) >> 15) & KYBER_Q as i16) as u16, + ); + t[k] = (((((t[k] as u32) << 11) + + KYBER_Q as u32 / 2) + / KYBER_Q as u32) + & 0x7ff) as u16; } r[idx] = (t[0]) as u8; r[idx + 1] = ((t[0] >> 8) | (t[1] << 3)) as u8; @@ -59,8 +63,13 @@ pub(crate) fn polyvec_compress(r: &mut [u8], a: Polyvec) { for j in 0..KYBER_N / 4 { for (k, item) in t.iter_mut().enumerate() { *item = a.vec[i].coeffs[4 * j + k] as u16; - *item = item.wrapping_add((((*item as i16) >> 15) & KYBER_Q as i16) as u16); - *item = (((((*item as u32) << 10) + KYBER_Q as u32 / 2) / KYBER_Q as u32) + *item = item.wrapping_add( + (((*item as i16) >> 15) & KYBER_Q as i16) + as u16, + ); + *item = (((((*item as u32) << 10) + + KYBER_Q as u32 / 2) + / KYBER_Q as u32) & 0x3ff) as u16; } r[idx] = (t[0]) as u8; @@ -89,20 +98,29 @@ pub(crate) fn polyvec_decompress(r: &mut Polyvec, a: &[u8]) { for i in 0..KYBER_SECURITY_PARAMETER { for j in 0..KYBER_N / 8 { t[0] = (a[idx]) as u16 | (a[idx + 1] as u16) << 8; - t[1] = (a[idx + 1] >> 3) as u16 | (a[idx + 2] as u16) << 5; - t[2] = - (a[idx + 2] >> 6) as u16 | (a[idx + 3] as u16) << 2 | (a[idx + 4] as u16) << 10; - t[3] = (a[idx + 4] >> 1) as u16 | (a[idx + 5] as u16) << 7; - t[4] = (a[idx + 5] >> 4) as u16 | (a[idx + 6] as u16) << 4; - t[5] = - (a[idx + 6] >> 7) as u16 | (a[idx + 7] as u16) << 1 | (a[idx + 8] as u16) << 9; - t[6] = (a[idx + 8] >> 2) as u16 | (a[idx + 9] as u16) << 6; - t[7] = (a[idx + 9] >> 5) as u16 | (a[idx + 10] as u16) << 3; + t[1] = + (a[idx + 1] >> 3) as u16 | (a[idx + 2] as u16) << 5; + t[2] = (a[idx + 2] >> 6) as u16 + | (a[idx + 3] as u16) << 2 + | (a[idx + 4] as u16) << 10; + t[3] = + (a[idx + 4] >> 1) as u16 | (a[idx + 5] as u16) << 7; + t[4] = + (a[idx + 5] >> 4) as u16 | (a[idx + 6] as u16) << 4; + t[5] = (a[idx + 6] >> 7) as u16 + | (a[idx + 7] as u16) << 1 + | (a[idx + 8] as u16) << 9; + t[6] = + (a[idx + 8] >> 2) as u16 | (a[idx + 9] as u16) << 6; + t[7] = (a[idx + 9] >> 5) as u16 + | (a[idx + 10] as u16) << 3; idx += 11; for k in 0..8 { r.vec[i].coeffs[8 * j + k] = - (((t[k] & 0x7FF) as u32 * KYBER_Q as u32 + 1024) >> 11) as i16; + (((t[k] & 0x7FF) as u32 * KYBER_Q as u32 + + 1024) + >> 11) as i16; } } } @@ -115,14 +133,19 @@ pub(crate) fn polyvec_decompress(r: &mut Polyvec, a: &[u8]) { for i in 0..KYBER_SECURITY_PARAMETER { for j in 0..KYBER_N / 4 { t[0] = (a[idx]) as u16 | (a[idx + 1] as u16) << 8; - t[1] = (a[idx + 1] >> 2) as u16 | (a[idx + 2] as u16) << 6; - t[2] = (a[idx + 2] >> 4) as u16 | (a[idx + 3] as u16) << 4; - t[3] = (a[idx + 3] >> 6) as u16 | (a[idx + 4] as u16) << 2; + t[1] = + (a[idx + 1] >> 2) as u16 | (a[idx + 2] as u16) << 6; + t[2] = + (a[idx + 2] >> 4) as u16 | (a[idx + 3] as u16) << 4; + t[3] = + (a[idx + 3] >> 6) as u16 | (a[idx + 4] as u16) << 2; idx += 5; for (k, item) in t.iter().enumerate() { r.vec[i].coeffs[4 * j + k] = - ((((*item as u32) & 0x3FF) * KYBER_Q as u32 + 512) >> 10) as i16; + ((((*item as u32) & 0x3FF) * KYBER_Q as u32 + + 512) + >> 10) as i16; } } } @@ -183,7 +206,11 @@ pub(crate) fn polyvec_invntt_tomont(r: &mut Polyvec) { /// Arguments: - poly *r: output polynomial /// - const Polyvec a: first input vector of polynomials /// - const Polyvec b: second input vector of polynomials -pub(crate) fn polyvec_basemul_acc_montgomery(r: &mut Poly, a: &Polyvec, b: &Polyvec) { +pub(crate) fn polyvec_basemul_acc_montgomery( + r: &mut Poly, + a: &Polyvec, + b: &Polyvec, +) { let mut t = Poly::new(); poly_basemul(r, &a.vec[0], &b.vec[0]); for i in 1..KYBER_SECURITY_PARAMETER { diff --git a/src/rng.rs b/src/rng.rs index f3a56ae..b0008e4 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -36,7 +36,11 @@ use rand_core::{CryptoRng, RngCore}; /// /// Ensure that the length of the buffer `x` is at least `len` bytes, /// otherwise the function will panic due to out-of-bounds memory access. -pub fn randombytes(x: &mut [u8], len: usize, rng: &mut R) -> Result<(), KyberLibError> +pub fn randombytes( + x: &mut [u8], + len: usize, + rng: &mut R, +) -> Result<(), KyberLibError> where R: RngCore + CryptoRng, { diff --git a/src/symmetric.rs b/src/symmetric.rs index a281551..9841bb6 100644 --- a/src/symmetric.rs +++ b/src/symmetric.rs @@ -11,7 +11,9 @@ use crate::{fips202::*, params::*}; use sha2::{Digest, Sha256, Sha512}; #[cfg(feature = "90s-fixslice")] -use aes::cipher::{generic_array::GenericArray, KeyIvInit, StreamCipher}; +use aes::cipher::{ + generic_array::GenericArray, KeyIvInit, StreamCipher, +}; #[cfg(feature = "90s-fixslice")] type Aes256Ctr = ctr::Ctr32BE; @@ -111,13 +113,21 @@ pub fn xof_absorb(state: &mut XofState, input: &[u8], x: u8, y: u8) { /// Squeezes XOF data into output in non-90s mode #[cfg(not(feature = "90s"))] -pub fn xof_squeezeblocks(out: &mut [u8], outblocks: usize, state: &mut XofState) { +pub fn xof_squeezeblocks( + out: &mut [u8], + outblocks: usize, + state: &mut XofState, +) { kyber_shake128_squeezeblocks(out, outblocks, state); } /// Squeezes XOF data into output in 90s mode #[cfg(feature = "90s")] -pub fn xof_squeezeblocks(out: &mut [u8], outblocks: usize, state: &mut XofState) { +pub fn xof_squeezeblocks( + out: &mut [u8], + outblocks: usize, + state: &mut XofState, +) { aes256ctr_squeezeblocks(out, outblocks, state); } @@ -162,7 +172,12 @@ pub fn kdf(out: &mut [u8], input: &[u8], inlen: usize) { /// Absorb step of the SHAKE128 specialized for the Kyber context #[cfg(not(feature = "90s"))] -pub fn kyber_shake128_absorb(s: &mut KeccakState, input: &[u8], x: u8, y: u8) { +pub fn kyber_shake128_absorb( + s: &mut KeccakState, + input: &[u8], + x: u8, + y: u8, +) { let mut extseed = [0u8; KYBER_SYM_BYTES + 2]; extseed[..KYBER_SYM_BYTES].copy_from_slice(input); extseed[KYBER_SYM_BYTES] = x; @@ -172,13 +187,22 @@ pub fn kyber_shake128_absorb(s: &mut KeccakState, input: &[u8], x: u8, y: u8) { /// Squeeze step of SHAKE128 XOF in non-90s mode #[cfg(not(feature = "90s"))] -pub fn kyber_shake128_squeezeblocks(output: &mut [u8], nblocks: usize, s: &mut KeccakState) { +pub fn kyber_shake128_squeezeblocks( + output: &mut [u8], + nblocks: usize, + s: &mut KeccakState, +) { shake128_squeezeblocks(output, nblocks, s); } /// Usage of SHAKE256 as a PRF in non-90s mode #[cfg(not(feature = "90s"))] -pub fn shake256_prf(output: &mut [u8], outlen: usize, key: &[u8], nonce: u8) { +pub fn shake256_prf( + output: &mut [u8], + outlen: usize, + key: &[u8], + nonce: u8, +) { let mut extkey = [0u8; KYBER_SYM_BYTES + 1]; extkey[..KYBER_SYM_BYTES].copy_from_slice(key); extkey[KYBER_SYM_BYTES] = nonce; diff --git a/src/wasm.rs b/src/wasm.rs index 25f0cfe..d8ce294 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -66,8 +66,13 @@ pub fn encapsulate(pk: Box<[u8]>) -> Result { /// /// Returns a `JsValue` that is `null()` if the input sizes are incorrect or if an error occurs during decapsulation. #[wasm_bindgen] -pub fn decapsulate(ct: Box<[u8]>, sk: Box<[u8]>) -> Result, JsValue> { - if ct.len() != KYBER_CIPHERTEXT_BYTES || sk.len() != KYBER_SECRET_KEY_BYTES { +pub fn decapsulate( + ct: Box<[u8]>, + sk: Box<[u8]>, +) -> Result, JsValue> { + if ct.len() != KYBER_CIPHERTEXT_BYTES + || sk.len() != KYBER_SECRET_KEY_BYTES + { return Err(JsValue::null()); } diff --git a/tests/test_api.rs b/tests/test_api.rs index 121b592..eb40b57 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -31,9 +31,11 @@ mod tests { // Generate keypair let keypair = keypair(&mut rng).unwrap(); // Encapsulate a shared secret - let (ciphertext, shared_secret1) = encapsulate(&keypair.public, &mut rng).unwrap(); + let (ciphertext, shared_secret1) = + encapsulate(&keypair.public, &mut rng).unwrap(); // Decapsulate the shared secret - let shared_secret2 = decapsulate(&ciphertext, &keypair.secret).unwrap(); + let shared_secret2 = + decapsulate(&ciphertext, &keypair.secret).unwrap(); // Assert equality of the shared secrets assert_eq!(shared_secret1, shared_secret2); } @@ -112,7 +114,9 @@ mod tests { let mut public_key = keypair.public; let mut secret_key = keypair.secret; // Import keypair using Keypair::import - let imported_keypair = Keypair::import(&mut public_key, &mut secret_key, &mut rng).unwrap(); + let imported_keypair = + Keypair::import(&mut public_key, &mut secret_key, &mut rng) + .unwrap(); // Assert equality of the imported keypair and the original keypair assert_eq!(imported_keypair.public, keypair.public); assert_eq!(imported_keypair.secret, keypair.secret); @@ -129,7 +133,9 @@ mod tests { let mut public_key = keypair.public; let mut secret_key = keypair.secret; // Create keypair using keypairfrom - let new_keypair = keypairfrom(&mut public_key, &mut secret_key, &mut rng).unwrap(); + let new_keypair = + keypairfrom(&mut public_key, &mut secret_key, &mut rng) + .unwrap(); // Assert equality of the new keypair and the original keypair assert_eq!(new_keypair.public, keypair.public); assert_eq!(new_keypair.secret, keypair.secret); @@ -147,7 +153,12 @@ mod tests { invalid_public_key[0] = 0xFF; invalid_secret_key[0] = 0xFF; // Assert error handling for keypairfrom with invalid public key and secret key - assert!(keypairfrom(&mut invalid_public_key, &mut invalid_secret_key, &mut rng).is_err()); + assert!(keypairfrom( + &mut invalid_public_key, + &mut invalid_secret_key, + &mut rng + ) + .is_err()); } // Test for handling of invalid inputs in Keypair::import @@ -162,9 +173,12 @@ mod tests { invalid_public_key[0] = 0xFF; invalid_secret_key[0] = 0xFF; // Assert error handling for Keypair::import with invalid public key and secret key - assert!( - Keypair::import(&mut invalid_public_key, &mut invalid_secret_key, &mut rng).is_err() - ); + assert!(Keypair::import( + &mut invalid_public_key, + &mut invalid_secret_key, + &mut rng + ) + .is_err()); } // Test for handling of invalid inputs in Keypair::generate @@ -204,8 +218,11 @@ mod tests { let invalid_ciphertext = [0u8; KYBER_CIPHERTEXT_BYTES - 1]; let invalid_secret_key = [0u8; KYBER_SECRET_KEY_BYTES - 1]; // Assert error handling for decapsulate with invalid ciphertext and secret key - assert!(decapsulate(&invalid_ciphertext, &keypair.secret).is_err()); - assert!(decapsulate(&invalid_ciphertext, &invalid_secret_key).is_err()); + assert!( + decapsulate(&invalid_ciphertext, &keypair.secret).is_err() + ); + assert!(decapsulate(&invalid_ciphertext, &invalid_secret_key) + .is_err()); } // Test for handling of invalid inputs in derive @@ -221,7 +238,10 @@ mod tests { #[test] fn test_public_invalid_secret_key_length() { let invalid_secret_key = [0u8; KYBER_SECRET_KEY_BYTES - 1]; - assert_eq!(public(&invalid_secret_key).len(), KYBER_PUBLIC_KEY_BYTES); + assert_eq!( + public(&invalid_secret_key).len(), + KYBER_PUBLIC_KEY_BYTES + ); } // Test for keypair equality @@ -248,10 +268,12 @@ mod tests { fn test_encapsulate_decapsulate_valid_input() { let mut rng = OsRng; let keypair = keypair(&mut rng).unwrap(); - let (ciphertext, shared_secret) = encapsulate(&keypair.public, &mut rng).unwrap(); + let (ciphertext, shared_secret) = + encapsulate(&keypair.public, &mut rng).unwrap(); assert_eq!(ciphertext.len(), KYBER_CIPHERTEXT_BYTES); assert_eq!(shared_secret.len(), KYBER_SHARED_SECRET_BYTES); - let decapsulated_secret = decapsulate(&ciphertext, &keypair.secret).unwrap(); + let decapsulated_secret = + decapsulate(&ciphertext, &keypair.secret).unwrap(); assert_eq!(shared_secret, decapsulated_secret); } } diff --git a/tests/test_error.rs b/tests/test_error.rs index 5ef88de..53de552 100644 --- a/tests/test_error.rs +++ b/tests/test_error.rs @@ -12,7 +12,10 @@ use kyberlib::KyberLibError; #[test] fn test_kyber_lib_error_display() { let error = KyberLibError::InvalidInput; - assert_eq!(error.to_string(), "Function input is of incorrect length"); + assert_eq!( + error.to_string(), + "Function input is of incorrect length" + ); let error = KyberLibError::Decapsulation; assert_eq!( @@ -21,5 +24,8 @@ fn test_kyber_lib_error_display() { ); let error = KyberLibError::RandomBytesGeneration; - assert_eq!(error.to_string(), "Random bytes generation function failed"); + assert_eq!( + error.to_string(), + "Random bytes generation function failed" + ); } diff --git a/tests/test_kat.rs b/tests/test_kat.rs index 4ba0556..822b926 100644 --- a/tests/test_kat.rs +++ b/tests/test_kat.rs @@ -36,8 +36,13 @@ fn encaps() { let encap_buf = Some(&buf1[..]); let mut ct = [0u8; KYBER_CIPHERTEXT_BYTES]; let mut ss = [0u8; KYBER_SHARED_SECRET_BYTES]; - encrypt_message(&mut ct, &mut ss, &pk, &mut _rng, encap_buf).unwrap(); - assert_eq!(&ss[..], &known_ss[..], "Shared secret KAT mismatch"); + encrypt_message(&mut ct, &mut ss, &pk, &mut _rng, encap_buf) + .unwrap(); + assert_eq!( + &ss[..], + &known_ss[..], + "Shared secret KAT mismatch" + ); } } @@ -73,6 +78,9 @@ pub fn encode_hex(bytes: &[u8]) -> String { pub fn decode_hex(s: &str) -> Vec { (0..s.len()) .step_by(2) - .map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("Hex string decoding")) + .map(|i| { + u8::from_str_radix(&s[i..i + 2], 16) + .expect("Hex string decoding") + }) .collect::>() } diff --git a/tests/test_kem.rs b/tests/test_kem.rs index 97fae89..ba927a2 100644 --- a/tests/test_kem.rs +++ b/tests/test_kem.rs @@ -16,7 +16,8 @@ fn keypair_encap_decap() { fn keypair_import_fake() { let mut rng = rand::thread_rng(); let mut keys = keypair(&mut rng).unwrap(); - let key = keypairfrom(&mut keys.public, &mut keys.secret, &mut rng).unwrap(); + let key = keypairfrom(&mut keys.public, &mut keys.secret, &mut rng) + .unwrap(); assert_eq!(keys.public, key.public); } @@ -32,28 +33,39 @@ fn keypair_encap_decap_invalid_ciphertext() { #[test] fn keypair_encap_pk_wrong_size() { let mut rng = rand::thread_rng(); - let pk: [u8; KYBER_PUBLIC_KEY_BYTES + 3] = [1u8; KYBER_PUBLIC_KEY_BYTES + 3]; - assert_eq!(encapsulate(&pk, &mut rng), Err(KyberLibError::InvalidInput)); + let pk: [u8; KYBER_PUBLIC_KEY_BYTES + 3] = + [1u8; KYBER_PUBLIC_KEY_BYTES + 3]; + assert_eq!( + encapsulate(&pk, &mut rng), + Err(KyberLibError::InvalidInput) + ); } #[test] fn keypair_decap_ct_wrong_size() { - let ct: [u8; KYBER_CIPHERTEXT_BYTES + 3] = [1u8; KYBER_CIPHERTEXT_BYTES + 3]; - let sk: [u8; KYBER_SECRET_KEY_BYTES] = [1u8; KYBER_SECRET_KEY_BYTES]; + let ct: [u8; KYBER_CIPHERTEXT_BYTES + 3] = + [1u8; KYBER_CIPHERTEXT_BYTES + 3]; + let sk: [u8; KYBER_SECRET_KEY_BYTES] = + [1u8; KYBER_SECRET_KEY_BYTES]; assert_eq!(decapsulate(&ct, &sk), Err(KyberLibError::InvalidInput)); } #[test] fn keypair_decap_sk_wrong_size() { - let ct: [u8; KYBER_CIPHERTEXT_BYTES] = [1u8; KYBER_CIPHERTEXT_BYTES]; - let sk: [u8; KYBER_SECRET_KEY_BYTES + 3] = [1u8; KYBER_SECRET_KEY_BYTES + 3]; + let ct: [u8; KYBER_CIPHERTEXT_BYTES] = + [1u8; KYBER_CIPHERTEXT_BYTES]; + let sk: [u8; KYBER_SECRET_KEY_BYTES + 3] = + [1u8; KYBER_SECRET_KEY_BYTES + 3]; assert_eq!(decapsulate(&ct, &sk), Err(KyberLibError::InvalidInput)); } #[test] fn keypair_failed_randombytes() { let mut rng = FailingRng::default(); - assert_eq!(keypair(&mut rng), Err(KyberLibError::RandomBytesGeneration)); + assert_eq!( + keypair(&mut rng), + Err(KyberLibError::RandomBytesGeneration) + ); } #[test] diff --git a/tests/test_kex.rs b/tests/test_kex.rs index a568743..4a4ff37 100644 --- a/tests/test_kex.rs +++ b/tests/test_kex.rs @@ -9,7 +9,8 @@ fn uake_valid() { let mut alice = Uake::new(); let mut bob = Uake::new(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob .server_receive(client_init, &bob_keys.secret, &mut rng) .unwrap(); @@ -24,8 +25,10 @@ fn uake_invalid_client_init_ciphertext() { let mut alice = Uake::new(); let mut bob = Uake::new(); let bob_keys = keypair(&mut rng).unwrap(); - let mut client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); - client_init[KYBER_PUBLIC_KEY_BYTES..][..4].copy_from_slice(&[255u8; 4]); + let mut client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); + client_init[KYBER_PUBLIC_KEY_BYTES..][..4] + .copy_from_slice(&[255u8; 4]); assert!(bob .server_receive(client_init, &bob_keys.secret, &mut rng) .is_ok()); @@ -39,7 +42,8 @@ fn uake_invalid_client_init_publickey() { let mut alice = Uake::new(); let mut bob = Uake::new(); let bob_keys = keypair(&mut rng).unwrap(); - let mut client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let mut client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); client_init[..4].copy_from_slice(&[255u8; 4]); let server_send = bob .server_receive(client_init, &bob_keys.secret, &mut rng) @@ -55,7 +59,8 @@ fn uake_invalid_server_send_ciphertext() { let mut alice = Uake::new(); let mut bob = Uake::new(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let mut server_send = bob .server_receive(client_init, &bob_keys.secret, &mut rng) .unwrap(); @@ -73,9 +78,15 @@ fn ake_valid() { let mut bob = Ake::new(); let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); alice .client_confirm(server_send, &alice_keys.secret) @@ -90,10 +101,17 @@ fn ake_invalid_client_init_ciphertext() { let mut bob = Ake::new(); let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let mut client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); - client_init[KYBER_PUBLIC_KEY_BYTES..][..4].copy_from_slice(&[255u8; 4]); + let mut client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); + client_init[KYBER_PUBLIC_KEY_BYTES..][..4] + .copy_from_slice(&[255u8; 4]); assert!(bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng + ) .is_ok()); assert_ne!(alice.shared_secret, bob.shared_secret); } @@ -105,10 +123,16 @@ fn ake_invalid_client_init_publickey() { let mut bob = Ake::new(); let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let mut client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let mut client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); client_init[..4].copy_from_slice(&[255u8; 4]); let server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); assert!(alice .client_confirm(server_send, &alice_keys.secret) @@ -123,9 +147,15 @@ fn ake_invalid_server_send_first_ciphertext() { let mut bob = Ake::new(); let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let mut server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); server_send[..4].copy_from_slice(&[255u8; 4]); assert!(alice @@ -141,11 +171,18 @@ fn ake_invalid_server_send_second_ciphertext() { let mut bob = Ake::new(); let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let mut server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); - server_send[KYBER_CIPHERTEXT_BYTES..][..4].copy_from_slice(&[255u8; 4]); + server_send[KYBER_CIPHERTEXT_BYTES..][..4] + .copy_from_slice(&[255u8; 4]); // assert!(alice.client_confirm(server_send, &alice_keys.secret).is_err()); } @@ -153,7 +190,10 @@ fn ake_invalid_server_send_second_ciphertext() { #[test] fn ake_uake_failed_randombytes_keypair() { let mut rng = FailingRng::default(); - assert_eq!(keypair(&mut rng), Err(KyberLibError::RandomBytesGeneration)); + assert_eq!( + keypair(&mut rng), + Err(KyberLibError::RandomBytesGeneration) + ); } // Rng function fails on Alice's client init function @@ -176,7 +216,8 @@ fn uake_failed_randombytes_server_receive() { let mut alice = Uake::new(); let mut bob = Uake::new(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let mut rng = FailingRng::default(); assert_eq!( bob.server_receive(client_init, &bob_keys.secret, &mut rng), @@ -203,10 +244,16 @@ fn ake_failed_randombytes_server_receive() { let mut bob = Ake::new(); let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let mut rng = FailingRng::default(); assert_eq!( - bob.server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng), + bob.server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng + ), Err(KyberLibError::RandomBytesGeneration) ) } diff --git a/tests/test_lib.rs b/tests/test_lib.rs index 243b22f..47e10b5 100644 --- a/tests/test_lib.rs +++ b/tests/test_lib.rs @@ -57,7 +57,9 @@ mod tests { assert!(cfg!(feature = "std")); } #[test] - #[should_panic(expected = "Only one security level can be specified")] + #[should_panic( + expected = "Only one security level can be specified" + )] #[cfg(all(feature = "kyber512", feature = "kyber1024"))] fn test_invalid_feature_combination() { // This test should panic with the expected error message @@ -87,8 +89,10 @@ mod tests { let mut rng = StdRng::from_seed([0u8; 32]); let keys = keypair(&mut rng).unwrap(); - let (ciphertext, shared_secret_alice) = encapsulate(&keys.public, &mut rng).unwrap(); - let shared_secret_bob = decapsulate(&ciphertext, &keys.secret).unwrap(); + let (ciphertext, shared_secret_alice) = + encapsulate(&keys.public, &mut rng).unwrap(); + let shared_secret_bob = + decapsulate(&ciphertext, &keys.secret).unwrap(); assert_eq!(shared_secret_alice, shared_secret_bob); } @@ -110,7 +114,8 @@ mod tests { let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob .server_receive(client_init, &bob_keys.secret, &mut rng) @@ -139,10 +144,16 @@ mod tests { let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); alice @@ -166,9 +177,13 @@ mod tests { let mut rng = StdRng::from_seed([0u8; 32]); let keys = keypair(&mut rng).unwrap(); - let invalid_ciphertext = vec![0u8; KYBER_CIPHERTEXT_BYTES - 1]; + let invalid_ciphertext = + vec![0u8; KYBER_CIPHERTEXT_BYTES - 1]; let result = decapsulate(&invalid_ciphertext, &keys.secret); - assert_eq!(result.unwrap_err(), KyberLibError::InvalidInput); + assert_eq!( + result.unwrap_err(), + KyberLibError::InvalidInput + ); } #[test] @@ -181,8 +196,10 @@ mod tests { let mut rng = StdRng::from_seed([0u8; 32]); let keys = keypair(&mut rng).unwrap(); - let (ciphertext, shared_secret_alice) = encapsulate(&keys.public, &mut rng).unwrap(); - let shared_secret_bob = decapsulate(&ciphertext, &keys.secret).unwrap(); + let (ciphertext, shared_secret_alice) = + encapsulate(&keys.public, &mut rng).unwrap(); + let shared_secret_bob = + decapsulate(&ciphertext, &keys.secret).unwrap(); assert_eq!(shared_secret_alice, shared_secret_bob); } @@ -198,9 +215,13 @@ mod tests { let mut rng = StdRng::from_seed([0u8; 32]); - let invalid_public_key = vec![0u8; KYBER_PUBLIC_KEY_BYTES - 1]; + let invalid_public_key = + vec![0u8; KYBER_PUBLIC_KEY_BYTES - 1]; let result = encapsulate(&invalid_public_key, &mut rng); - assert_eq!(result.unwrap_err(), KyberLibError::InvalidInput); + assert_eq!( + result.unwrap_err(), + KyberLibError::InvalidInput + ); } #[test] // Test invalid input secret key with encapsulate function @@ -213,9 +234,13 @@ mod tests { let mut rng = StdRng::from_seed([0u8; 32]); - let invalid_secret_key = vec![0u8; KYBER_SECRET_KEY_BYTES - 1]; + let invalid_secret_key = + vec![0u8; KYBER_SECRET_KEY_BYTES - 1]; let result = encapsulate(&invalid_secret_key, &mut rng); - assert_eq!(result.unwrap_err(), KyberLibError::InvalidInput); + assert_eq!( + result.unwrap_err(), + KyberLibError::InvalidInput + ); } #[test] // Test invalid input secret key with decapsulate function @@ -225,9 +250,16 @@ mod tests { use kyberlib::KYBER_CIPHERTEXT_BYTES; use kyberlib::KYBER_SECRET_KEY_BYTES; - let invalid_secret_key = vec![0u8; KYBER_SECRET_KEY_BYTES - 1]; - let result = decapsulate(&vec![0u8; KYBER_CIPHERTEXT_BYTES], &invalid_secret_key); - assert_eq!(result.unwrap_err(), KyberLibError::InvalidInput); + let invalid_secret_key = + vec![0u8; KYBER_SECRET_KEY_BYTES - 1]; + let result = decapsulate( + &vec![0u8; KYBER_CIPHERTEXT_BYTES], + &invalid_secret_key, + ); + assert_eq!( + result.unwrap_err(), + KyberLibError::InvalidInput + ); } #[test] // Test invalid input ciphertext with decapsulate function @@ -237,9 +269,16 @@ mod tests { use kyberlib::KyberLibError; use kyberlib::KYBER_CIPHERTEXT_BYTES; - let invalid_ciphertext = vec![0u8; KYBER_CIPHERTEXT_BYTES - 1]; - let result = decapsulate(&invalid_ciphertext, &vec![0u8; KYBER_SECRET_KEY_BYTES]); - assert_eq!(result.unwrap_err(), KyberLibError::InvalidInput); + let invalid_ciphertext = + vec![0u8; KYBER_CIPHERTEXT_BYTES - 1]; + let result = decapsulate( + &invalid_ciphertext, + &vec![0u8; KYBER_SECRET_KEY_BYTES], + ); + assert_eq!( + result.unwrap_err(), + KyberLibError::InvalidInput + ); } #[test] // Test UAKE with invalid public key @@ -256,7 +295,8 @@ mod tests { let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob .server_receive(client_init, &bob_keys.secret, &mut rng) .unwrap(); @@ -278,7 +318,8 @@ mod tests { let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob .server_receive(client_init, &bob_keys.secret, &mut rng) .unwrap(); @@ -301,9 +342,15 @@ mod tests { let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); alice @@ -326,9 +373,15 @@ mod tests { let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); alice @@ -351,9 +404,15 @@ mod tests { let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); alice @@ -376,9 +435,15 @@ mod tests { let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); alice @@ -401,9 +466,15 @@ mod tests { let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); alice @@ -429,13 +500,17 @@ mod tests { #[test] // Test decapsulate with invalid secret key length fn test_decapsulate_invalid_secret_key_length() { - use kyberlib::{decapsulate, encapsulate, keypair, KyberLibError, KYBER_SECRET_KEY_BYTES}; + use kyberlib::{ + decapsulate, encapsulate, keypair, KyberLibError, + KYBER_SECRET_KEY_BYTES, + }; use rand::rngs::StdRng; use rand::SeedableRng; let mut rng = StdRng::from_seed([0u8; 32]); let keys = keypair(&mut rng).unwrap(); - let (ciphertext, _) = encapsulate(&keys.public, &mut rng).unwrap(); + let (ciphertext, _) = + encapsulate(&keys.public, &mut rng).unwrap(); let invalid_secret_key = vec![0u8; KYBER_SECRET_KEY_BYTES - 1]; let result = decapsulate(&ciphertext, &invalid_secret_key); @@ -444,7 +519,9 @@ mod tests { #[test] // Test encapsulate with invalid secret key length fn test_encapsulate_invalid_public_key_length() { - use kyberlib::{encapsulate, KyberLibError, KYBER_PUBLIC_KEY_BYTES}; + use kyberlib::{ + encapsulate, KyberLibError, KYBER_PUBLIC_KEY_BYTES, + }; use rand::rngs::StdRng; use rand::SeedableRng; @@ -468,10 +545,16 @@ mod tests { let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = alice.client_init(&bob_keys.public, &mut rng).unwrap(); + let client_init = + alice.client_init(&bob_keys.public, &mut rng).unwrap(); let server_send = bob - .server_receive(client_init, &alice_keys.public, &bob_keys.secret, &mut rng) + .server_receive( + client_init, + &alice_keys.public, + &bob_keys.secret, + &mut rng, + ) .unwrap(); alice diff --git a/tests/test_macros.rs b/tests/test_macros.rs index 2cab923..8def7f0 100644 --- a/tests/test_macros.rs +++ b/tests/test_macros.rs @@ -5,16 +5,18 @@ mod tests { use kyberlib::{ keypair, kyberlib_ake_client_confirm, kyberlib_ake_client_init, - kyberlib_ake_server_receive, kyberlib_assert, kyberlib_max, kyberlib_min, - kyberlib_uake_client_confirm, kyberlib_uake_client_init, kyberlib_uake_server_receive, Ake, + kyberlib_ake_server_receive, kyberlib_assert, kyberlib_max, + kyberlib_min, kyberlib_uake_client_confirm, + kyberlib_uake_client_init, kyberlib_uake_server_receive, Ake, Uake, }; use kyberlib::{ - kyberlib_decrypt_message, kyberlib_encrypt_message, kyberlib_generate_key_pair, + kyberlib_decrypt_message, kyberlib_encrypt_message, + kyberlib_generate_key_pair, }; use kyberlib::{ - KYBER_CIPHERTEXT_BYTES, KYBER_PUBLIC_KEY_BYTES, KYBER_SECRET_KEY_BYTES, - KYBER_SHARED_SECRET_BYTES, + KYBER_CIPHERTEXT_BYTES, KYBER_PUBLIC_KEY_BYTES, + KYBER_SECRET_KEY_BYTES, KYBER_SHARED_SECRET_BYTES, }; use rand_core::OsRng; use rlg::{log::Log, log_format::LogFormat, log_level::LogLevel}; @@ -102,7 +104,13 @@ mod tests { let mut public_key = [0u8; KYBER_PUBLIC_KEY_BYTES]; let mut secret_key = [0u8; KYBER_SECRET_KEY_BYTES]; - kyberlib_generate_key_pair!(&mut public_key, &mut secret_key, &mut rng, None).unwrap(); + kyberlib_generate_key_pair!( + &mut public_key, + &mut secret_key, + &mut rng, + None + ) + .unwrap(); assert_eq!(public_key.len(), KYBER_PUBLIC_KEY_BYTES); assert_eq!(secret_key.len(), KYBER_SECRET_KEY_BYTES); @@ -114,7 +122,13 @@ mod tests { let mut public_key = [0u8; KYBER_PUBLIC_KEY_BYTES]; let mut secret_key = [0u8; KYBER_SECRET_KEY_BYTES]; - kyberlib_generate_key_pair!(&mut public_key, &mut secret_key, &mut rng, None).unwrap(); + kyberlib_generate_key_pair!( + &mut public_key, + &mut secret_key, + &mut rng, + None + ) + .unwrap(); let mut ciphertext = [0u8; KYBER_CIPHERTEXT_BYTES]; let mut shared_secret1 = [0u8; KYBER_SHARED_SECRET_BYTES]; @@ -129,7 +143,11 @@ mod tests { .unwrap(); let mut shared_secret2 = [0u8; KYBER_SHARED_SECRET_BYTES]; - kyberlib_decrypt_message!(&mut shared_secret2, &ciphertext, &secret_key); + kyberlib_decrypt_message!( + &mut shared_secret2, + &ciphertext, + &secret_key + ); assert_eq!(shared_secret1, shared_secret2); } @@ -140,7 +158,13 @@ mod tests { let mut public_key = [0u8; KYBER_PUBLIC_KEY_BYTES]; let mut secret_key = [0u8; KYBER_SECRET_KEY_BYTES]; - kyberlib_generate_key_pair!(&mut public_key, &mut secret_key, &mut rng, None).unwrap(); + kyberlib_generate_key_pair!( + &mut public_key, + &mut secret_key, + &mut rng, + None + ) + .unwrap(); let mut ciphertext = [0u8; KYBER_CIPHERTEXT_BYTES]; let mut shared_secret1 = [0u8; KYBER_SHARED_SECRET_BYTES]; @@ -155,7 +179,11 @@ mod tests { .unwrap(); let mut shared_secret2 = [0u8; KYBER_SHARED_SECRET_BYTES]; - kyberlib_decrypt_message!(&mut shared_secret2, &ciphertext, &secret_key); + kyberlib_decrypt_message!( + &mut shared_secret2, + &ciphertext, + &secret_key + ); assert_eq!(shared_secret1, shared_secret2); } @@ -164,7 +192,9 @@ mod tests { fn test_kyberlib_uake_client_init() { let mut rng = OsRng; let bob_keys = keypair(&mut rng).unwrap(); - let client_init = kyberlib_uake_client_init!(&bob_keys.public, &mut rng).unwrap(); + let client_init = + kyberlib_uake_client_init!(&bob_keys.public, &mut rng) + .unwrap(); assert_eq!(client_init.len(), 2272); } @@ -173,9 +203,15 @@ mod tests { fn test_kyberlib_uake_server_receive() { let mut rng = OsRng; let bob_keys = keypair(&mut rng).unwrap(); - let client_init = kyberlib_uake_client_init!(&bob_keys.public, &mut rng).unwrap(); - let server_send = - kyberlib_uake_server_receive!(client_init, &bob_keys.secret, &mut rng).unwrap(); + let client_init = + kyberlib_uake_client_init!(&bob_keys.public, &mut rng) + .unwrap(); + let server_send = kyberlib_uake_server_receive!( + client_init, + &bob_keys.secret, + &mut rng + ) + .unwrap(); assert_eq!(server_send.len(), 1088); } @@ -187,9 +223,15 @@ mod tests { let bob = Uake::new(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = kyberlib_uake_client_init!(&bob_keys.public, &mut rng).unwrap(); - let server_send = - kyberlib_uake_server_receive!(client_init, &bob_keys.secret, &mut rng).unwrap(); + let client_init = + kyberlib_uake_client_init!(&bob_keys.public, &mut rng) + .unwrap(); + let server_send = kyberlib_uake_server_receive!( + client_init, + &bob_keys.secret, + &mut rng + ) + .unwrap(); kyberlib_uake_client_confirm!(server_send).unwrap(); assert_eq!(alice.shared_secret, bob.shared_secret); @@ -199,7 +241,9 @@ mod tests { fn test_kyberlib_ake_client_init() { let mut rng = OsRng; let bob_keys = keypair(&mut rng).unwrap(); - let client_init = kyberlib_ake_client_init!(&bob_keys.public, &mut rng).unwrap(); + let client_init = + kyberlib_ake_client_init!(&bob_keys.public, &mut rng) + .unwrap(); assert_eq!(client_init.len(), 2272); } @@ -209,7 +253,9 @@ mod tests { let mut rng = OsRng; let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = kyberlib_ake_client_init!(&bob_keys.public, &mut rng).unwrap(); + let client_init = + kyberlib_ake_client_init!(&bob_keys.public, &mut rng) + .unwrap(); let server_send = kyberlib_ake_server_receive!( client_init, &alice_keys.public, @@ -229,7 +275,9 @@ mod tests { let alice_keys = keypair(&mut rng).unwrap(); let bob_keys = keypair(&mut rng).unwrap(); - let client_init = kyberlib_ake_client_init!(&bob_keys.public, &mut rng).unwrap(); + let client_init = + kyberlib_ake_client_init!(&bob_keys.public, &mut rng) + .unwrap(); let server_send = kyberlib_ake_server_receive!( client_init, &alice_keys.public, @@ -237,7 +285,8 @@ mod tests { &mut rng ) .unwrap(); - kyberlib_ake_client_confirm!(server_send, &alice_keys.secret).unwrap(); + kyberlib_ake_client_confirm!(server_send, &alice_keys.secret) + .unwrap(); assert_eq!(alice.shared_secret, bob.shared_secret); } diff --git a/tests/test_params.rs b/tests/test_params.rs index 181a96b..eef9c06 100644 --- a/tests/test_params.rs +++ b/tests/test_params.rs @@ -62,7 +62,10 @@ mod tests { #[test] fn test_kyber_polyveccompressedbytes() { // Test KYBER_POLYVECCOMPRESSEDBYTES for non-kyber1024 - assert_eq!(KYBER_POLYVECCOMPRESSEDBYTES, KYBER_SECURITY_PARAMETER * 320); + assert_eq!( + KYBER_POLYVECCOMPRESSEDBYTES, + KYBER_SECURITY_PARAMETER * 320 + ); } #[test] @@ -78,7 +81,9 @@ mod tests { // Test KYBER_SECRET_KEY_BYTES assert_eq!( KYBER_SECRET_KEY_BYTES, - KYBER_INDCPA_SECRETKEYBYTES + KYBER_INDCPA_PUBLICKEYBYTES + 2 * KYBER_SYM_BYTES + KYBER_INDCPA_SECRETKEYBYTES + + KYBER_INDCPA_PUBLICKEYBYTES + + 2 * KYBER_SYM_BYTES ); } @@ -119,7 +124,10 @@ mod tests { #[test] fn test_kyber_polyveccompressedbytes_kyber1024() { // Test KYBER_POLYVECCOMPRESSEDBYTES for kyber1024 - assert_eq!(KYBER_POLYVECCOMPRESSEDBYTES, KYBER_SECURITY_PARAMETER * 352); + assert_eq!( + KYBER_POLYVECCOMPRESSEDBYTES, + KYBER_SECURITY_PARAMETER * 352 + ); } // Test Kyber parameters related to indcpa diff --git a/tests/test_symmetric.rs b/tests/test_symmetric.rs index 920d5d4..570c59a 100644 --- a/tests/test_symmetric.rs +++ b/tests/test_symmetric.rs @@ -42,7 +42,9 @@ mod tests { fn test_xof_absorb_squeeze() { use kyberlib::params::KYBER_SYM_BYTES; use kyberlib::symmetric::KeccakState; - use kyberlib::symmetric::{kyber_shake128_absorb, kyber_shake128_squeezeblocks}; + use kyberlib::symmetric::{ + kyber_shake128_absorb, kyber_shake128_squeezeblocks, + }; const SHAKE128_RATE: usize = 168; @@ -101,7 +103,9 @@ mod tests { fn test_kyber_shake128_absorb_squeeze() { use kyberlib::params::KYBER_SYM_BYTES; use kyberlib::symmetric::KeccakState; - use kyberlib::symmetric::{kyber_shake128_absorb, kyber_shake128_squeezeblocks}; + use kyberlib::symmetric::{ + kyber_shake128_absorb, kyber_shake128_squeezeblocks, + }; const SHAKE128_RATE: usize = 168; diff --git a/tests/test_wasm.rs b/tests/test_wasm.rs index dc3b27d..ee5dc2d 100644 --- a/tests/test_wasm.rs +++ b/tests/test_wasm.rs @@ -57,7 +57,8 @@ mod tests { let keys = keypair_result.unwrap(); // Test encapsulation with valid input sizes - let result = encapsulate(&keys.public, &mut rand::rngs::OsRng {}); + let result = + encapsulate(&keys.public, &mut rand::rngs::OsRng {}); assert!(result.is_ok()); // Test decapsulation with valid input sizes @@ -69,7 +70,9 @@ mod tests { #[wasm_bindgen_test] fn test_keys() { // Create a new Keys instance - let keys = Keys::new().unwrap_or_else(|_| panic!("Failed to create Keys instance")); + let keys = Keys::new().unwrap_or_else(|_| { + panic!("Failed to create Keys instance") + }); // Ensure the public key and secret key have expected lengths assert_eq!(keys.pubkey().len(), KYBER_PUBLIC_KEY_BYTES); @@ -96,8 +99,10 @@ mod tests { assert_eq!(kex.sharedSecret().len(), KYBER_SHARED_SECRET_BYTES); // Test the set_ciphertext and set_sharedSecret methods - let new_ct = vec![0u8; KYBER_CIPHERTEXT_BYTES].into_boxed_slice(); - let new_ss = vec![0u8; KYBER_SHARED_SECRET_BYTES].into_boxed_slice(); + let new_ct = + vec![0u8; KYBER_CIPHERTEXT_BYTES].into_boxed_slice(); + let new_ss = + vec![0u8; KYBER_SHARED_SECRET_BYTES].into_boxed_slice(); kex.set_ciphertext(new_ct.clone()); kex.set_sharedSecret(new_ss.clone()); assert_eq!(kex.ciphertext(), new_ct); @@ -128,6 +133,9 @@ mod tests { assert_eq!(Params::publicKeyBytes(), KYBER_PUBLIC_KEY_BYTES); assert_eq!(Params::secretKeyBytes(), KYBER_SECRET_KEY_BYTES); assert_eq!(Params::ciphertextBytes(), KYBER_CIPHERTEXT_BYTES); - assert_eq!(Params::sharedSecretBytes(), KYBER_SHARED_SECRET_BYTES); + assert_eq!( + Params::sharedSecretBytes(), + KYBER_SHARED_SECRET_BYTES + ); } } From 5c9797c7c804480cb94668d77749c3b8dd010d3a Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Thu, 9 May 2024 14:32:47 +0100 Subject: [PATCH 3/9] style(kyberlib): :art: minor style tweaks and formatting --- src/api.rs | 8 ++--- src/avx2/indcpa.rs | 20 ++++++------- src/avx2/poly.rs | 4 +-- src/avx2/polyvec.rs | 4 +-- src/kem.rs | 12 ++++---- src/lib.rs | 2 +- src/params.rs | 38 +++++++++++------------- src/reference/indcpa.rs | 39 ++++++++++++++---------- src/reference/poly.rs | 23 ++++++++------- src/reference/polyvec.rs | 12 ++++---- tests/test_params.rs | 64 +++++++++++++++++++++------------------- 11 files changed, 119 insertions(+), 107 deletions(-) diff --git a/src/api.rs b/src/api.rs index c3f4f69..c83ee53 100644 --- a/src/api.rs +++ b/src/api.rs @@ -310,11 +310,11 @@ pub fn derive(seed: &[u8]) -> Result { /// /// Returns the public key as a `PublicKey`. pub fn public(sk: &[u8]) -> PublicKey { - let mut pk = [0u8; KYBER_INDCPA_PUBLICKEYBYTES]; + let mut pk = [0u8; KYBER_INDCPA_PUBLIC_KEY_BYTES]; pk.copy_from_slice( - &sk[KYBER_INDCPA_SECRETKEYBYTES - ..KYBER_INDCPA_SECRETKEYBYTES - + KYBER_INDCPA_PUBLICKEYBYTES], + &sk[KYBER_INDCPA_SECRET_KEY_BYTES + ..KYBER_INDCPA_SECRET_KEY_BYTES + + KYBER_INDCPA_PUBLIC_KEY_BYTES], ); pk } diff --git a/src/avx2/indcpa.rs b/src/avx2/indcpa.rs index 14d5cbd..a8ed896 100644 --- a/src/avx2/indcpa.rs +++ b/src/avx2/indcpa.rs @@ -14,9 +14,9 @@ use crate::{ /// const poly *pk: the input public-key polynomial /// const [u8] seed: the input public seed fn pack_pk(r: &mut [u8], pk: &mut Polyvec, seed: &[u8]) { - const END: usize = KYBER_SYM_BYTES + KYBER_POLYVECBYTES; + const END: usize = KYBER_SYM_BYTES + KYBER_POLYVEC_BYTES; polyvec_tobytes(r, pk); - r[KYBER_POLYVECBYTES..END] + r[KYBER_POLYVEC_BYTES..END] .copy_from_slice(&seed[..KYBER_SYM_BYTES]); } @@ -29,10 +29,10 @@ fn pack_pk(r: &mut [u8], pk: &mut Polyvec, seed: &[u8]) { /// - [u8] seed: output seed to generate matrix A /// - const [u8] packedpk: input serialized public key fn unpack_pk(pk: &mut Polyvec, seed: &mut [u8], packedpk: &[u8]) { - const END: usize = KYBER_SYM_BYTES + KYBER_POLYVECBYTES; + const END: usize = KYBER_SYM_BYTES + KYBER_POLYVEC_BYTES; polyvec_frombytes(pk, packedpk); seed[..KYBER_SYM_BYTES] - .copy_from_slice(&packedpk[KYBER_POLYVECBYTES..END]); + .copy_from_slice(&packedpk[KYBER_POLYVEC_BYTES..END]); } /// Name: pack_sk @@ -66,7 +66,7 @@ fn unpack_sk(sk: &mut Polyvec, packedsk: &[u8]) { /// const [u8] seed: the input polynomial v fn pack_ciphertext(r: &mut [u8], b: &mut Polyvec, v: Poly) { polyvec_compress(r, *b); - poly_compress(&mut r[KYBER_POLYVECCOMPRESSEDBYTES..], v); + poly_compress(&mut r[KYBER_POLYVEC_COMPRESSED_BYTES..], v); } /// Name: unpack_ciphertext @@ -79,7 +79,7 @@ fn pack_ciphertext(r: &mut [u8], b: &mut Polyvec, v: Poly) { /// - const [u8] c: input serialized ciphertext fn unpack_ciphertext(b: &mut Polyvec, v: &mut Poly, c: &[u8]) { polyvec_decompress(b, c); - poly_decompress(v, &c[KYBER_POLYVECCOMPRESSEDBYTES..]); + poly_decompress(v, &c[KYBER_POLYVEC_COMPRESSED_BYTES..]); } /// Name: rej_uniform @@ -190,8 +190,8 @@ fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) { // Description: Generates public and private key for the CPA-secure // public-key encryption scheme underlying Kyber // -// Arguments: - [u8] pk: output public key (length KYBER_INDCPA_PUBLICKEYBYTES) -// - [u8] sk: output private key (length KYBER_INDCPA_SECRETKEYBYTES) +// Arguments: - [u8] pk: output public key (length KYBER_INDCPA_PUBLIC_KEY_BYTES) +// - [u8] sk: output private key (length KYBER_INDCPA_SECRET_KEY_BYTES) pub(crate) fn indcpa_keypair( pk: &mut [u8], sk: &mut [u8], @@ -257,7 +257,7 @@ where /// /// Arguments: - [u8] c: output ciphertext (length KYBER_INDCPA_BYTES) /// - const [u8] m: input message (length KYBER_SYM_BYTES) -/// - const [u8] pk: input public key (length KYBER_INDCPA_PUBLICKEYBYTES) +/// - const [u8] pk: input public key (length KYBER_INDCPA_PUBLIC_KEY_BYTES) /// - const [u8] coin: input random coins used as seed (length KYBER_SYM_BYTES) /// to deterministically generate all randomness pub(crate) fn indcpa_enc( @@ -325,7 +325,7 @@ pub(crate) fn indcpa_enc( /// /// Arguments: - [u8] m: output decrypted message (of length KYBER_SYM_BYTES) /// - const [u8] c: input ciphertext (of length KYBER_INDCPA_BYTES) -/// - const [u8] sk: input secret key (of length KYBER_INDCPA_SECRETKEYBYTES) +/// - const [u8] sk: input secret key (of length KYBER_INDCPA_SECRET_KEY_BYTES) pub(crate) fn indcpa_dec(m: &mut [u8], c: &[u8], sk: &[u8]) { let (mut b, mut skpv) = (Polyvec::new(), Polyvec::new()); let (mut v, mut mp) = (Poly::new(), Poly::new()); diff --git a/src/avx2/poly.rs b/src/avx2/poly.rs index 79a289f..a405bc0 100644 --- a/src/avx2/poly.rs +++ b/src/avx2/poly.rs @@ -193,11 +193,11 @@ pub fn poly_frombytes(r: &mut Poly, a: &[u8]) { } pub fn poly_tobytes(r: &mut [u8], a: Poly) { - let mut buf = [0u8; KYBER_POLYBYTES]; + let mut buf = [0u8; KYBER_POLY_BYTES]; unsafe { ntttobytes_avx(buf.as_mut_ptr(), &a.coeffs, &QDATA.coeffs); } - r[..KYBER_POLYBYTES].copy_from_slice(&buf[..]); + r[..KYBER_POLY_BYTES].copy_from_slice(&buf[..]); } pub unsafe fn poly_frommsg(r: &mut Poly, msg: &[u8]) { diff --git a/src/avx2/polyvec.rs b/src/avx2/polyvec.rs index 227ed1d..0c451d9 100644 --- a/src/avx2/polyvec.rs +++ b/src/avx2/polyvec.rs @@ -190,13 +190,13 @@ pub unsafe fn polyvec_decompress(r: &mut Polyvec, a: &[u8]) { pub fn polyvec_tobytes(r: &mut [u8], a: &Polyvec) { for i in 0..KYBER_SECURITY_PARAMETER { - poly_tobytes(&mut r[i * KYBER_POLYBYTES..], a.vec[i]); + poly_tobytes(&mut r[i * KYBER_POLY_BYTES..], a.vec[i]); } } pub unsafe fn polyvec_frombytes(r: &mut Polyvec, a: &[u8]) { for i in 0..KYBER_SECURITY_PARAMETER { - poly_frombytes(&mut r.vec[i], &a[i * KYBER_POLYBYTES..]); + poly_frombytes(&mut r.vec[i], &a[i * KYBER_POLY_BYTES..]); } } diff --git a/src/kem.rs b/src/kem.rs index c1193ef..1b06a96 100644 --- a/src/kem.rs +++ b/src/kem.rs @@ -32,12 +32,12 @@ where KYBER_SECRET_KEY_BYTES - (2 * KYBER_SYM_BYTES); const SK_START: usize = KYBER_SECRET_KEY_BYTES - KYBER_SYM_BYTES; const END: usize = - KYBER_INDCPA_PUBLICKEYBYTES + KYBER_INDCPA_SECRETKEYBYTES; + KYBER_INDCPA_PUBLIC_KEY_BYTES + KYBER_INDCPA_SECRET_KEY_BYTES; indcpa_keypair(pk, sk, _seed, _rng)?; - sk[KYBER_INDCPA_SECRETKEYBYTES..END] - .copy_from_slice(&pk[..KYBER_INDCPA_PUBLICKEYBYTES]); + sk[KYBER_INDCPA_SECRET_KEY_BYTES..END] + .copy_from_slice(&pk[..KYBER_INDCPA_PUBLIC_KEY_BYTES]); hash_h(&mut sk[PK_START..], pk, KYBER_PUBLIC_KEY_BYTES); if let Some(s) = _seed { @@ -115,11 +115,11 @@ pub fn decrypt_message(ss: &mut [u8], ct: &[u8], sk: &[u8]) { let mut buf = [0u8; 2 * KYBER_SYM_BYTES]; let mut kr = [0u8; 2 * KYBER_SYM_BYTES]; let mut cmp = [0u8; KYBER_CIPHERTEXT_BYTES]; - let mut pk = [0u8; KYBER_INDCPA_PUBLICKEYBYTES]; + let mut pk = [0u8; KYBER_INDCPA_PUBLIC_KEY_BYTES]; pk.copy_from_slice( - &sk[KYBER_INDCPA_SECRETKEYBYTES..] - [..KYBER_INDCPA_PUBLICKEYBYTES], + &sk[KYBER_INDCPA_SECRET_KEY_BYTES..] + [..KYBER_INDCPA_PUBLIC_KEY_BYTES], ); indcpa_dec(&mut buf, ct, sk); diff --git a/src/lib.rs b/src/lib.rs index d8fc0e9..141d293 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -170,7 +170,7 @@ use reference::*; #[cfg(any(not(target_arch = "x86_64"), not(feature = "avx2")))] #[cfg(feature = "hazmat")] -use reference::indcpa; +pub use reference::indcpa; #[cfg(feature = "wasm")] /// WebAssembly bindings for the KyberLib library. diff --git a/src/params.rs b/src/params.rs index c9db827..4d4178e 100644 --- a/src/params.rs +++ b/src/params.rs @@ -23,29 +23,32 @@ pub const KYBER_ETA1: usize = /// - It determines the noise distribution's width in the encryption process. pub const KYBER_ETA2: usize = 2; +// Size of the hashes and seeds +pub const KYBER_SYM_BYTES: usize = 32; + /// The parameter N, representing the degree of the polynomial used in Kyber. /// /// - This constant is a fundamental part of the scheme's structure. pub const KYBER_N: usize = 256; /// The size in bytes of the polynomials used in Kyber, derived from the parameter N. -pub const KYBER_POLYBYTES: usize = 384; +pub const KYBER_POLY_BYTES: usize = 384; /// Compressed byte size of the polynomial for Kyber variants except Kyber1024. /// /// - Determines how data is compacted when not using Kyber1024. #[cfg(not(feature = "kyber1024"))] -pub const KYBER_POLYCOMPRESSEDBYTES: usize = 128; +pub const KYBER_POLY_COMPRESSED_BYTES: usize = 128; -/// The byte size of the vector of polynomials in Kyber, calculated from the security parameter and KYBER_POLYBYTES. -pub const KYBER_POLYVECBYTES: usize = - KYBER_SECURITY_PARAMETER * KYBER_POLYBYTES; +/// The byte size of the vector of polynomials in Kyber, calculated from the security parameter and KYBER_POLY_BYTES. +pub const KYBER_POLYVEC_BYTES: usize = + KYBER_SECURITY_PARAMETER * KYBER_POLY_BYTES; /// Compressed byte size of the polynomial vector for Kyber variants except Kyber1024. /// /// - This setting affects data compression in non-Kyber1024 configurations. #[cfg(not(feature = "kyber1024"))] -pub const KYBER_POLYVECCOMPRESSEDBYTES: usize = +pub const KYBER_POLYVEC_COMPRESSED_BYTES: usize = KYBER_SECURITY_PARAMETER * 320; /// The modulus Q used in the Kyber scheme. @@ -57,8 +60,8 @@ pub const KYBER_Q: usize = 3329; /// /// - It is computed as the sum of IND-CPA secret key and public key sizes, along with twice the size of symmetric keys. /// - This size is crucial for memory allocation during key generation and storage. -pub const KYBER_SECRET_KEY_BYTES: usize = KYBER_INDCPA_SECRETKEYBYTES - + KYBER_INDCPA_PUBLICKEYBYTES +pub const KYBER_SECRET_KEY_BYTES: usize = KYBER_INDCPA_SECRET_KEY_BYTES + + KYBER_INDCPA_PUBLIC_KEY_BYTES + 2 * KYBER_SYM_BYTES; /// The security parameter for Kyber, affecting the overall security level. @@ -84,45 +87,40 @@ pub const KYBER_SECURITY_PARAMETER: usize = /// - This size is pivotal for ensuring the security and efficiency of the cryptographic process. pub const KYBER_SHARED_SECRET_BYTES: usize = 32; -/// The size in bytes of symmetric keys, hash values, and RNG seeds in Kyber. -/// -/// - This constant is critical for maintaining the integrity and compatibility of cryptographic operations within the scheme. -pub const KYBER_SYM_BYTES: usize = 32; - /// Compressed byte size of the polynomial for Kyber1024. /// /// - It determines the efficiency of data compression in Kyber1024. #[cfg(feature = "kyber1024")] -pub const KYBER_POLYCOMPRESSEDBYTES: usize = 160; +pub const KYBER_POLY_COMPRESSED_BYTES: usize = 160; /// Compressed byte size of the polynomial vector for Kyber1024. /// /// - Affects how polynomial vector data is compressed in the Kyber1024 variant. #[cfg(feature = "kyber1024")] -pub const KYBER_POLYVECCOMPRESSEDBYTES: usize = +pub const KYBER_POLYVEC_COMPRESSED_BYTES: usize = KYBER_SECURITY_PARAMETER * 352; /// Byte size of the IND-CPA public key in Kyber. /// /// - This constant is used to allocate memory for storing and transmitting public keys. -pub const KYBER_INDCPA_PUBLICKEYBYTES: usize = - KYBER_POLYVECBYTES + KYBER_SYM_BYTES; +pub const KYBER_INDCPA_PUBLIC_KEY_BYTES: usize = + KYBER_POLYVEC_BYTES + KYBER_SYM_BYTES; /// Byte size of the IND-CPA secret key in Kyber. /// /// - This size is essential for understanding the memory requirements for secure key storage. -pub const KYBER_INDCPA_SECRETKEYBYTES: usize = KYBER_POLYVECBYTES; +pub const KYBER_INDCPA_SECRET_KEY_BYTES: usize = KYBER_POLYVEC_BYTES; /// Total byte size of the IND-CPA data in Kyber. /// /// - It includes the sizes of compressed polynomial vectors and compressed polynomials. pub const KYBER_INDCPA_BYTES: usize = - KYBER_POLYVECCOMPRESSEDBYTES + KYBER_POLYCOMPRESSEDBYTES; + KYBER_POLYVEC_COMPRESSED_BYTES + KYBER_POLY_COMPRESSED_BYTES; /// Size in bytes of a public key in Kyber KEM. /// /// - This size is vital for memory allocation when handling public keys. -pub const KYBER_PUBLIC_KEY_BYTES: usize = KYBER_INDCPA_PUBLICKEYBYTES; +pub const KYBER_PUBLIC_KEY_BYTES: usize = KYBER_INDCPA_PUBLIC_KEY_BYTES; /// Size in bytes of a ciphertext in Kyber KEM. /// diff --git a/src/reference/indcpa.rs b/src/reference/indcpa.rs index 4a6939c..eaa2d41 100644 --- a/src/reference/indcpa.rs +++ b/src/reference/indcpa.rs @@ -4,6 +4,13 @@ use crate::{ KyberLibError, RngCore, }; +#[cfg(feature = "hazmat")] +/// This module provides public constants related to the Kyber IND-CPA scheme. +pub use crate::params::{ + KYBER_INDCPA_BYTES, KYBER_INDCPA_PUBLIC_KEY_BYTES, + KYBER_INDCPA_SECRET_KEY_BYTES, +}; + /// Name: pack_pk /// /// Description: Serialize the public key as concatenation of the @@ -14,9 +21,9 @@ use crate::{ /// const poly *pk: the input public-key polynomial /// const [u8] seed: the input public seed fn pack_pk(r: &mut [u8], pk: &mut Polyvec, seed: &[u8]) { - const END: usize = KYBER_SYM_BYTES + KYBER_POLYVECBYTES; + const END: usize = KYBER_SYM_BYTES + KYBER_POLYVEC_BYTES; polyvec_tobytes(r, pk); - r[KYBER_POLYVECBYTES..END] + r[KYBER_POLYVEC_BYTES..END] .copy_from_slice(&seed[..KYBER_SYM_BYTES]); } @@ -29,10 +36,10 @@ fn pack_pk(r: &mut [u8], pk: &mut Polyvec, seed: &[u8]) { /// - [u8] seed: output seed to generate matrix A /// - const [u8] packedpk: input serialized public key fn unpack_pk(pk: &mut Polyvec, seed: &mut [u8], packedpk: &[u8]) { - const END: usize = KYBER_SYM_BYTES + KYBER_POLYVECBYTES; + const END: usize = KYBER_SYM_BYTES + KYBER_POLYVEC_BYTES; polyvec_frombytes(pk, packedpk); seed[..KYBER_SYM_BYTES] - .copy_from_slice(&packedpk[KYBER_POLYVECBYTES..END]); + .copy_from_slice(&packedpk[KYBER_POLYVEC_BYTES..END]); } /// Name: pack_sk @@ -66,7 +73,7 @@ fn unpack_sk(sk: &mut Polyvec, packedsk: &[u8]) { /// const [u8] seed: the input polynomial v fn pack_ciphertext(r: &mut [u8], b: &mut Polyvec, v: Poly) { polyvec_compress(r, *b); - poly_compress(&mut r[KYBER_POLYVECCOMPRESSEDBYTES..], v); + poly_compress(&mut r[KYBER_POLYVEC_COMPRESSED_BYTES..], v); } /// Name: unpack_ciphertext @@ -79,7 +86,7 @@ fn pack_ciphertext(r: &mut [u8], b: &mut Polyvec, v: Poly) { /// - const [u8] c: input serialized ciphertext fn unpack_ciphertext(b: &mut Polyvec, v: &mut Poly, c: &[u8]) { polyvec_decompress(b, c); - poly_decompress(v, &c[KYBER_POLYVECCOMPRESSEDBYTES..]); + poly_decompress(v, &c[KYBER_POLYVEC_COMPRESSED_BYTES..]); } /// Name: rej_uniform @@ -190,8 +197,8 @@ fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool) { // Description: Generates public and private key for the CPA-secure // public-key encryption scheme underlying Kyber // -// Arguments: - [u8] pk: output public key (length KYBER_INDCPA_PUBLICKEYBYTES) -// - [u8] sk: output private key (length KYBER_INDCPA_SECRETKEYBYTES) +// Arguments: - [u8] pk: output public key (length KYBER_INDCPA_PUBLIC_KEY_BYTES) +// - [u8] sk: output private key (length KYBER_INDCPA_SECRET_KEY_BYTES) pub(crate) fn indcpa_keypair( pk: &mut [u8], sk: &mut [u8], @@ -250,11 +257,12 @@ where /// Description: Encryption function of the CPA-secure /// public-key encryption scheme underlying Kyber. /// -/// Arguments: - [u8] c: output ciphertext (length KYBER_INDCPA_BYTES) -/// - const [u8] m: input message (length KYBER_SYM_BYTES) -/// - const [u8] pk: input public key (length KYBER_INDCPA_PUBLICKEYBYTES) +/// Arguments: +/// - const [u8] c: output ciphertext (length KYBER_INDCPA_BYTES) +/// - const [u8] m: input message (length KYBER_SYM_BYTES) +/// - const [u8] pk: input public key (length KYBER_INDCPA_PUBLIC_KEY_BYTES) /// - const [u8] coin: input random coins used as seed (length KYBER_SYM_BYTES) -/// to deterministically generate all randomness +/// to deterministically generate all randomness pub(crate) fn indcpa_enc( c: &mut [u8], m: &[u8], @@ -313,9 +321,10 @@ pub(crate) fn indcpa_enc( /// Description: Decryption function of the CPA-secure /// public-key encryption scheme underlying Kyber. /// -/// Arguments: - [u8] m: output decrypted message (of length KYBER_SYM_BYTES) -/// - const [u8] c: input ciphertext (of length KYBER_INDCPA_BYTES) -/// - const [u8] sk: input secret key (of length KYBER_INDCPA_SECRETKEYBYTES) +/// Arguments: +/// - const [u8] m: output decrypted message (of length KYBER_SYM_BYTES) +/// - const [u8] c: input ciphertext (of length KYBER_INDCPA_BYTES) +/// - const [u8] sk: input secret key (of length KYBER_INDCPA_SECRET_KEY_BYTES) pub(crate) fn indcpa_dec(m: &mut [u8], c: &[u8], sk: &[u8]) { let (mut b, mut skpv) = (Polyvec::new(), Polyvec::new()); let (mut v, mut mp) = (Poly::new(), Poly::new()); diff --git a/src/reference/poly.rs b/src/reference/poly.rs index a150c8f..c764510 100644 --- a/src/reference/poly.rs +++ b/src/reference/poly.rs @@ -26,14 +26,14 @@ impl Poly { /// /// Description: Compression and subsequent serialization of a polynomial /// -/// Arguments: - [u8] r: output byte array (needs space for KYBER_POLYCOMPRESSEDBYTES bytes) +/// Arguments: - [u8] r: output byte array (needs space for KYBER_POLY_COMPRESSED_BYTES bytes) /// - const poly *a: input polynomial pub(crate) fn poly_compress(r: &mut [u8], a: Poly) { let mut t = [0u8; 8]; let mut k = 0usize; let mut u: i16; - match KYBER_POLYCOMPRESSEDBYTES { + match KYBER_POLY_COMPRESSED_BYTES { 128 => { #[allow(clippy::needless_range_loop)] for i in 0..KYBER_N / 8 { @@ -72,7 +72,7 @@ pub(crate) fn poly_compress(r: &mut [u8], a: Poly) { } } _ => panic!( - "KYBER_POLYCOMPRESSEDBYTES needs to be one of (128, 160)" + "KYBER_POLY_COMPRESSED_BYTES needs to be one of (128, 160)" ), } } @@ -83,9 +83,9 @@ pub(crate) fn poly_compress(r: &mut [u8], a: Poly) { /// approximate inverse of poly_compress /// /// Arguments: - poly *r: output polynomial -/// - const [u8] a: input byte array (of length KYBER_POLYCOMPRESSEDBYTES bytes) +/// - const [u8] a: input byte array (of length KYBER_POLY_COMPRESSED_BYTES bytes) pub(crate) fn poly_decompress(r: &mut Poly, a: &[u8]) { - match KYBER_POLYCOMPRESSEDBYTES { + match KYBER_POLY_COMPRESSED_BYTES { 128 => { for (idx, i) in (0..KYBER_N / 2).enumerate() { r.coeffs[2 * i] = ((((a[idx] & 15) as usize * KYBER_Q) @@ -118,7 +118,7 @@ pub(crate) fn poly_decompress(r: &mut Poly, a: &[u8]) { } } _ => panic!( - "KYBER_POLYCOMPRESSEDBYTES needs to be either (128, 160)" + "KYBER_POLY_COMPRESSED_BYTES needs to be either (128, 160)" ), } } @@ -127,7 +127,7 @@ pub(crate) fn poly_decompress(r: &mut Poly, a: &[u8]) { /// /// Description: Serialization of a polynomial /// -/// Arguments: - [u8] r: output byte array (needs space for KYBER_POLYBYTES bytes) +/// Arguments: - [u8] r: output byte array (needs space for KYBER_POLY_BYTES bytes) /// - const poly *a: input polynomial pub(crate) fn poly_tobytes(r: &mut [u8], a: Poly) { let (mut t0, mut t1); @@ -150,7 +150,7 @@ pub(crate) fn poly_tobytes(r: &mut [u8], a: Poly) { /// inverse of poly_tobytes /// /// Arguments: - poly *r: output polynomial -/// - const [u8] a: input byte array (of KYBER_POLYBYTES bytes) +/// - const [u8] a: input byte array (of KYBER_POLY_BYTES bytes) pub(crate) fn poly_frombytes(r: &mut Poly, a: &[u8]) { for i in 0..(KYBER_N / 2) { r.coeffs[2 * i] = ((a[3 * i]) as u16 @@ -288,9 +288,10 @@ pub(crate) fn poly_add(r: &mut Poly, b: &Poly) { /// /// Description: Subtract two polynomials; no modular reduction is performed /// -/// Arguments: - poly *r: output polynomial -/// - const poly *a: first input polynomial -/// - const poly *b: second input polynomial +/// Arguments: +/// - poly *r: output polynomial +/// - const poly *a: first input polynomial +/// - const poly *b: second input polynomial pub(crate) fn poly_sub(r: &mut Poly, a: &Poly) { #[allow(clippy::needless_range_loop)] for i in 0..KYBER_N { diff --git a/src/reference/polyvec.rs b/src/reference/polyvec.rs index 8b90618..b2dc24d 100644 --- a/src/reference/polyvec.rs +++ b/src/reference/polyvec.rs @@ -20,7 +20,7 @@ impl Polyvec { /// /// Description: Compress and serialize vector of polynomials /// -/// Arguments: - [u8] r: output byte array (needs space for KYBER_POLYVECCOMPRESSEDBYTES) +/// Arguments: - [u8] r: output byte array (needs space for KYBER_POLYVEC_COMPRESSED_BYTES) /// - const Polyvec a: input vector of polynomials pub(crate) fn polyvec_compress(r: &mut [u8], a: Polyvec) { #[cfg(feature = "kyber1024")] @@ -89,7 +89,7 @@ pub(crate) fn polyvec_compress(r: &mut [u8], a: Polyvec) { /// approximate inverse of polyvec_compress /// /// Arguments: - Polyvec r: output vector of polynomials -/// - [u8] a: input byte array (of length KYBER_POLYVECCOMPRESSEDBYTES) +/// - [u8] a: input byte array (of length KYBER_POLYVEC_COMPRESSED_BYTES) pub(crate) fn polyvec_decompress(r: &mut Polyvec, a: &[u8]) { #[cfg(feature = "kyber1024")] { @@ -156,11 +156,11 @@ pub(crate) fn polyvec_decompress(r: &mut Polyvec, a: &[u8]) { /// /// Description: Serialize vector of polynomials /// -/// Arguments: - [u8] r: output byte array (needs space for KYBER_POLYVECBYTES) +/// Arguments: - [u8] r: output byte array (needs space for KYBER_POLYVEC_BYTES) /// - const Polyvec a: input vector of polynomials pub(crate) fn polyvec_tobytes(r: &mut [u8], a: &Polyvec) { for i in 0..KYBER_SECURITY_PARAMETER { - poly_tobytes(&mut r[i * KYBER_POLYBYTES..], a.vec[i]); + poly_tobytes(&mut r[i * KYBER_POLY_BYTES..], a.vec[i]); } } @@ -170,10 +170,10 @@ pub(crate) fn polyvec_tobytes(r: &mut [u8], a: &Polyvec) { /// inverse of polyvec_tobytes /// /// Arguments: - [u8] r: output byte array -/// - const Polyvec a: input vector of polynomials (of length KYBER_POLYVECBYTES) +/// - const Polyvec a: input vector of polynomials (of length KYBER_POLYVEC_BYTES) pub(crate) fn polyvec_frombytes(r: &mut Polyvec, a: &[u8]) { for i in 0..KYBER_SECURITY_PARAMETER { - poly_frombytes(&mut r.vec[i], &a[i * KYBER_POLYBYTES..]); + poly_frombytes(&mut r.vec[i], &a[i * KYBER_POLY_BYTES..]); } } diff --git a/tests/test_params.rs b/tests/test_params.rs index eef9c06..d1e6e31 100644 --- a/tests/test_params.rs +++ b/tests/test_params.rs @@ -37,33 +37,33 @@ mod tests { } #[test] - fn test_kyber_polybytes() { - // Test KYBER_POLYBYTES - assert_eq!(KYBER_POLYBYTES, 384); + fn test_kyber_poly_bytes() { + // Test KYBER_POLY_BYTES + assert_eq!(KYBER_POLY_BYTES, 384); } #[cfg(not(feature = "kyber1024"))] #[test] - fn test_kyber_polycompressedbytes() { - // Test KYBER_POLYCOMPRESSEDBYTES for non-kyber1024 - assert_eq!(KYBER_POLYCOMPRESSEDBYTES, 128); + fn test_kyber_poly_compressed_bytes() { + // Test KYBER_POLY_COMPRESSED_BYTES for non-kyber1024 + assert_eq!(KYBER_POLY_COMPRESSED_BYTES, 128); } #[test] - fn test_kyber_polyvecbytes() { - // Test KYBER_POLYVECBYTES + fn test_kyber_polyvec_bytes() { + // Test KYBER_POLYVEC_BYTES assert_eq!( - KYBER_POLYVECBYTES, - KYBER_SECURITY_PARAMETER * KYBER_POLYBYTES + KYBER_POLYVEC_BYTES, + KYBER_SECURITY_PARAMETER * KYBER_POLY_BYTES ); } #[cfg(not(feature = "kyber1024"))] #[test] - fn test_kyber_polyveccompressedbytes() { - // Test KYBER_POLYVECCOMPRESSEDBYTES for non-kyber1024 + fn test_kyber_polyvec_compressed_bytes() { + // Test KYBER_POLYVEC_COMPRESSED_BYTES for non-kyber1024 assert_eq!( - KYBER_POLYVECCOMPRESSEDBYTES, + KYBER_POLYVEC_COMPRESSED_BYTES, KYBER_SECURITY_PARAMETER * 320 ); } @@ -81,8 +81,8 @@ mod tests { // Test KYBER_SECRET_KEY_BYTES assert_eq!( KYBER_SECRET_KEY_BYTES, - KYBER_INDCPA_SECRETKEYBYTES - + KYBER_INDCPA_PUBLICKEYBYTES + KYBER_INDCPA_SECRET_KEY_BYTES + + KYBER_INDCPA_PUBLIC_KEY_BYTES + 2 * KYBER_SYM_BYTES ); } @@ -115,17 +115,17 @@ mod tests { #[cfg(feature = "kyber1024")] #[test] - fn test_kyber_polycompressedbytes_kyber1024() { - // Test KYBER_POLYCOMPRESSEDBYTES for kyber1024 - assert_eq!(KYBER_POLYCOMPRESSEDBYTES, 160); + fn test_KYBER_POLY_COMPRESSED_BYTES_kyber1024() { + // Test KYBER_POLY_COMPRESSED_BYTES for kyber1024 + assert_eq!(KYBER_POLY_COMPRESSED_BYTES, 160); } #[cfg(feature = "kyber1024")] #[test] - fn test_kyber_polyveccompressedbytes_kyber1024() { - // Test KYBER_POLYVECCOMPRESSEDBYTES for kyber1024 + fn test_KYBER_POLYVEC_COMPRESSED_BYTES_kyber1024() { + // Test KYBER_POLYVEC_COMPRESSED_BYTES for kyber1024 assert_eq!( - KYBER_POLYVECCOMPRESSEDBYTES, + KYBER_POLYVEC_COMPRESSED_BYTES, KYBER_SECURITY_PARAMETER * 352 ); } @@ -133,18 +133,18 @@ mod tests { // Test Kyber parameters related to indcpa #[test] - fn test_kyber_indcpa_publickeybytes() { - // Test KYBER_INDCPA_PUBLICKEYBYTES + fn test_kyber_indcpa_public_key_bytes() { + // Test KYBER_INDCPA_PUBLIC_KEY_BYTES assert_eq!( - KYBER_INDCPA_PUBLICKEYBYTES, - KYBER_POLYVECBYTES + KYBER_SYM_BYTES + KYBER_INDCPA_PUBLIC_KEY_BYTES, + KYBER_POLYVEC_BYTES + KYBER_SYM_BYTES ); } #[test] - fn test_kyber_indcpa_secretkeybytes() { - // Test KYBER_INDCPA_SECRETKEYBYTES - assert_eq!(KYBER_INDCPA_SECRETKEYBYTES, KYBER_POLYVECBYTES); + fn test_kyber_indcpa_secret_key_bytes() { + // Test KYBER_INDCPA_SECRET_KEY_BYTES + assert_eq!(KYBER_INDCPA_SECRET_KEY_BYTES, KYBER_POLYVEC_BYTES); } #[test] @@ -152,7 +152,8 @@ mod tests { // Test KYBER_INDCPA_BYTES assert_eq!( KYBER_INDCPA_BYTES, - KYBER_POLYVECCOMPRESSEDBYTES + KYBER_POLYCOMPRESSEDBYTES + KYBER_POLYVEC_COMPRESSED_BYTES + + KYBER_POLY_COMPRESSED_BYTES ); } @@ -161,7 +162,10 @@ mod tests { #[test] fn test_kyber_public_key_bytes() { // Test KYBER_PUBLIC_KEY_BYTES - assert_eq!(KYBER_PUBLIC_KEY_BYTES, KYBER_INDCPA_PUBLICKEYBYTES); + assert_eq!( + KYBER_PUBLIC_KEY_BYTES, + KYBER_INDCPA_PUBLIC_KEY_BYTES + ); } #[test] From f41d7fee2b957c2852ee491435debd97905d4410 Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Thu, 9 May 2024 14:43:20 +0100 Subject: [PATCH 4/9] test(kyberlib): :white_check_mark: Add unit tests for KyberLibError --- tests/test_error.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/test_error.rs b/tests/test_error.rs index 53de552..c4555fa 100644 --- a/tests/test_error.rs +++ b/tests/test_error.rs @@ -28,4 +28,40 @@ fn test_kyber_lib_error_display() { error.to_string(), "Random bytes generation function failed" ); + + let error = KyberLibError::InvalidKey; + assert_eq!( + error.to_string(), + "The secret and public key given does not match." + ); +} + +#[test] +fn test_kyber_lib_error_partial_eq() { + let error1 = KyberLibError::InvalidInput; + let error2 = KyberLibError::InvalidInput; + assert_eq!(error1, error2); + + let error1 = KyberLibError::Decapsulation; + let error2 = KyberLibError::Decapsulation; + assert_eq!(error1, error2); + + let error1 = KyberLibError::RandomBytesGeneration; + let error2 = KyberLibError::RandomBytesGeneration; + assert_eq!(error1, error2); + + let error1 = KyberLibError::InvalidKey; + let error2 = KyberLibError::InvalidKey; + assert_eq!(error1, error2); + + let error1 = KyberLibError::InvalidInput; + let error2 = KyberLibError::Decapsulation; + assert_ne!(error1, error2); +} + +#[cfg(feature = "std")] +#[test] +fn test_kyber_lib_error_std_error() { + let error = KyberLibError::InvalidInput; + let _std_error: &dyn std::error::Error = &error; } From 9c3f39286471b8bf88ed99b3faf4401e41115fd3 Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Thu, 9 May 2024 17:51:47 +0100 Subject: [PATCH 5/9] test(kyberlib): :recycle: minor refactoring, add unit tests for `rng.rs` --- src/error.rs | 6 ++++ src/params.rs | 2 +- src/rng.rs | 4 +++ tests/test_rng.rs | 92 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/src/error.rs b/src/error.rs index 83a6fb1..f209ca6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -11,6 +11,9 @@ pub enum KyberLibError { /// Error when generating keys InvalidKey, + /// The length of the input buffer is invalid. + InvalidLength, + /// The ciphertext was unable to be authenticated. The shared secret was not decapsulated. Decapsulation, @@ -31,6 +34,9 @@ impl core::fmt::Display for KyberLibError { } KyberLibError::InvalidKey => { write!(f, "The secret and public key given does not match.") + }, + KyberLibError::InvalidLength => { + write!(f, "The length of the input buffer is invalid.") } } } diff --git a/src/params.rs b/src/params.rs index 4d4178e..9134e9a 100644 --- a/src/params.rs +++ b/src/params.rs @@ -23,7 +23,7 @@ pub const KYBER_ETA1: usize = /// - It determines the noise distribution's width in the encryption process. pub const KYBER_ETA2: usize = 2; -// Size of the hashes and seeds +/// Size of the hashes and seeds pub const KYBER_SYM_BYTES: usize = 32; /// The parameter N, representing the degree of the polynomial used in Kyber. diff --git a/src/rng.rs b/src/rng.rs index b0008e4..6b3e192 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -44,6 +44,10 @@ pub fn randombytes( where R: RngCore + CryptoRng, { + if len > x.len() { + return Err(KyberLibError::InvalidLength); + } + rng.try_fill_bytes(&mut x[..len]) .map_err(|_| KyberLibError::RandomBytesGeneration) } diff --git a/tests/test_rng.rs b/tests/test_rng.rs index c55ddbd..cbffbf0 100644 --- a/tests/test_rng.rs +++ b/tests/test_rng.rs @@ -4,7 +4,7 @@ #[cfg(test)] mod tests { - use kyberlib::rng::randombytes; + use kyberlib::{rng::randombytes, KyberLibError}; use rand_core::OsRng; #[test] @@ -113,4 +113,94 @@ mod tests { assert!(result2.is_ok()); assert_ne!(&buffer1[..], &buffer2[..]); } + + #[test] + fn test_randombytes_partial_fill() { + // Test filling a partial buffer + let mut buffer = [0u8; 32]; + let partial_len = 16; + + // Use OsRng as the RNG + let mut rng = OsRng; + + // Call randombytes to partially fill the buffer + let result = randombytes(&mut buffer, partial_len, &mut rng); + + // Check if the result is Ok, indicating successful random byte generation + assert!(result.is_ok()); + // Check that the buffer length is unchanged + assert_eq!(buffer.len(), 32); + // Check that the first 16 bytes are filled with random data + assert_ne!(&buffer[..partial_len], &[0u8; 16]); + } + + #[test] + fn test_randombytes_error_handling() { + // Test with a buffer of size 32 + let mut buffer = [0u8; 32]; + let buffer_len = buffer.len(); + + // Use OsRng as the RNG + let mut rng = OsRng; + + // Call randombytes with a valid length + let result = randombytes(&mut buffer, buffer_len, &mut rng); + + // Check if the result is ok + assert!(result.is_ok()); + + // Call randombytes with an invalid length + let result = randombytes(&mut buffer, buffer_len + 1, &mut rng); + + // Check if the result is an error + assert!(matches!(result, Err(KyberLibError::InvalidLength))); + } + + #[test] + fn test_randombytes_out_of_bounds() { + // Test with a buffer of size 32 + let mut buffer = [0u8; 32]; + let buffer_len = buffer.len(); + + // Use OsRng as the RNG + let mut rng = OsRng; + + // Call randombytes with an out-of-bounds length + let result = randombytes(&mut buffer, buffer_len + 1, &mut rng); + + // Check if the result is an InvalidLength error + assert!(matches!(result, Err(KyberLibError::InvalidLength))); + } + + #[test] + fn test_randombytes_invalid_rng() { + // Test with a buffer of size 32 + let mut buffer = [0u8; 32]; + let buffer_len = buffer.len(); + + // Use OsRng as the RNG + let mut rng = OsRng; + + // Call randombytes with a valid RNG + let result = randombytes(&mut buffer, buffer_len, &mut rng); + + // Check if the result is ok + assert!(result.is_ok()); + } + + #[test] + fn test_randombytes_invalid_length() { + // Test with a buffer of size 32 + let mut buffer = [0u8; 32]; + let invalid_len = 33; + + // Use OsRng as the RNG + let mut rng = OsRng; + + // Call randombytes with an invalid length + let result = randombytes(&mut buffer, invalid_len, &mut rng); + + // Check if the result is an InvalidLength error + assert!(matches!(result, Err(KyberLibError::InvalidLength))); + } } From ffbbe373bc3db58def0c961a773f93b2e7273517 Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Thu, 9 May 2024 18:43:03 +0100 Subject: [PATCH 6/9] fix(kyberlib): :white_check_mark: add comprehensive test suite for wasm module --- tests/test_wasm.rs | 178 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/tests/test_wasm.rs b/tests/test_wasm.rs index ee5dc2d..1eeb9a8 100644 --- a/tests/test_wasm.rs +++ b/tests/test_wasm.rs @@ -138,4 +138,182 @@ mod tests { KYBER_SHARED_SECRET_BYTES ); } + + // Test the Kex::new() method with an invalid public key size + #[wasm_bindgen_test] + fn test_kex_new_invalid_pubkey_size() { + // Generate an invalid public key with incorrect size + let invalid_pk = + vec![0u8; KYBER_PUBLIC_KEY_BYTES - 1].into_boxed_slice(); + + // Call Kex::new() with the invalid public key and expect a panic + std::panic::catch_unwind(|| { + Kex::new(invalid_pk); + }) + .unwrap_err(); + } + + // Test the decapsulate() function with mismatched ciphertext and secret key + #[wasm_bindgen_test] + fn test_decapsulate_mismatched_inputs() { + // Generate a key pair + let keys = match Keys::new() { + Ok(keys) => keys, + Err(_) => return, + }; + + // Encapsulate with the public key to get a valid ciphertext + let kex = Kex::new(keys.pubkey()); + + // Generate a different key pair + let different_keys = match Keys::new() { + Ok(keys) => keys, + Err(_) => return, + }; + + // Call decapsulate() with mismatched ciphertext and secret key + let result = + decapsulate(&kex.ciphertext(), &different_keys.secret()); + assert!(result.is_err()); + } + + // Test the decapsulate() function with a valid ciphertext and secret key + #[wasm_bindgen_test] + fn test_decapsulate_valid_inputs() { + // Generate a key pair + let keys = match Keys::new() { + Ok(keys) => keys, + Err(_) => return, + }; + + // Encapsulate with the public key to get a valid ciphertext + let kex = Kex::new(keys.pubkey()); + + // Call decapsulate() with the valid ciphertext and secret key + let result = decapsulate(&kex.ciphertext(), &keys.secret()); + assert!(result.is_ok()); + } + + // Test the decapsulate() function with an invalid ciphertext size + #[wasm_bindgen_test] + fn test_decapsulate_invalid_ciphertext_size() { + // Generate a key pair + let keys = match Keys::new() { + Ok(keys) => keys, + Err(_) => return, + }; + + // Create an invalid ciphertext with incorrect size + let invalid_ct = + vec![0u8; KYBER_CIPHERTEXT_BYTES - 1].into_boxed_slice(); + + // Call decapsulate() with the invalid ciphertext and valid secret key + let result = decapsulate(&invalid_ct, &keys.secret()); + assert!(result.is_err()); + } + + // Test the decapsulate() function with an invalid secret key size + #[wasm_bindgen_test] + fn test_decapsulate_invalid_secret_key_size() { + // Generate a key pair + let keys = match Keys::new() { + Ok(keys) => keys, + Err(_) => return, + }; + + // Encapsulate with the public key to get a valid ciphertext + let kex = Kex::new(keys.pubkey()); + + // Create an invalid secret key with incorrect size + let invalid_sk = + vec![0u8; KYBER_SECRET_KEY_BYTES - 1].into_boxed_slice(); + + // Call decapsulate() with the valid ciphertext and invalid secret key + let result = decapsulate(&kex.ciphertext(), &invalid_sk); + assert!(result.is_err()); + } + + // Test the Keys struct's pubkey() and secret() methods + #[wasm_bindgen_test] + fn test_keys_methods() { + // Generate a key pair + let keys = match Keys::new() { + Ok(keys) => keys, + Err(_) => return, + }; + + // Check if pubkey() returns the expected public key + assert_eq!(keys.pubkey().len(), KYBER_PUBLIC_KEY_BYTES); + + // Check if secret() returns the expected secret key + assert_eq!(keys.secret().len(), KYBER_SECRET_KEY_BYTES); + } + + // Test the Kex struct's ciphertext(), sharedSecret(), set_ciphertext(), and set_sharedSecret() methods + #[wasm_bindgen_test] + fn test_kex_methods() { + // Generate a key pair + let keys = match Keys::new() { + Ok(keys) => keys, + Err(_) => return, + }; + + // Create a Kex instance + let mut kex = Kex::new(keys.pubkey()); + + // Check if ciphertext() returns the expected ciphertext + assert_eq!(kex.ciphertext().len(), KYBER_CIPHERTEXT_BYTES); + + // Check if sharedSecret() returns the expected shared secret + assert_eq!(kex.sharedSecret().len(), KYBER_SHARED_SECRET_BYTES); + + // Create new ciphertext and shared secret + let new_ct = + vec![1u8; KYBER_CIPHERTEXT_BYTES].into_boxed_slice(); + let new_ss = + vec![2u8; KYBER_SHARED_SECRET_BYTES].into_boxed_slice(); + + // Set the new ciphertext and shared secret + kex.set_ciphertext(new_ct.clone()); + kex.set_sharedSecret(new_ss.clone()); + + // Check if the ciphertext and shared secret are updated correctly + assert_eq!(kex.ciphertext(), new_ct); + assert_eq!(kex.sharedSecret(), new_ss); + } + + // Test the encapsulate() function with a valid public key and an invalid RNG + #[wasm_bindgen_test] + fn test_encapsulate_invalid_rng() { + // Generate a valid key pair + let keys = match Keys::new() { + Ok(keys) => keys, + Err(_) => return, + }; + + // Create a mock RNG that always returns an error + #[allow(dead_code)] + struct MockRng; + impl rand_core::RngCore for MockRng { + fn next_u32(&mut self) -> u32 { + 0 + } + fn next_u64(&mut self) -> u64 { + 0 + } + fn fill_bytes(&mut self, _dest: &mut [u8]) {} + + fn try_fill_bytes( + &mut self, + _dest: &mut [u8], + ) -> Result<(), rand_core::Error> { + Err(rand_core::Error::new("MockRng error")) + } + } + impl rand_core::CryptoRng for MockRng {} + + // Call encapsulate() with the valid public key and the mock RNG + let result = encapsulate(&keys.pubkey(), &mut MockRng); + assert!(result.is_err()); + } } From b90bb2b2c4586903dca34f6d45bf850816564225 Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Thu, 9 May 2024 19:15:17 +0100 Subject: [PATCH 7/9] docs(kyberlib): :memo: updates on documentation macros and `KyberLibError` --- README.md | 43 +++++++++++++++++++++++++------------------ src/lib.rs | 41 ++++++++++++++++++++++++----------------- 2 files changed, 49 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 4cd2be2..94775a0 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ A Robust Rust Library for CRYSTALS-Kyber Post-Quantum Cryptography. ## Overview 📖 -KyberLib is a robust Rust library designed for CRYSTALS-Kyber Post-Quantum Cryptography, offering strong security guarantees. This library is compatible with `no_std`, making it suitable for embedded devices and avoids memory allocations. Additionally, it contains reference implementations with no unsafe code and provides an optimized AVX2 version by default on x86_64 platforms. You can also compile it to WebAssembly (WASM) using wasm-bindgen. +KyberLib is a robust Rust library designed for **CRYSTALS-Kyber Post-Quantum Cryptography**, offering strong security guarantees. This library is compatible with `no_std`, making it suitable for embedded devices and avoids memory allocations. Additionally, it contains reference implementations with no unsafe code and provides an optimized AVX2 version by default on x86_64 platforms. You can also compile it to WebAssembly (WASM) using wasm-bindgen. ## Features ✨ @@ -105,6 +105,8 @@ For optimisations on x86 platforms enable the `avx2` feature and the following R export RUSTFLAGS="-C target-feature=+aes,+avx2,+sse2,+sse4.1,+bmi2,+popcnt" ``` +## Crate Features 📦 + ### Key Encapsulation ```rust @@ -169,32 +171,38 @@ alice.client_confirm(server_response, &alice_keys.secret)?; assert_eq!(alice.shared_secret, bob.shared_secret); ``` -## Macros +## Macros 🦀 The KyberLib crate provides several macros to simplify common cryptographic operations: -- `kyberlib_assert!`: Asserts that a given expression is true. Panics if the assertion fails. -- `kyberlib_min!`: Returns the minimum of the given values. -- `kyberlib_max!`: Returns the maximum of the given values. -- `kyberlib_generate_key_pair!`: Generates a public and private key pair for CCA-secure Kyber key encapsulation mechanism. -- `kyberlib_encrypt_message!`: Generates cipher text and a shared secret for a given public key. -- `kyberlib_decrypt_message!`: Generates a shared secret for a given cipher text and private key. -- `kyberlib_uake_client_init!`: Initiates a Unilaterally Authenticated Key Exchange. -- `kyberlib_uake_server_receive!`: Handles the output of a `kyberlib_uake_client_init()` request. -- `kyberlib_uake_client_confirm!`: Decapsulates and authenticates the shared secret from the output of `kyberlib_uake_server_receive()`. -- `kyberlib_ake_client_init!`: Initiates a Mutually Authenticated Key Exchange. -- `kyberlib_ake_server_receive!`: Handles and authenticates the output of a `kyberlib_ake_client_init()` request. -- `kyberlib_ake_client_confirm!`: Decapsulates and authenticates the shared secret from the output of `kyberlib_ake_server_receive()`. - -See the [macros module documentation](https://docs.rs/kyberlib/latest/kyberlib/macros/index.html) for more details and usage examples. +- [`kyberlib_generate_key_pair!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_generate_key_pair.html): Generates a public and private key pair for CCA-secure Kyber key encapsulation mechanism. + +- [`kyberlib_encrypt_message!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_encrypt_message.html): Generates cipher text and a shared secret for a given public key. + +- [`kyberlib_decrypt_message!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_decrypt_message.html): Generates a shared secret for a given cipher text and private key. + +- [`kyberlib_uake_client_init!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_uake_client_init.html): Initiates a Unilaterally Authenticated Key Exchange. + +- [`kyberlib_uake_server_receive!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_uake_server_receive.html): Handles the output of a `kyberlib_uake_client_init()` request. + +- [`kyberlib_uake_client_confirm!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_uake_client_confirm.html): Decapsulates and authenticates the shared secret from the output of `kyberlib_uake_server_receive()`. + +- [`kyberlib_ake_client_init!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_ake_client_init.html): Initiates a Mutually Authenticated Key Exchange. + +- [`kyberlib_ake_server_receive!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_uake_server_receive.html): Handles and authenticates the output of a `kyberlib_ake_client_init()` request. + +- [`kyberlib_ake_client_confirm!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_ake_client_confirm.html): Decapsulates and authenticates the shared secret from the output of `kyberlib_ake_server_receive()`. + +See the [macros module documentation](https://docs.rs/kyberlib/latest/kyberlib/index.html#macros) for more details and usage examples. ## Errors The KyberLibError enum has two variants: - **InvalidInput** - One or more inputs to a function are incorrectly sized. A possible cause of this is two parties using different security levels while trying to negotiate a key exchange. +- **InvalidKey** - Error when generating keys. - **Decapsulation** - The ciphertext was unable to be authenticated. The shared secret was not decapsulated. -- **RandomBytesGeneration** - Error trying to fill random bytes (i.e external (hardware) RNG modules can fail). +- **RandomBytesGeneration** - Error trying to fill random bytes (i.e., external (hardware) RNG modules can fail). ## Examples @@ -281,7 +289,6 @@ A special thank you goes to the [Rust Reddit][12] community for providing a lot of useful suggestions on how to improve this project. [00]: https://kyberlib.com/ "KyberLib, A Robust Rust Library for CRYSTALS-Kyber Post-Quantum Cryptography" -[01]: https://kura.pro/common/images/elements/divider.svg "Divider" [02]: http://opensource.org/licenses/MIT "KyberLib license" [03]: https://github.com/sebastienrousseau/kyberlib/kyberlib/issues "KyberLib Issues" [04]: https://github.com/sebastienrousseau/kyberlib/kyberlib/blob/main/CONTRIBUTING.md "KyberLib Contributing Guidelines" diff --git a/src/lib.rs b/src/lib.rs index 141d293..b62ea8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,27 +122,34 @@ //! //! The KyberLib crate provides several macros to simplify common cryptographic operations: //! -//! - `kyberlib_assert!`: Asserts that a given expression is true. Panics if the assertion fails. -//! - `kyberlib_min!`: Returns the minimum of the given values. -//! - `kyberlib_max!`: Returns the maximum of the given values. -//! - `kyberlib_generate_key_pair!`: Generates a public and private key pair for CCA-secure Kyber key encapsulation mechanism. -//! - `kyberlib_encrypt_message!`: Generates cipher text and a shared secret for a given public key. -//! - `kyberlib_decrypt_message!`: Generates a shared secret for a given cipher text and private key. -//! - `kyberlib_uake_client_init!`: Initiates a Unilaterally Authenticated Key Exchange. -//! - `kyberlib_uake_server_receive!`: Handles the output of a `kyberlib_uake_client_init()` request. -//! - `kyberlib_uake_client_confirm!`: Decapsulates and authenticates the shared secret from the output of `kyberlib_uake_server_receive()`. -//! - `kyberlib_ake_client_init!`: Initiates a Mutually Authenticated Key Exchange. -//! - `kyberlib_ake_server_receive!`: Handles and authenticates the output of a `kyberlib_ake_client_init()` request. -//! - `kyberlib_ake_client_confirm!`: Decapsulates and authenticates the shared secret from the output of `kyberlib_ake_server_receive()`. -//! -//! See the [macros module documentation](https://docs.rs/kyberlib/latest/kyberlib/macros/index.html) for more details and usage examples. +//! - [`kyberlib_generate_key_pair!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_generate_key_pair.html): Generates a public and private key pair for CCA-secure Kyber key encapsulation mechanism. +//! +//! - [`kyberlib_encrypt_message!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_encrypt_message.html): Generates cipher text and a shared secret for a given public key. +//! +//! - [`kyberlib_decrypt_message!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_decrypt_message.html): Generates a shared secret for a given cipher text and private key. +//! +//! - [`kyberlib_uake_client_init!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_uake_client_init.html): Initiates a Unilaterally Authenticated Key Exchange. +//! +//! - [`kyberlib_uake_server_receive!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_uake_server_receive.html): Handles the output of a `kyberlib_uake_client_init()` request. +//! +//! - [`kyberlib_uake_client_confirm!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_uake_client_confirm.html): Decapsulates and authenticates the shared secret from the output of `kyberlib_uake_server_receive()`. +//! +//! - [`kyberlib_ake_client_init!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_ake_client_init.html): Initiates a Mutually Authenticated Key Exchange. +//! +//! - [`kyberlib_ake_server_receive!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_uake_server_receive.html): Handles and authenticates the output of a `kyberlib_ake_client_init()` request. +//! +//! - [`kyberlib_ake_client_confirm!`](https://docs.rs/kyberlib/latest/kyberlib/macro.kyberlib_ake_client_confirm.html): Decapsulates and authenticates the shared secret from the output of `kyberlib_ake_server_receive()`. +//! +//! See the [macros module documentation](https://docs.rs/kyberlib/latest/kyberlib/index.html#macros) for more details and usage examples. //! //! ## Errors //! -//! The [KyberLibError](enum.KyberLibError.html) enum handles errors with two variants: +//! The [KyberLibError](https://docs.rs/kyberlib/latest/kyberlib/error/enum.KyberLibError.html) enum handles errors with two variants: //! -//! - **InvalidInput**: Occurs when one or more byte inputs to a function are incorrectly sized. This typically happens when two parties use different security levels while attempting to negotiate a key exchange. -//! - **Decapsulation**: This error indicates that the ciphertext could not be authenticated, and the shared secret was not successfully decapsulated. +//! - **InvalidInput** - One or more inputs to a function are incorrectly sized. A possible cause of this is two parties using different security levels while trying to negotiate a key exchange. +//! - **InvalidKey** - Error when generating keys. +//! - **Decapsulation** - The ciphertext was unable to be authenticated. The shared secret was not decapsulated. +//! - **RandomBytesGeneration** - Error trying to fill random bytes (i.e., external (hardware) RNG modules can fail). //! #![doc( html_favicon_url = "https://kura.pro/kyberlib/images/favicon.ico", From d3a926bb240e58ccb9bdfed484d19cc3c0ef4d7d Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Thu, 9 May 2024 19:31:53 +0100 Subject: [PATCH 8/9] fix(kyberlib): :bug: fix derive declarations --- Cargo.toml | 15 +++++++++------ README.md | 12 +++++++----- src/error.rs | 2 +- src/wasm.rs | 2 +- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d9fd415..012c5f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ repository = "https://github.com/sebastienrousseau/kyberlib" version = "0.0.5" [dependencies] +# Dependencies for the library aes = { version = "0.8.4", optional = true } ctr = { version = "0.9.2", optional = true } pqc_core = { version = "0.3.0", features = ["zero"]} @@ -45,18 +46,20 @@ wasm-bindgen = "0.2.92" zeroize = { version = "1.7.0", features = ["derive"] } [dev-dependencies] +# Dependencies for testing criterion = "0.5.1" -rand = "0.8.5" wasm-bindgen-test = "0.3.42" # benchmarking = ["criterion"] [build-dependencies] +# Dependencies for the build script cc = {version = "1.0.97", optional = true } nasm-rs = {version = "0.3.0", optional = true } [lib] -crate-type = ["cdylib", "rlib"] +# Metadata about the library +crate-type = ["cdylib", "rlib", "staticlib"] name = "kyberlib" path = "src/lib.rs" @@ -110,12 +113,12 @@ std = [] ## Warn # box_pointers = "warn" -# missing_copy_implementations = "warn" -# missing_docs = "warn" -# unstable_features = "warn" +missing_copy_implementations = "warn" +missing_docs = "warn" +unstable_features = "warn" # unused_crate_dependencies = "warn" # unused_extern_crates = "warn" -# unused_results = "warn" +unused_results = "warn" ## Allow bare_trait_objects = "allow" diff --git a/README.md b/README.md index 94775a0..83ea60d 100644 --- a/README.md +++ b/README.md @@ -244,7 +244,7 @@ cargo run --example uake ### Platform support -`kyberlib` is supported and tested on MacOS, Linux, and Windows. The [GitHub Actions][10] shows the platforms in which the `kyberlib` library tests are run. +`kyberlib` supports a variety of CPU architectures. It is supported and tested on MacOS, Linux, and Windows. ### Documentation @@ -258,8 +258,10 @@ backward compatibility, `kyberlib` follows [semantic versioning][06]. ## License 📝 -The project is licensed under the terms of Apache License, Version 2.0 and the -MIT license. +KyberLib is distributed under the terms of both the MIT license and the +Apache License (Version 2.0). + +See [LICENSE-APACHE][01] and [LICENSE-MIT][02] for details. ## Contribution 🤝 @@ -289,7 +291,8 @@ A special thank you goes to the [Rust Reddit][12] community for providing a lot of useful suggestions on how to improve this project. [00]: https://kyberlib.com/ "KyberLib, A Robust Rust Library for CRYSTALS-Kyber Post-Quantum Cryptography" -[02]: http://opensource.org/licenses/MIT "KyberLib license" +[01]: http://opensource.org/licenses/Apache-2.0 "Apache License, Version 2.0" +[02]: http://opensource.org/licenses/MIT "MIT License" [03]: https://github.com/sebastienrousseau/kyberlib/kyberlib/issues "KyberLib Issues" [04]: https://github.com/sebastienrousseau/kyberlib/kyberlib/blob/main/CONTRIBUTING.md "KyberLib Contributing Guidelines" [05]: https://github.com/sebastienrousseau/kyberlib/kyberlib/graphs/contributors "KyberLib Contributors" @@ -297,7 +300,6 @@ providing a lot of useful suggestions on how to improve this project. [07]: https://crates.io/crates/kyberlib "KyberLib on Crates.io" [08]: https://docs.rs/kyberlib "KyberLib on Docs.rs" [09]: https://lib.rs/crates/kyberlib "KyberLib on Lib.rs" -[10]: https://github.com/sebastienrousseau/kyberlib/kyberlib/actions "KyberLib on GitHub Actions" [11]: https://www.rust-lang.org/policies/code-of-conduct "KyberLib Code of Conduct" [12]: https://www.reddit.com/r/rust/ "Reddit" [13]: https://www.rust-lang.org/learn/get-started "Rust" diff --git a/src/error.rs b/src/error.rs index f209ca6..8e825e4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT /// Error types for the failure modes in Kyber key exchange. -#[derive(Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum KyberLibError { /// One or more inputs to a function are incorrectly sized. A likely cause of this is /// two parties using different security levels while trying to negotiate a key exchange. diff --git a/src/wasm.rs b/src/wasm.rs index d8ce294..f55586a 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -184,7 +184,7 @@ impl Kex { /// Represents Kyber parameters. #[wasm_bindgen] -#[derive(Debug)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Params { /// The size of public key bytes. #[wasm_bindgen(readonly)] From c3989ccaca109fe45cc66e048318008c65d26501 Mon Sep 17 00:00:00 2001 From: Sebastien Rousseau Date: Thu, 9 May 2024 20:09:21 +0100 Subject: [PATCH 9/9] test(kyberlib): :bug: address the warning about the unused result of type `Box` --- tests/test_wasm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_wasm.rs b/tests/test_wasm.rs index 1eeb9a8..cd31c2f 100644 --- a/tests/test_wasm.rs +++ b/tests/test_wasm.rs @@ -147,8 +147,8 @@ mod tests { vec![0u8; KYBER_PUBLIC_KEY_BYTES - 1].into_boxed_slice(); // Call Kex::new() with the invalid public key and expect a panic - std::panic::catch_unwind(|| { - Kex::new(invalid_pk); + let _ = std::panic::catch_unwind(|| { + let _ = Kex::new(invalid_pk); }) .unwrap_err(); }