diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-19 09:26:03 +0000 |
commit | 9918693037dce8aa4bb6f08741b6812923486c18 (patch) | |
tree | 21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /vendor/orion | |
parent | Releasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff) | |
download | rustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip |
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/orion')
26 files changed, 2700 insertions, 86 deletions
diff --git a/vendor/orion/.cargo-checksum.json b/vendor/orion/.cargo-checksum.json index 2c7666e85..c5bbf78a1 100644 --- a/vendor/orion/.cargo-checksum.json +++ b/vendor/orion/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"50c3dc7c847a954271d6fb3bf98040a23bfb1447658deeb5cc8208014302bb49","CONTRIBUTING.md":"2e70efc8cc811b6f05f889d2cdb6cb8fe4f1c7ecbe628a2db49e0f0fe8b07142","Cargo.toml":"cb26d7f0d5e71db0acaab42ec5aedea9967d333e777d1548d3c90ff386002912","LICENSE":"d077f4de8cd932e30f9d15dca609e12b093b9a78c36e3c4a2a421fa9f9ed3760","README.md":"baeefcb09fd6c21bb63a7e46698fe059ddcbbffe20a1757a6d0000c32d52af88","SECURITY.md":"374e065f2f624fabda6f9dba059609a81f8377f8d153f050fc9c59171eb62f7e","benches/bench.rs":"2fed74e4762117dde5452f6ba6be5edfd5c6f3355fcd25565dd11cdb77239b49","deny.toml":"e8b8b0af0503711bbbb045fb802aa587911161fd202b74cf485ad3b39f9f58d8","src/errors.rs":"5990c08528bba2b193fb2d717551c9bc5918bf0e68ea6df7d8ebbadb9a8c642a","src/hazardous/aead/chacha20poly1305.rs":"f26f5dbd3107fd74b72f1e5f31a35c0c41b52677646827a92c1bbbc2ed3835c4","src/hazardous/aead/mod.rs":"8455ebef75b4490c55c800467579aeaff304d75b69635087f56664e59611a2fe","src/hazardous/aead/streaming.rs":"d6b1a7f0adf64b4ff72a7a286748233287a110a8b4cdb89715d56fec5e1bef56","src/hazardous/aead/xchacha20poly1305.rs":"cde0c2186ad7eeacd1aed58bb20ced4ab2971d3f80cf26a60723e35a2d1ebd1a","src/hazardous/ecc/mod.rs":"c6e2359f0f7a688870225e4ce24cdd357fcccda6fe9344a1d645642eecbe2d2b","src/hazardous/ecc/x25519.rs":"c5d8c5e73b8fba986ca115fe21d8d1c9e50709a9c52c8796ac11e9fc438a69bd","src/hazardous/hash/blake2/blake2b.rs":"a6eaded794734e8c55ec6e9d3aff2dfd372780a5fe991a28c96b243d2f291246","src/hazardous/hash/blake2/mod.rs":"2eeae3d7e57ff0480260c43e8c907cc80e688f5b0f24b76717a2e06e17f2cf00","src/hazardous/hash/mod.rs":"7c5ed9fdb08cebe81770c25c248b8ef41473be3fc1cf5c01fe2096019fbfe9c2","src/hazardous/hash/sha2/mod.rs":"92901ab9e34f3a2ca27955090079533547ae0424d9b88ccb9af4fb77abac2b70","src/hazardous/hash/sha2/sha256.rs":"976b1ce55b9513c52e9912c2502fee89020be83042fbda963c2c397e1a3a16a9","src/hazardous/hash/sha2/sha384.rs":"73e567f8b359519cd68fc7d9246dcb3c1972296a6ecba4383f7a3cf238ff75b9","src/hazardous/hash/sha2/sha512.rs":"419344ec6c998e39b9f54cfc5206e0642f090b0d351df7128ecf422e6923b456","src/hazardous/kdf/argon2i.rs":"7dfc465975ba17b88bb78b00b1cb1aedef53d6c911ec6814c2ce7859515e7f79","src/hazardous/kdf/hkdf.rs":"06ff0eae15c066847546c812095350e18dabdae242874dc48bff5c6ca0f39e74","src/hazardous/kdf/mod.rs":"9305110c66f5c550ebade1c5836cd4e6b98d973688acb48fada8eec6bb2be955","src/hazardous/kdf/pbkdf2.rs":"b05d262d759e975c082da5b2a6b7732bd0c638d2e86b685087076c5c6b94e6a4","src/hazardous/mac/blake2b.rs":"95fa45b3038c1d84c8253b9a3e0c2d247050c6bcc08a24dc15a974c01a998b3b","src/hazardous/mac/hmac.rs":"398f78a3d74327af3c2b95d90892ff6e9e32111a299c31754226f87ae42af902","src/hazardous/mac/mod.rs":"e903ccaa200c767e04cf049fe2a943e29649459dab8919b56d11597b879f34e1","src/hazardous/mac/poly1305.rs":"1162dfda047968910b4339cc6af0ff955206811d90fddb9471e6b7c0a114faa0","src/hazardous/mod.rs":"a7dfcabb514e914f61d64fbc0b3da0b440ddf918bdef093f70d3af09d6df6f5b","src/hazardous/stream/chacha20.rs":"74caa20f8c01c84c46abefac25a23034e42f23283fe09cc5d21f6fb77f7c61b6","src/hazardous/stream/mod.rs":"4a17bdd8f6f4eddece7172ca974e84be9f52d9313bf8c4139750bbec73616a82","src/hazardous/stream/xchacha20.rs":"d3505b0556b3053a7e8402586e9f64e86eb5381dfdcfa4f2e7292c09c02c5e1e","src/high_level/aead.rs":"fad1b6988b6c27c3959aa2ebfc541d4dbb6f542bcd74baccc0aa2c9076209109","src/high_level/auth.rs":"f097441b50525f51f3a9f97a24f58ec39250e6203599218d9a9d556440bd7302","src/high_level/hash.rs":"00033ca3274161d70c07b11357724ff9d7c9ca0add2c8b7f991b6a61ca45b8c4","src/high_level/hltypes.rs":"73f6256509f12ad02d44803934a881e3826469973e47d5283fccdc6878978d19","src/high_level/kdf.rs":"3ca97c61e5f7158c471c3df760f83c825bc49e082978c5d9e183493bb618b54b","src/high_level/kex.rs":"dc9973f98bbfabd31b57299adf506c062f379115490de6addc1df2aa4ca5d448","src/high_level/mod.rs":"ec28cfd546bcdf468114f5a7717a30282b637fb5f0c1d7b8a163f90fec47ffb1","src/high_level/pwhash.rs":"3f30a2ea7c057fa074b2e0b90a565c525cc6c2224347dc3a7f91aaea29b9f827","src/lib.rs":"6ed6a80b6f0f40492a6b0eb746b337bd8adbbe471efabb3c8d507147533e602f","src/test_framework/aead_interface.rs":"b476bbd515ce06f647af4c7112d89c5e9a4ef11d2f22349d3043601b99a70dc1","src/test_framework/incremental_interface.rs":"70aaa65295e98cbcd48d9435673d8024efad6b85b888ef5cd774c92d69a4c382","src/test_framework/mod.rs":"eea0f1f8dacacb365f87d55278623c4746df10185b0732fcbd2c4abce7caab17","src/test_framework/streamcipher_interface.rs":"bc990773291d005f660e77a3abe1dafe78f42e78d1b9f31f3f2f101bf447d927","src/typedefs.rs":"811df47f87ae70e40a282ac8433678fa7415f99074846d56f92d94dc2b1fe1e7","src/util/endianness.rs":"23975059ec10fc71dcd0558ef5523071b90f6ca21169c0f6ef7cb710ad317776","src/util/mod.rs":"cb2946140bcd230644cb3e549807395512c4510f15c2e5acc51285d3cb3e6df3","src/util/u32x4.rs":"00087108b55bfd8f60bb0ce8c33fd5398c805f722dbaf48754ebb92e8e50faad","src/util/u64x4.rs":"b55c6349e3a8e5d2ceb9aaee927766d3867c213d3ae103cff762cd59b8830dfb"},"package":"cbe74a766292f94f7e69db5a7bf010eadd944f24186c463fe578a7e637582066"}
\ No newline at end of file +{"files":{"CHANGELOG.md":"738f8d806ee2d1ecedd4ac0212b32eebf2bce00562747baba4c34704d3d9c467","CONTRIBUTING.md":"2e70efc8cc811b6f05f889d2cdb6cb8fe4f1c7ecbe628a2db49e0f0fe8b07142","Cargo.toml":"8ca43de0e4d40f03e3e141024b53215b8aac14ad15a816794f385890b299b7a5","LICENSE":"d077f4de8cd932e30f9d15dca609e12b093b9a78c36e3c4a2a421fa9f9ed3760","README.md":"17d786fdfe85cf1b0b5145a2180358b82eb98786fed169ef3700e6517b63c2dc","SECURITY.md":"a6a07cb0ef0ddfbfaa06ebab644c5d82daee4c5ceac56d463f995c3bc79dd198","benches/bench.rs":"2fed74e4762117dde5452f6ba6be5edfd5c6f3355fcd25565dd11cdb77239b49","deny.toml":"da56c595699fa1ddff69d27233483d1e60698bd704645994aa55fd1c4173e6ad","src/errors.rs":"5990c08528bba2b193fb2d717551c9bc5918bf0e68ea6df7d8ebbadb9a8c642a","src/hazardous/aead/chacha20poly1305.rs":"2d44e79870c408cf121390091025c81234ad1e5881426a8b0b002a62170069c3","src/hazardous/aead/mod.rs":"8455ebef75b4490c55c800467579aeaff304d75b69635087f56664e59611a2fe","src/hazardous/aead/streaming.rs":"d6b1a7f0adf64b4ff72a7a286748233287a110a8b4cdb89715d56fec5e1bef56","src/hazardous/aead/xchacha20poly1305.rs":"cde0c2186ad7eeacd1aed58bb20ced4ab2971d3f80cf26a60723e35a2d1ebd1a","src/hazardous/cae/chacha20poly1305blake2b.rs":"1ea0f9832017d6c21a8e80e35009dbb2d3b49295f14d6254b420d5a6672dae0b","src/hazardous/cae/mod.rs":"33e8618ce037379bf77734cb4cf47204631493d51b849fb2554db09b4719c1ae","src/hazardous/cae/xchacha20poly1305blake2b.rs":"ac51c6899a5eba743a657537ca7036e5a192f5e38d8f810e5e29ab0912aae11f","src/hazardous/ecc/mod.rs":"c6e2359f0f7a688870225e4ce24cdd357fcccda6fe9344a1d645642eecbe2d2b","src/hazardous/ecc/x25519.rs":"44f84292181f5072cf13b99bdf6bf52919531f00e110a4f69b7bc912ecadf391","src/hazardous/hash/blake2/blake2b.rs":"a6eaded794734e8c55ec6e9d3aff2dfd372780a5fe991a28c96b243d2f291246","src/hazardous/hash/blake2/mod.rs":"2eeae3d7e57ff0480260c43e8c907cc80e688f5b0f24b76717a2e06e17f2cf00","src/hazardous/hash/mod.rs":"1cd124695688a6ec33fbd4ef3850752ac8f535ff4bb2ff60527fdc4be8bab88e","src/hazardous/hash/sha2/mod.rs":"92901ab9e34f3a2ca27955090079533547ae0424d9b88ccb9af4fb77abac2b70","src/hazardous/hash/sha2/sha256.rs":"d54eee36b96769255e89d4df615118027137ad50570fb23cfc02acd10bb3fc5f","src/hazardous/hash/sha2/sha384.rs":"f8fbfe922c0cfd684d53376d48ea406d8d3bde349f0d8b220ee531cdba93fbda","src/hazardous/hash/sha2/sha512.rs":"036d4610dc7e4657c39895a8d71f8b5279f344579cd5b71a3cf2a2da1e67d95e","src/hazardous/hash/sha3/mod.rs":"def5bd777e23a6920f0cb7d08265887ec661f05c9fe0505f8c31f0072aa091b3","src/hazardous/hash/sha3/sha3_224.rs":"3ac0c3abacb37be3ef46d820176e5d228a58ec9638b5f136c70af27a5f2b1e7c","src/hazardous/hash/sha3/sha3_256.rs":"3244dcf177e7c66c64e3b63888ccb977d6d85c448a124dd01172cc99c2c1cc81","src/hazardous/hash/sha3/sha3_384.rs":"cf1ba5ae04d92c6bd37ac989f55dd46f7fa9e2ca41fa5360815cb2553b28f8a4","src/hazardous/hash/sha3/sha3_512.rs":"c78d71628a28a9919eea00f2d9a9c5728f06feace52cf60d5b73edbc9c72fdbf","src/hazardous/kdf/argon2i.rs":"7dfc465975ba17b88bb78b00b1cb1aedef53d6c911ec6814c2ce7859515e7f79","src/hazardous/kdf/hkdf.rs":"06ff0eae15c066847546c812095350e18dabdae242874dc48bff5c6ca0f39e74","src/hazardous/kdf/mod.rs":"9305110c66f5c550ebade1c5836cd4e6b98d973688acb48fada8eec6bb2be955","src/hazardous/kdf/pbkdf2.rs":"b05d262d759e975c082da5b2a6b7732bd0c638d2e86b685087076c5c6b94e6a4","src/hazardous/kem/mod.rs":"c79611e899f54f7445b5fe0d642905f9c012bdfde18771ebbe4b0342a3c805e3","src/hazardous/kem/x25519_hkdf_sha256.rs":"e82fedfd188559c2f546546e75b658b27fdbd2be75eef3734b1911ee611d5fd9","src/hazardous/mac/blake2b.rs":"95fa45b3038c1d84c8253b9a3e0c2d247050c6bcc08a24dc15a974c01a998b3b","src/hazardous/mac/hmac.rs":"398f78a3d74327af3c2b95d90892ff6e9e32111a299c31754226f87ae42af902","src/hazardous/mac/mod.rs":"e903ccaa200c767e04cf049fe2a943e29649459dab8919b56d11597b879f34e1","src/hazardous/mac/poly1305.rs":"8b232b3a5e918f01c3e98e0833e7de1e7630f1075b67150f7fa7747b09d91f41","src/hazardous/mod.rs":"7958abfca996e3cb6cc7ce7a3cfeafec74857e746233b490b0ba4f27db52d41d","src/hazardous/stream/chacha20.rs":"74caa20f8c01c84c46abefac25a23034e42f23283fe09cc5d21f6fb77f7c61b6","src/hazardous/stream/mod.rs":"4a17bdd8f6f4eddece7172ca974e84be9f52d9313bf8c4139750bbec73616a82","src/hazardous/stream/xchacha20.rs":"d3505b0556b3053a7e8402586e9f64e86eb5381dfdcfa4f2e7292c09c02c5e1e","src/high_level/aead.rs":"fad1b6988b6c27c3959aa2ebfc541d4dbb6f542bcd74baccc0aa2c9076209109","src/high_level/auth.rs":"f097441b50525f51f3a9f97a24f58ec39250e6203599218d9a9d556440bd7302","src/high_level/hash.rs":"00033ca3274161d70c07b11357724ff9d7c9ca0add2c8b7f991b6a61ca45b8c4","src/high_level/hltypes.rs":"73f6256509f12ad02d44803934a881e3826469973e47d5283fccdc6878978d19","src/high_level/kdf.rs":"3ca97c61e5f7158c471c3df760f83c825bc49e082978c5d9e183493bb618b54b","src/high_level/kex.rs":"dc9973f98bbfabd31b57299adf506c062f379115490de6addc1df2aa4ca5d448","src/high_level/mod.rs":"ec28cfd546bcdf468114f5a7717a30282b637fb5f0c1d7b8a163f90fec47ffb1","src/high_level/pwhash.rs":"3f30a2ea7c057fa074b2e0b90a565c525cc6c2224347dc3a7f91aaea29b9f827","src/lib.rs":"6ed6a80b6f0f40492a6b0eb746b337bd8adbbe471efabb3c8d507147533e602f","src/test_framework/aead_interface.rs":"e801fa760804f4db14249902a2cf1b5cfa4b3d78eac44a89236c0aa0924784d5","src/test_framework/incremental_interface.rs":"70aaa65295e98cbcd48d9435673d8024efad6b85b888ef5cd774c92d69a4c382","src/test_framework/mod.rs":"eea0f1f8dacacb365f87d55278623c4746df10185b0732fcbd2c4abce7caab17","src/test_framework/streamcipher_interface.rs":"bc990773291d005f660e77a3abe1dafe78f42e78d1b9f31f3f2f101bf447d927","src/typedefs.rs":"811df47f87ae70e40a282ac8433678fa7415f99074846d56f92d94dc2b1fe1e7","src/util/endianness.rs":"49e9a661ffc5854830a3ca2c230cd6c41a0a8dd49403ace78da4475182b22fc9","src/util/mod.rs":"cb2946140bcd230644cb3e549807395512c4510f15c2e5acc51285d3cb3e6df3","src/util/u32x4.rs":"00087108b55bfd8f60bb0ce8c33fd5398c805f722dbaf48754ebb92e8e50faad","src/util/u64x4.rs":"b55c6349e3a8e5d2ceb9aaee927766d3867c213d3ae103cff762cd59b8830dfb"},"package":"7abdb10181903c8c4b016ba45d6d6d5af1a1e2a461aa4763a83b87f5df4695e5"}
\ No newline at end of file diff --git a/vendor/orion/CHANGELOG.md b/vendor/orion/CHANGELOG.md index e97f513a9..11105d214 100644 --- a/vendor/orion/CHANGELOG.md +++ b/vendor/orion/CHANGELOG.md @@ -1,3 +1,22 @@ +### 0.17.6 + +__Date:__ September 19, 2023. + +__Changelog:__ +- Bump MSRV to `1.70.0`. +- Bump `fiat-crypto` to `0.2.1`. + +### 0.17.5 + +__Date:__ July 4, 2023. + +__Changelog:__ +- Add `experimental` crate feature. +- Add support for fully-committing AEAD variants based on CTX ([#324](https://github.com/orion-rs/orion/pull/324)). +- Add support for SHA3 ([#327](https://github.com/orion-rs/orion/pull/327)). +- Bump MSRV to `1.64`. +- Add support for DHKEM(X25519, HKDF-SHA256) from HPKE [RFC 9180](https://www.rfc-editor.org/rfc/rfc9180). + ### 0.17.4 __Date:__ March 4, 2023. diff --git a/vendor/orion/Cargo.toml b/vendor/orion/Cargo.toml index 253c60a02..0c5cc9820 100644 --- a/vendor/orion/Cargo.toml +++ b/vendor/orion/Cargo.toml @@ -11,9 +11,9 @@ [package] edition = "2021" -rust-version = "1.59" +rust-version = "1.70" name = "orion" -version = "0.17.4" +version = "0.17.6" authors = ["brycx <brycx@protonmail.com>"] exclude = [ ".gitignore", @@ -56,7 +56,7 @@ version = "1.1.1" optional = true [dependencies.fiat-crypto] -version = "0.1.11" +version = "0.2.1" default-features = false [dependencies.getrandom] @@ -78,7 +78,7 @@ version = "1.1.0" default-features = false [dev-dependencies.criterion] -version = "0.4.0" +version = "0.5.0" [dev-dependencies.hex] version = "0.4.0" @@ -99,6 +99,7 @@ version = "1.0.41" [features] alloc = [] default = ["safe_api"] +experimental = [] safe_api = [ "getrandom", "ct-codecs", diff --git a/vendor/orion/README.md b/vendor/orion/README.md index 833cd3ba2..cfc9fe8e8 100644 --- a/vendor/orion/README.md +++ b/vendor/orion/README.md @@ -1,16 +1,20 @@ # orion -[![Tests](https://github.com/orion-rs/orion/workflows/Tests/badge.svg)](https://github.com/orion-rs/orion/actions) [![Daily tests](https://github.com/orion-rs/orion/workflows/Daily%20tests/badge.svg)](https://github.com/orion-rs/orion/actions) [![dudect](https://github.com/orion-rs/orion-dudect/workflows/dudect/badge.svg)](https://github.com/orion-rs/orion-dudect/actions) [![Audit](https://github.com/orion-rs/orion/actions/workflows/audit_check.yml/badge.svg)](https://github.com/orion-rs/orion/actions/workflows/audit_check.yml) [![codecov](https://codecov.io/gh/orion-rs/orion/branch/master/graph/badge.svg)](https://codecov.io/gh/orion-rs/orion) [![Documentation](https://docs.rs/orion/badge.svg)](https://docs.rs/orion/) [![Crates.io](https://img.shields.io/crates/v/orion.svg)](https://crates.io/crates/orion) [![Safety Dance](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/) [![MSRV](https://img.shields.io/badge/MSRV-1.59-informational.svg)](https://img.shields.io/badge/MSRV-1.59-informational) [![Matrix](https://img.shields.io/matrix/orion-rs:matrix.org.svg?logo=matrix)](https://matrix.to/#/#orion-rs:matrix.org) +[![Tests](https://github.com/orion-rs/orion/workflows/Tests/badge.svg)](https://github.com/orion-rs/orion/actions) [![Daily tests](https://github.com/orion-rs/orion/workflows/Daily%20tests/badge.svg)](https://github.com/orion-rs/orion/actions) [![dudect](https://github.com/orion-rs/orion-dudect/workflows/dudect/badge.svg)](https://github.com/orion-rs/orion-dudect/actions) [![Audit](https://github.com/orion-rs/orion/actions/workflows/audit_check.yml/badge.svg)](https://github.com/orion-rs/orion/actions/workflows/audit_check.yml) [![codecov](https://codecov.io/gh/orion-rs/orion/branch/master/graph/badge.svg)](https://codecov.io/gh/orion-rs/orion) [![Documentation](https://docs.rs/orion/badge.svg)](https://docs.rs/orion/) [![Crates.io](https://img.shields.io/crates/v/orion.svg)](https://crates.io/crates/orion) [![Safety Dance](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/) [![MSRV](https://img.shields.io/badge/MSRV-1.70-informational.svg)](https://img.shields.io/badge/MSRV-1.70-informational) [![Matrix](https://img.shields.io/matrix/orion-rs:matrix.org.svg?logo=matrix)](https://matrix.to/#/#orion-rs:matrix.org) ### About Orion is a cryptography library written in pure Rust. It aims to provide easy and usable crypto while trying to minimize the use of unsafe code. You can read more about Orion in the [wiki](https://github.com/orion-rs/orion/wiki). Currently supports: -* **AEAD**: (X)ChaCha20Poly1305. -* **Hashing**: BLAKE2b, SHA2. +* **AEAD**: (X)ChaCha20-Poly1305. +* **Hashing**: BLAKE2b, SHA2, SHA3. * **KDF**: HKDF, PBKDF2, Argon2i. * **Key exchange**: X25519. * **MAC**: HMAC, Poly1305. * **Stream ciphers**: (X)ChaCha20. +* **KEM**: DHKEM(X25519, HKDF-SHA256). + +Experimental support (with `experimental` feature enabled): +* **Committing AEAD**: (X)ChaCha20-Poly1305-BLAKE2b. ### Security This library has **not undergone any third-party security audit**. Usage is at **own risk**. @@ -20,7 +24,7 @@ Orion uses formally verified arithmetic, generated by Fiat Crypto, for the X2551 See the [SECURITY.md](https://github.com/orion-rs/orion/blob/master/SECURITY.md) regarding recommendations on correct use, reporting security issues and more. Additional information about security regarding Orion is available in the [wiki](https://github.com/orion-rs/orion/wiki/Security). ### Minimum Supported Rust Version -Rust 1.59 or later is supported however, the majority of testing happens with latest stable Rust. +Rust 1.70 or later is supported however, the majority of testing happens with latest stable Rust. MSRV may be changed at any point and will not be considered a SemVer breaking change. @@ -30,6 +34,7 @@ MSRV may be changed at any point and will not be considered a SemVer breaking ch - `serde`: Requires either `alloc` or `default`/`safe_api`. - `alloc`: Argon2i in `hazardous` when `default`/`safe_api` is not available. - `no_std`: Implicit feature that represents no heap allocations. Enabled by disabling default features and not selecting any additional features. +- `experimental`: These APIs may contain breaking changes in any non SemVer-breaking crate releases. More detailed explanation of the features in the [wiki](https://github.com/orion-rs/orion/wiki/Crate-features). diff --git a/vendor/orion/SECURITY.md b/vendor/orion/SECURITY.md index 6f3c9a565..ade4da392 100644 --- a/vendor/orion/SECURITY.md +++ b/vendor/orion/SECURITY.md @@ -1,5 +1,5 @@ ### Reporting security issues -All security issues should be reported to the author at [brycx@protonmail.com](mailto:brycx@protonmail.com). +All security issues should be reported using either GitHub [private vulnerability reporting](https://github.com/orion-rs/orion/security/advisories/new) or email the author at [brycx@protonmail.com](mailto:brycx@protonmail.com). We try to follow the [RFPolicy](https://en.wikipedia.org/wiki/RFPolicy), but with an initial response time of 2 weeks maximum. In practice, however, the initial response will most often be faster. @@ -34,4 +34,4 @@ These are recommendations on how to use Orion correctly: - Use `cargo audit` to ensure the current version has no published security vulnerabilities - Never use `opt-level=0`, always build in release mode -- Always use the latest version of Orion
\ No newline at end of file +- Always use the latest version of Orion diff --git a/vendor/orion/deny.toml b/vendor/orion/deny.toml index f0b0f321a..eb9e60cf4 100644 --- a/vendor/orion/deny.toml +++ b/vendor/orion/deny.toml @@ -11,14 +11,7 @@ yanked = "deny" notice = "deny" unsound = "deny" vulnerability = "deny" -ignore = [ - # serde_cbor is unmaintained, used in criterion. - # See https://github.com/bheisler/criterion.rs/issues/534 - "RUSTSEC-2021-0127", - # atty has unaligned read, used in criterion. - # See https://github.com/bheisler/criterion.rs/issues/629 - "RUSTSEC-2021-0145", -] +ignore = [] [licenses] unlicensed = "deny" diff --git a/vendor/orion/src/hazardous/aead/chacha20poly1305.rs b/vendor/orion/src/hazardous/aead/chacha20poly1305.rs index bc1175809..821125381 100644 --- a/vendor/orion/src/hazardous/aead/chacha20poly1305.rs +++ b/vendor/orion/src/hazardous/aead/chacha20poly1305.rs @@ -123,10 +123,10 @@ use core::convert::TryInto; use zeroize::Zeroizing; /// The initial counter used for encryption and decryption. -const ENC_CTR: u32 = 1; +pub(crate) const ENC_CTR: u32 = 1; /// The initial counter used for Poly1305 key generation. -const AUTH_CTR: u32 = 0; +pub(crate) const AUTH_CTR: u32 = 0; /// The maximum size of the plaintext (see [RFC 8439](https://www.rfc-editor.org/rfc/rfc8439#section-2.8)). pub const P_MAX: u64 = (u32::MAX as u64) * 64; @@ -147,7 +147,7 @@ pub(crate) fn poly1305_key_gen( } /// Authenticates the ciphertext, ad and their lengths. -fn process_authentication( +pub(crate) fn process_authentication( auth_ctx: &mut Poly1305, ad: &[u8], ciphertext: &[u8], diff --git a/vendor/orion/src/hazardous/cae/chacha20poly1305blake2b.rs b/vendor/orion/src/hazardous/cae/chacha20poly1305blake2b.rs new file mode 100644 index 000000000..19cef00fa --- /dev/null +++ b/vendor/orion/src/hazardous/cae/chacha20poly1305blake2b.rs @@ -0,0 +1,262 @@ +// MIT License + +// Copyright (c) 2023 The orion Developers + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//! # About +//! This provides a fully committing AEAD, using the CTX construction proposed by Chan and Rogaway, +//! in the ["On Committing Authenticated Encryption"] paper. Specifically, CTX is instantiated with BLAKE2b-256. +//! +//! A fully committing AEAD is important if attacks like the [partitioning oracle attack] are a part of the threat model. +//! +//! # Parameters: +//! - `secret_key`: The secret key. +//! - `nonce`: The nonce value. +//! - `ad`: Additional data to authenticate (this is not encrypted and can be [`None`]). +//! - `ciphertext_with_tag`: The encrypted data with the corresponding 32 byte +//! BLAKE2b tag appended to it. +//! - `plaintext`: The data to be encrypted. +//! - `dst_out`: Destination array that will hold the +//! `ciphertext_with_tag`/`plaintext` after encryption/decryption. +//! +//! `ad`: "A typical use for these data is to authenticate version numbers, +//! timestamps or monotonically increasing counters in order to discard previous +//! messages and prevent replay attacks." See [libsodium docs] for more information. +//! +//! `nonce`: "Counters and LFSRs are both acceptable ways of generating unique +//! nonces, as is encrypting a counter using a block cipher with a 64-bit block +//! size such as DES. Note that it is not acceptable to use a truncation of a +//! counter encrypted with block ciphers with 128-bit or 256-bit blocks, +//! because such a truncation may repeat after a short time." See [RFC] for more information. +//! +//! `dst_out`: The output buffer may have a capacity greater than the input. If this is the case, +//! only the first input length amount of bytes in `dst_out` are modified, while the rest remain untouched. +//! +//! # Errors: +//! An error will be returned if: +//! - The length of `dst_out` is less than `plaintext` + [`TAG_SIZE`] when calling [`seal()`]. +//! - The length of `dst_out` is less than `ciphertext_with_tag` - [`TAG_SIZE`] when +//! calling [`open()`]. +//! - The length of `ciphertext_with_tag` is not at least [`TAG_SIZE`]. +//! - The received tag does not match the calculated tag when calling [`open()`]. +//! - `plaintext.len()` + [`TAG_SIZE`] overflows when calling [`seal()`]. +//! - Converting `usize` to `u64` would be a lossy conversion. +//! - `plaintext.len() >` [`P_MAX`] +//! - `ad.len() >` [`A_MAX`] +//! - `ciphertext_with_tag.len() >` [`C_MAX`] +//! +//! # Panics: +//! A panic will occur if: +//! - More than `2^32-1 * 64` bytes of data are processed. +//! +//! # Security: +//! - It is critical for security that a given nonce is not re-used with a given +//! key. Should this happen, the security of all data that has been encrypted +//! with that given key is compromised. +//! - Only a nonce for XChaCha20Poly1305 is big enough to be randomly generated +//! using a CSPRNG. +//! - To securely generate a strong key, use [`SecretKey::generate()`]. +//! - The length of the `plaintext` is not hidden, only its contents. +//! +//! # Recommendation: +//! - It is recommended to use [`XChaCha20Poly1305-BLAKE2b`] when possible. +//! +//! # Example: +//! ```rust +//! # #[cfg(feature = "safe_api")] { +//! use orion::hazardous::cae; +//! +//! let secret_key = cae::chacha20poly1305blake2b::SecretKey::generate(); +//! +//! // WARNING: This nonce is only meant for demonstration and should not +//! // be repeated. Please read the security section. +//! let nonce = cae::chacha20poly1305blake2b::Nonce::from([0u8; 12]); +//! let ad = "Additional data".as_bytes(); +//! let message = "Data to protect".as_bytes(); +//! +//! // Length of the above message is 15 and then we accommodate 32 for the BLAKE2b +//! // tag. +//! +//! let mut dst_out_ct = [0u8; 15 + 32]; +//! let mut dst_out_pt = [0u8; 15]; +//! // Encrypt and place ciphertext + tag in dst_out_ct +//! cae::chacha20poly1305blake2b::seal(&secret_key, &nonce, message, Some(&ad), &mut dst_out_ct)?; +//! // Verify tag, if correct then decrypt and place message in dst_out_pt +//! cae::chacha20poly1305blake2b::open(&secret_key, &nonce, &dst_out_ct, Some(&ad), &mut dst_out_pt)?; +//! +//! assert_eq!(dst_out_pt.as_ref(), message.as_ref()); +//! # } +//! # Ok::<(), orion::errors::UnknownCryptoError>(()) +//! ``` +//! [`SecretKey::generate()`]: super::stream::chacha20::SecretKey::generate +//! [`XChaCha20Poly1305-BLAKE2b`]: xchacha20poly1305blake2b +//! [`TAG_SIZE`]: chacha20poly1305blake2b::TAG_SIZE +//! [`seal()`]: chacha20poly1305blake2b::seal +//! [`open()`]: chacha20poly1305blake2b::open +//! [RFC]: https://tools.ietf.org/html/rfc8439#section-3 +//! [libsodium docs]: https://download.libsodium.org/doc/secret-key_cryptography/aead#additional-data +//! [`P_MAX`]: chacha20poly1305blake2b::P_MAX +//! [`A_MAX`]: chacha20poly1305blake2b::A_MAX +//! [`C_MAX`]: chacha20poly1305blake2b::C_MAX +//! ["On Committing Authenticated Encryption"]: https://eprint.iacr.org/2022/1260 +//! [partitioning oracle attack]: https://www.usenix.org/conference/usenixsecurity21/presentation/len + +use crate::errors::UnknownCryptoError; +use crate::hazardous::aead; +use crate::hazardous::aead::chacha20poly1305::{poly1305_key_gen, process_authentication, ENC_CTR}; +use crate::hazardous::hash::blake2::blake2b::Blake2b; +use crate::hazardous::mac::poly1305::Poly1305; +use crate::hazardous::mac::poly1305::POLY1305_OUTSIZE; +use crate::hazardous::stream::chacha20::{self, ChaCha20, CHACHA_BLOCKSIZE}; +use crate::util; +use zeroize::Zeroizing; + +pub use crate::hazardous::aead::chacha20poly1305::A_MAX; +pub use crate::hazardous::aead::chacha20poly1305::P_MAX; +pub use crate::hazardous::stream::chacha20::{Nonce, SecretKey}; + +/// The size of the BLAKE2b authentication tag. +pub const TAG_SIZE: usize = 32; + +/// The maximum size of the ciphertext. +pub const C_MAX: u64 = P_MAX + (TAG_SIZE as u64); + +#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] +/// CTX ChaCha20Poly1305 with BLAKE2b-256. +pub fn seal( + secret_key: &SecretKey, + nonce: &Nonce, + plaintext: &[u8], + ad: Option<&[u8]>, + dst_out: &mut [u8], +) -> Result<(), UnknownCryptoError> { + if u64::try_from(plaintext.len()).map_err(|_| UnknownCryptoError)? > P_MAX { + return Err(UnknownCryptoError); + } + + let ad = ad.unwrap_or(&[0u8; 0]); + #[allow(clippy::absurd_extreme_comparisons)] + if u64::try_from(ad.len()).map_err(|_| UnknownCryptoError)? > A_MAX { + return Err(UnknownCryptoError); + } + + match plaintext.len().checked_add(TAG_SIZE) { + Some(out_min_len) => { + if dst_out.len() < out_min_len { + return Err(UnknownCryptoError); + } + } + None => return Err(UnknownCryptoError), + }; + + aead::chacha20poly1305::seal( + secret_key, + nonce, + plaintext, + Some(ad), + &mut dst_out[..plaintext.len() + POLY1305_OUTSIZE], + )?; + + let mut blake2b = Blake2b::new(32)?; + blake2b.update(secret_key.unprotected_as_bytes())?; + blake2b.update(nonce.as_ref())?; + blake2b.update(ad)?; + blake2b.update(&dst_out[plaintext.len()..plaintext.len() + POLY1305_OUTSIZE])?; + let tag = blake2b.finalize()?; + + dst_out[plaintext.len()..plaintext.len() + TAG_SIZE].copy_from_slice(tag.as_ref()); + + Ok(()) +} + +#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] +/// CTX ChaCha20Poly1305 with BLAKE2b-256. +pub fn open( + secret_key: &SecretKey, + nonce: &Nonce, + ciphertext_with_tag: &[u8], + ad: Option<&[u8]>, + dst_out: &mut [u8], +) -> Result<(), UnknownCryptoError> { + if u64::try_from(ciphertext_with_tag.len()).map_err(|_| UnknownCryptoError)? > C_MAX { + return Err(UnknownCryptoError); + } + let ad = ad.unwrap_or(&[0u8; 0]); + #[allow(clippy::absurd_extreme_comparisons)] + if u64::try_from(ad.len()).map_err(|_| UnknownCryptoError)? > A_MAX { + return Err(UnknownCryptoError); + } + if ciphertext_with_tag.len() < TAG_SIZE { + return Err(UnknownCryptoError); + } + if dst_out.len() < ciphertext_with_tag.len() - TAG_SIZE { + return Err(UnknownCryptoError); + } + + let mut blake2b = Blake2b::new(32)?; + blake2b.update(secret_key.unprotected_as_bytes())?; + blake2b.update(nonce.as_ref())?; + blake2b.update(ad)?; + + let mut dec_ctx = + ChaCha20::new(secret_key.unprotected_as_bytes(), nonce.as_ref(), true).unwrap(); + let mut tmp = Zeroizing::new([0u8; CHACHA_BLOCKSIZE]); + let mut auth_ctx = Poly1305::new(&poly1305_key_gen(&mut dec_ctx, &mut tmp)); + + let ciphertext_len = ciphertext_with_tag.len() - TAG_SIZE; + process_authentication(&mut auth_ctx, ad, &ciphertext_with_tag[..ciphertext_len])?; + + blake2b.update(auth_ctx.finalize()?.unprotected_as_bytes())?; + + util::secure_cmp( + blake2b.finalize()?.as_ref(), + &ciphertext_with_tag[ciphertext_len..], + )?; + + if ciphertext_len != 0 { + dst_out[..ciphertext_len].copy_from_slice(&ciphertext_with_tag[..ciphertext_len]); + chacha20::xor_keystream( + &mut dec_ctx, + ENC_CTR, + tmp.as_mut(), + &mut dst_out[..ciphertext_len], + )?; + } + + Ok(()) +} + +// Testing public functions in the module. +#[cfg(test)] +#[cfg(feature = "safe_api")] +mod public { + use super::*; + use crate::test_framework::aead_interface::{test_diff_params_err, AeadTestRunner}; + + #[quickcheck] + #[cfg(feature = "safe_api")] + fn prop_aead_interface(input: Vec<u8>, ad: Vec<u8>) -> bool { + let secret_key = SecretKey::generate(); + let nonce = Nonce::from_slice(&[0u8; chacha20::IETF_CHACHA_NONCESIZE]).unwrap(); + AeadTestRunner(seal, open, secret_key, nonce, &input, None, TAG_SIZE, &ad); + test_diff_params_err(&seal, &open, &input, TAG_SIZE); + true + } +} diff --git a/vendor/orion/src/hazardous/cae/mod.rs b/vendor/orion/src/hazardous/cae/mod.rs new file mode 100644 index 000000000..270821b61 --- /dev/null +++ b/vendor/orion/src/hazardous/cae/mod.rs @@ -0,0 +1,33 @@ +// MIT License + +// Copyright (c) 2023 The orion Developers + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#![cfg_attr(docsrs, doc(cfg(feature = "experimental")))] + +/// Fully-committing ChaCha20-Poly1305 with BLAKE2b based on the [CTX] construction by John Chan & Phillip Rogaway. +/// +/// [CTX]: https://eprint.iacr.org/2022/1260 +pub mod chacha20poly1305blake2b; + +/// Fully-committing XChaCha20-Poly1305 with BLAKE2b based on the [CTX] construction by John Chan & Phillip Rogaway. +/// +/// [CTX]: https://eprint.iacr.org/2022/1260 +pub mod xchacha20poly1305blake2b; diff --git a/vendor/orion/src/hazardous/cae/xchacha20poly1305blake2b.rs b/vendor/orion/src/hazardous/cae/xchacha20poly1305blake2b.rs new file mode 100644 index 000000000..25d3c32ef --- /dev/null +++ b/vendor/orion/src/hazardous/cae/xchacha20poly1305blake2b.rs @@ -0,0 +1,246 @@ +// MIT License + +// Copyright (c) 2023 The orion Developers + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//! # About +//! This provides a fully committing AEAD, using the CTX construction proposed by Chan and Rogaway, +//! in the ["On Committing Authenticated Encryption"] paper. Specifically, CTX is instantiated with BLAKE2b-256. +//! +//! A fully committing AEAD is important if attacks like the [partitioning oracle attack] are a part of the threat model. +//! +//! # Parameters: +//! - `secret_key`: The secret key. +//! - `nonce`: The nonce value. +//! - `ad`: Additional data to authenticate (this is not encrypted and can be [`None`]). +//! - `ciphertext_with_tag`: The encrypted data with the corresponding 32 byte +//! BLAKE2b tag appended to it. +//! - `plaintext`: The data to be encrypted. +//! - `dst_out`: Destination array that will hold the +//! `ciphertext_with_tag`/`plaintext` after encryption/decryption. +//! +//! `ad`: "A typical use for these data is to authenticate version numbers, +//! timestamps or monotonically increasing counters in order to discard previous +//! messages and prevent replay attacks." See [libsodium docs] for more information. +//! +//! `dst_out`: The output buffer may have a capacity greater than the input. If this is the case, +//! only the first input length amount of bytes in `dst_out` are modified, while the rest remain untouched. +//! +//! # Errors: +//! An error will be returned if: +//! - The length of `dst_out` is less than `plaintext` + [`TAG_SIZE`] when calling [`seal()`]. +//! - The length of `dst_out` is less than `ciphertext_with_tag` - [`TAG_SIZE`] when +//! calling [`open()`]. +//! - The length of `ciphertext_with_tag` is not at least [`TAG_SIZE`]. +//! - The received tag does not match the calculated tag when calling [`open()`]. +//! - `plaintext.len()` + [`TAG_SIZE`] overflows when calling [`seal()`]. +//! - Converting `usize` to `u64` would be a lossy conversion. +//! - `plaintext.len() >` [`P_MAX`] +//! - `ad.len() >` [`A_MAX`] +//! - `ciphertext_with_tag.len() >` [`C_MAX`] +//! +//! # Panics: +//! A panic will occur if: +//! - More than `2^32-1 * 64` bytes of data are processed. +//! +//! # Security: +//! - It is critical for security that a given nonce is not re-used with a given +//! key. Should this happen, the security of all data that has been encrypted +//! with that given key is compromised. +//! - Only a nonce for XChaCha20Poly1305 is big enough to be randomly generated +//! using a CSPRNG. [`Nonce::generate()`] can be used for this. +//! - To securely generate a strong key, use [`SecretKey::generate()`]. +//! - The length of the `plaintext` is not hidden, only its contents. +//! +//! # Example: +//! ```rust +//! # #[cfg(feature = "safe_api")] { +//! use orion::hazardous::cae; +//! +//! let secret_key = cae::xchacha20poly1305blake2b::SecretKey::generate(); +//! let nonce = cae::xchacha20poly1305blake2b::Nonce::generate(); +//! let ad = "Additional data".as_bytes(); +//! let message = "Data to protect".as_bytes(); +//! +//! // Length of the above message is 15 and then we accommodate 32 for the BLAKE2b +//! // tag. +//! +//! let mut dst_out_ct = [0u8; 15 + 32]; +//! let mut dst_out_pt = [0u8; 15]; +//! // Encrypt and place ciphertext + tag in dst_out_ct +//! cae::xchacha20poly1305blake2b::seal(&secret_key, &nonce, message, Some(&ad), &mut dst_out_ct)?; +//! // Verify tag, if correct then decrypt and place message in dst_out_pt +//! cae::xchacha20poly1305blake2b::open(&secret_key, &nonce, &dst_out_ct, Some(&ad), &mut dst_out_pt)?; +//! +//! assert_eq!(dst_out_pt.as_ref(), message.as_ref()); +//! # } +//! # Ok::<(), orion::errors::UnknownCryptoError>(()) +//! ``` +//! [`SecretKey::generate()`]: super::stream::chacha20::SecretKey::generate +//! [`Nonce::generate()`]: super::stream::xchacha20::Nonce::generate +//! [`TAG_SIZE`]: xchacha20poly1305blake2b::TAG_SIZE +//! [`seal()`]: xchacha20poly1305blake2b::seal +//! [`open()`]: xchacha20poly1305blake2b::open +//! [RFC]: https://tools.ietf.org/html/rfc8439#section-3 +//! [libsodium docs]: https://download.libsodium.org/doc/secret-key_cryptography/aead#additional-data +//! [`P_MAX`]: xchacha20poly1305blake2b::P_MAX +//! [`A_MAX`]: xchacha20poly1305blake2b::A_MAX +//! [`C_MAX`]: xchacha20poly1305blake2b::C_MAX +//! ["On Committing Authenticated Encryption"]: https://eprint.iacr.org/2022/1260 +//! [partitioning oracle attack]: https://www.usenix.org/conference/usenixsecurity21/presentation/len + +use crate::errors::UnknownCryptoError; +use crate::hazardous::aead; +pub use crate::hazardous::aead::chacha20poly1305::A_MAX; +pub use crate::hazardous::aead::chacha20poly1305::P_MAX; +use crate::hazardous::aead::chacha20poly1305::{poly1305_key_gen, process_authentication, ENC_CTR}; +pub use crate::hazardous::cae::chacha20poly1305blake2b::{C_MAX, TAG_SIZE}; +use crate::hazardous::hash::blake2::blake2b::Blake2b; +use crate::hazardous::mac::poly1305::{Poly1305, POLY1305_OUTSIZE}; +use crate::hazardous::stream::chacha20::{self, ChaCha20, CHACHA_BLOCKSIZE}; +use crate::hazardous::stream::xchacha20::subkey_and_nonce; +pub use crate::hazardous::stream::{chacha20::SecretKey, xchacha20::Nonce}; +use crate::util; +use zeroize::Zeroizing; + +#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] +/// CTX XChaCha20Poly1305 with BLAKE2b-256. +pub fn seal( + secret_key: &SecretKey, + nonce: &Nonce, + plaintext: &[u8], + ad: Option<&[u8]>, + dst_out: &mut [u8], +) -> Result<(), UnknownCryptoError> { + if u64::try_from(plaintext.len()).map_err(|_| UnknownCryptoError)? > P_MAX { + return Err(UnknownCryptoError); + } + + let ad = ad.unwrap_or(&[0u8; 0]); + #[allow(clippy::absurd_extreme_comparisons)] + if u64::try_from(ad.len()).map_err(|_| UnknownCryptoError)? > A_MAX { + return Err(UnknownCryptoError); + } + + match plaintext.len().checked_add(TAG_SIZE) { + Some(out_min_len) => { + if dst_out.len() < out_min_len { + return Err(UnknownCryptoError); + } + } + None => return Err(UnknownCryptoError), + }; + + let (subkey, ietf_nonce) = subkey_and_nonce(secret_key, nonce); + aead::chacha20poly1305::seal( + &subkey, + &ietf_nonce, + plaintext, + Some(ad), + &mut dst_out[..plaintext.len() + POLY1305_OUTSIZE], + )?; + + let mut blake2b = Blake2b::new(32)?; + blake2b.update(secret_key.unprotected_as_bytes())?; + blake2b.update(nonce.as_ref())?; + blake2b.update(ad)?; + blake2b.update(&dst_out[plaintext.len()..plaintext.len() + POLY1305_OUTSIZE])?; + let tag = blake2b.finalize()?; + + dst_out[plaintext.len()..plaintext.len() + TAG_SIZE].copy_from_slice(tag.as_ref()); + + Ok(()) +} + +#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] +/// CTX XChaCha20Poly1305 with BLAKE2b-256. +pub fn open( + secret_key: &SecretKey, + nonce: &Nonce, + ciphertext_with_tag: &[u8], + ad: Option<&[u8]>, + dst_out: &mut [u8], +) -> Result<(), UnknownCryptoError> { + if u64::try_from(ciphertext_with_tag.len()).map_err(|_| UnknownCryptoError)? > C_MAX { + return Err(UnknownCryptoError); + } + let ad = ad.unwrap_or(&[0u8; 0]); + #[allow(clippy::absurd_extreme_comparisons)] + if u64::try_from(ad.len()).map_err(|_| UnknownCryptoError)? > A_MAX { + return Err(UnknownCryptoError); + } + if ciphertext_with_tag.len() < TAG_SIZE { + return Err(UnknownCryptoError); + } + if dst_out.len() < ciphertext_with_tag.len() - TAG_SIZE { + return Err(UnknownCryptoError); + } + + let mut blake2b = Blake2b::new(32)?; + blake2b.update(secret_key.unprotected_as_bytes())?; + blake2b.update(nonce.as_ref())?; + blake2b.update(ad)?; + + let (subkey, ietf_nonce) = subkey_and_nonce(secret_key, nonce); + let mut dec_ctx = + ChaCha20::new(subkey.unprotected_as_bytes(), ietf_nonce.as_ref(), true).unwrap(); + let mut tmp = Zeroizing::new([0u8; CHACHA_BLOCKSIZE]); + let mut auth_ctx = Poly1305::new(&poly1305_key_gen(&mut dec_ctx, &mut tmp)); + + let ciphertext_len = ciphertext_with_tag.len() - TAG_SIZE; + process_authentication(&mut auth_ctx, ad, &ciphertext_with_tag[..ciphertext_len])?; + + blake2b.update(auth_ctx.finalize()?.unprotected_as_bytes())?; + + util::secure_cmp( + blake2b.finalize()?.as_ref(), + &ciphertext_with_tag[ciphertext_len..], + )?; + + if ciphertext_len != 0 { + dst_out[..ciphertext_len].copy_from_slice(&ciphertext_with_tag[..ciphertext_len]); + chacha20::xor_keystream( + &mut dec_ctx, + ENC_CTR, + tmp.as_mut(), + &mut dst_out[..ciphertext_len], + )?; + } + + Ok(()) +} + +// Testing public functions in the module. +#[cfg(test)] +#[cfg(feature = "safe_api")] +mod public { + use super::*; + use crate::test_framework::aead_interface::{test_diff_params_err, AeadTestRunner}; + + #[quickcheck] + #[cfg(feature = "safe_api")] + fn prop_aead_interface(input: Vec<u8>, ad: Vec<u8>) -> bool { + let secret_key = SecretKey::generate(); + let nonce = Nonce::generate(); + AeadTestRunner(seal, open, secret_key, nonce, &input, None, TAG_SIZE, &ad); + test_diff_params_err(&seal, &open, &input, TAG_SIZE); + true + } +} diff --git a/vendor/orion/src/hazardous/ecc/x25519.rs b/vendor/orion/src/hazardous/ecc/x25519.rs index 4bbbbc869..806777feb 100644 --- a/vendor/orion/src/hazardous/ecc/x25519.rs +++ b/vendor/orion/src/hazardous/ecc/x25519.rs @@ -68,6 +68,11 @@ use core::ops::{Add, Mul, Sub}; /// Formally verified Curve25519 field arithmetic from: <https://github.com/mit-plv/fiat-crypto>. use fiat_crypto::curve25519_64 as fiat_curve25519_u64; +use fiat_curve25519_u64::{ + fiat_25519_add, fiat_25519_carry, fiat_25519_carry_mul, fiat_25519_carry_scmul_121666, + fiat_25519_carry_square, fiat_25519_loose_field_element, fiat_25519_relax, fiat_25519_sub, + fiat_25519_tight_field_element, +}; /// The size of a public key used in X25519. pub const PUBLIC_KEY_SIZE: usize = 32; @@ -86,9 +91,9 @@ const BASEPOINT: [u8; 32] = [ /// The result of computing a shared secret with a low order point. const LOW_ORDER_POINT_RESULT: [u8; 32] = [0u8; 32]; -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy)] /// Represent an element in the curve field. -struct FieldElement([u64; 5]); +struct FieldElement(fiat_25519_tight_field_element); impl Eq for FieldElement {} @@ -99,15 +104,25 @@ impl PartialEq for FieldElement { } } +impl core::fmt::Debug for FieldElement { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "FieldElement({:?})", &self.0 .0) + } +} + /// The function fiat_25519_carry_mul multiplies two field elements and reduces the result. impl Mul for FieldElement { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { - use fiat_curve25519_u64::fiat_25519_carry_mul; + let mut ret = fiat_25519_tight_field_element([0u64; 5]); + let mut self_relaxed = fiat_25519_loose_field_element([0u64; 5]); + let mut rhs_relaxed = fiat_25519_loose_field_element([0u64; 5]); + + fiat_25519_relax(&mut self_relaxed, &self.0); + fiat_25519_relax(&mut rhs_relaxed, &rhs.0); - let mut ret = [0u64; 5]; - fiat_25519_carry_mul(&mut ret, &self.0, &rhs.0); + fiat_25519_carry_mul(&mut ret, &self_relaxed, &rhs_relaxed); Self(ret) } @@ -118,12 +133,11 @@ impl Add for FieldElement { type Output = Self; fn add(self, rhs: Self) -> Self::Output { - use fiat_curve25519_u64::{fiat_25519_add, fiat_25519_carry}; + let mut ret = fiat_25519_tight_field_element([0u64; 5]); + let mut ret_add = fiat_25519_loose_field_element([0u64; 5]); - let mut ret = [0u64; 5]; - fiat_25519_add(&mut ret, &self.0, &rhs.0); - let tmp = ret; - fiat_25519_carry(&mut ret, &tmp); + fiat_25519_add(&mut ret_add, &self.0, &rhs.0); + fiat_25519_carry(&mut ret, &ret_add); Self(ret) } @@ -134,12 +148,11 @@ impl Sub for FieldElement { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { - use fiat_curve25519_u64::{fiat_25519_carry, fiat_25519_sub}; + let mut ret = fiat_25519_tight_field_element([0u64; 5]); + let mut ret_sub = fiat_25519_loose_field_element([0u64; 5]); - let mut ret = [0u64; 5]; - fiat_25519_sub(&mut ret, &self.0, &rhs.0); - let tmp = ret; - fiat_25519_carry(&mut ret, &tmp); + fiat_25519_sub(&mut ret_sub, &self.0, &rhs.0); + fiat_25519_carry(&mut ret, &ret_sub); Self(ret) } @@ -148,12 +161,16 @@ impl Sub for FieldElement { impl FieldElement { /// Create a `FieldElement` that is `0`. fn zero() -> Self { - Self([0u64, 0u64, 0u64, 0u64, 0u64]) + Self(fiat_25519_tight_field_element([ + 0u64, 0u64, 0u64, 0u64, 0u64, + ])) } /// Create a `FieldElement` that is `1`. fn one() -> Self { - Self([1u64, 0u64, 0u64, 0u64, 0u64]) + Self(fiat_25519_tight_field_element([ + 1u64, 0u64, 0u64, 0u64, 0u64, + ])) } /// Serialize the `FieldElement` as a byte-array. @@ -179,7 +196,7 @@ impl FieldElement { temp[31] &= 127u8; // See RFC: "When receiving such an array, implementations of X25519 // (but not X448) MUST mask the most significant bit in the final byte." - let mut ret = [0u64; 5]; + let mut ret = fiat_25519_tight_field_element([0u64; 5]); fiat_25519_from_bytes(&mut ret, &temp); Self(ret) @@ -196,26 +213,28 @@ impl FieldElement { let tmp_a = *a; let tmp_b = *b; - fiat_25519_selectznz(&mut a.0, swap, &tmp_a.0, &tmp_b.0); - fiat_25519_selectznz(&mut b.0, swap, &tmp_b.0, &tmp_a.0); + fiat_25519_selectznz(&mut a.0 .0, swap, &tmp_a.0 .0, &tmp_b.0 .0); + fiat_25519_selectznz(&mut b.0 .0, swap, &tmp_b.0 .0, &tmp_a.0 .0); } /// Square the `FieldElement` and reduce the result. fn square(&self) -> Self { - use fiat_curve25519_u64::fiat_25519_carry_square; + let mut self_relaxed = fiat_25519_loose_field_element([0u64; 5]); + let mut ret = fiat_25519_tight_field_element([0u64; 5]); - let mut ret = [0u64; 5]; - fiat_25519_carry_square(&mut ret, &self.0); + fiat_25519_relax(&mut self_relaxed, &self.0); + fiat_25519_carry_square(&mut ret, &self_relaxed); Self(ret) } /// Multiply the `FieldElement` by 121666 and reduce the result. fn mul_121666(&self) -> Self { - use fiat_curve25519_u64::fiat_25519_carry_scmul_121666; + let mut self_relaxed = fiat_25519_loose_field_element([0u64; 5]); + let mut ret = fiat_25519_tight_field_element([0u64; 5]); - let mut ret = [0u64; 5]; - fiat_25519_carry_scmul_121666(&mut ret, &self.0); + fiat_25519_relax(&mut self_relaxed, &self.0); + fiat_25519_carry_scmul_121666(&mut ret, &self_relaxed); Self(ret) } diff --git a/vendor/orion/src/hazardous/hash/mod.rs b/vendor/orion/src/hazardous/hash/mod.rs index ad3ac155e..01b04c22f 100644 --- a/vendor/orion/src/hazardous/hash/mod.rs +++ b/vendor/orion/src/hazardous/hash/mod.rs @@ -23,5 +23,8 @@ /// SHA2 as specified in the [FIPS PUB 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf). pub mod sha2; +/// SHA3 as specified in the [FIPS PUB 202](https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf). +pub mod sha3; + /// BLAKE2 hash functions. pub mod blake2; diff --git a/vendor/orion/src/hazardous/hash/sha2/sha256.rs b/vendor/orion/src/hazardous/hash/sha2/sha256.rs index 737660715..720d8053d 100644 --- a/vendor/orion/src/hazardous/hash/sha2/sha256.rs +++ b/vendor/orion/src/hazardous/hash/sha2/sha256.rs @@ -89,7 +89,7 @@ use super::w32::WordU32; /// SHA256 streaming state. pub(crate) struct V256; -impl Variant<WordU32, { N_CONSTS }> for V256 { +impl Variant<WordU32, N_CONSTS> for V256 { #[rustfmt::skip] #[allow(clippy::unreadable_literal)] /// The SHA256 constants as defined in FIPS 180-4. @@ -144,7 +144,7 @@ impl Variant<WordU32, { N_CONSTS }> for V256 { #[derive(Clone, Debug)] /// SHA256 streaming state. pub struct Sha256 { - pub(crate) _state: State<WordU32, V256, { SHA256_BLOCKSIZE }, { SHA256_OUTSIZE }, { N_CONSTS }>, + pub(crate) _state: State<WordU32, V256, SHA256_BLOCKSIZE, SHA256_OUTSIZE, N_CONSTS>, } impl Default for Sha256 { @@ -157,9 +157,7 @@ impl Sha256 { /// Initialize a `Sha256` struct. pub fn new() -> Self { Self { - _state: - State::<WordU32, V256, { SHA256_BLOCKSIZE }, { SHA256_OUTSIZE }, { N_CONSTS }>::_new( - ), + _state: State::<WordU32, V256, SHA256_BLOCKSIZE, SHA256_OUTSIZE, N_CONSTS>::_new(), } } diff --git a/vendor/orion/src/hazardous/hash/sha2/sha384.rs b/vendor/orion/src/hazardous/hash/sha2/sha384.rs index e4df99d7a..c0430512e 100644 --- a/vendor/orion/src/hazardous/hash/sha2/sha384.rs +++ b/vendor/orion/src/hazardous/hash/sha2/sha384.rs @@ -88,7 +88,7 @@ const N_CONSTS: usize = 80; #[derive(Clone)] pub(crate) struct V384; -impl Variant<WordU64, { N_CONSTS }> for V384 { +impl Variant<WordU64, N_CONSTS> for V384 { /// The SHA384 constants as defined in FIPS 180-4. const K: [WordU64; N_CONSTS] = super::sha512::V512::K; @@ -124,7 +124,7 @@ impl Variant<WordU64, { N_CONSTS }> for V384 { #[derive(Clone, Debug)] /// SHA384 streaming state. pub struct Sha384 { - pub(crate) _state: State<WordU64, V384, { SHA384_BLOCKSIZE }, { SHA384_OUTSIZE }, { N_CONSTS }>, + pub(crate) _state: State<WordU64, V384, SHA384_BLOCKSIZE, SHA384_OUTSIZE, N_CONSTS>, } impl Default for Sha384 { @@ -137,9 +137,7 @@ impl Sha384 { /// Initialize a `Sha384` struct. pub fn new() -> Self { Self { - _state: - State::<WordU64, V384, { SHA384_BLOCKSIZE }, { SHA384_OUTSIZE }, { N_CONSTS }>::_new( - ), + _state: State::<WordU64, V384, SHA384_BLOCKSIZE, SHA384_OUTSIZE, N_CONSTS>::_new(), } } diff --git a/vendor/orion/src/hazardous/hash/sha2/sha512.rs b/vendor/orion/src/hazardous/hash/sha2/sha512.rs index f582f78c2..0e865c57d 100644 --- a/vendor/orion/src/hazardous/hash/sha2/sha512.rs +++ b/vendor/orion/src/hazardous/hash/sha2/sha512.rs @@ -88,7 +88,7 @@ const N_CONSTS: usize = 80; #[derive(Clone)] pub(crate) struct V512; -impl Variant<WordU64, { N_CONSTS }> for V512 { +impl Variant<WordU64, N_CONSTS> for V512 { #[rustfmt::skip] #[allow(clippy::unreadable_literal)] /// The SHA512 constants as defined in FIPS 180-4. @@ -147,7 +147,7 @@ impl Variant<WordU64, { N_CONSTS }> for V512 { #[derive(Clone, Debug)] /// SHA512 streaming state. pub struct Sha512 { - pub(crate) _state: State<WordU64, V512, { SHA512_BLOCKSIZE }, { SHA512_OUTSIZE }, { N_CONSTS }>, + pub(crate) _state: State<WordU64, V512, SHA512_BLOCKSIZE, SHA512_OUTSIZE, N_CONSTS>, } impl Default for Sha512 { @@ -160,9 +160,7 @@ impl Sha512 { /// Initialize a `Sha512` struct. pub fn new() -> Self { Self { - _state: - State::<WordU64, V512, { SHA512_BLOCKSIZE }, { SHA512_OUTSIZE }, { N_CONSTS }>::_new( - ), + _state: State::<WordU64, V512, SHA512_BLOCKSIZE, SHA512_OUTSIZE, N_CONSTS>::_new(), } } diff --git a/vendor/orion/src/hazardous/hash/sha3/mod.rs b/vendor/orion/src/hazardous/hash/sha3/mod.rs new file mode 100644 index 000000000..28be25deb --- /dev/null +++ b/vendor/orion/src/hazardous/hash/sha3/mod.rs @@ -0,0 +1,558 @@ +// MIT License + +// Copyright (c) 2023 The orion Developers + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +/// SHA3-224 as specified in the [FIPS PUB 202](https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf). +pub mod sha3_224; + +/// SHA3-256 as specified in the [FIPS PUB 202](https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf). +pub mod sha3_256; + +/// SHA3-384 as specified in the [FIPS PUB 202](https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf). +pub mod sha3_384; + +/// SHA3-512 as specified in the [FIPS PUB 202](https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf). +pub mod sha3_512; + +use crate::errors::UnknownCryptoError; +use core::fmt::Debug; +use zeroize::Zeroize; + +/// Round constants. See NIST intermediate test vectors for source. +const RC: [u64; 24] = [ + 0x0000000000000001, + 0x0000000000008082, + 0x800000000000808A, + 0x8000000080008000, + 0x000000000000808B, + 0x0000000080000001, + 0x8000000080008081, + 0x8000000000008009, + 0x000000000000008A, + 0x0000000000000088, + 0x0000000080008009, + 0x000000008000000A, + 0x000000008000808B, + 0x800000000000008B, + 0x8000000000008089, + 0x8000000000008003, + 0x8000000000008002, + 0x8000000000000080, + 0x000000000000800A, + 0x800000008000000A, + 0x8000000080008081, + 0x8000000000008080, + 0x0000000080000001, + 0x8000000080008008, +]; + +/// Rho offsets. See NIST intermediate test vectors for source. +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, +]; + +/// Indices precomputed based on spec of Pi. +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, +]; + +fn keccakf<const ROUNDS: usize>(state: &mut [u64; 25]) { + for round in 0..ROUNDS { + let mut buf = [0u64; 5]; + + theta(state, &mut buf); + rho_and_pi(state, &mut buf); + chi(state, &mut buf); + iota(state, round); + } +} + +#[allow(clippy::erasing_op)] +#[allow(clippy::identity_op)] +// Theta (θ). +fn theta(state: &mut [u64; 25], buf: &mut [u64; 5]) { + buf[0] ^= state[0 + (0 * 5)]; + buf[0] ^= state[0 + (1 * 5)]; + buf[0] ^= state[0 + (2 * 5)]; + buf[0] ^= state[0 + (3 * 5)]; + buf[0] ^= state[0 + (4 * 5)]; + + buf[1] ^= state[1 + (0 * 5)]; + buf[1] ^= state[1 + (1 * 5)]; + buf[1] ^= state[1 + (2 * 5)]; + buf[1] ^= state[1 + (3 * 5)]; + buf[1] ^= state[1 + (4 * 5)]; + + buf[2] ^= state[2 + (0 * 5)]; + buf[2] ^= state[2 + (1 * 5)]; + buf[2] ^= state[2 + (2 * 5)]; + buf[2] ^= state[2 + (3 * 5)]; + buf[2] ^= state[2 + (4 * 5)]; + + buf[3] ^= state[3 + (0 * 5)]; + buf[3] ^= state[3 + (1 * 5)]; + buf[3] ^= state[3 + (2 * 5)]; + buf[3] ^= state[3 + (3 * 5)]; + buf[3] ^= state[3 + (4 * 5)]; + + buf[4] ^= state[4 + (0 * 5)]; + buf[4] ^= state[4 + (1 * 5)]; + buf[4] ^= state[4 + (2 * 5)]; + buf[4] ^= state[4 + (3 * 5)]; + buf[4] ^= state[4 + (4 * 5)]; + + state[(0 * 5) + 0] ^= buf[(0 + 4) % 5] ^ buf[(0 + 1) % 5].rotate_left(1); + state[(1 * 5) + 0] ^= buf[(0 + 4) % 5] ^ buf[(0 + 1) % 5].rotate_left(1); + state[(2 * 5) + 0] ^= buf[(0 + 4) % 5] ^ buf[(0 + 1) % 5].rotate_left(1); + state[(3 * 5) + 0] ^= buf[(0 + 4) % 5] ^ buf[(0 + 1) % 5].rotate_left(1); + state[(4 * 5) + 0] ^= buf[(0 + 4) % 5] ^ buf[(0 + 1) % 5].rotate_left(1); + + state[(0 * 5) + 1] ^= buf[(1 + 4) % 5] ^ buf[(1 + 1) % 5].rotate_left(1); + state[(1 * 5) + 1] ^= buf[(1 + 4) % 5] ^ buf[(1 + 1) % 5].rotate_left(1); + state[(2 * 5) + 1] ^= buf[(1 + 4) % 5] ^ buf[(1 + 1) % 5].rotate_left(1); + state[(3 * 5) + 1] ^= buf[(1 + 4) % 5] ^ buf[(1 + 1) % 5].rotate_left(1); + state[(4 * 5) + 1] ^= buf[(1 + 4) % 5] ^ buf[(1 + 1) % 5].rotate_left(1); + + state[(0 * 5) + 2] ^= buf[(2 + 4) % 5] ^ buf[(2 + 1) % 5].rotate_left(1); + state[(1 * 5) + 2] ^= buf[(2 + 4) % 5] ^ buf[(2 + 1) % 5].rotate_left(1); + state[(2 * 5) + 2] ^= buf[(2 + 4) % 5] ^ buf[(2 + 1) % 5].rotate_left(1); + state[(3 * 5) + 2] ^= buf[(2 + 4) % 5] ^ buf[(2 + 1) % 5].rotate_left(1); + state[(4 * 5) + 2] ^= buf[(2 + 4) % 5] ^ buf[(2 + 1) % 5].rotate_left(1); + + state[(0 * 5) + 3] ^= buf[(3 + 4) % 5] ^ buf[(3 + 1) % 5].rotate_left(1); + state[(1 * 5) + 3] ^= buf[(3 + 4) % 5] ^ buf[(3 + 1) % 5].rotate_left(1); + state[(2 * 5) + 3] ^= buf[(3 + 4) % 5] ^ buf[(3 + 1) % 5].rotate_left(1); + state[(3 * 5) + 3] ^= buf[(3 + 4) % 5] ^ buf[(3 + 1) % 5].rotate_left(1); + state[(4 * 5) + 3] ^= buf[(3 + 4) % 5] ^ buf[(3 + 1) % 5].rotate_left(1); + + state[(0 * 5) + 4] ^= buf[(4 + 4) % 5] ^ buf[(4 + 1) % 5].rotate_left(1); + state[(1 * 5) + 4] ^= buf[(4 + 4) % 5] ^ buf[(4 + 1) % 5].rotate_left(1); + state[(2 * 5) + 4] ^= buf[(4 + 4) % 5] ^ buf[(4 + 1) % 5].rotate_left(1); + state[(3 * 5) + 4] ^= buf[(4 + 4) % 5] ^ buf[(4 + 1) % 5].rotate_left(1); + state[(4 * 5) + 4] ^= buf[(4 + 4) % 5] ^ buf[(4 + 1) % 5].rotate_left(1); +} + +// Rho (ρ) & Pi (π). +fn rho_and_pi(state: &mut [u64; 25], buf: &mut [u64; 5]) { + let mut prev = state[1]; + + buf[0] = state[PI[0]]; + state[PI[0]] = prev.rotate_left(RHO[0]); + prev = buf[0]; + + buf[0] = state[PI[1]]; + state[PI[1]] = prev.rotate_left(RHO[1]); + prev = buf[0]; + + buf[0] = state[PI[2]]; + state[PI[2]] = prev.rotate_left(RHO[2]); + prev = buf[0]; + + buf[0] = state[PI[3]]; + state[PI[3]] = prev.rotate_left(RHO[3]); + prev = buf[0]; + + buf[0] = state[PI[4]]; + state[PI[4]] = prev.rotate_left(RHO[4]); + prev = buf[0]; + + buf[0] = state[PI[5]]; + state[PI[5]] = prev.rotate_left(RHO[5]); + prev = buf[0]; + + buf[0] = state[PI[6]]; + state[PI[6]] = prev.rotate_left(RHO[6]); + prev = buf[0]; + + buf[0] = state[PI[7]]; + state[PI[7]] = prev.rotate_left(RHO[7]); + prev = buf[0]; + + buf[0] = state[PI[8]]; + state[PI[8]] = prev.rotate_left(RHO[8]); + prev = buf[0]; + + buf[0] = state[PI[9]]; + state[PI[9]] = prev.rotate_left(RHO[9]); + prev = buf[0]; + + buf[0] = state[PI[10]]; + state[PI[10]] = prev.rotate_left(RHO[10]); + prev = buf[0]; + + buf[0] = state[PI[11]]; + state[PI[11]] = prev.rotate_left(RHO[11]); + prev = buf[0]; + + buf[0] = state[PI[12]]; + state[PI[12]] = prev.rotate_left(RHO[12]); + prev = buf[0]; + + buf[0] = state[PI[13]]; + state[PI[13]] = prev.rotate_left(RHO[13]); + prev = buf[0]; + + buf[0] = state[PI[14]]; + state[PI[14]] = prev.rotate_left(RHO[14]); + prev = buf[0]; + + buf[0] = state[PI[15]]; + state[PI[15]] = prev.rotate_left(RHO[15]); + prev = buf[0]; + + buf[0] = state[PI[16]]; + state[PI[16]] = prev.rotate_left(RHO[16]); + prev = buf[0]; + + buf[0] = state[PI[17]]; + state[PI[17]] = prev.rotate_left(RHO[17]); + prev = buf[0]; + + buf[0] = state[PI[18]]; + state[PI[18]] = prev.rotate_left(RHO[18]); + prev = buf[0]; + + buf[0] = state[PI[19]]; + state[PI[19]] = prev.rotate_left(RHO[19]); + prev = buf[0]; + + buf[0] = state[PI[20]]; + state[PI[20]] = prev.rotate_left(RHO[20]); + prev = buf[0]; + + buf[0] = state[PI[21]]; + state[PI[21]] = prev.rotate_left(RHO[21]); + prev = buf[0]; + + buf[0] = state[PI[22]]; + state[PI[22]] = prev.rotate_left(RHO[22]); + prev = buf[0]; + + buf[0] = state[PI[23]]; + state[PI[23]] = prev.rotate_left(RHO[23]); +} + +#[allow(clippy::identity_op)] +// Chi (χ). +fn chi(state: &mut [u64; 25], buf: &mut [u64; 5]) { + buf[0] = state[0 + 0]; + buf[1] = state[0 + 1]; + buf[2] = state[0 + 2]; + buf[3] = state[0 + 3]; + buf[4] = state[0 + 4]; + + state[0 + 0] = buf[0] ^ ((!buf[(0 + 1) % 5]) & (buf[(0 + 2) % 5])); + state[0 + 1] = buf[1] ^ ((!buf[(1 + 1) % 5]) & (buf[(1 + 2) % 5])); + state[0 + 2] = buf[2] ^ ((!buf[(2 + 1) % 5]) & (buf[(2 + 2) % 5])); + state[0 + 3] = buf[3] ^ ((!buf[(3 + 1) % 5]) & (buf[(3 + 2) % 5])); + state[0 + 4] = buf[4] ^ ((!buf[(4 + 1) % 5]) & (buf[(4 + 2) % 5])); + + buf[0] = state[5 + 0]; + buf[1] = state[5 + 1]; + buf[2] = state[5 + 2]; + buf[3] = state[5 + 3]; + buf[4] = state[5 + 4]; + + state[5 + 0] = buf[0] ^ ((!buf[(0 + 1) % 5]) & (buf[(0 + 2) % 5])); + state[5 + 1] = buf[1] ^ ((!buf[(1 + 1) % 5]) & (buf[(1 + 2) % 5])); + state[5 + 2] = buf[2] ^ ((!buf[(2 + 1) % 5]) & (buf[(2 + 2) % 5])); + state[5 + 3] = buf[3] ^ ((!buf[(3 + 1) % 5]) & (buf[(3 + 2) % 5])); + state[5 + 4] = buf[4] ^ ((!buf[(4 + 1) % 5]) & (buf[(4 + 2) % 5])); + + buf[0] = state[10 + 0]; + buf[1] = state[10 + 1]; + buf[2] = state[10 + 2]; + buf[3] = state[10 + 3]; + buf[4] = state[10 + 4]; + + state[10 + 0] = buf[0] ^ ((!buf[(0 + 1) % 5]) & (buf[(0 + 2) % 5])); + state[10 + 1] = buf[1] ^ ((!buf[(1 + 1) % 5]) & (buf[(1 + 2) % 5])); + state[10 + 2] = buf[2] ^ ((!buf[(2 + 1) % 5]) & (buf[(2 + 2) % 5])); + state[10 + 3] = buf[3] ^ ((!buf[(3 + 1) % 5]) & (buf[(3 + 2) % 5])); + state[10 + 4] = buf[4] ^ ((!buf[(4 + 1) % 5]) & (buf[(4 + 2) % 5])); + + buf[0] = state[15 + 0]; + buf[1] = state[15 + 1]; + buf[2] = state[15 + 2]; + buf[3] = state[15 + 3]; + buf[4] = state[15 + 4]; + + state[15 + 0] = buf[0] ^ ((!buf[(0 + 1) % 5]) & (buf[(0 + 2) % 5])); + state[15 + 1] = buf[1] ^ ((!buf[(1 + 1) % 5]) & (buf[(1 + 2) % 5])); + state[15 + 2] = buf[2] ^ ((!buf[(2 + 1) % 5]) & (buf[(2 + 2) % 5])); + state[15 + 3] = buf[3] ^ ((!buf[(3 + 1) % 5]) & (buf[(3 + 2) % 5])); + state[15 + 4] = buf[4] ^ ((!buf[(4 + 1) % 5]) & (buf[(4 + 2) % 5])); + + buf[0] = state[20 + 0]; + buf[1] = state[20 + 1]; + buf[2] = state[20 + 2]; + buf[3] = state[20 + 3]; + buf[4] = state[20 + 4]; + + state[20 + 0] = buf[0] ^ ((!buf[(0 + 1) % 5]) & (buf[(0 + 2) % 5])); + state[20 + 1] = buf[1] ^ ((!buf[(1 + 1) % 5]) & (buf[(1 + 2) % 5])); + state[20 + 2] = buf[2] ^ ((!buf[(2 + 1) % 5]) & (buf[(2 + 2) % 5])); + state[20 + 3] = buf[3] ^ ((!buf[(3 + 1) % 5]) & (buf[(3 + 2) % 5])); + state[20 + 4] = buf[4] ^ ((!buf[(4 + 1) % 5]) & (buf[(4 + 2) % 5])); +} + +// Iota (ι). +fn iota(state: &mut [u64; 25], round: usize) { + debug_assert!(round <= 24); + state[0] ^= RC[round]; +} + +// <https://github.com/XKCP/XKCP/blob/master/tests/TestVectors/KeccakF-1600-IntermediateValues.txt> +#[test] +fn test_full_round() { + let mut state = [0u64; 25]; + let expected_state_from_zero = [ + 0xF1258F7940E1DDE7, + 0x84D5CCF933C0478A, + 0xD598261EA65AA9EE, + 0xBD1547306F80494D, + 0x8B284E056253D057, + 0xFF97A42D7F8E6FD4, + 0x90FEE5A0A44647C4, + 0x8C5BDA0CD6192E76, + 0xAD30A6F71B19059C, + 0x30935AB7D08FFC64, + 0xEB5AA93F2317D635, + 0xA9A6E6260D712103, + 0x81A57C16DBCF555F, + 0x43B831CD0347C826, + 0x01F22F1A11A5569F, + 0x05E5635A21D9AE61, + 0x64BEFEF28CC970F2, + 0x613670957BC46611, + 0xB87C5A554FD00ECB, + 0x8C3EE88A1CCF32C8, + 0x940C7922AE3A2614, + 0x1841F924A2C509E4, + 0x16F53526E70465C2, + 0x75F644E97F30A13B, + 0xEAF1FF7B5CECA249, + ]; + let expected_state_rerun = [ + 0x2D5C954DF96ECB3C, + 0x6A332CD07057B56D, + 0x093D8D1270D76B6C, + 0x8A20D9B25569D094, + 0x4F9C4F99E5E7F156, + 0xF957B9A2DA65FB38, + 0x85773DAE1275AF0D, + 0xFAF4F247C3D810F7, + 0x1F1B9EE6F79A8759, + 0xE4FECC0FEE98B425, + 0x68CE61B6B9CE68A1, + 0xDEEA66C4BA8F974F, + 0x33C43D836EAFB1F5, + 0xE00654042719DBD9, + 0x7CF8A9F009831265, + 0xFD5449A6BF174743, + 0x97DDAD33D8994B40, + 0x48EAD5FC5D0BE774, + 0xE3B8C8EE55B7B03C, + 0x91A0226E649E42E9, + 0x900E3129E7BADD7B, + 0x202A9EC5FAA3CCE8, + 0x5B3402464E1C3DB6, + 0x609F4E62A44C1059, + 0x20D06CD26A8FBF5C, + ]; + + keccakf::<24>(&mut state); + assert_eq!(&state, &expected_state_from_zero); + keccakf::<24>(&mut state); + assert_eq!(&state, &expected_state_rerun); +} + +#[derive(Clone)] +/// SHA3 streaming state. +pub(crate) struct Sha3<const RATE: usize> { + pub(crate) state: [u64; 25], + pub(crate) buffer: [u8; RATE], + pub(crate) capacity: usize, + leftover: usize, + is_finalized: bool, +} + +impl<const RATE: usize> Drop for Sha3<RATE> { + fn drop(&mut self) { + self.state.iter_mut().zeroize(); + self.buffer.iter_mut().zeroize(); + self.leftover.zeroize(); + } +} + +impl<const RATE: usize> Debug for Sha3<RATE> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!( + f, + "State {{ state: [***OMITTED***], buffer: [***OMITTED***], capacity: {:?}, leftover: {:?}, \ + is_finalized: {:?} }}", + self.capacity, self.leftover, self.is_finalized + ) + } +} + +impl<const RATE: usize> Sha3<RATE> { + /// Initialize a new state. + /// `capacity` should be in bytes. + pub(crate) fn _new(capacity: usize) -> Self { + Self { + state: [0u64; 25], + buffer: [0u8; RATE], + capacity, + leftover: 0, + is_finalized: false, + } + } + + /// Process data in `self.buffer` or optionally `data`. + pub(crate) fn process_block(&mut self, data: Option<&[u8]>) { + // If `data.is_none()` then we want to process leftover data within `self.buffer`. + let data_block = match data { + Some(bytes) => { + debug_assert_eq!(bytes.len(), RATE); + bytes + } + None => &self.buffer, + }; + + debug_assert_eq!(data_block.len() % 8, 0); + + // We process data in terms of bitrate, but we need to XOR in an entire Keccak state. + // So the 25 - bitrate values will be zero. That's the same as not XORing those values + // so we leave it be as this. + for (b, s) in data_block + .chunks_exact(core::mem::size_of::<u64>()) + .zip(self.state.iter_mut()) + { + *s ^= u64::from_le_bytes(b.try_into().unwrap()); + } + + keccakf::<24>(&mut self.state); + } + + /// Reset to `new()` state. + pub(crate) fn _reset(&mut self) { + self.state = [0u64; 25]; + self.buffer = [0u8; RATE]; + self.leftover = 0; + self.is_finalized = false; + } + + /// Update state with `data`. This can be called multiple times. + pub(crate) fn _update(&mut self, data: &[u8]) -> Result<(), UnknownCryptoError> { + if self.is_finalized { + return Err(UnknownCryptoError); + } + if data.is_empty() { + return Ok(()); + } + + let mut bytes = data; + + if self.leftover != 0 { + debug_assert!(self.leftover <= RATE); + + let mut want = RATE - self.leftover; + if want > bytes.len() { + want = bytes.len(); + } + + for (idx, itm) in bytes.iter().enumerate().take(want) { + self.buffer[self.leftover + idx] = *itm; + } + + bytes = &bytes[want..]; + self.leftover += want; + + if self.leftover < RATE { + return Ok(()); + } + + self.process_block(None); + self.leftover = 0; + } + + while bytes.len() >= RATE { + self.process_block(Some(bytes[..RATE].as_ref())); + bytes = &bytes[RATE..]; + } + + if !bytes.is_empty() { + debug_assert_eq!(self.leftover, 0); + self.buffer[..bytes.len()].copy_from_slice(bytes); + self.leftover = bytes.len(); + } + + Ok(()) + } + + /// Finalize the hash and put the final digest into `dest`. + pub(crate) fn _finalize(&mut self, dest: &mut [u8]) -> Result<(), UnknownCryptoError> { + if self.is_finalized { + return Err(UnknownCryptoError); + } + + self.is_finalized = true; + // self.leftover should not be greater than SHA3(256/384/512)_RATE + // as that would have been processed in the update call + debug_assert!(self.leftover < RATE); + // Set padding byte and pad with zeroes after + self.buffer[self.leftover] = 0x06; + self.leftover += 1; + for itm in self.buffer.iter_mut().skip(self.leftover) { + *itm = 0; + } + + self.buffer[self.buffer.len() - 1] |= 0x80; + self.process_block(None); + + // The reason we can't work with chunks_exact here is that for SHA3-224 + // the `dest` is not evenly divisible by 8/`core::mem::size_of::<u64>()`. + for (out_chunk, state_value) in dest + .chunks_mut(core::mem::size_of::<u64>()) + .zip(self.state.iter()) + { + // We need to slice the state value in bytes here for same reason as mentioned + // above. + out_chunk.copy_from_slice(&state_value.to_le_bytes()[..out_chunk.len()]); + } + + Ok(()) + } + + #[cfg(test)] + /// Compare two Sha3 state objects to check if their fields + /// are the same. + pub(crate) fn compare_state_to_other(&self, other: &Self) { + for idx in 0..25 { + assert_eq!(self.state[idx], other.state[idx]); + } + assert_eq!(self.buffer, other.buffer); + assert_eq!(self.capacity, other.capacity); + assert_eq!(self.leftover, other.leftover); + assert_eq!(self.is_finalized, other.is_finalized); + } +} diff --git a/vendor/orion/src/hazardous/hash/sha3/sha3_224.rs b/vendor/orion/src/hazardous/hash/sha3/sha3_224.rs new file mode 100644 index 000000000..e235f2b65 --- /dev/null +++ b/vendor/orion/src/hazardous/hash/sha3/sha3_224.rs @@ -0,0 +1,274 @@ +// MIT License + +// Copyright (c) 2023 The orion Developers + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//! # Parameters: +//! - `data`: The data to be hashed. +//! +//! # Errors: +//! An error will be returned if: +//! - [`finalize()`] is called twice without a [`reset()`] in between. +//! - [`update()`] is called after [`finalize()`] without a [`reset()`] in +//! between. +//! +//! # Example: +//! ```rust +//! use orion::hazardous::hash::sha3::sha3_224::Sha3_224; +//! +//! // Using the streaming interface +//! let mut state = Sha3_224::new(); +//! state.update(b"Hello world")?; +//! let hash = state.finalize()?; +//! +//! // Using the one-shot function +//! let hash_one_shot = Sha3_224::digest(b"Hello world")?; +//! +//! assert_eq!(hash, hash_one_shot); +//! # Ok::<(), orion::errors::UnknownCryptoError>(()) +//! ``` +//! [`update()`]: sha3_224::Sha3_224::update +//! [`reset()`]: sha3_224::Sha3_224::reset +//! [`finalize()`]: sha3_224::Sha3_224::finalize + +use crate::errors::UnknownCryptoError; +#[cfg(feature = "safe_api")] +use std::io; + +use super::Sha3; + +/// Rate of SHA3-224 (equivalent to blocksize in SHA2). +pub const SHA3_224_RATE: usize = 144; + +/// Output size of SHA3-224 in bytes. +pub const SHA3_224_OUTSIZE: usize = 28; + +construct_public! { + /// A type to represent the `Digest` that SHA3-224 returns. + /// + /// # Errors: + /// An error will be returned if: + /// - `slice` is not 28 bytes. + (Digest, test_digest, SHA3_224_OUTSIZE, SHA3_224_OUTSIZE) +} + +impl_from_trait!(Digest, SHA3_224_OUTSIZE); + +#[derive(Clone, Debug)] +/// SHA3-224 streaming state. +pub struct Sha3_224 { + pub(crate) _state: Sha3<SHA3_224_RATE>, +} + +impl Default for Sha3_224 { + fn default() -> Self { + Self::new() + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "safe_api")))] +/// Example: hashing from a [`Read`](std::io::Read)er with SHA3-224. +/// ```rust +/// use orion::{ +/// hazardous::hash::sha3::sha3_224::{Sha3_224, Digest}, +/// errors::UnknownCryptoError, +/// }; +/// use std::io::{self, Read, Write}; +/// +/// // `reader` could also be a `File::open(...)?`. +/// let mut reader = io::Cursor::new(b"some data"); +/// let mut hasher = Sha3_224::new(); +/// std::io::copy(&mut reader, &mut hasher)?; +/// +/// let digest: Digest = hasher.finalize()?; +/// +/// # Ok::<(), Box<dyn std::error::Error>>(()) +/// ``` +#[cfg(feature = "safe_api")] +impl io::Write for Sha3_224 { + /// Update the hasher's internal state with *all* of the bytes given. + /// If this function returns the `Ok` variant, it's guaranteed that it + /// will contain the length of the buffer passed to [`Write`](std::io::Write). + /// Note that this function is just a small wrapper over + /// [`Sha3_224::update`](crate::hazardous::hash::sha3::sha3_224::Sha3_224::update). + /// + /// ## Errors: + /// This function will only ever return the [`std::io::ErrorKind::Other`]() + /// variant when it returns an error. Additionally, this will always contain Orion's + /// [`UnknownCryptoError`](crate::errors::UnknownCryptoError) type. + fn write(&mut self, bytes: &[u8]) -> io::Result<usize> { + self.update(bytes) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + Ok(bytes.len()) + } + + /// This type doesn't buffer writes, so flushing is a no-op. + fn flush(&mut self) -> Result<(), std::io::Error> { + Ok(()) + } +} + +impl Sha3_224 { + /// Initialize a `Sha3_224` struct. + pub fn new() -> Self { + Self { + _state: Sha3::<SHA3_224_RATE>::_new(56), + } + } + + /// Reset to `new()` state. + pub fn reset(&mut self) { + self._state._reset(); + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Update state with `data`. This can be called multiple times. + pub fn update(&mut self, data: &[u8]) -> Result<(), UnknownCryptoError> { + self._state._update(data) + } + + /// Finalize the hash and put the final digest into `dest`. + pub(crate) fn _finalize_internal(&mut self, dest: &mut [u8]) -> Result<(), UnknownCryptoError> { + self._state._finalize(dest) + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Return a SHA3-224 digest. + pub fn finalize(&mut self) -> Result<Digest, UnknownCryptoError> { + let mut digest = [0u8; SHA3_224_OUTSIZE]; + self._finalize_internal(&mut digest)?; + + Ok(Digest::from(digest)) + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Calculate a SHA3-224 digest of some `data`. + pub fn digest(data: &[u8]) -> Result<Digest, UnknownCryptoError> { + let mut ctx = Self::new(); + ctx.update(data)?; + ctx.finalize() + } +} + +// Testing public functions in the module. +#[cfg(test)] +mod public { + use super::*; + + #[test] + fn test_default_equals_new() { + let new = Sha3_224::new(); + let default = Sha3_224::default(); + new._state.compare_state_to_other(&default._state); + } + + #[test] + #[cfg(feature = "safe_api")] + fn test_debug_impl() { + let initial_state = Sha3_224::new(); + let debug = format!("{:?}", initial_state); + let expected = "Sha3_224 { _state: State { state: [***OMITTED***], buffer: [***OMITTED***], capacity: 56, leftover: 0, is_finalized: false } }"; + assert_eq!(debug, expected); + } + + mod test_streaming_interface { + use super::*; + use crate::test_framework::incremental_interface::*; + + impl TestableStreamingContext<Digest> for Sha3_224 { + fn reset(&mut self) -> Result<(), UnknownCryptoError> { + self.reset(); + Ok(()) + } + + fn update(&mut self, input: &[u8]) -> Result<(), UnknownCryptoError> { + self.update(input) + } + + fn finalize(&mut self) -> Result<Digest, UnknownCryptoError> { + self.finalize() + } + + fn one_shot(input: &[u8]) -> Result<Digest, UnknownCryptoError> { + Sha3_224::digest(input) + } + + fn verify_result(expected: &Digest, input: &[u8]) -> Result<(), UnknownCryptoError> { + let actual: Digest = Self::one_shot(input)?; + + if &actual == expected { + Ok(()) + } else { + Err(UnknownCryptoError) + } + } + + fn compare_states(state_1: &Sha3_224, state_2: &Sha3_224) { + state_1._state.compare_state_to_other(&state_2._state); + } + } + + #[test] + fn default_consistency_tests() { + let initial_state: Sha3_224 = Sha3_224::new(); + + let test_runner = StreamingContextConsistencyTester::<Digest, Sha3_224>::new( + initial_state, + SHA3_224_RATE, + ); + test_runner.run_all_tests(); + } + + #[quickcheck] + #[cfg(feature = "safe_api")] + /// Related bug: https://github.com/orion-rs/orion/issues/46 + /// Test different streaming state usage patterns. + fn prop_input_to_consistency(data: Vec<u8>) -> bool { + let initial_state: Sha3_224 = Sha3_224::new(); + + let test_runner = StreamingContextConsistencyTester::<Digest, Sha3_224>::new( + initial_state, + SHA3_224_RATE, + ); + test_runner.run_all_tests_property(&data); + true + } + } + + #[cfg(feature = "safe_api")] + mod test_io_impls { + use crate::hazardous::hash::sha3::sha3_224::Sha3_224; + use std::io::Write; + + #[quickcheck] + fn prop_hasher_write_same_as_update(data: Vec<u8>) -> bool { + let mut hasher_a = Sha3_224::new(); + let mut hasher_b = hasher_a.clone(); + + hasher_a.update(&data).unwrap(); + hasher_b.write_all(&data).unwrap(); + + let hash_a = hasher_a.finalize().unwrap(); + let hash_b = hasher_b.finalize().unwrap(); + + hash_a == hash_b + } + } +} diff --git a/vendor/orion/src/hazardous/hash/sha3/sha3_256.rs b/vendor/orion/src/hazardous/hash/sha3/sha3_256.rs new file mode 100644 index 000000000..f972db988 --- /dev/null +++ b/vendor/orion/src/hazardous/hash/sha3/sha3_256.rs @@ -0,0 +1,336 @@ +// MIT License + +// Copyright (c) 2023 The orion Developers + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//! # Parameters: +//! - `data`: The data to be hashed. +//! +//! # Errors: +//! An error will be returned if: +//! - [`finalize()`] is called twice without a [`reset()`] in between. +//! - [`update()`] is called after [`finalize()`] without a [`reset()`] in +//! between. +//! +//! # Example: +//! ```rust +//! use orion::hazardous::hash::sha3::sha3_256::Sha3_256; +//! +//! // Using the streaming interface +//! let mut state = Sha3_256::new(); +//! state.update(b"Hello world")?; +//! let hash = state.finalize()?; +//! +//! // Using the one-shot function +//! let hash_one_shot = Sha3_256::digest(b"Hello world")?; +//! +//! assert_eq!(hash, hash_one_shot); +//! # Ok::<(), orion::errors::UnknownCryptoError>(()) +//! ``` +//! [`update()`]: sha3_256::Sha3_256::update +//! [`reset()`]: sha3_256::Sha3_256::reset +//! [`finalize()`]: sha3_256::Sha3_256::finalize + +use crate::errors::UnknownCryptoError; +#[cfg(feature = "safe_api")] +use std::io; + +use super::Sha3; + +/// Rate of SHA3-256 (equivalent to blocksize in SHA2). +pub const SHA3_256_RATE: usize = 136; + +/// Output size of SHA3-256 in bytes. +pub const SHA3_256_OUTSIZE: usize = 32; + +construct_public! { + /// A type to represent the `Digest` that SHA3-256 returns. + /// + /// # Errors: + /// An error will be returned if: + /// - `slice` is not 32 bytes. + (Digest, test_digest, SHA3_256_OUTSIZE, SHA3_256_OUTSIZE) +} + +impl_from_trait!(Digest, SHA3_256_OUTSIZE); + +#[derive(Clone, Debug)] +/// SHA3-256 streaming state. +pub struct Sha3_256 { + pub(crate) _state: Sha3<SHA3_256_RATE>, +} + +impl Default for Sha3_256 { + fn default() -> Self { + Self::new() + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "safe_api")))] +/// Example: hashing from a [`Read`](std::io::Read)er with SHA3-256. +/// ```rust +/// use orion::{ +/// hazardous::hash::sha3::sha3_256::{Sha3_256, Digest}, +/// errors::UnknownCryptoError, +/// }; +/// use std::io::{self, Read, Write}; +/// +/// // `reader` could also be a `File::open(...)?`. +/// let mut reader = io::Cursor::new(b"some data"); +/// let mut hasher = Sha3_256::new(); +/// std::io::copy(&mut reader, &mut hasher)?; +/// +/// let digest: Digest = hasher.finalize()?; +/// +/// # Ok::<(), Box<dyn std::error::Error>>(()) +/// ``` +#[cfg(feature = "safe_api")] +impl io::Write for Sha3_256 { + /// Update the hasher's internal state with *all* of the bytes given. + /// If this function returns the `Ok` variant, it's guaranteed that it + /// will contain the length of the buffer passed to [`Write`](std::io::Write). + /// Note that this function is just a small wrapper over + /// [`Sha3_256::update`](crate::hazardous::hash::sha3::sha3_256::Sha3_256::update). + /// + /// ## Errors: + /// This function will only ever return the [`std::io::ErrorKind::Other`]() + /// variant when it returns an error. Additionally, this will always contain Orion's + /// [`UnknownCryptoError`](crate::errors::UnknownCryptoError) type. + fn write(&mut self, bytes: &[u8]) -> io::Result<usize> { + self.update(bytes) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + Ok(bytes.len()) + } + + /// This type doesn't buffer writes, so flushing is a no-op. + fn flush(&mut self) -> Result<(), std::io::Error> { + Ok(()) + } +} + +impl Sha3_256 { + /// Initialize a `Sha3_256` struct. + pub fn new() -> Self { + Self { + _state: Sha3::<{ SHA3_256_RATE }>::_new(64), + } + } + + /// Reset to `new()` state. + pub fn reset(&mut self) { + self._state._reset(); + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Update state with `data`. This can be called multiple times. + pub fn update(&mut self, data: &[u8]) -> Result<(), UnknownCryptoError> { + self._state._update(data) + } + + /// Finalize the hash and put the final digest into `dest`. + pub(crate) fn _finalize_internal(&mut self, dest: &mut [u8]) -> Result<(), UnknownCryptoError> { + self._state._finalize(dest) + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Return a SHA3-256 digest. + pub fn finalize(&mut self) -> Result<Digest, UnknownCryptoError> { + let mut digest = [0u8; SHA3_256_OUTSIZE]; + self._finalize_internal(&mut digest)?; + + Ok(Digest::from(digest)) + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Calculate a SHA3-256 digest of some `data`. + pub fn digest(data: &[u8]) -> Result<Digest, UnknownCryptoError> { + let mut ctx = Self::new(); + ctx.update(data)?; + ctx.finalize() + } +} + +// Testing public functions in the module. +#[cfg(test)] +mod public { + use super::*; + + #[test] + fn test_default_equals_new() { + let new = Sha3_256::new(); + let default = Sha3_256::default(); + new._state.compare_state_to_other(&default._state); + } + + #[test] + #[cfg(feature = "safe_api")] + fn test_debug_impl() { + let initial_state = Sha3_256::new(); + let debug = format!("{:?}", initial_state); + let expected = "Sha3_256 { _state: State { state: [***OMITTED***], buffer: [***OMITTED***], capacity: 64, leftover: 0, is_finalized: false } }"; + assert_eq!(debug, expected); + } + + #[test] + // <https://github.com/ziglang/zig/issues/14851> + fn test_zig_cryptofuzz() { + let expected_hash: [u8; 32] = [ + 0x57, 0x80, 0x4, 0x8d, 0xfa, 0x38, 0x1a, 0x1d, 0x1, 0xc7, 0x47, 0x90, 0x6e, 0x4a, 0x8, + 0x71, 0x1d, 0xd3, 0x4f, 0xd7, 0x12, 0xec, 0xd7, 0xc6, 0x80, 0x1d, 0xd2, 0xb3, 0x8f, + 0xd8, 0x1a, 0x89, + ]; + let msg: [u8; 613] = [ + 0x97, 0xd1, 0x2d, 0x1a, 0x16, 0x2d, 0x36, 0x4d, 0x20, 0x62, 0x19, 0x0b, 0x14, 0x93, + 0xbb, 0xf8, 0x5b, 0xea, 0x04, 0xc2, 0x61, 0x8e, 0xd6, 0x08, 0x81, 0xa1, 0x1d, 0x73, + 0x27, 0x48, 0xbf, 0xa4, 0xba, 0xb1, 0x9a, 0x48, 0x9c, 0xf9, 0x9b, 0xff, 0x34, 0x48, + 0xa9, 0x75, 0xea, 0xc8, 0xa3, 0x48, 0x24, 0x9d, 0x75, 0x27, 0x48, 0xec, 0x03, 0xb0, + 0xbb, 0xdf, 0x33, 0x90, 0xe3, 0x93, 0xed, 0x68, 0x24, 0x39, 0x12, 0xdf, 0xea, 0xee, + 0x8c, 0x9f, 0x96, 0xde, 0x42, 0x46, 0x8c, 0x2b, 0x17, 0x83, 0x36, 0xfb, 0xf4, 0xf7, + 0xff, 0x79, 0xb9, 0x45, 0x41, 0xc9, 0x56, 0x1a, 0x6b, 0x0c, 0xa4, 0x1a, 0xdd, 0x6b, + 0x95, 0xe8, 0x03, 0x0f, 0x09, 0x29, 0x40, 0x1b, 0xea, 0x87, 0xfa, 0xb9, 0x18, 0xa9, + 0x95, 0x07, 0x7c, 0x2f, 0x7c, 0x33, 0xfb, 0xc5, 0x11, 0x5e, 0x81, 0x0e, 0xbc, 0xae, + 0xec, 0xb3, 0xe1, 0x4a, 0x26, 0x56, 0xe8, 0x5b, 0x11, 0x9d, 0x37, 0x06, 0x9b, 0x34, + 0x31, 0x6e, 0xa3, 0xba, 0x41, 0xbc, 0x11, 0xd8, 0xc5, 0x15, 0xc9, 0x30, 0x2c, 0x9b, + 0xb6, 0x71, 0xd8, 0x7c, 0xbc, 0x38, 0x2f, 0xd5, 0xbd, 0x30, 0x96, 0xd4, 0xa3, 0x00, + 0x77, 0x9d, 0x55, 0x4a, 0x33, 0x53, 0xb6, 0xb3, 0x35, 0x1b, 0xae, 0xe5, 0xdc, 0x22, + 0x23, 0x85, 0x95, 0x88, 0xf9, 0x3b, 0xbf, 0x74, 0x13, 0xaa, 0xcb, 0x0a, 0x60, 0x79, + 0x13, 0x79, 0xc0, 0x4a, 0x02, 0xdb, 0x1c, 0xc9, 0xff, 0x60, 0x57, 0x9a, 0x70, 0x28, + 0x58, 0x60, 0xbc, 0x57, 0x07, 0xc7, 0x47, 0x1a, 0x45, 0x71, 0x76, 0x94, 0xfb, 0x05, + 0xad, 0xec, 0x12, 0x29, 0x5a, 0x44, 0x6a, 0x81, 0xd9, 0xc6, 0xf0, 0xb6, 0x9b, 0x97, + 0x83, 0x69, 0xfb, 0xdc, 0x0d, 0x4a, 0x67, 0xbc, 0x72, 0xf5, 0x43, 0x5e, 0x9b, 0x13, + 0xf2, 0xe4, 0x6d, 0x49, 0xdb, 0x76, 0xcb, 0x42, 0x6a, 0x3c, 0x9f, 0xa1, 0xfe, 0x5e, + 0xca, 0x0a, 0xfc, 0xfa, 0x39, 0x27, 0xd1, 0x3c, 0xcb, 0x9a, 0xde, 0x4c, 0x6b, 0x09, + 0x8b, 0x49, 0xfd, 0x1e, 0x3d, 0x5e, 0x67, 0x7c, 0x57, 0xad, 0x90, 0xcc, 0x46, 0x5f, + 0x5c, 0xae, 0x6a, 0x9c, 0xb2, 0xcd, 0x2c, 0x89, 0x78, 0xcf, 0xf1, 0x49, 0x96, 0x55, + 0x1e, 0x04, 0xef, 0x0e, 0x1c, 0xde, 0x6c, 0x96, 0x51, 0x00, 0xee, 0x9a, 0x1f, 0x8d, + 0x61, 0xbc, 0xeb, 0xb1, 0xa6, 0xa5, 0x21, 0x8b, 0xa7, 0xf8, 0x25, 0x41, 0x48, 0x62, + 0x5b, 0x01, 0x6c, 0x7c, 0x2a, 0xe8, 0xff, 0xf9, 0xf9, 0x1f, 0xe2, 0x79, 0x2e, 0xd1, + 0xff, 0xa3, 0x2e, 0x1c, 0x3a, 0x1a, 0x5d, 0x2b, 0x7b, 0x87, 0x25, 0x22, 0xa4, 0x90, + 0xea, 0x26, 0x9d, 0xdd, 0x13, 0x60, 0x4c, 0x10, 0x03, 0xf6, 0x99, 0xd3, 0x21, 0x0c, + 0x69, 0xc6, 0xd8, 0xc8, 0x9e, 0x94, 0x89, 0x51, 0x21, 0xe3, 0x9a, 0xcd, 0xda, 0x54, + 0x72, 0x64, 0xae, 0x94, 0x79, 0x36, 0x81, 0x44, 0x14, 0x6d, 0x3a, 0x0e, 0xa6, 0x30, + 0xbf, 0x95, 0x99, 0xa6, 0xf5, 0x7f, 0x4f, 0xef, 0xc6, 0x71, 0x2f, 0x36, 0x13, 0x14, + 0xa2, 0x9d, 0xc2, 0x0c, 0x0d, 0x4e, 0xc0, 0x02, 0xd3, 0x6f, 0xee, 0x98, 0x5e, 0x24, + 0x31, 0x74, 0x11, 0x96, 0x6e, 0x43, 0x57, 0xe8, 0x8e, 0xa0, 0x8d, 0x3d, 0x79, 0x38, + 0x20, 0xc2, 0x0f, 0xb4, 0x75, 0x99, 0x3b, 0xb1, 0xf0, 0xe8, 0xe1, 0xda, 0xf9, 0xd4, + 0xe6, 0xd6, 0xf4, 0x8a, 0x32, 0x4a, 0x4a, 0x25, 0xa8, 0xd9, 0x60, 0xd6, 0x33, 0x31, + 0x97, 0xb9, 0xb6, 0xed, 0x5f, 0xfc, 0x15, 0xbd, 0x13, 0xc0, 0x3a, 0x3f, 0x1f, 0x2d, + 0x09, 0x1d, 0xeb, 0x69, 0x6a, 0xfe, 0xd7, 0x95, 0x3e, 0x8a, 0x4e, 0xe1, 0x6e, 0x61, + 0xb2, 0x6c, 0xe3, 0x2b, 0x70, 0x60, 0x7e, 0x8c, 0xe4, 0xdd, 0x27, 0x30, 0x7e, 0x0d, + 0xc7, 0xb7, 0x9a, 0x1a, 0x3c, 0xcc, 0xa7, 0x22, 0x77, 0x14, 0x05, 0x50, 0x57, 0x31, + 0x1b, 0xc8, 0xbf, 0xce, 0x52, 0xaf, 0x9c, 0x8e, 0x10, 0x2e, 0xd2, 0x16, 0xb6, 0x6e, + 0x43, 0x10, 0xaf, 0x8b, 0xde, 0x1d, 0x60, 0xb2, 0x7d, 0xe6, 0x2f, 0x08, 0x10, 0x12, + 0x7e, 0xb4, 0x76, 0x45, 0xb6, 0xd8, 0x9b, 0x26, 0x40, 0xa1, 0x63, 0x5c, 0x7a, 0x2a, + 0xb1, 0x8c, 0xd6, 0xa4, 0x6f, 0x5a, 0xae, 0x33, 0x7e, 0x6d, 0x71, 0xf5, 0xc8, 0x6d, + 0x80, 0x1c, 0x35, 0xfc, 0x3f, 0xc1, 0xa6, 0xc6, 0x1a, 0x15, 0x04, 0x6d, 0x76, 0x38, + 0x32, 0x95, 0xb2, 0x51, 0x1a, 0xe9, 0x3e, 0x89, 0x9f, 0x0c, 0x79, + ]; + + let mut ctx = Sha3_256::new(); + ctx.update(&msg[..64]).unwrap(); + ctx.update(&msg[64..]).unwrap(); + + assert_eq!(ctx.finalize().unwrap().as_ref(), &expected_hash); + } + + mod test_streaming_interface { + use super::*; + use crate::test_framework::incremental_interface::*; + + impl TestableStreamingContext<Digest> for Sha3_256 { + fn reset(&mut self) -> Result<(), UnknownCryptoError> { + self.reset(); + Ok(()) + } + + fn update(&mut self, input: &[u8]) -> Result<(), UnknownCryptoError> { + self.update(input) + } + + fn finalize(&mut self) -> Result<Digest, UnknownCryptoError> { + self.finalize() + } + + fn one_shot(input: &[u8]) -> Result<Digest, UnknownCryptoError> { + Sha3_256::digest(input) + } + + fn verify_result(expected: &Digest, input: &[u8]) -> Result<(), UnknownCryptoError> { + let actual: Digest = Self::one_shot(input)?; + + if &actual == expected { + Ok(()) + } else { + Err(UnknownCryptoError) + } + } + + fn compare_states(state_1: &Sha3_256, state_2: &Sha3_256) { + state_1._state.compare_state_to_other(&state_2._state); + } + } + + #[test] + fn default_consistency_tests() { + let initial_state: Sha3_256 = Sha3_256::new(); + + let test_runner = StreamingContextConsistencyTester::<Digest, Sha3_256>::new( + initial_state, + SHA3_256_RATE, + ); + test_runner.run_all_tests(); + } + + #[quickcheck] + #[cfg(feature = "safe_api")] + /// Related bug: https://github.com/orion-rs/orion/issues/46 + /// Test different streaming state usage patterns. + fn prop_input_to_consistency(data: Vec<u8>) -> bool { + let initial_state: Sha3_256 = Sha3_256::new(); + + let test_runner = StreamingContextConsistencyTester::<Digest, Sha3_256>::new( + initial_state, + SHA3_256_RATE, + ); + test_runner.run_all_tests_property(&data); + true + } + } + + #[cfg(feature = "safe_api")] + mod test_io_impls { + use crate::hazardous::hash::sha3::sha3_256::Sha3_256; + use std::io::Write; + + #[quickcheck] + fn prop_hasher_write_same_as_update(data: Vec<u8>) -> bool { + let mut hasher_a = Sha3_256::new(); + let mut hasher_b = hasher_a.clone(); + + hasher_a.update(&data).unwrap(); + hasher_b.write_all(&data).unwrap(); + + let hash_a = hasher_a.finalize().unwrap(); + let hash_b = hasher_b.finalize().unwrap(); + + hash_a == hash_b + } + } +} diff --git a/vendor/orion/src/hazardous/hash/sha3/sha3_384.rs b/vendor/orion/src/hazardous/hash/sha3/sha3_384.rs new file mode 100644 index 000000000..96ccdb318 --- /dev/null +++ b/vendor/orion/src/hazardous/hash/sha3/sha3_384.rs @@ -0,0 +1,274 @@ +// MIT License + +// Copyright (c) 2023 The orion Developers + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//! # Parameters: +//! - `data`: The data to be hashed. +//! +//! # Errors: +//! An error will be returned if: +//! - [`finalize()`] is called twice without a [`reset()`] in between. +//! - [`update()`] is called after [`finalize()`] without a [`reset()`] in +//! between. +//! +//! # Example: +//! ```rust +//! use orion::hazardous::hash::sha3::sha3_384::Sha3_384; +//! +//! // Using the streaming interface +//! let mut state = Sha3_384::new(); +//! state.update(b"Hello world")?; +//! let hash = state.finalize()?; +//! +//! // Using the one-shot function +//! let hash_one_shot = Sha3_384::digest(b"Hello world")?; +//! +//! assert_eq!(hash, hash_one_shot); +//! # Ok::<(), orion::errors::UnknownCryptoError>(()) +//! ``` +//! [`update()`]: sha3_384::Sha3_384::update +//! [`reset()`]: sha3_384::Sha3_384::reset +//! [`finalize()`]: sha3_384::Sha3_384::finalize + +use crate::errors::UnknownCryptoError; +#[cfg(feature = "safe_api")] +use std::io; + +use super::Sha3; + +/// Rate of SHA3-384 (equivalent to blocksize in SHA2). +pub const SHA3_384_RATE: usize = 104; + +/// Output size of SHA3-384 in bytes. +pub const SHA3_384_OUTSIZE: usize = 48; + +construct_public! { + /// A type to represent the `Digest` that SHA3-384 returns. + /// + /// # Errors: + /// An error will be returned if: + /// - `slice` is not 48 bytes. + (Digest, test_digest, SHA3_384_OUTSIZE, SHA3_384_OUTSIZE) +} + +impl_from_trait!(Digest, SHA3_384_OUTSIZE); + +#[derive(Clone, Debug)] +/// SHA3-384 streaming state. +pub struct Sha3_384 { + pub(crate) _state: Sha3<SHA3_384_RATE>, +} + +impl Default for Sha3_384 { + fn default() -> Self { + Self::new() + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "safe_api")))] +/// Example: hashing from a [`Read`](std::io::Read)er with SHA3-384. +/// ```rust +/// use orion::{ +/// hazardous::hash::sha3::sha3_384::{Sha3_384, Digest}, +/// errors::UnknownCryptoError, +/// }; +/// use std::io::{self, Read, Write}; +/// +/// // `reader` could also be a `File::open(...)?`. +/// let mut reader = io::Cursor::new(b"some data"); +/// let mut hasher = Sha3_384::new(); +/// std::io::copy(&mut reader, &mut hasher)?; +/// +/// let digest: Digest = hasher.finalize()?; +/// +/// # Ok::<(), Box<dyn std::error::Error>>(()) +/// ``` +#[cfg(feature = "safe_api")] +impl io::Write for Sha3_384 { + /// Update the hasher's internal state with *all* of the bytes given. + /// If this function returns the `Ok` variant, it's guaranteed that it + /// will contain the length of the buffer passed to [`Write`](std::io::Write). + /// Note that this function is just a small wrapper over + /// [`Sha3_384::update`](crate::hazardous::hash::sha3::sha3_384::Sha3_384::update). + /// + /// ## Errors: + /// This function will only ever return the [`std::io::ErrorKind::Other`]() + /// variant when it returns an error. Additionally, this will always contain Orion's + /// [`UnknownCryptoError`](crate::errors::UnknownCryptoError) type. + fn write(&mut self, bytes: &[u8]) -> io::Result<usize> { + self.update(bytes) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + Ok(bytes.len()) + } + + /// This type doesn't buffer writes, so flushing is a no-op. + fn flush(&mut self) -> Result<(), std::io::Error> { + Ok(()) + } +} + +impl Sha3_384 { + /// Initialize a `Sha3_384` struct. + pub fn new() -> Self { + Self { + _state: Sha3::<SHA3_384_RATE>::_new(96), + } + } + + /// Reset to `new()` state. + pub fn reset(&mut self) { + self._state._reset(); + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Update state with `data`. This can be called multiple times. + pub fn update(&mut self, data: &[u8]) -> Result<(), UnknownCryptoError> { + self._state._update(data) + } + + /// Finalize the hash and put the final digest into `dest`. + pub(crate) fn _finalize_internal(&mut self, dest: &mut [u8]) -> Result<(), UnknownCryptoError> { + self._state._finalize(dest) + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Return a SHA3-384 digest. + pub fn finalize(&mut self) -> Result<Digest, UnknownCryptoError> { + let mut digest = [0u8; SHA3_384_OUTSIZE]; + self._finalize_internal(&mut digest)?; + + Ok(Digest::from(digest)) + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Calculate a SHA3-384 digest of some `data`. + pub fn digest(data: &[u8]) -> Result<Digest, UnknownCryptoError> { + let mut ctx = Self::new(); + ctx.update(data)?; + ctx.finalize() + } +} + +// Testing public functions in the module. +#[cfg(test)] +mod public { + use super::*; + + #[test] + fn test_default_equals_new() { + let new = Sha3_384::new(); + let default = Sha3_384::default(); + new._state.compare_state_to_other(&default._state); + } + + #[test] + #[cfg(feature = "safe_api")] + fn test_debug_impl() { + let initial_state = Sha3_384::new(); + let debug = format!("{:?}", initial_state); + let expected = "Sha3_384 { _state: State { state: [***OMITTED***], buffer: [***OMITTED***], capacity: 96, leftover: 0, is_finalized: false } }"; + assert_eq!(debug, expected); + } + + mod test_streaming_interface { + use super::*; + use crate::test_framework::incremental_interface::*; + + impl TestableStreamingContext<Digest> for Sha3_384 { + fn reset(&mut self) -> Result<(), UnknownCryptoError> { + self.reset(); + Ok(()) + } + + fn update(&mut self, input: &[u8]) -> Result<(), UnknownCryptoError> { + self.update(input) + } + + fn finalize(&mut self) -> Result<Digest, UnknownCryptoError> { + self.finalize() + } + + fn one_shot(input: &[u8]) -> Result<Digest, UnknownCryptoError> { + Sha3_384::digest(input) + } + + fn verify_result(expected: &Digest, input: &[u8]) -> Result<(), UnknownCryptoError> { + let actual: Digest = Self::one_shot(input)?; + + if &actual == expected { + Ok(()) + } else { + Err(UnknownCryptoError) + } + } + + fn compare_states(state_1: &Sha3_384, state_2: &Sha3_384) { + state_1._state.compare_state_to_other(&state_2._state); + } + } + + #[test] + fn default_consistency_tests() { + let initial_state: Sha3_384 = Sha3_384::new(); + + let test_runner = StreamingContextConsistencyTester::<Digest, Sha3_384>::new( + initial_state, + SHA3_384_RATE, + ); + test_runner.run_all_tests(); + } + + #[quickcheck] + #[cfg(feature = "safe_api")] + /// Related bug: https://github.com/orion-rs/orion/issues/46 + /// Test different streaming state usage patterns. + fn prop_input_to_consistency(data: Vec<u8>) -> bool { + let initial_state: Sha3_384 = Sha3_384::new(); + + let test_runner = StreamingContextConsistencyTester::<Digest, Sha3_384>::new( + initial_state, + SHA3_384_RATE, + ); + test_runner.run_all_tests_property(&data); + true + } + } + + #[cfg(feature = "safe_api")] + mod test_io_impls { + use crate::hazardous::hash::sha3::sha3_384::Sha3_384; + use std::io::Write; + + #[quickcheck] + fn prop_hasher_write_same_as_update(data: Vec<u8>) -> bool { + let mut hasher_a = Sha3_384::new(); + let mut hasher_b = hasher_a.clone(); + + hasher_a.update(&data).unwrap(); + hasher_b.write_all(&data).unwrap(); + + let hash_a = hasher_a.finalize().unwrap(); + let hash_b = hasher_b.finalize().unwrap(); + + hash_a == hash_b + } + } +} diff --git a/vendor/orion/src/hazardous/hash/sha3/sha3_512.rs b/vendor/orion/src/hazardous/hash/sha3/sha3_512.rs new file mode 100644 index 000000000..d1b243233 --- /dev/null +++ b/vendor/orion/src/hazardous/hash/sha3/sha3_512.rs @@ -0,0 +1,274 @@ +// MIT License + +// Copyright (c) 2023 The orion Developers + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//! # Parameters: +//! - `data`: The data to be hashed. +//! +//! # Errors: +//! An error will be returned if: +//! - [`finalize()`] is called twice without a [`reset()`] in between. +//! - [`update()`] is called after [`finalize()`] without a [`reset()`] in +//! between. +//! +//! # Example: +//! ```rust +//! use orion::hazardous::hash::sha3::sha3_512::Sha3_512; +//! +//! // Using the streaming interface +//! let mut state = Sha3_512::new(); +//! state.update(b"Hello world")?; +//! let hash = state.finalize()?; +//! +//! // Using the one-shot function +//! let hash_one_shot = Sha3_512::digest(b"Hello world")?; +//! +//! assert_eq!(hash, hash_one_shot); +//! # Ok::<(), orion::errors::UnknownCryptoError>(()) +//! ``` +//! [`update()`]: sha3_512::Sha3_512::update +//! [`reset()`]: sha3_512::Sha3_512::reset +//! [`finalize()`]: sha3_512::Sha3_512::finalize + +use crate::errors::UnknownCryptoError; +#[cfg(feature = "safe_api")] +use std::io; + +use super::Sha3; + +/// Rate of SHA3-512 (equivalent to blocksize in SHA2). +pub const SHA3_512_RATE: usize = 72; + +/// Output size of SHA3-512 in bytes. +pub const SHA3_512_OUTSIZE: usize = 64; + +construct_public! { + /// A type to represent the `Digest` that SHA3-512 returns. + /// + /// # Errors: + /// An error will be returned if: + /// - `slice` is not 64 bytes. + (Digest, test_digest, SHA3_512_OUTSIZE, SHA3_512_OUTSIZE) +} + +impl_from_trait!(Digest, SHA3_512_OUTSIZE); + +#[derive(Clone, Debug)] +/// SHA3-512 streaming state. +pub struct Sha3_512 { + pub(crate) _state: Sha3<SHA3_512_RATE>, +} + +impl Default for Sha3_512 { + fn default() -> Self { + Self::new() + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "safe_api")))] +/// Example: hashing from a [`Read`](std::io::Read)er with SHA3-512. +/// ```rust +/// use orion::{ +/// hazardous::hash::sha3::sha3_512::{Sha3_512, Digest}, +/// errors::UnknownCryptoError, +/// }; +/// use std::io::{self, Read, Write}; +/// +/// // `reader` could also be a `File::open(...)?`. +/// let mut reader = io::Cursor::new(b"some data"); +/// let mut hasher = Sha3_512::new(); +/// std::io::copy(&mut reader, &mut hasher)?; +/// +/// let digest: Digest = hasher.finalize()?; +/// +/// # Ok::<(), Box<dyn std::error::Error>>(()) +/// ``` +#[cfg(feature = "safe_api")] +impl io::Write for Sha3_512 { + /// Update the hasher's internal state with *all* of the bytes given. + /// If this function returns the `Ok` variant, it's guaranteed that it + /// will contain the length of the buffer passed to [`Write`](std::io::Write). + /// Note that this function is just a small wrapper over + /// [`Sha3_512::update`](crate::hazardous::hash::sha3::sha3_512::Sha3_512::update). + /// + /// ## Errors: + /// This function will only ever return the [`std::io::ErrorKind::Other`]() + /// variant when it returns an error. Additionally, this will always contain Orion's + /// [`UnknownCryptoError`](crate::errors::UnknownCryptoError) type. + fn write(&mut self, bytes: &[u8]) -> io::Result<usize> { + self.update(bytes) + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + Ok(bytes.len()) + } + + /// This type doesn't buffer writes, so flushing is a no-op. + fn flush(&mut self) -> Result<(), std::io::Error> { + Ok(()) + } +} + +impl Sha3_512 { + /// Initialize a `Sha3_512` struct. + pub fn new() -> Self { + Self { + _state: Sha3::<SHA3_512_RATE>::_new(128), + } + } + + /// Reset to `new()` state. + pub fn reset(&mut self) { + self._state._reset(); + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Update state with `data`. This can be called multiple times. + pub fn update(&mut self, data: &[u8]) -> Result<(), UnknownCryptoError> { + self._state._update(data) + } + + /// Finalize the hash and put the final digest into `dest`. + pub(crate) fn _finalize_internal(&mut self, dest: &mut [u8]) -> Result<(), UnknownCryptoError> { + self._state._finalize(dest) + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Return a SHA3-512 digest. + pub fn finalize(&mut self) -> Result<Digest, UnknownCryptoError> { + let mut digest = [0u8; SHA3_512_OUTSIZE]; + self._finalize_internal(&mut digest)?; + + Ok(Digest::from(digest)) + } + + #[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."] + /// Calculate a SHA3-512 digest of some `data`. + pub fn digest(data: &[u8]) -> Result<Digest, UnknownCryptoError> { + let mut ctx = Self::new(); + ctx.update(data)?; + ctx.finalize() + } +} + +// Testing public functions in the module. +#[cfg(test)] +mod public { + use super::*; + + #[test] + fn test_default_equals_new() { + let new = Sha3_512::new(); + let default = Sha3_512::default(); + new._state.compare_state_to_other(&default._state); + } + + #[test] + #[cfg(feature = "safe_api")] + fn test_debug_impl() { + let initial_state = Sha3_512::new(); + let debug = format!("{:?}", initial_state); + let expected = "Sha3_512 { _state: State { state: [***OMITTED***], buffer: [***OMITTED***], capacity: 128, leftover: 0, is_finalized: false } }"; + assert_eq!(debug, expected); + } + + mod test_streaming_interface { + use super::*; + use crate::test_framework::incremental_interface::*; + + impl TestableStreamingContext<Digest> for Sha3_512 { + fn reset(&mut self) -> Result<(), UnknownCryptoError> { + self.reset(); + Ok(()) + } + + fn update(&mut self, input: &[u8]) -> Result<(), UnknownCryptoError> { + self.update(input) + } + + fn finalize(&mut self) -> Result<Digest, UnknownCryptoError> { + self.finalize() + } + + fn one_shot(input: &[u8]) -> Result<Digest, UnknownCryptoError> { + Sha3_512::digest(input) + } + + fn verify_result(expected: &Digest, input: &[u8]) -> Result<(), UnknownCryptoError> { + let actual: Digest = Self::one_shot(input)?; + + if &actual == expected { + Ok(()) + } else { + Err(UnknownCryptoError) + } + } + + fn compare_states(state_1: &Sha3_512, state_2: &Sha3_512) { + state_1._state.compare_state_to_other(&state_2._state); + } + } + + #[test] + fn default_consistency_tests() { + let initial_state: Sha3_512 = Sha3_512::new(); + + let test_runner = StreamingContextConsistencyTester::<Digest, Sha3_512>::new( + initial_state, + SHA3_512_RATE, + ); + test_runner.run_all_tests(); + } + + #[quickcheck] + #[cfg(feature = "safe_api")] + /// Related bug: https://github.com/orion-rs/orion/issues/46 + /// Test different streaming state usage patterns. + fn prop_input_to_consistency(data: Vec<u8>) -> bool { + let initial_state: Sha3_512 = Sha3_512::new(); + + let test_runner = StreamingContextConsistencyTester::<Digest, Sha3_512>::new( + initial_state, + SHA3_512_RATE, + ); + test_runner.run_all_tests_property(&data); + true + } + } + + #[cfg(feature = "safe_api")] + mod test_io_impls { + use crate::hazardous::hash::sha3::sha3_512::Sha3_512; + use std::io::Write; + + #[quickcheck] + fn prop_hasher_write_same_as_update(data: Vec<u8>) -> bool { + let mut hasher_a = Sha3_512::new(); + let mut hasher_b = hasher_a.clone(); + + hasher_a.update(&data).unwrap(); + hasher_b.write_all(&data).unwrap(); + + let hash_a = hasher_a.finalize().unwrap(); + let hash_b = hasher_b.finalize().unwrap(); + + hash_a == hash_b + } + } +} diff --git a/vendor/orion/src/hazardous/kem/mod.rs b/vendor/orion/src/hazardous/kem/mod.rs new file mode 100644 index 000000000..767b65337 --- /dev/null +++ b/vendor/orion/src/hazardous/kem/mod.rs @@ -0,0 +1,25 @@ +// MIT License + +// Copyright (c) 2023 The orion Developers + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#[cfg(feature = "safe_api")] +/// DHKEM(X25519, HKDF-SHA256) as specified in HPKE [RFC 9180](https://www.rfc-editor.org/rfc/rfc9180.html). +pub mod x25519_hkdf_sha256; diff --git a/vendor/orion/src/hazardous/kem/x25519_hkdf_sha256.rs b/vendor/orion/src/hazardous/kem/x25519_hkdf_sha256.rs new file mode 100644 index 000000000..0ea9609f2 --- /dev/null +++ b/vendor/orion/src/hazardous/kem/x25519_hkdf_sha256.rs @@ -0,0 +1,289 @@ +// MIT License + +// Copyright (c) 2023 The orion Developers + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +//! # Parameters: +//! - `public_recipient`: The public X25519 key of the recipient. +//! - `public_ephemeral`: The ephemeral X25519 key fro this KEM operation. +//! - `secret_recipient`: The private X25519 of the recipient. +//! - `secret_sender`: The private X25519 of the sender. +//! +//! # Errors: +//! An error will be returned if: +//! - If a shared X25519 secret is all-zero. +//! - If `ikm.len() < 32` when calling [`derive_keypair()`]. +//! +//! # Panics: +//! A panic will occur if: +//! - [`generate()`] panics during [`encap()`], [`auth_encap()`], [`decap()`] or [`auth_decap()`]. +//! +//! # Security: +//! - The `ikm` used as input for [`derive_keypair()`] must never be reused. +//! - This KEM is vulnerable to key-compromise impersonation attacks (KCI), meaning +//! that if the recipients private key `secret_recipient` is leaked at any point, sender authentication +//! no longer holds. See [KCI section](https://www.rfc-editor.org/rfc/rfc9180.html#section-9.1.1) of the RFC +//! on recommendations on how to mitigate this. +//! - Please refer to the RFC for a detailed description of all security properties provided: <https://www.rfc-editor.org/rfc/rfc9180.html#section-9>. +//! +//! # Example: +//! ```rust +//! # #[cfg(feature = "safe_api")] { +//! use orion::hazardous::kem::x25519_hkdf_sha256::DhKem; +//! +//! let (sender_secret, sender_public) = DhKem::generate_keypair()?; +//! let (recipient_secret, recipient_public) = DhKem::generate_keypair()?; +//! +//! let (sender_shared_secret, public_eph) = +//! DhKem::auth_encap(&recipient_public, &sender_secret)?; +//! let recipient_shared_secret = DhKem::auth_decap(&public_eph, &recipient_secret, &sender_public)?; +//! +//! assert_eq!(sender_shared_secret, recipient_shared_secret); +//! # } +//! # Ok::<(), orion::errors::UnknownCryptoError>(()) +//! ``` +//! [`encap()`]: x25519_hkdf_sha256::DhKem::encap +//! [`decap()`]: x25519_hkdf_sha256::DhKem::decap +//! [`auth_encap()`]: x25519_hkdf_sha256::DhKem::auth_encap +//! [`auth_decap()`]: x25519_hkdf_sha256::DhKem::auth_decap +//! [`derive_keypair()`]: x25519_hkdf_sha256::DhKem::derive_keypair +//! [`generate()`]: crate::hazardous::ecc::x25519::PrivateKey::generate + +#![cfg_attr(docsrs, doc(cfg(feature = "safe_api")))] + +use crate::errors::UnknownCryptoError; +use crate::hazardous::ecc::x25519; +use crate::hazardous::kdf::hkdf::sha256; +use zeroize::Zeroize; + +pub use crate::hazardous::ecc::x25519::PrivateKey; +pub use crate::hazardous::ecc::x25519::PublicKey; + +construct_secret_key! { + /// A type to represent the `SharedSecret` that DH-KEM(X25519, HKDF-SHA256) produces. + /// + /// This type simply holds bytes. Creating an instance from slices or similar, + /// performs no checks whatsoever. + /// + /// # Errors: + /// An error will be returned if: + /// - `slice` is not 32 bytes. + (SharedSecret, test_shared_key, 32, 32) +} + +/// DHKEM(X25519, HKDF-SHA256) as specified in HPKE [RFC 9180](https://www.rfc-editor.org/rfc/rfc9180.html). +pub struct DhKem {} + +impl DhKem { + /// ID for this DH-KEM. See <https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1> + pub const KEM_ID: u16 = 0x0020; + + /// Version of HPKE implemented. See <https://www.rfc-editor.org/rfc/rfc9180.html#section-4-10>. + pub const HPKE_VERSION_ID: &'static str = "HPKE-v1"; + + /// Length of bytes of a shared secret produced by this KEM. See <https://www.rfc-editor.org/rfc/rfc9180.html#section-4-1>. + const N_SECRET: u16 = 32; + + fn labeled_extract( + salt: &[u8], + label: &[u8; 7], + ikm: &[u8], + ) -> Result<sha256::Tag, UnknownCryptoError> { + let mut labeled_ikm = Vec::<u8>::new(); + labeled_ikm.extend_from_slice(Self::HPKE_VERSION_ID.as_bytes()); + labeled_ikm.extend_from_slice(b"KEM"); + labeled_ikm.extend_from_slice(&Self::KEM_ID.to_be_bytes()); + labeled_ikm.extend_from_slice(label); + labeled_ikm.extend_from_slice(ikm); + + sha256::extract(salt, &labeled_ikm) + } + + fn labeled_expand<const L: u16>( + prk: &sha256::Tag, + label: &[u8], + info: &[u8], + ) -> Result<Vec<u8>, UnknownCryptoError> { + let mut labeled_info = Vec::<u8>::new(); + labeled_info.extend_from_slice(&L.to_be_bytes()); + labeled_info.extend_from_slice(Self::HPKE_VERSION_ID.as_bytes()); + labeled_info.extend_from_slice(b"KEM"); + labeled_info.extend_from_slice(&Self::KEM_ID.to_be_bytes()); + labeled_info.extend_from_slice(label); + labeled_info.extend_from_slice(info); + + let mut out = vec![0u8; L as usize]; + sha256::expand(prk, Some(&labeled_info), &mut out)?; + + Ok(out) + } + + fn extract_and_expand(dh: &[u8], kem_context: &[u8]) -> Result<Vec<u8>, UnknownCryptoError> { + let eae_prk = Self::labeled_extract(b"", b"eae_prk", dh)?; + let shared_secret = + Self::labeled_expand::<{ Self::N_SECRET }>(&eae_prk, b"shared_secret", kem_context)?; + + Ok(shared_secret) + } + + /// Generate random X25519 keypair. + pub fn generate_keypair() -> Result<(PrivateKey, PublicKey), UnknownCryptoError> { + let sk = PrivateKey::generate(); + let pk = PublicKey::try_from(&sk)?; + + Ok((sk, pk)) + } + + /// Deterministically derive a X25519 keyapir from `ikm`. + pub fn derive_keypair(ikm: &[u8]) -> Result<(PrivateKey, PublicKey), UnknownCryptoError> { + if ikm.len() < 32 { + return Err(UnknownCryptoError); + } + + let dkp_prk = Self::labeled_extract(b"", b"dkp_prk", ikm)?; + let sk = PrivateKey::from_slice(&Self::labeled_expand::<32>(&dkp_prk, b"sk", b"")?)?; + let pk = PublicKey::try_from(&sk)?; + + Ok((sk, pk)) + } + + /// Derive ephemeral shared secret and encapsulation thereof, which can be + /// decapsulated by the holder of `public_recipient`. + pub fn encap( + public_recipient: &PublicKey, + ) -> Result<(SharedSecret, PublicKey), UnknownCryptoError> { + let secret_ephemeral = PrivateKey::generate(); + let public_ephemeral = PublicKey::try_from(&secret_ephemeral)?; + + let dh = x25519::key_agreement(&secret_ephemeral, public_recipient)?; + let mut kem_context = [0u8; 32 + 32]; + kem_context[..32].copy_from_slice(&public_ephemeral.to_bytes()); + kem_context[32..64].copy_from_slice(&public_recipient.to_bytes()); + + let shared_secret = Self::extract_and_expand(dh.unprotected_as_bytes(), &kem_context)?; + + Ok((SharedSecret::from_slice(&shared_secret)?, public_ephemeral)) + } + + /// Decapsulate `public_ephemeral` and return the shared ephemeral secrety, + /// using `secret_recipient` private key. + pub fn decap( + public_ephemeral: &PublicKey, + secret_recipient: &PrivateKey, + ) -> Result<SharedSecret, UnknownCryptoError> { + let dh = x25519::key_agreement(secret_recipient, public_ephemeral)?; + + let mut kem_context = [0u8; 32 + 32]; + kem_context[..32].copy_from_slice(&public_ephemeral.to_bytes()); + kem_context[32..64].copy_from_slice(&PublicKey::try_from(secret_recipient)?.to_bytes()); + + let shared_secret = Self::extract_and_expand(dh.unprotected_as_bytes(), &kem_context)?; + + SharedSecret::from_slice(&shared_secret) + } + + /// Equivalent to [`Self::encap()`], additionally ensuring the holder of `secret_sender` was + /// the one to generate the shared secret. + pub fn auth_encap( + public_recipient: &PublicKey, + secret_sender: &PrivateKey, + ) -> Result<(SharedSecret, PublicKey), UnknownCryptoError> { + let secret_ehemeral = PrivateKey::generate(); + let public_ephemeral = PublicKey::try_from(&secret_ehemeral)?; + + let mut dh = [0u8; 64]; + dh[..32].copy_from_slice( + x25519::key_agreement(&secret_ehemeral, public_recipient)?.unprotected_as_bytes(), + ); + dh[32..64].copy_from_slice( + x25519::key_agreement(secret_sender, public_recipient)?.unprotected_as_bytes(), + ); + + let mut kem_context = [0u8; 32 * 3]; + kem_context[..32].copy_from_slice(&public_ephemeral.to_bytes()); + kem_context[32..64].copy_from_slice(&public_recipient.to_bytes()); + kem_context[64..96].copy_from_slice(&PublicKey::try_from(secret_sender)?.to_bytes()); + + let shared_secret = Self::extract_and_expand(&dh, &kem_context)?; + dh.iter_mut().zeroize(); + + Ok((SharedSecret::from_slice(&shared_secret)?, public_ephemeral)) + } + + /// Equivalent to [`Self::decap()`], additionally ensuring the holder of `secret_sender` was + /// the one to generate the shared secret. + pub fn auth_decap( + public_ephemeral: &PublicKey, + secret_recipient: &PrivateKey, + public_sender: &PublicKey, + ) -> Result<SharedSecret, UnknownCryptoError> { + let mut dh = [0u8; 64]; + dh[..32].copy_from_slice( + x25519::key_agreement(secret_recipient, public_ephemeral)?.unprotected_as_bytes(), + ); + dh[32..64].copy_from_slice( + x25519::key_agreement(secret_recipient, public_sender)?.unprotected_as_bytes(), + ); + + let mut kem_context = [0u8; 32 * 3]; + kem_context[..32].copy_from_slice(&public_ephemeral.to_bytes()); + kem_context[32..64].copy_from_slice(&PublicKey::try_from(secret_recipient)?.to_bytes()); + kem_context[64..96].copy_from_slice(&public_sender.to_bytes()); + + let shared_secret = Self::extract_and_expand(&dh, &kem_context)?; + dh.iter_mut().zeroize(); + + SharedSecret::from_slice(&shared_secret) + } +} + +#[cfg(test)] +#[cfg(feature = "safe_api")] +mod public { + use crate::hazardous::ecc::x25519::{PrivateKey, PublicKey}; + use crate::hazardous::kem::x25519_hkdf_sha256::*; + + #[test] + fn encap_decap_roundtrip() { + let recipient_secret = PrivateKey::generate(); + let recipient_public = PublicKey::try_from(&recipient_secret).unwrap(); + + let (shared_secret_1, public_eph) = DhKem::encap(&recipient_public).unwrap(); + let shared_secret_2 = DhKem::decap(&public_eph, &recipient_secret).unwrap(); + + assert_eq!(shared_secret_1, shared_secret_2); + } + + #[test] + fn auth_encap_decap_roundtrip() { + let sender_secret = PrivateKey::generate(); + let sender_public = PublicKey::try_from(&sender_secret).unwrap(); + + let recipient_secret = PrivateKey::generate(); + let recipient_public = PublicKey::try_from(&recipient_secret).unwrap(); + + let (shared_secret_1, public_eph) = + DhKem::auth_encap(&recipient_public, &sender_secret).unwrap(); + let shared_secret_2 = + DhKem::auth_decap(&public_eph, &recipient_secret, &sender_public).unwrap(); + + assert_eq!(shared_secret_1, shared_secret_2); + } +} diff --git a/vendor/orion/src/hazardous/mac/poly1305.rs b/vendor/orion/src/hazardous/mac/poly1305.rs index 29853f566..b9c974d6e 100644 --- a/vendor/orion/src/hazardous/mac/poly1305.rs +++ b/vendor/orion/src/hazardous/mac/poly1305.rs @@ -77,8 +77,8 @@ use crate::{ }; use fiat_crypto::poly1305_32::{ fiat_poly1305_add, fiat_poly1305_carry, fiat_poly1305_carry_mul, fiat_poly1305_from_bytes, - fiat_poly1305_loose_field_element, fiat_poly1305_selectznz, fiat_poly1305_subborrowx_u26, - fiat_poly1305_tight_field_element, fiat_poly1305_u1, + fiat_poly1305_loose_field_element, fiat_poly1305_relax, fiat_poly1305_selectznz, + fiat_poly1305_subborrowx_u26, fiat_poly1305_tight_field_element, fiat_poly1305_u1, }; /// The blocksize which Poly1305 operates on. @@ -119,8 +119,8 @@ impl_from_trait!(Tag, POLY1305_OUTSIZE); #[derive(Clone)] /// Poly1305 streaming state. pub struct Poly1305 { - a: [u32; 5], - r: [u32; 5], + a: fiat_poly1305_tight_field_element, + r: fiat_poly1305_loose_field_element, s: [u32; 4], leftover: usize, buffer: [u8; POLY1305_BLOCKSIZE], @@ -130,8 +130,8 @@ pub struct Poly1305 { impl Drop for Poly1305 { fn drop(&mut self) { use zeroize::Zeroize; - self.a.zeroize(); - self.r.zeroize(); + self.a.0.zeroize(); + self.r.0.zeroize(); self.s.zeroize(); self.buffer.zeroize(); } @@ -164,11 +164,11 @@ impl Poly1305 { // One byte is appended to detect trailing zeroes if not last chunk. // See https://cr.yp.to/mac/poly1305-20050329.pdf, Section 2 "Conversion and padding". mb[16] = u8::from(!self.is_finalized); - let mut m: fiat_poly1305_tight_field_element = [0u32; 5]; + let mut m = fiat_poly1305_tight_field_element([0u32; 5]); fiat_poly1305_from_bytes(&mut m, &mb); // h += m - let mut h: fiat_poly1305_loose_field_element = [0u32; 5]; + let mut h = fiat_poly1305_loose_field_element([0u32; 5]); fiat_poly1305_add(&mut h, &self.a, &m); // h *= r with partial reduction modulo p fiat_poly1305_carry_mul(&mut self.a, &h, &self.r); @@ -181,11 +181,13 @@ impl Poly1305 { /// Remaining processing after all data blocks have been processed. fn process_end_of_stream(&mut self) { // full carry h - let mut buf_h: fiat_poly1305_tight_field_element = [0u32; 5]; - fiat_poly1305_carry(&mut buf_h, &self.a); + let mut buf_h = fiat_poly1305_tight_field_element([0u32; 5]); + let mut a_relaxed = fiat_poly1305_loose_field_element([0u32; 5]); + fiat_poly1305_relax(&mut a_relaxed, &self.a); + fiat_poly1305_carry(&mut buf_h, &a_relaxed); // compute h + -p - let mut p: fiat_poly1305_tight_field_element = [0u32; 5]; + let mut p = fiat_poly1305_tight_field_element([0u32; 5]); fiat_poly1305_from_bytes(&mut p, &Self::PRIME); let mut carry: fiat_poly1305_u1 = 0; @@ -197,7 +199,7 @@ impl Poly1305 { // select h if h < p, or h + -p if h >= p let mut ret = [0u32; 5]; - fiat_poly1305_selectznz(&mut ret, carry,&[g0, g1, g2, g3, g4], &buf_h); + fiat_poly1305_selectznz(&mut ret, carry,&[g0, g1, g2, g3, g4], &buf_h.0); let mut h0 = ret[0]; let mut h1 = ret[1]; @@ -228,8 +230,8 @@ impl Poly1305 { /// Initialize a `Poly1305` struct with a given one-time key. pub fn new(one_time_key: &OneTimeKey) -> Self { let mut state = Self { - a: [0u32; 5], - r: [0u32; 5], + a: fiat_poly1305_tight_field_element([0u32; 5]), + r: fiat_poly1305_loose_field_element([0u32; 5]), s: [0u32; 4], leftover: 0, buffer: [0u8; POLY1305_BLOCKSIZE], @@ -280,7 +282,7 @@ impl Poly1305 { /// Reset to `new()` state. pub fn reset(&mut self) { - self.a = [0u32; 5]; + self.a = fiat_poly1305_tight_field_element([0u32; 5]); self.leftover = 0; self.is_finalized = false; self.buffer = [0u8; POLY1305_BLOCKSIZE]; @@ -358,7 +360,7 @@ impl Poly1305 { } self.process_end_of_stream(); - store_u32_into_le(&self.a[0..4], &mut local_buffer); + store_u32_into_le(&self.a.0[0..4], &mut local_buffer); Ok(Tag::from(local_buffer)) } @@ -455,8 +457,8 @@ mod public { } fn compare_states(state_1: &Poly1305, state_2: &Poly1305) { - assert_eq!(state_1.a, state_2.a); - assert_eq!(state_1.r, state_2.r); + assert_eq!(state_1.a.0, state_2.a.0); + assert_eq!(state_1.r.0, state_2.r.0); assert_eq!(state_1.s, state_2.s); assert_eq!(state_1.leftover, state_2.leftover); assert_eq!(state_1.buffer[..], state_2.buffer[..]); diff --git a/vendor/orion/src/hazardous/mod.rs b/vendor/orion/src/hazardous/mod.rs index 25a5ae227..ff8c188ae 100644 --- a/vendor/orion/src/hazardous/mod.rs +++ b/vendor/orion/src/hazardous/mod.rs @@ -44,3 +44,10 @@ pub mod stream; /// Elliptic-Curve Cryptography. pub mod ecc; + +#[cfg(feature = "experimental")] +/// Fully-committing Authenticated Encryption. __WARNING:__ Experimental feature. +pub mod cae; + +/// Key Encapsulation Mechanisms (KEMs). +pub mod kem; diff --git a/vendor/orion/src/test_framework/aead_interface.rs b/vendor/orion/src/test_framework/aead_interface.rs index 93ed41b25..b19c44f67 100644 --- a/vendor/orion/src/test_framework/aead_interface.rs +++ b/vendor/orion/src/test_framework/aead_interface.rs @@ -65,7 +65,7 @@ pub fn AeadTestRunner<Sealer, Opener, Key, Nonce>( } #[cfg(feature = "safe_api")] -/// Related bug: https://github.com/orion-rs/orion/issues/52 +/// Related bug: <https://github.com/orion-rs/orion/issues/52> /// Test dst_out mutable array sizes when using seal(). fn seal_dst_out_length<Sealer, Key, Nonce>( sealer: &Sealer, @@ -95,7 +95,7 @@ fn seal_dst_out_length<Sealer, Key, Nonce>( } #[cfg(feature = "safe_api")] -/// Related bug: https://github.com/orion-rs/orion/issues/52 +/// Related bug: <https://github.com/orion-rs/orion/issues/52> /// Test input sizes when using seal(). fn seal_plaintext_length<Sealer, Key, Nonce>( sealer: &Sealer, @@ -122,7 +122,7 @@ fn seal_plaintext_length<Sealer, Key, Nonce>( } #[cfg(feature = "safe_api")] -/// Related bug: https://github.com/orion-rs/orion/issues/52 +/// Related bug: <https://github.com/orion-rs/orion/issues/52> /// Test dst_out mutable array sizes when using open(). fn open_dst_out_length<Sealer, Opener, Key, Nonce>( sealer: &Sealer, diff --git a/vendor/orion/src/util/endianness.rs b/vendor/orion/src/util/endianness.rs index e40087350..b8d0d92e6 100644 --- a/vendor/orion/src/util/endianness.rs +++ b/vendor/orion/src/util/endianness.rs @@ -30,7 +30,7 @@ macro_rules! impl_store_into { let type_alias_len = mem::size_of::<$type_alias>(); // The length of src must be evenly divisible with the length of dst, // making sure .chunks_exact() leaves no remainder. - assert_eq!((type_alias_len * src.len()), dst.len()); + assert_eq!(mem::size_of_val(src), dst.len()); for (src_elem, dst_chunk) in src.iter().zip(dst.chunks_exact_mut(type_alias_len)) { dst_chunk.copy_from_slice(&src_elem.$conv_function()); @@ -46,7 +46,7 @@ macro_rules! impl_load_into { let type_alias_len = mem::size_of::<$type_alias>(); // The length of src must be evenly divisible with the length of dst, // making sure .chunks_exact() leaves no remainder. - assert_eq!((dst.len() * type_alias_len), src.len()); + assert_eq!(mem::size_of_val(dst), src.len()); for (src_chunk, dst_elem) in src.chunks_exact(type_alias_len).zip(dst.iter_mut()) { // The above assert and this debug assert should prove that .unwrap() |