diff --git a/.github/workflows/sha1-checked.yml b/.github/workflows/sha1-checked.yml new file mode 100644 index 00000000..313fed11 --- /dev/null +++ b/.github/workflows/sha1-checked.yml @@ -0,0 +1,155 @@ +name: sha1-checked + +on: + pull_request: + paths: + - ".github/workflows/sha1-checked.yml" + - "sha1-checked/**" + - "Cargo.*" + push: + branches: master + +defaults: + run: + working-directory: sha1-checked + +env: + RUSTFLAGS: "-Dwarnings" + CARGO_INCREMENTAL: 0 + +jobs: + set-msrv: + uses: RustCrypto/actions/.github/workflows/set-msrv.yml@master + with: + msrv: 1.72.0 + + # Builds for no_std platforms + build: + needs: set-msrv + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - ${{needs.set-msrv.outputs.msrv}} + - stable + target: + - thumbv7em-none-eabi + - wasm32-unknown-unknown + - loongarch64-unknown-linux-gnu + steps: + - uses: actions/checkout@v4 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: ${{ matrix.target }} + - uses: RustCrypto/actions/cargo-hack-install@master + - run: cargo hack build --target ${{ matrix.target }} --each-feature --exclude-features default,std + + minimal-versions: + uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + with: + working-directory: ${{ github.workflow }} + + # Linux tests + linux: + needs: set-msrv + strategy: + matrix: + include: + # 32-bit Linux/x86 + #- target: i686-unknown-linux-gnu + # rust: ${{needs.set-msrv.outputs.msrv}} + # deps: sudo apt update && sudo apt install gcc-multilib + #- target: i686-unknown-linux-gnu + # rust: stable + # deps: sudo apt update && sudo apt install gcc-multilib + + # 64-bit Linux/x86_64 + - target: x86_64-unknown-linux-gnu + rust: ${{needs.set-msrv.outputs.msrv}} + - target: x86_64-unknown-linux-gnu + rust: stable + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: ${{ matrix.target }} + - uses: RustCrypto/actions/cargo-hack-install@master + - run: ${{ matrix.deps }} + - run: cargo hack test --feature-powerset + + # macOS tests + macos: + needs: set-msrv + strategy: + matrix: + rust: + - ${{needs.set-msrv.outputs.msrv}} + - stable + + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: x86_64-apple-darwin + - run: cargo test --no-default-features + - run: cargo test + - run: cargo test --all-features + + # Windows tests + windows: + needs: set-msrv + strategy: + matrix: + include: + # 64-bit Windows (GNU) + - target: x86_64-pc-windows-gnu + toolchain: ${{needs.set-msrv.outputs.msrv}} + - target: x86_64-pc-windows-gnu + toolchain: stable + + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.toolchain }} + targets: ${{ matrix.target }} + - uses: msys2/setup-msys2@v2 + - run: cargo test --target ${{ matrix.target }} + + # Cross-compiled tests + cross: + strategy: + matrix: + rust: + - 1.72.0 + - stable + target: + - aarch64-unknown-linux-gnu + - powerpc-unknown-linux-gnu + features: + - default + + runs-on: ubuntu-latest + defaults: + run: + # Cross mounts only current package, i.e. by default it ignores workspace's Cargo.toml + working-directory: . + steps: + - uses: actions/checkout@v4 + - uses: ./.github/actions/cross-tests + with: + rust: ${{ matrix.rust }} + package: ${{ github.workflow }} + target: ${{ matrix.target }} + features: ${{ matrix.features }} diff --git a/Cargo.lock b/Cargo.lock index 6d42be8f..62074006 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,7 +16,7 @@ name = "ascon-hash" version = "0.3.0-pre" dependencies = [ "ascon", - "digest", + "digest 0.11.0-pre.8", "hex", "hex-literal", "spectral", @@ -33,7 +33,7 @@ name = "belt-hash" version = "0.2.0-pre.3" dependencies = [ "belt-block", - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -41,7 +41,7 @@ dependencies = [ name = "blake2" version = "0.11.0-pre.3" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -51,13 +51,22 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "847495c209977a90e8aad588b959d0ca9f5dc228096d29a6bd3defd53f35eaec" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.11.0-pre.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ded684142010808eb980d9974ef794da2bcf97d13396143b1515e9f0fb4a10e" dependencies = [ - "crypto-common", + "crypto-common 0.2.0-pre.5", "zeroize", ] @@ -67,6 +76,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "const-oid" version = "0.10.0-pre.2" @@ -82,6 +97,16 @@ dependencies = [ "libc", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "crypto-common" version = "0.2.0-pre.5" @@ -93,6 +118,18 @@ dependencies = [ "rand_core", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "blobby", + "block-buffer 0.10.4", + "const-oid 0.9.6", + "crypto-common 0.1.6", +] + [[package]] name = "digest" version = "0.11.0-pre.8" @@ -100,9 +137,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "065d93ead7c220b85d5b4be4795d8398eac4ff68b5ee63895de0a3c1fb6edf25" dependencies = [ "blobby", - "block-buffer", - "const-oid", - "crypto-common", + "block-buffer 0.11.0-pre.5", + "const-oid 0.10.0-pre.2", + "crypto-common 0.2.0-pre.5", "subtle", "zeroize", ] @@ -111,11 +148,21 @@ dependencies = [ name = "fsb" version = "0.2.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", "whirlpool", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.12" @@ -131,7 +178,7 @@ dependencies = [ name = "gost94" version = "0.11.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -139,7 +186,7 @@ dependencies = [ name = "groestl" version = "0.11.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -168,7 +215,7 @@ dependencies = [ name = "jh" version = "0.2.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", "ppv-lite86", ] @@ -177,7 +224,7 @@ dependencies = [ name = "k12" version = "0.4.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", "sha3", ] @@ -202,7 +249,7 @@ name = "md-5" version = "0.11.0-pre.3" dependencies = [ "cfg-if", - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -210,7 +257,7 @@ dependencies = [ name = "md2" version = "0.11.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -218,7 +265,7 @@ dependencies = [ name = "md4" version = "0.11.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -241,27 +288,48 @@ dependencies = [ name = "ripemd" version = "0.2.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha1" version = "0.11.0-pre.3" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] +[[package]] +name = "sha1-checked" +version = "0.10.0" +dependencies = [ + "digest 0.10.7", + "hex-literal", + "sha1 0.10.6", + "zeroize", +] + [[package]] name = "sha2" version = "0.11.0-pre.3" dependencies = [ "cfg-if", "cpufeatures", - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -269,7 +337,7 @@ dependencies = [ name = "sha3" version = "0.11.0-pre.3" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", "keccak", ] @@ -278,7 +346,7 @@ dependencies = [ name = "shabal" version = "0.5.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -286,7 +354,7 @@ dependencies = [ name = "skein" version = "0.2.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", "threefish", ] @@ -295,7 +363,7 @@ dependencies = [ name = "sm3" version = "0.5.0-pre.3" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -309,7 +377,7 @@ checksum = "ae3c15181f4b14e52eeaac3efaeec4d2764716ce9c86da0c934c3e318649c5ba" name = "streebog" version = "0.11.0-pre.3" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -332,7 +400,7 @@ dependencies = [ name = "tiger" version = "0.3.0-pre" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] @@ -342,6 +410,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -352,7 +426,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" name = "whirlpool" version = "0.11.0-pre.2" dependencies = [ - "digest", + "digest 0.11.0-pre.8", "hex-literal", ] diff --git a/Cargo.toml b/Cargo.toml index 26637761..54e8d97a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [ "md5", "ripemd", "sha1", + "sha1-checked", "sha2", "sha3", "shabal", diff --git a/README.md b/README.md index f104f710..101c3fca 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Additionally all crates do not require the standard library (i.e. `no_std` capab | [MD5] | [`md5`] [:exclamation:] | [![crates.io](https://img.shields.io/crates/v/md-5.svg)](https://crates.io/crates/md-5) | [![Documentation](https://docs.rs/md-5/badge.svg)](https://docs.rs/md-5) | ![MSRV 1.72][msrv-1.72] | :broken_heart: | | [RIPEMD] | [`ripemd`] | [![crates.io](https://img.shields.io/crates/v/ripemd.svg)](https://crates.io/crates/ripemd) | [![Documentation](https://docs.rs/ripemd/badge.svg)](https://docs.rs/ripemd) | ![MSRV 1.71][msrv-1.71] | :green_heart: | | [SHA-1] | [`sha1`] | [![crates.io](https://img.shields.io/crates/v/sha1.svg)](https://crates.io/crates/sha1) | [![Documentation](https://docs.rs/sha1/badge.svg)](https://docs.rs/sha1) | ![MSRV 1.72][msrv-1.72] | :broken_heart: | +| [SHA-1 Checked] | [`sha1-checked`] | [![crates.io](https://img.shields.io/crates/v/sha1-checked.svg)](https://crates.io/crates/sha1-checked) | [![Documentation](https://docs.rs/sha1-checked/badge.svg)](https://docs.rs/sha1-checked) | ![MSRV 1.72][msrv-1.72] | :yellow_heart: | | [SHA-2] | [`sha2`] | [![crates.io](https://img.shields.io/crates/v/sha2.svg)](https://crates.io/crates/sha2) | [![Documentation](https://docs.rs/sha2/badge.svg)](https://docs.rs/sha2) | ![MSRV 1.72][msrv-1.72] | :green_heart: | | [SHA-3] (Keccak) | [`sha3`] | [![crates.io](https://img.shields.io/crates/v/sha3.svg)](https://crates.io/crates/sha3) | [![Documentation](https://docs.rs/sha3/badge.svg)](https://docs.rs/sha3) | ![MSRV 1.71][msrv-1.71] | :green_heart: | | [SHABAL] | [`shabal`] | [![crates.io](https://img.shields.io/crates/v/shabal.svg)](https://crates.io/crates/shabal) | [![Documentation](https://docs.rs/shabal/badge.svg)](https://docs.rs/shabal) | ![MSRV 1.71][msrv-1.71] | :green_heart: | @@ -252,6 +253,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [`md5`]: ./md5 [`ripemd`]: ./ripemd [`sha1`]: ./sha1 +[`sha1-checked`]: ./sha1-checked [`sha2`]: ./sha2 [`sha3`]: ./sha3 [`shabal`]: ./shabal @@ -293,6 +295,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [MD5]: https://en.wikipedia.org/wiki/MD5 [RIPEMD]: https://en.wikipedia.org/wiki/RIPEMD [SHA-1]: https://en.wikipedia.org/wiki/SHA-1 +[SHA-1 Checked]: https://github.com/cr-marcstevens/sha1collisiondetection [SHA-2]: https://en.wikipedia.org/wiki/SHA-2 [SHA-3]: https://en.wikipedia.org/wiki/SHA-3 [SHABAL]: https://www.cs.rit.edu/~ark/20090927/Round2Candidates/Shabal.pdf diff --git a/sha1-checked/CHANGELOG.md b/sha1-checked/CHANGELOG.md new file mode 100644 index 00000000..dadf7856 --- /dev/null +++ b/sha1-checked/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## UNRELEASED diff --git a/sha1-checked/Cargo.toml b/sha1-checked/Cargo.toml new file mode 100644 index 00000000..afd9bae9 --- /dev/null +++ b/sha1-checked/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "sha1-checked" +version = "0.10.0" +description = "SHA-1 hash function with collision detection" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" +edition = "2021" +documentation = "https://docs.rs/sha1-checked" +repository = "https://github.com/RustCrypto/hashes" +keywords = ["crypto", "sha1", "hash", "digest"] +categories = ["cryptography", "no-std"] +rust-version = "1.72" + +exclude = [ + "sha1-checked/tests/data/shattered-1.pdf", + "sha1-checked/tests/data/shattered-2.pdf", +] + +[dependencies] +digest = "0.10.7" +sha1 = { version = "0.10.6", default-features = false, features = ["compress"] } +zeroize = { version = "1.7", default-features = false, optional = true } + +[dev-dependencies] +digest = { version = "0.10.7", features = ["dev"] } +hex-literal = "0.4" + +[features] +default = ["oid", "std"] +std = ["digest/std", "sha1/std"] +oid = ["digest/oid", "sha1/oid"] # Enable OID support +zeroize = ["dep:zeroize"] + + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/sha1-checked/LICENSE-APACHE b/sha1-checked/LICENSE-APACHE new file mode 100644 index 00000000..78173fa2 --- /dev/null +++ b/sha1-checked/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/sha1-checked/LICENSE-MIT b/sha1-checked/LICENSE-MIT new file mode 100644 index 00000000..455de7c8 --- /dev/null +++ b/sha1-checked/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2024 The RustCrypto Project 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. diff --git a/sha1-checked/README.md b/sha1-checked/README.md new file mode 100644 index 00000000..32c4bc91 --- /dev/null +++ b/sha1-checked/README.md @@ -0,0 +1,98 @@ +# RustCrypto: SHA-1 Checked + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] +[![Build Status][build-image]][build-link] + +Pure Rust implementation of the [SHA-1] cryptographic hash algorithm with collision detection. + +## 🚨 Warning: Cryptographically Broken! 🚨 + +The SHA-1 hash function should be considered cryptographically broken and +unsuitable for further use in any security critical capacity, as it is +[practically vulnerable to chosen-prefix collisions][1]. + +But, this crate provides the detection [algorithm] pioneered by git, to detect hash collisions when they +occur and prevent them. The [paper] has more details on how this works. + +This implementation will be slower to use than the pure SHA-1 implementation, as more work as to be done. + +## Examples + +### One-shot API + +```rust +use hex_literal::hex; +use sha1_checked::Sha1; + +let result = Sha1::try_digest(b"hello world"); +assert_eq!(result.hash().as_ref(), hex!("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")); +assert!(!result.has_collision()); +``` + +### Incremental API + +```rust +use hex_literal::hex; +use sha1_checked::{Sha1, Digest}; + +let mut hasher = Sha1::new(); +hasher.update(b"hello world"); +let result = hasher.try_finalize(); + +assert_eq!(result.hash().as_ref(), hex!("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")); +assert!(!result.has_collision()); +``` + +Also, see the [examples section] in the RustCrypto/hashes readme. + +## Minimum Supported Rust Version + +Rust **1.72** or higher. + +Minimum supported Rust version can be changed in the future, but it will be +done with a minor version bump. + +## SemVer Policy + +- All on-by-default features of this library are covered by SemVer +- MSRV is considered exempt from SemVer as noted above + +## License + +The crate is licensed under either of: + +* [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) +* [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/sha1-checked.svg +[crate-link]: https://crates.io/crates/sha1-checked +[docs-image]: https://docs.rs/sha1-checked/badge.svg +[docs-link]: https://docs.rs/sha1-checked/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.72+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260041-hashes +[build-image]: https://github.com/RustCrypto/hashes/workflows/sha1-checked/badge.svg?branch=master +[build-link]: https://github.com/RustCrypto/hashes/actions?query=workflow%3Asha1-checked + +[//]: # (general links) + +[SHA-1]: https://en.wikipedia.org/wiki/SHA-1 +[1]: https://sha-mbles.github.io/ +[examples section]: https://github.com/RustCrypto/hashes#Examples +[algorithm]: https://github.com/cr-marcstevens/sha1collisiondetection +[paper]: https://marc-stevens.nl/research/papers/C13-S.pdf diff --git a/sha1-checked/benches/mod.rs b/sha1-checked/benches/mod.rs new file mode 100644 index 00000000..feeb366d --- /dev/null +++ b/sha1-checked/benches/mod.rs @@ -0,0 +1,39 @@ +#![feature(test)] +extern crate test; + +use digest::bench_update; +use sha1::Sha1; +use sha1_checked::Sha1 as Sha1Checked; +use test::Bencher; + +bench_update!( + Sha1::default(); + sha1_10 10; + sha1_100 100; + sha1_1000 1000; + sha1_10000 10000; +); + +bench_update!( + Sha1Checked::default(); + sha1_checked_10 10; + sha1_checked_100 100; + sha1_checked_1000 1000; + sha1_checked_10000 10000; +); + +bench_update!( + Sha1Checked::builder().detect_collision(false).build(); + sha1_checked_no_check_10 10; + sha1_checked_no_check_100 100; + sha1_checked_no_check_1000 1000; + sha1_checked_no_check_10000 10000; +); + +bench_update!( + Sha1Checked::builder().use_ubc(false).build(); + sha1_checked_no_ubc_10 10; + sha1_checked_no_ubc_100 100; + sha1_checked_no_ubc_1000 1000; + sha1_checked_no_ubc_10000 10000; +); diff --git a/sha1-checked/src/compress.rs b/sha1-checked/src/compress.rs new file mode 100644 index 00000000..60e4bf87 --- /dev/null +++ b/sha1-checked/src/compress.rs @@ -0,0 +1,787 @@ +//! Direct translation of the C code found at +//! [sha1.c](https://github.com/cr-marcstevens/sha1collisiondetection/blob/master/lib/sha1.c). +//! +//! For the original license and source details see the comments in `src/checked.rs`. + +#![allow(clippy::many_single_char_names, clippy::too_many_arguments)] + +use crate::{ + BLOCK_SIZE, + {ubc_check::Testt, DetectionState}, +}; + +const K: [u32; 4] = [0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6]; + +#[inline(always)] +fn mix(w: &mut [u32; 80], t: usize) -> u32 { + (w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]).rotate_left(1) +} + +#[inline(always)] +fn f1(b: u32, c: u32, d: u32) -> u32 { + d ^ b & (c ^ d) +} + +#[inline(always)] +fn f2(b: u32, c: u32, d: u32) -> u32 { + b ^ c ^ d +} + +#[inline(always)] +fn f3(b: u32, c: u32, d: u32) -> u32 { + (b & c).wrapping_add(d & (b ^ c)) +} + +#[inline(always)] +fn f4(b: u32, c: u32, d: u32) -> u32 { + b ^ c ^ d +} + +#[inline(always)] +fn round3_step(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { + *e = e.wrapping_add( + a.rotate_left(5) + .wrapping_add(f3(*b, c, d)) + .wrapping_add(K[2]) + .wrapping_add(mt), + ); + *b = b.rotate_left(30); +} + +#[inline(always)] +fn round4_step(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { + *e = e.wrapping_add( + a.rotate_left(5) + .wrapping_add(f4(*b, c, d)) + .wrapping_add(K[3]) + .wrapping_add(mt), + ); + *b = b.rotate_left(30); +} + +#[inline(always)] +fn round1_step_bw(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { + *b = b.rotate_right(30); + *e = e.wrapping_sub( + a.rotate_left(5) + .wrapping_add(f1(*b, c, d)) + .wrapping_add(K[0]) + .wrapping_add(mt), + ); +} + +#[inline(always)] +fn round2_step_bw(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { + *b = b.rotate_right(30); + *e = e.wrapping_sub( + a.rotate_left(5) + .wrapping_add(f2(*b, c, d)) + .wrapping_add(K[1]) + .wrapping_add(mt), + ); +} + +#[inline(always)] +fn round3_step_bw(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { + *b = b.rotate_right(30); + *e = e.wrapping_sub( + a.rotate_left(5) + .wrapping_add(f3(*b, c, d)) + .wrapping_add(K[2]) + .wrapping_add(mt), + ); +} + +#[inline(always)] +fn round4_step_bw(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, mt: u32) { + *b = b.rotate_right(30); + *e = e.wrapping_sub( + a.rotate_left(5) + .wrapping_add(f4(*b, c, d)) + .wrapping_add(K[3]) + .wrapping_add(mt), + ); +} + +#[inline(always)] +fn full_round3_step(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, w: &mut [u32; 80], t: usize) { + w[t] = mix(w, t); + *e = e.wrapping_add( + w[t].wrapping_add(a.rotate_left(5)) + .wrapping_add(f3(*b, c, d)) + .wrapping_add(K[2]), + ); + *b = b.rotate_left(30); +} + +#[inline(always)] +fn full_round4_step(a: u32, b: &mut u32, c: u32, d: u32, e: &mut u32, w: &mut [u32; 80], t: usize) { + w[t] = mix(w, t); + *e = e.wrapping_add( + w[t].wrapping_add(a.rotate_left(5)) + .wrapping_add(f4(*b, c, d)) + .wrapping_add(K[3]), + ); + *b = b.rotate_left(30); +} + +#[inline] +fn round2_step4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + w: &[u32; 80], + t: usize, +) { + // 1 + *e = e.wrapping_add( + w[t].wrapping_add(a.rotate_left(5)) + .wrapping_add(f2(*b, *c, *d)) + .wrapping_add(K[1]), + ); + *b = b.rotate_left(30); + + // 2 + *d = d.wrapping_add( + w[t + 1] + .wrapping_add(e.rotate_left(5)) + .wrapping_add(f2(*a, *b, *c)) + .wrapping_add(K[1]), + ); + *a = a.rotate_left(30); + + // 3 + *c = c.wrapping_add( + w[t + 2] + .wrapping_add(d.rotate_left(5)) + .wrapping_add(f2(*e, *a, *b)) + .wrapping_add(K[1]), + ); + *e = e.rotate_left(30); + + // 4 + *b = b.wrapping_add( + w[t + 3] + .wrapping_add(c.rotate_left(5)) + .wrapping_add(f2(*d, *e, *a)) + .wrapping_add(K[1]), + ); + *d = d.rotate_left(30); +} + +#[inline] +fn round3_step4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + w: &[u32; 80], + t: usize, +) { + // 1 + *e = e.wrapping_add( + w[t].wrapping_add(a.rotate_left(5)) + .wrapping_add(f3(*b, *c, *d)) + .wrapping_add(K[2]), + ); + *b = b.rotate_left(30); + + // 2 + *d = d.wrapping_add( + w[t + 1] + .wrapping_add(e.rotate_left(5)) + .wrapping_add(f3(*a, *b, *c)) + .wrapping_add(K[2]), + ); + *a = a.rotate_left(30); + + // 3 + *c = c.wrapping_add( + w[t + 2] + .wrapping_add(d.rotate_left(5)) + .wrapping_add(f3(*e, *a, *b)) + .wrapping_add(K[2]), + ); + *e = e.rotate_left(30); + + // 4 + *b = b.wrapping_add( + w[t + 3] + .wrapping_add(c.rotate_left(5)) + .wrapping_add(f3(*d, *e, *a)) + .wrapping_add(K[2]), + ); + *d = d.rotate_left(30); +} + +#[inline] +fn round4_step4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + w: &[u32; 80], + t: usize, +) { + // 1 + *e = e.wrapping_add( + w[t].wrapping_add(a.rotate_left(5)) + .wrapping_add(f4(*b, *c, *d)) + .wrapping_add(K[3]), + ); + *b = b.rotate_left(30); + + // 2 + *d = d.wrapping_add( + w[t + 1] + .wrapping_add(e.rotate_left(5)) + .wrapping_add(f4(*a, *b, *c)) + .wrapping_add(K[3]), + ); + *a = a.rotate_left(30); + + // 3 + *c = c.wrapping_add( + w[t + 2] + .wrapping_add(d.rotate_left(5)) + .wrapping_add(f4(*e, *a, *b)) + .wrapping_add(K[3]), + ); + *e = e.rotate_left(30); + + // 4 + *b = b.wrapping_add( + w[t + 3] + .wrapping_add(c.rotate_left(5)) + .wrapping_add(f4(*d, *e, *a)) + .wrapping_add(K[3]), + ); + *d = d.rotate_left(30); +} + +#[inline] +fn full_round1_step_load4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + m: &[u32; 16], + w: &mut [u32; 80], + t: usize, +) { + // load + w[t..t + 4].copy_from_slice(&m[t..t + 4]); + round1_step4(a, b, c, d, e, w, t); +} + +#[inline(always)] +fn round1_step4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + w: &[u32; 80], + t: usize, +) { + // 1 + *e = e.wrapping_add( + w[t].wrapping_add(a.rotate_left(5)) + .wrapping_add(f1(*b, *c, *d)) + .wrapping_add(K[0]), + ); + *b = b.rotate_left(30); + + // 2 + *d = d.wrapping_add( + w[t + 1] + .wrapping_add(e.rotate_left(5)) + .wrapping_add(f1(*a, *b, *c)) + .wrapping_add(K[0]), + ); + *a = a.rotate_left(30); + + // 3 + *c = c.wrapping_add( + w[t + 2] + .wrapping_add(d.rotate_left(5)) + .wrapping_add(f1(*e, *a, *b)) + .wrapping_add(K[0]), + ); + *e = e.rotate_left(30); + + // 4 + *b = b.wrapping_add( + w[t + 3] + .wrapping_add(c.rotate_left(5)) + .wrapping_add(f1(*d, *e, *a)) + .wrapping_add(K[0]), + ); + *d = d.rotate_left(30); +} + +#[inline] +fn full_round1_step_expand4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + w: &mut [u32; 80], + t: usize, +) { + w[t] = mix(w, t); + w[t + 1] = mix(w, t + 1); + w[t + 2] = mix(w, t + 2); + w[t + 3] = mix(w, t + 3); + round1_step4(a, b, c, d, e, w, t); +} + +#[inline] +fn full_round2_step4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + w: &mut [u32; 80], + t: usize, +) { + w[t] = mix(w, t); + w[t + 1] = mix(w, t + 1); + w[t + 2] = mix(w, t + 2); + w[t + 3] = mix(w, t + 3); + round2_step4(a, b, c, d, e, w, t); +} + +#[inline] +fn full_round3_step4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + w: &mut [u32; 80], + t: usize, +) { + w[t] = mix(w, t); + w[t + 1] = mix(w, t + 1); + w[t + 2] = mix(w, t + 2); + w[t + 3] = mix(w, t + 3); + round3_step4(a, b, c, d, e, w, t); +} + +#[inline] +fn full_round4_step4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + w: &mut [u32; 80], + t: usize, +) { + w[t] = mix(w, t); + w[t + 1] = mix(w, t + 1); + w[t + 2] = mix(w, t + 2); + w[t + 3] = mix(w, t + 3); + round4_step4(a, b, c, d, e, w, t); +} + +#[inline] +fn round1_step_bw4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + m: &[u32; 80], + t: usize, +) { + round1_step_bw(*a, b, *c, *d, e, m[t]); + round1_step_bw(*b, c, *d, *e, a, m[t - 1]); + round1_step_bw(*c, d, *e, *a, b, m[t - 2]); + round1_step_bw(*d, e, *a, *b, c, m[t - 3]); +} + +#[inline] +fn round2_step_bw4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + m: &[u32; 80], + t: usize, +) { + round2_step_bw(*a, b, *c, *d, e, m[t]); + round2_step_bw(*b, c, *d, *e, a, m[t - 1]); + round2_step_bw(*c, d, *e, *a, b, m[t - 2]); + round2_step_bw(*d, e, *a, *b, c, m[t - 3]); +} + +#[inline] +fn round3_step_bw4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + m: &[u32; 80], + t: usize, +) { + round3_step_bw(*a, b, *c, *d, e, m[t]); + round3_step_bw(*b, c, *d, *e, a, m[t - 1]); + round3_step_bw(*c, d, *e, *a, b, m[t - 2]); + round3_step_bw(*d, e, *a, *b, c, m[t - 3]); +} + +#[inline] +fn round4_step_bw4( + a: &mut u32, + b: &mut u32, + c: &mut u32, + d: &mut u32, + e: &mut u32, + m: &[u32; 80], + t: usize, +) { + round4_step_bw(*a, b, *c, *d, e, m[t]); + round4_step_bw(*b, c, *d, *e, a, m[t - 1]); + round4_step_bw(*c, d, *e, *a, b, m[t - 2]); + round4_step_bw(*d, e, *a, *b, c, m[t - 3]); +} + +fn add_assign(left: &mut [u32; 5], right: [u32; 5]) { + left[0] = left[0].wrapping_add(right[0]); + left[1] = left[1].wrapping_add(right[1]); + left[2] = left[2].wrapping_add(right[2]); + left[3] = left[3].wrapping_add(right[3]); + left[4] = left[4].wrapping_add(right[4]); +} + +fn compression_w(ihv: &mut [u32; 5], w: &[u32; 80]) { + let [mut a, mut b, mut c, mut d, mut e] = ihv; + + round1_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 0); + round1_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 4); + round1_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 8); + round1_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 12); + round1_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 16); + + round2_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 20); + round2_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 24); + round2_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 28); + round2_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 32); + round2_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 36); + + round3_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 40); + round3_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 44); + round3_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 48); + round3_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 52); + round3_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 56); + + round4_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 60); + round4_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 64); + round4_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 68); + round4_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 72); + round4_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 76); + + add_assign(ihv, [a, b, c, d, e]); +} + +fn compression_states( + ihv: &mut [u32; 5], + m: &[u32; 16], + w: &mut [u32; 80], + state_58: &mut [u32; 5], + state_65: &mut [u32; 5], +) { + let [mut a, mut b, mut c, mut d, mut e] = ihv; + + full_round1_step_load4(&mut a, &mut b, &mut c, &mut d, &mut e, m, w, 0); + full_round1_step_load4(&mut b, &mut c, &mut d, &mut e, &mut a, m, w, 4); + full_round1_step_load4(&mut c, &mut d, &mut e, &mut a, &mut b, m, w, 8); + full_round1_step_load4(&mut d, &mut e, &mut a, &mut b, &mut c, m, w, 12); + + full_round1_step_expand4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 16); + + full_round2_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 20); + full_round2_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 24); + full_round2_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 28); + full_round2_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 32); + full_round2_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 36); + + full_round3_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 40); + full_round3_step4(&mut b, &mut c, &mut d, &mut e, &mut a, w, 44); + full_round3_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 48); + full_round3_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 52); + + full_round3_step(e, &mut a, b, c, &mut d, w, 56); + full_round3_step(d, &mut e, a, b, &mut c, w, 57); + + // Store state58 + *state_58 = [a, b, c, d, e]; + + full_round3_step(c, &mut d, e, a, &mut b, w, 58); + full_round3_step(b, &mut c, d, e, &mut a, w, 59); + + full_round4_step4(&mut a, &mut b, &mut c, &mut d, &mut e, w, 60); + full_round4_step(b, &mut c, d, e, &mut a, w, 64); + + // Store state65 + *state_65 = [a, b, c, d, e]; + + full_round4_step(a, &mut b, c, d, &mut e, w, 65); + full_round4_step(e, &mut a, b, c, &mut d, w, 66); + full_round4_step(d, &mut e, a, b, &mut c, w, 67); + + full_round4_step4(&mut c, &mut d, &mut e, &mut a, &mut b, w, 68); + full_round4_step4(&mut d, &mut e, &mut a, &mut b, &mut c, w, 72); + full_round4_step4(&mut e, &mut a, &mut b, &mut c, &mut d, w, 76); + + add_assign(ihv, [a, b, c, d, e]); +} + +fn recompress_fast_58( + ihvin: &mut [u32; 5], + ihvout: &mut [u32; 5], + me2: &[u32; 80], + state: &[u32; 5], +) { + let [mut a, mut b, mut c, mut d, mut e] = state; + + round3_step_bw(d, &mut e, a, b, &mut c, me2[57]); + round3_step_bw(e, &mut a, b, c, &mut d, me2[56]); + + round3_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 55); + round3_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 51); + round3_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 47); + round3_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 43); + + round2_step_bw4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 39); + round2_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 35); + round2_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 31); + round2_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 27); + round2_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 23); + + round1_step_bw4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 19); + round1_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 15); + round1_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 11); + round1_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 7); + round1_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 3); + + *ihvin = [a, b, c, d, e]; + [a, b, c, d, e] = *state; + + round3_step(c, &mut d, e, a, &mut b, me2[58]); + round3_step(b, &mut c, d, e, &mut a, me2[59]); + + round4_step4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 60); + round4_step4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 64); + round4_step4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 68); + round4_step4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 72); + round4_step4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 76); + + ihvout[0] = ihvin[0].wrapping_add(a); + ihvout[1] = ihvin[1].wrapping_add(b); + ihvout[2] = ihvin[2].wrapping_add(c); + ihvout[3] = ihvin[3].wrapping_add(d); + ihvout[4] = ihvin[4].wrapping_add(e); +} + +fn recompress_fast_65( + ihvin: &mut [u32; 5], + ihvout: &mut [u32; 5], + me2: &[u32; 80], + state: &[u32; 5], +) { + let [mut a, mut b, mut c, mut d, mut e] = state; + + round4_step_bw(b, &mut c, d, e, &mut a, me2[64]); + round4_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 63); + + round3_step_bw4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 59); + round3_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 55); + round3_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 51); + round3_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 47); + round3_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 43); + + round2_step_bw4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 39); + round2_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 35); + round2_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 31); + round2_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 27); + round2_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 23); + + round1_step_bw4(&mut b, &mut c, &mut d, &mut e, &mut a, me2, 19); + round1_step_bw4(&mut a, &mut b, &mut c, &mut d, &mut e, me2, 15); + round1_step_bw4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 11); + round1_step_bw4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 7); + round1_step_bw4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 3); + + *ihvin = [a, b, c, d, e]; + [a, b, c, d, e] = *state; + + round4_step(a, &mut b, c, d, &mut e, me2[65]); + round4_step(e, &mut a, b, c, &mut d, me2[66]); + round4_step(d, &mut e, a, b, &mut c, me2[67]); + + round4_step4(&mut c, &mut d, &mut e, &mut a, &mut b, me2, 68); + round4_step4(&mut d, &mut e, &mut a, &mut b, &mut c, me2, 72); + round4_step4(&mut e, &mut a, &mut b, &mut c, &mut d, me2, 76); + + ihvout[0] = ihvin[0].wrapping_add(a); + ihvout[1] = ihvin[1].wrapping_add(b); + ihvout[2] = ihvin[2].wrapping_add(c); + ihvout[3] = ihvin[3].wrapping_add(d); + ihvout[4] = ihvin[4].wrapping_add(e); +} + +fn recompression_step( + step: Testt, + ihvin: &mut [u32; 5], + ihvout: &mut [u32; 5], + me2: &[u32; 80], + state: &[u32; 5], +) { + match step { + Testt::T58 => { + recompress_fast_58(ihvin, ihvout, me2, state); + } + Testt::T65 => { + recompress_fast_65(ihvin, ihvout, me2, state); + } + } +} + +#[inline(always)] +fn xor(a: &[u32; 5], b: &[u32; 5]) -> u32 { + a[0] ^ b[0] | a[1] ^ b[1] | a[2] ^ b[2] | a[3] ^ b[3] | a[4] ^ b[4] +} + +#[inline] +pub(super) fn compress( + state: &mut [u32; 5], + ctx: &mut DetectionState, + blocks: &[[u8; BLOCK_SIZE]], +) { + let mut block_u32 = [0u32; BLOCK_SIZE / 4]; + + for block in blocks.iter() { + ctx.ihv1.copy_from_slice(&*state); + + for (o, chunk) in block_u32.iter_mut().zip(block.chunks_exact(4)) { + *o = u32::from_be_bytes(chunk.try_into().unwrap()); + } + + let DetectionState { + m1, + state_58, + state_65, + .. + } = ctx; + + compression_states(state, &block_u32, m1, state_58, state_65); + + let ubc_mask = if ctx.ubc_check { + crate::ubc_check::ubc_check(&ctx.m1) + } else { + 0xFFFFFFFF + }; + + if ubc_mask != 0 { + let mut ihvtmp = [0u32; 5]; + for dv_type in &crate::ubc_check::SHA1_DVS { + if ubc_mask & (1 << dv_type.maskb) != 0 { + for ((m2, m1), dm) in + ctx.m2.iter_mut().zip(ctx.m1.iter()).zip(dv_type.dm.iter()) + { + *m2 = m1 ^ dm; + } + let DetectionState { + ihv2, + m2, + state_58, + state_65, + .. + } = ctx; + + recompression_step( + dv_type.testt, + ihv2, + &mut ihvtmp, + m2, + match dv_type.testt { + Testt::T58 => state_58, + Testt::T65 => state_65, + }, + ); + + // to verify SHA-1 collision detection code with collisions for reduced-step SHA-1 + if (0 == xor(&ihvtmp, &*state)) + || (ctx.reduced_round_collision && 0 == xor(&ctx.ihv1, &ctx.ihv2)) + { + ctx.found_collision = true; + + if ctx.safe_hash { + compression_w(state, &ctx.m1); + compression_w(state, &ctx.m1); + } + break; + } + } + } + } + } +} + +const SHA1_PADDING: [u8; 64] = [ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, +]; + +#[inline] +pub(super) fn finalize( + state: &mut [u32; 5], + total: u64, + last_block: &[u8], + ctx: &mut DetectionState, +) { + let mut total = total + last_block.len() as u64; + let last = last_block.len(); + let needs_two_blocks = last >= 56; + + let mut buffer = [0u8; BLOCK_SIZE]; + buffer[..last].copy_from_slice(last_block); + let left = BLOCK_SIZE - last; + + if needs_two_blocks { + let padn = 120 - last; + let (pad0, pad1) = SHA1_PADDING[..padn].split_at(left); + buffer[last..].copy_from_slice(pad0); + compress(state, ctx, &[buffer]); + buffer[..pad1.len()].copy_from_slice(pad1); + } else { + let padn = 56 - last; + buffer[last..56].copy_from_slice(&SHA1_PADDING[..padn]); + } + + total <<= 3; + + buffer[56] = (total >> 56) as u8; + buffer[57] = (total >> 48) as u8; + buffer[58] = (total >> 40) as u8; + buffer[59] = (total >> 32) as u8; + buffer[60] = (total >> 24) as u8; + buffer[61] = (total >> 16) as u8; + buffer[62] = (total >> 8) as u8; + buffer[63] = total as u8; + + compress(state, ctx, &[buffer]); +} diff --git a/sha1-checked/src/lib.rs b/sha1-checked/src/lib.rs new file mode 100644 index 00000000..1dcf28da --- /dev/null +++ b/sha1-checked/src/lib.rs @@ -0,0 +1,369 @@ +#![no_std] +#![doc = include_str!("../README.md")] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" +)] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![warn(missing_docs, rust_2018_idioms)] + +//! Collision checked Sha1. +//! +//! General techniques and implementation are based on the research and implementation done in [1], [2] by +//! Marc Stevens. +//! +//! +//! Original license can be found in [3]. +//! +//! [1]: https://github.com/cr-marcstevens/sha1collisiondetection +//! [2]: https://marc-stevens.nl/research/papers/C13-S.pdf +//! [3]: https://github.com/cr-marcstevens/sha1collisiondetection/blob/master/LICENSE.txt + +pub use digest::{self, Digest}; + +use core::slice::from_ref; + +#[cfg(feature = "std")] +extern crate std; + +use digest::{ + block_buffer::{BlockBuffer, Eager}, + core_api::BlockSizeUser, + typenum::{Unsigned, U20, U64}, + FixedOutput, FixedOutputReset, HashMarker, Output, OutputSizeUser, Reset, Update, +}; +#[cfg(feature = "zeroize")] +use zeroize::{Zeroize, ZeroizeOnDrop}; + +const BLOCK_SIZE: usize = ::BlockSize::USIZE; +const STATE_LEN: usize = 5; +const INITIAL_H: [u32; 5] = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0]; + +mod compress; +mod ubc_check; + +/// SHA-1 collision detection hasher state. +#[derive(Clone)] +pub struct Sha1 { + h: [u32; STATE_LEN], + block_len: u64, + detection: Option, + buffer: BlockBuffer, +} + +impl HashMarker for Sha1 {} + +impl Default for Sha1 { + fn default() -> Self { + Builder::default().build() + } +} + +impl Sha1 { + /// Create a new Sha1 instance, with collision detection enabled. + pub fn new() -> Self { + Self::default() + } + + /// Create a new Sha1 builder to configure detection. + pub fn builder() -> Builder { + Builder::default() + } + + /// Oneshot hashing, reporting the collision state. + /// + /// # Examples + /// + /// ``` + /// use hex_literal::hex; + /// use sha1_checked::Sha1; + /// + /// let result = Sha1::try_digest(b"hello world"); + /// assert_eq!(result.hash().as_ref(), hex!("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")); + /// assert!(!result.has_collision()); + /// ``` + pub fn try_digest(data: impl AsRef<[u8]>) -> CollisionResult { + let mut hasher = Self::default(); + Digest::update(&mut hasher, data); + hasher.try_finalize() + } + + /// Try finalization, reporting the collision state. + pub fn try_finalize(mut self) -> CollisionResult { + let mut out = Output::::default(); + self.finalize_inner(&mut out); + + if let Some(ref ctx) = self.detection { + if ctx.found_collision { + if ctx.safe_hash { + return CollisionResult::Mitigated(out); + } + return CollisionResult::Collision(out); + } + } + CollisionResult::Ok(out) + } + + fn finalize_inner(&mut self, out: &mut Output) { + let bs = 64; + let buffer = &mut self.buffer; + let h = &mut self.h; + + if let Some(ref mut ctx) = self.detection { + let last_block = buffer.get_data(); + compress::finalize(h, bs * self.block_len, last_block, ctx); + } else { + let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len); + buffer.len64_padding_be(bit_len, |b| sha1::compress(h, from_ref(b))); + } + + for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) { + chunk.copy_from_slice(&v.to_be_bytes()); + } + } +} + +/// Result when trying to finalize a hash. +#[derive(Debug)] +pub enum CollisionResult { + /// No collision. + Ok(Output), + /// Collision occured, but was mititgated. + Mitigated(Output), + /// Collision occured, the hash is the one that collided. + Collision(Output), +} + +impl CollisionResult { + /// Returns the output hash. + pub fn hash(&self) -> &Output { + match self { + CollisionResult::Ok(ref s) => s, + CollisionResult::Mitigated(ref s) => s, + CollisionResult::Collision(ref s) => s, + } + } + + /// Returns if there was a collision + pub fn has_collision(&self) -> bool { + !matches!(self, CollisionResult::Ok(_)) + } +} + +impl core::fmt::Debug for Sha1 { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> { + f.write_str("Sha1CollisionDetection { .. }") + } +} + +impl Reset for Sha1 { + #[inline] + fn reset(&mut self) { + self.h = INITIAL_H; + self.block_len = 0; + self.buffer.reset(); + if let Some(ref mut ctx) = self.detection { + ctx.reset(); + } + } +} + +impl Update for Sha1 { + #[inline] + fn update(&mut self, input: &[u8]) { + let Self { + h, + detection, + buffer, + .. + } = self; + buffer.digest_blocks(input, |blocks| { + self.block_len += blocks.len() as u64; + if let Some(ref mut ctx) = detection { + // SAFETY: GenericArray and [u8; 64] have + // exactly the same memory layout + let blocks: &[[u8; BLOCK_SIZE]] = + unsafe { &*(blocks as *const _ as *const [[u8; BLOCK_SIZE]]) }; + compress::compress(h, ctx, blocks); + } else { + sha1::compress(h, blocks); + } + }); + } +} + +impl OutputSizeUser for Sha1 { + type OutputSize = U20; +} + +impl FixedOutput for Sha1 { + #[inline] + fn finalize_into(mut self, out: &mut Output) { + self.finalize_inner(out); + } +} + +impl FixedOutputReset for Sha1 { + #[inline] + fn finalize_into_reset(&mut self, out: &mut Output) { + self.finalize_inner(out); + Reset::reset(self); + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for Sha1 {} + +impl Drop for DetectionState { + #[inline] + fn drop(&mut self) { + #[cfg(feature = "zeroize")] + { + self.ihv1.zeroize(); + self.ihv2.zeroize(); + self.m1.zeroize(); + self.m2.zeroize(); + self.state_58.zeroize(); + self.state_65.zeroize(); + } + } +} + +#[cfg(feature = "zeroize")] +impl ZeroizeOnDrop for DetectionState {} + +#[cfg(feature = "oid")] +#[cfg_attr(docsrs, doc(cfg(feature = "oid")))] +impl digest::const_oid::AssociatedOid for Sha1 { + const OID: digest::const_oid::ObjectIdentifier = sha1::Sha1Core::OID; +} + +#[cfg(feature = "std")] +impl std::io::Write for Sha1 { + #[inline] + fn write(&mut self, buf: &[u8]) -> std::io::Result { + Update::update(self, buf); + Ok(buf.len()) + } + + #[inline] + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +/// Builder for collision detection configuration. +#[derive(Clone)] +pub struct Builder { + detect_collision: bool, + safe_hash: bool, + ubc_check: bool, + reduced_round_collision: bool, +} + +impl Default for Builder { + fn default() -> Self { + Self { + detect_collision: true, + safe_hash: true, + ubc_check: true, + reduced_round_collision: false, + } + } +} + +impl Builder { + /// Should we detect collisions at all? Default: true + pub fn detect_collision(mut self, detect: bool) -> Self { + self.detect_collision = detect; + self + } + + /// Should a fix be automatically be applied, or the original hash be returned? Default: true + pub fn safe_hash(mut self, safe_hash: bool) -> Self { + self.safe_hash = safe_hash; + self + } + + /// Should unavoidable bitconditions be used to speed up the check? Default: true + pub fn use_ubc(mut self, ubc: bool) -> Self { + self.ubc_check = ubc; + self + } + + /// Should reduced round collisions be used? Default: false + pub fn reduced_round_collision(mut self, reduced: bool) -> Self { + self.reduced_round_collision = reduced; + self + } + + fn into_detection_state(self) -> Option { + if self.detect_collision { + Some(DetectionState { + safe_hash: self.safe_hash, + reduced_round_collision: self.reduced_round_collision, + ubc_check: self.ubc_check, + found_collision: false, + ihv1: Default::default(), + ihv2: Default::default(), + m1: [0; 80], + m2: [0; 80], + state_58: Default::default(), + state_65: Default::default(), + }) + } else { + None + } + } + + /// Create a Sha1 with a specific collision detection configuration. + pub fn build(self) -> Sha1 { + let detection = self.into_detection_state(); + Sha1 { + h: INITIAL_H, + block_len: 0, + detection, + buffer: Default::default(), + } + } +} + +/// The internal state used to do collision detection. +#[derive(Clone, Debug)] +struct DetectionState { + safe_hash: bool, + ubc_check: bool, + reduced_round_collision: bool, + /// Has a collision been detected? + found_collision: bool, + ihv1: [u32; 5], + ihv2: [u32; 5], + m1: [u32; 80], + m2: [u32; 80], + /// Stores past states, for faster recompression. + state_58: [u32; 5], + state_65: [u32; 5], +} + +impl Default for DetectionState { + fn default() -> Self { + Builder::default() + .into_detection_state() + .expect("enabled by default") + } +} + +impl DetectionState { + fn reset(&mut self) { + // Do not reset the config, it needs to be preserved + + self.found_collision = false; + self.ihv1 = Default::default(); + self.ihv2 = Default::default(); + self.m1 = [0; 80]; + self.m2 = [0; 80]; + self.state_58 = Default::default(); + self.state_65 = Default::default(); + } +} diff --git a/sha1-checked/src/ubc_check.rs b/sha1-checked/src/ubc_check.rs new file mode 100644 index 00000000..2ce34455 --- /dev/null +++ b/sha1-checked/src/ubc_check.rs @@ -0,0 +1,1175 @@ +//! Direct translation of the C code found at +//! [ubc_check.c](https://github.com/cr-marcstevens/sha1collisiondetection/blob/master/lib/ubc_check.c). +//! +//! For the original license and source details see the comments in `src/checked.rs`. +//! +//! The original C code file was generated by the 'parse_bitrel' program in the tools section +//! using the data files from directory 'tools/data/3565'. + +const DV_I_43_0_BIT: u32 = 1 << 0; +const DV_I_44_0_BIT: u32 = 1 << 1; +const DV_I_45_0_BIT: u32 = 1 << 2; +const DV_I_46_0_BIT: u32 = 1 << 3; +const DV_I_46_2_BIT: u32 = 1 << 4; +const DV_I_47_0_BIT: u32 = 1 << 5; +const DV_I_47_2_BIT: u32 = 1 << 6; +const DV_I_48_0_BIT: u32 = 1 << 7; +const DV_I_48_2_BIT: u32 = 1 << 8; +const DV_I_49_0_BIT: u32 = 1 << 9; +const DV_I_49_2_BIT: u32 = 1 << 10; +const DV_I_50_0_BIT: u32 = 1 << 11; +const DV_I_50_2_BIT: u32 = 1 << 12; +const DV_I_51_0_BIT: u32 = 1 << 13; +const DV_I_51_2_BIT: u32 = 1 << 14; +const DV_I_52_0_BIT: u32 = 1 << 15; +const DV_II_45_0_BIT: u32 = 1 << 16; +const DV_II_46_0_BIT: u32 = 1 << 17; +const DV_II_46_2_BIT: u32 = 1 << 18; +const DV_II_47_0_BIT: u32 = 1 << 19; +const DV_II_48_0_BIT: u32 = 1 << 20; +const DV_II_49_0_BIT: u32 = 1 << 21; +const DV_II_49_2_BIT: u32 = 1 << 22; +const DV_II_50_0_BIT: u32 = 1 << 23; +const DV_II_50_2_BIT: u32 = 1 << 24; +const DV_II_51_0_BIT: u32 = 1 << 25; +const DV_II_51_2_BIT: u32 = 1 << 26; +const DV_II_52_0_BIT: u32 = 1 << 27; +const DV_II_53_0_BIT: u32 = 1 << 28; +const DV_II_54_0_BIT: u32 = 1 << 29; +const DV_II_55_0_BIT: u32 = 1 << 30; +const DV_II_56_0_BIT: u32 = 1 << 31; + +pub struct Info { + pub dv_type: u32, + pub dv_k: u32, + pub dv_b: u32, + pub testt: Testt, + pub maski: i32, + pub maskb: i32, + pub dm: [u32; 80], +} + +#[derive(Copy, Clone)] +#[repr(u32)] +pub enum Testt { + T58 = 58, + T65 = 65, +} + +/// Contains a list of SHA-1 Disturbance Vectors (DV) to check +/// `dv_type`, `dv_k` and `dv_b` define the DV: I(K,B) or II(K,B) (see the paper) +/// `dm[80]` is the expanded message block XOR-difference defined by the DV +/// testt is the step to do the recompression from for collision detection +/// `maski` and `maskb` define the bit to check for each DV in the dvmask returned by [`ubc_check`]. +pub const SHA1_DVS: [Info; 32] = [ + Info { + dv_type: 1, + dv_k: 43, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 0, + dm: [ + 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, 0x60000000, 0x8, + 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, 0x20000010, 0x48000000, + 0x8000018, 0x60000000, 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, + 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, + 0x90000010, 0x90000010, 0x90000000, 0x80000000, 0x10, 0xa0000000, 0x20000000, + 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, + 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, + 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, + 0x80000012, 0x80000202, 0x18, 0x164, 0x408, 0x800000e6, 0x8000004c, 0x803, 0x80000161, + 0x80000599, + ], + }, + Info { + dv_type: 1, + dv_k: 44, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 1, + dm: [ + 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, + 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, + 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, 0xf0000010, 0x90000008, + 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, + 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, 0x10, + 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, + 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, + 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, 0x18, 0x164, 0x408, 0x800000e6, + 0x8000004c, 0x803, 0x80000161, + ], + }, + Info { + dv_type: 1, + dv_k: 45, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 2, + dm: [ + 0xf4000014, 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, + 0x98000000, 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, + 0x28000000, 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, 0xf0000010, + 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, + 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, + 0x10, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, + 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, + 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, 0x18, 0x164, 0x408, 0x800000e6, + 0x8000004c, 0x803, + ], + }, + Info { + dv_type: 1, + dv_k: 46, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 3, + dm: [ + 0x2c000010, 0xf4000014, 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, + 0xb8000010, 0x98000000, 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, + 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, + 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, + 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, + 0x80000000, 0x10, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, + 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, + 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, 0x18, 0x164, + 0x408, 0x800000e6, 0x8000004c, + ], + }, + Info { + dv_type: 1, + dv_k: 46, + dv_b: 2, + testt: Testt::T58, + maski: 0, + maskb: 4, + dm: [ + 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, 0x60000032, 0x60000043, 0x20000040, + 0xe0000042, 0x60000002, 0x80000001, 0x20, 0x3, 0x40000052, 0x40000040, 0xe0000052, + 0xa0000000, 0x80000040, 0x20000001, 0x20000060, 0x80000001, 0x40000042, 0xc0000043, + 0x40000022, 0x3, 0x40000042, 0xc0000043, 0xc0000022, 0x1, 0x40000002, 0xc0000043, + 0x40000062, 0x80000001, 0x40000042, 0x40000042, 0x40000002, 0x2, 0x40, 0x80000002, + 0x80000000, 0x80000002, 0x80000040, 0, 0x80000040, 0x80000000, 0x40, 0x80000000, 0x40, + 0x80000002, 0, 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, + 0x9, 0x101, 0x9, 0x12, 0x202, 0x1a, 0x124, 0x40c, 0x26, 0x4a, 0x80a, 0x60, 0x590, + 0x1020, 0x39a, 0x132, + ], + }, + Info { + dv_type: 1, + dv_k: 47, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 5, + dm: [ + 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, + 0x8000010, 0xb8000010, 0x98000000, 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, + 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, + 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, + 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, + 0x80000000, 0x10, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, + 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, + 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, 0x18, 0x164, + 0x408, 0x800000e6, + ], + }, + Info { + dv_type: 1, + dv_k: 47, + dv_b: 2, + testt: Testt::T58, + maski: 0, + maskb: 6, + dm: [ + 0x20000043, 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, 0x60000032, 0x60000043, + 0x20000040, 0xe0000042, 0x60000002, 0x80000001, 0x20, 0x3, 0x40000052, 0x40000040, + 0xe0000052, 0xa0000000, 0x80000040, 0x20000001, 0x20000060, 0x80000001, 0x40000042, + 0xc0000043, 0x40000022, 0x3, 0x40000042, 0xc0000043, 0xc0000022, 0x1, 0x40000002, + 0xc0000043, 0x40000062, 0x80000001, 0x40000042, 0x40000042, 0x40000002, 0x2, 0x40, + 0x80000002, 0x80000000, 0x80000002, 0x80000040, 0, 0x80000040, 0x80000000, 0x40, + 0x80000000, 0x40, 0x80000002, 0, 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x4, 0x80, 0x4, 0x9, 0x101, 0x9, 0x12, 0x202, 0x1a, 0x124, 0x40c, 0x26, 0x4a, 0x80a, + 0x60, 0x590, 0x1020, 0x39a, + ], + }, + Info { + dv_type: 1, + dv_k: 48, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 7, + dm: [ + 0xb800000a, 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, 0x8000000, 0x9800000c, + 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, 0x60000000, 0x8, 0xc0000000, 0x90000014, + 0x10000010, 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x8000018, 0x60000000, + 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, + 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, + 0x90000000, 0x80000000, 0x10, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, + 0x20000010, 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, + 0x80000004, 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, + 0x18, 0x164, 0x408, + ], + }, + Info { + dv_type: 1, + dv_k: 48, + dv_b: 2, + testt: Testt::T58, + maski: 0, + maskb: 8, + dm: [ + 0xe000002a, 0x20000043, 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, 0x60000032, + 0x60000043, 0x20000040, 0xe0000042, 0x60000002, 0x80000001, 0x20, 0x3, 0x40000052, + 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, 0x20000001, 0x20000060, 0x80000001, + 0x40000042, 0xc0000043, 0x40000022, 0x3, 0x40000042, 0xc0000043, 0xc0000022, 0x1, + 0x40000002, 0xc0000043, 0x40000062, 0x80000001, 0x40000042, 0x40000042, 0x40000002, + 0x2, 0x40, 0x80000002, 0x80000000, 0x80000002, 0x80000040, 0, 0x80000040, 0x80000000, + 0x40, 0x80000000, 0x40, 0x80000002, 0, 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0x4, 0x80, 0x4, 0x9, 0x101, 0x9, 0x12, 0x202, 0x1a, 0x124, 0x40c, 0x26, 0x4a, + 0x80a, 0x60, 0x590, 0x1020, + ], + }, + Info { + dv_type: 1, + dv_k: 49, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 9, + dm: [ + 0x18000000, 0xb800000a, 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, 0x8000000, + 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, 0x60000000, 0x8, 0xc0000000, + 0x90000014, 0x10000010, 0xb8000014, 0x28000000, 0x20000010, 0x48000000, 0x8000018, + 0x60000000, 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, + 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, 0x90000010, + 0x90000010, 0x90000000, 0x80000000, 0x10, 0xa0000000, 0x20000000, 0xa0000000, + 0x20000010, 0, 0x20000010, 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, 0, + 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, + 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, + 0x80000012, 0x80000202, 0x18, 0x164, + ], + }, + Info { + dv_type: 1, + dv_k: 49, + dv_b: 2, + testt: Testt::T58, + maski: 0, + maskb: 10, + dm: [ + 0x60000000, 0xe000002a, 0x20000043, 0xb0000040, 0xd0000053, 0xd0000022, 0x20000000, + 0x60000032, 0x60000043, 0x20000040, 0xe0000042, 0x60000002, 0x80000001, 0x20, 0x3, + 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, 0x20000001, 0x20000060, + 0x80000001, 0x40000042, 0xc0000043, 0x40000022, 0x3, 0x40000042, 0xc0000043, + 0xc0000022, 0x1, 0x40000002, 0xc0000043, 0x40000062, 0x80000001, 0x40000042, + 0x40000042, 0x40000002, 0x2, 0x40, 0x80000002, 0x80000000, 0x80000002, 0x80000040, 0, + 0x80000040, 0x80000000, 0x40, 0x80000000, 0x40, 0x80000002, 0, 0x80000000, 0x80000000, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x101, 0x9, 0x12, 0x202, 0x1a, + 0x124, 0x40c, 0x26, 0x4a, 0x80a, 0x60, 0x590, + ], + }, + Info { + dv_type: 1, + dv_k: 50, + dv_b: 0, + testt: Testt::T65, + maski: 0, + maskb: 11, + dm: [ + 0x800000c, 0x18000000, 0xb800000a, 0xc8000010, 0x2c000010, 0xf4000014, 0xb4000008, + 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, 0x60000000, 0x8, + 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, 0x20000010, 0x48000000, + 0x8000018, 0x60000000, 0x90000010, 0xf0000010, 0x90000008, 0xc0000000, 0x90000010, + 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, 0x90000018, 0x60000000, + 0x90000010, 0x90000010, 0x90000000, 0x80000000, 0x10, 0xa0000000, 0x20000000, + 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, 0x20000000, 0x10, 0xa0000000, + 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, + 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, 0x49, 0x103, 0x80000009, + 0x80000012, 0x80000202, 0x18, + ], + }, + Info { + dv_type: 1, + dv_k: 50, + dv_b: 2, + testt: Testt::T65, + maski: 0, + maskb: 12, + dm: [ + 0x20000030, 0x60000000, 0xe000002a, 0x20000043, 0xb0000040, 0xd0000053, 0xd0000022, + 0x20000000, 0x60000032, 0x60000043, 0x20000040, 0xe0000042, 0x60000002, 0x80000001, + 0x20, 0x3, 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, 0x20000001, + 0x20000060, 0x80000001, 0x40000042, 0xc0000043, 0x40000022, 0x3, 0x40000042, + 0xc0000043, 0xc0000022, 0x1, 0x40000002, 0xc0000043, 0x40000062, 0x80000001, + 0x40000042, 0x40000042, 0x40000002, 0x2, 0x40, 0x80000002, 0x80000000, 0x80000002, + 0x80000040, 0, 0x80000040, 0x80000000, 0x40, 0x80000000, 0x40, 0x80000002, 0, + 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x101, 0x9, + 0x12, 0x202, 0x1a, 0x124, 0x40c, 0x26, 0x4a, 0x80a, 0x60, + ], + }, + Info { + dv_type: 1, + dv_k: 51, + dv_b: 0, + testt: Testt::T65, + maski: 0, + maskb: 13, + dm: [ + 0xe8000000, 0x800000c, 0x18000000, 0xb800000a, 0xc8000010, 0x2c000010, 0xf4000014, + 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, 0x98000000, + 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, 0x28000000, + 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, 0xf0000010, 0x90000008, + 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, 0xf0000010, + 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, 0x10, + 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, + 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, + 0x49, 0x103, 0x80000009, 0x80000012, 0x80000202, + ], + }, + Info { + dv_type: 1, + dv_k: 51, + dv_b: 2, + testt: Testt::T65, + maski: 0, + maskb: 14, + dm: [ + 0xa0000003, 0x20000030, 0x60000000, 0xe000002a, 0x20000043, 0xb0000040, 0xd0000053, + 0xd0000022, 0x20000000, 0x60000032, 0x60000043, 0x20000040, 0xe0000042, 0x60000002, + 0x80000001, 0x20, 0x3, 0x40000052, 0x40000040, 0xe0000052, 0xa0000000, 0x80000040, + 0x20000001, 0x20000060, 0x80000001, 0x40000042, 0xc0000043, 0x40000022, 0x3, + 0x40000042, 0xc0000043, 0xc0000022, 0x1, 0x40000002, 0xc0000043, 0x40000062, + 0x80000001, 0x40000042, 0x40000042, 0x40000002, 0x2, 0x40, 0x80000002, 0x80000000, + 0x80000002, 0x80000040, 0, 0x80000040, 0x80000000, 0x40, 0x80000000, 0x40, 0x80000002, + 0, 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x101, + 0x9, 0x12, 0x202, 0x1a, 0x124, 0x40c, 0x26, 0x4a, 0x80a, + ], + }, + Info { + dv_type: 1, + dv_k: 52, + dv_b: 0, + testt: Testt::T65, + maski: 0, + maskb: 15, + dm: [ + 0x4000010, 0xe8000000, 0x800000c, 0x18000000, 0xb800000a, 0xc8000010, 0x2c000010, + 0xf4000014, 0xb4000008, 0x8000000, 0x9800000c, 0xd8000010, 0x8000010, 0xb8000010, + 0x98000000, 0x60000000, 0x8, 0xc0000000, 0x90000014, 0x10000010, 0xb8000014, + 0x28000000, 0x20000010, 0x48000000, 0x8000018, 0x60000000, 0x90000010, 0xf0000010, + 0x90000008, 0xc0000000, 0x90000010, 0xf0000010, 0xb0000008, 0x40000000, 0x90000000, + 0xf0000010, 0x90000018, 0x60000000, 0x90000010, 0x90000010, 0x90000000, 0x80000000, + 0x10, 0xa0000000, 0x20000000, 0xa0000000, 0x20000010, 0, 0x20000010, 0x20000000, 0x10, + 0x20000000, 0x10, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x1, 0x20, 0x1, 0x40000002, 0x40000040, 0x40000002, 0x80000004, 0x80000080, 0x80000006, + 0x49, 0x103, 0x80000009, 0x80000012, + ], + }, + Info { + dv_type: 2, + dv_k: 45, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 16, + dm: [ + 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0xc, + 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, 0xb800001c, 0xe8000000, + 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, + 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, 0x10, + 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, + 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, + 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, + 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, 0xc0000082, + 0xc0000046, 0x4000004b, 0x80000107, 0x89, 0x14, 0x8000024b, 0x11b, 0x8000016d, + 0x8000041a, 0x2e4, 0x80000054, 0x967, + ], + }, + Info { + dv_type: 2, + dv_k: 46, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 17, + dm: [ + 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, + 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, 0xb800001c, + 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, + 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, + 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, + 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, + 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, + 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, 0xc0000082, + 0xc0000046, 0x4000004b, 0x80000107, 0x89, 0x14, 0x8000024b, 0x11b, 0x8000016d, + 0x8000041a, 0x2e4, 0x80000054, + ], + }, + Info { + dv_type: 2, + dv_k: 46, + dv_b: 2, + testt: Testt::T58, + maski: 0, + maskb: 18, + dm: [ + 0x90000070, 0xb0000053, 0x30000008, 0x43, 0xd0000072, 0xb0000010, 0xf0000062, + 0xc0000042, 0x30, 0xe0000042, 0x20000060, 0xe0000041, 0x20000050, 0xc0000041, + 0xe0000072, 0xa0000003, 0xc0000012, 0x60000041, 0xc0000032, 0x20000001, 0xc0000002, + 0xe0000042, 0x60000042, 0x80000002, 0, 0, 0x80000000, 0x2, 0x40, 0, 0x80000040, + 0x80000000, 0x40, 0x80000001, 0x60, 0x80000003, 0x40000002, 0xc0000040, 0xc0000002, + 0x80000000, 0x80000000, 0x80000002, 0x40, 0x2, 0x80000000, 0x80000000, 0x80000000, 0x2, + 0x40, 0, 0x80000040, 0x80000002, 0, 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0x4, + 0x80, 0x4, 0x9, 0x105, 0x89, 0x16, 0x20b, 0x11b, 0x12d, 0x41e, 0x224, 0x50, 0x92e, + 0x46c, 0x5b6, 0x106a, 0xb90, 0x152, + ], + }, + Info { + dv_type: 2, + dv_k: 47, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 19, + dm: [ + 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, + 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, + 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, + 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, + 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, + 0x20000000, 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, + 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, + 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, + 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, 0x89, 0x14, 0x8000024b, 0x11b, + 0x8000016d, 0x8000041a, 0x2e4, + ], + }, + Info { + dv_type: 2, + dv_k: 48, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 20, + dm: [ + 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, + 0x2c000004, 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, + 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, + 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, + 0x20000010, 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, + 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, + 0x20000000, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, + 0x20000000, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, + 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, 0x89, 0x14, 0x8000024b, + 0x11b, 0x8000016d, 0x8000041a, + ], + }, + Info { + dv_type: 2, + dv_k: 49, + dv_b: 0, + testt: Testt::T58, + maski: 0, + maskb: 21, + dm: [ + 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, + 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, + 0x8000014, 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, + 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, + 0x80000000, 0x10, 0, 0x20000010, 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, + 0x90000000, 0x30000010, 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, 0x10, + 0x80000000, 0x20000000, 0x20000000, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, + 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, + 0x40000041, 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, + 0x89, 0x14, 0x8000024b, 0x11b, 0x8000016d, + ], + }, + Info { + dv_type: 2, + dv_k: 49, + dv_b: 2, + testt: Testt::T58, + maski: 0, + maskb: 22, + dm: [ + 0xf0000010, 0xf000006a, 0x80000040, 0x90000070, 0xb0000053, 0x30000008, 0x43, + 0xd0000072, 0xb0000010, 0xf0000062, 0xc0000042, 0x30, 0xe0000042, 0x20000060, + 0xe0000041, 0x20000050, 0xc0000041, 0xe0000072, 0xa0000003, 0xc0000012, 0x60000041, + 0xc0000032, 0x20000001, 0xc0000002, 0xe0000042, 0x60000042, 0x80000002, 0, 0, + 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000000, 0x40, 0x80000001, 0x60, 0x80000003, + 0x40000002, 0xc0000040, 0xc0000002, 0x80000000, 0x80000000, 0x80000002, 0x40, 0x2, + 0x80000000, 0x80000000, 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000002, 0, + 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x105, 0x89, 0x16, + 0x20b, 0x11b, 0x12d, 0x41e, 0x224, 0x50, 0x92e, 0x46c, 0x5b6, + ], + }, + Info { + dv_type: 2, + dv_k: 50, + dv_b: 0, + testt: Testt::T65, + maski: 0, + maskb: 23, + dm: [ + 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, 0xc000002, + 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, + 0x78000010, 0x8000014, 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, + 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0, 0, + 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, 0x10, 0x60000000, 0x18, + 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, + 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, + 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, + 0x40000041, 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, + 0x89, 0x14, 0x8000024b, 0x11b, + ], + }, + Info { + dv_type: 2, + dv_k: 50, + dv_b: 2, + testt: Testt::T65, + maski: 0, + maskb: 24, + dm: [ + 0xd0000072, 0xf0000010, 0xf000006a, 0x80000040, 0x90000070, 0xb0000053, 0x30000008, + 0x43, 0xd0000072, 0xb0000010, 0xf0000062, 0xc0000042, 0x30, 0xe0000042, 0x20000060, + 0xe0000041, 0x20000050, 0xc0000041, 0xe0000072, 0xa0000003, 0xc0000012, 0x60000041, + 0xc0000032, 0x20000001, 0xc0000002, 0xe0000042, 0x60000042, 0x80000002, 0, 0, + 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000000, 0x40, 0x80000001, 0x60, 0x80000003, + 0x40000002, 0xc0000040, 0xc0000002, 0x80000000, 0x80000000, 0x80000002, 0x40, 0x2, + 0x80000000, 0x80000000, 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000002, 0, + 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x105, 0x89, 0x16, + 0x20b, 0x11b, 0x12d, 0x41e, 0x224, 0x50, 0x92e, 0x46c, + ], + }, + Info { + dv_type: 2, + dv_k: 51, + dv_b: 0, + testt: Testt::T65, + maski: 0, + maskb: 25, + dm: [ + 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, + 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0xc, 0xb8000010, + 0x8000018, 0x78000010, 0x8000014, 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, + 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0, + 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, 0x10, 0x60000000, 0x18, + 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, + 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, + 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, + 0x40000041, 0x40000022, 0x80000005, 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, + 0x89, 0x14, 0x8000024b, + ], + }, + Info { + dv_type: 2, + dv_k: 51, + dv_b: 2, + testt: Testt::T65, + maski: 0, + maskb: 26, + dm: [ + 0x43, 0xd0000072, 0xf0000010, 0xf000006a, 0x80000040, 0x90000070, 0xb0000053, + 0x30000008, 0x43, 0xd0000072, 0xb0000010, 0xf0000062, 0xc0000042, 0x30, 0xe0000042, + 0x20000060, 0xe0000041, 0x20000050, 0xc0000041, 0xe0000072, 0xa0000003, 0xc0000012, + 0x60000041, 0xc0000032, 0x20000001, 0xc0000002, 0xe0000042, 0x60000042, 0x80000002, 0, + 0, 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000000, 0x40, 0x80000001, 0x60, + 0x80000003, 0x40000002, 0xc0000040, 0xc0000002, 0x80000000, 0x80000000, 0x80000002, + 0x40, 0x2, 0x80000000, 0x80000000, 0x80000000, 0x2, 0x40, 0, 0x80000040, 0x80000002, 0, + 0x80000000, 0x80000000, 0, 0, 0, 0, 0, 0, 0x4, 0x80, 0x4, 0x9, 0x105, 0x89, 0x16, + 0x20b, 0x11b, 0x12d, 0x41e, 0x224, 0x50, 0x92e, + ], + }, + Info { + dv_type: 2, + dv_k: 52, + dv_b: 0, + testt: Testt::T65, + maski: 0, + maskb: 27, + dm: [ + 0xc000002, 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, 0x2400001c, + 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, 0xb0000010, 0xc, + 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, 0xb800001c, 0xe8000000, + 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, 0x98000010, + 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, 0x10, + 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, + 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, + 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, + 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, 0xc0000082, + 0xc0000046, 0x4000004b, 0x80000107, 0x89, 0x14, + ], + }, + Info { + dv_type: 2, + dv_k: 53, + dv_b: 0, + testt: Testt::T65, + maski: 0, + maskb: 28, + dm: [ + 0xcc000014, 0xc000002, 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, 0x20000010, + 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, 0xbc000018, + 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, 0xb800001c, + 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, 0xb8000010, + 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0x20000000, + 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, 0x20000000, + 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, 0x20000000, + 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, 0, 0, 0, 0, + 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, 0xc0000082, + 0xc0000046, 0x4000004b, 0x80000107, 0x89, + ], + }, + Info { + dv_type: 2, + dv_k: 54, + dv_b: 0, + testt: Testt::T65, + maski: 0, + maskb: 29, + dm: [ + 0x400001c, 0xcc000014, 0xc000002, 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, + 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, + 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, + 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, + 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, + 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, + 0x20000000, 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, + 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, + 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, + 0xc0000082, 0xc0000046, 0x4000004b, 0x80000107, + ], + }, + Info { + dv_type: 2, + dv_k: 55, + dv_b: 0, + testt: Testt::T65, + maski: 0, + maskb: 30, + dm: [ + 0x10, 0x400001c, 0xcc000014, 0xc000002, 0xc0000010, 0xb400001c, 0x3c000004, 0xbc00001a, + 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, 0x2c000004, + 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, 0x70000010, + 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, 0xb0000000, + 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, + 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, 0xb0000000, + 0x20000000, 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, 0x20000000, + 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, 0x20000000, 0, + 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, 0x80000005, + 0xc0000082, 0xc0000046, 0x4000004b, + ], + }, + Info { + dv_type: 2, + dv_k: 56, + dv_b: 0, + testt: Testt::T65, + maski: 0, + maskb: 31, + dm: [ + 0x2600001a, 0x10, 0x400001c, 0xcc000014, 0xc000002, 0xc0000010, 0xb400001c, 0x3c000004, + 0xbc00001a, 0x20000010, 0x2400001c, 0xec000014, 0xc000002, 0xc0000010, 0xb400001c, + 0x2c000004, 0xbc000018, 0xb0000010, 0xc, 0xb8000010, 0x8000018, 0x78000010, 0x8000014, + 0x70000010, 0xb800001c, 0xe8000000, 0xb0000004, 0x58000010, 0xb000000c, 0x48000000, + 0xb0000000, 0xb8000010, 0x98000010, 0xa0000000, 0, 0, 0x20000000, 0x80000000, 0x10, 0, + 0x20000010, 0x20000000, 0x10, 0x60000000, 0x18, 0xe0000000, 0x90000000, 0x30000010, + 0xb0000000, 0x20000000, 0x20000000, 0xa0000000, 0x10, 0x80000000, 0x20000000, + 0x20000000, 0x20000000, 0x80000000, 0x10, 0, 0x20000010, 0xa0000000, 0, 0x20000000, + 0x20000000, 0, 0, 0, 0, 0, 0, 0x1, 0x20, 0x1, 0x40000002, 0x40000041, 0x40000022, + 0x80000005, 0xc0000082, 0xc0000046, + ], + }, +]; + +/// Takes as input an expanded message block and verifies the unavoidable bitconditions +/// for all listed DVs it returns a dvmask where each bit belonging to a DV is set if +/// all unavoidable bitconditions for that DV have been met thus one needs to do the +/// recompression check for each DV that has its bit set. +#[inline] +pub const fn ubc_check(w: &[u32; 80]) -> u32 { + let mut mask: u32 = !0; + mask &= ((w[44] ^ w[45]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_48_0_BIT + | DV_I_51_0_BIT + | DV_I_52_0_BIT + | DV_II_45_0_BIT + | DV_II_46_0_BIT + | DV_II_50_0_BIT + | DV_II_51_0_BIT); + mask &= ((w[49] ^ w[50]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_46_0_BIT + | DV_II_45_0_BIT + | DV_II_50_0_BIT + | DV_II_51_0_BIT + | DV_II_55_0_BIT + | DV_II_56_0_BIT); + mask &= ((w[48] ^ w[49]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_45_0_BIT + | DV_I_52_0_BIT + | DV_II_49_0_BIT + | DV_II_50_0_BIT + | DV_II_54_0_BIT + | DV_II_55_0_BIT); + mask &= ((w[47] ^ w[50] >> 25) & (1 << 4)).wrapping_sub((1) << 4) + | !(DV_I_47_0_BIT + | DV_I_49_0_BIT + | DV_I_51_0_BIT + | DV_II_45_0_BIT + | DV_II_51_0_BIT + | DV_II_56_0_BIT); + mask &= ((w[47] ^ w[48]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_44_0_BIT + | DV_I_51_0_BIT + | DV_II_48_0_BIT + | DV_II_49_0_BIT + | DV_II_53_0_BIT + | DV_II_54_0_BIT); + mask &= ((w[46] >> 4 ^ w[49] >> 29) & 1).wrapping_sub(1) + | !(DV_I_46_0_BIT + | DV_I_48_0_BIT + | DV_I_50_0_BIT + | DV_I_52_0_BIT + | DV_II_50_0_BIT + | DV_II_55_0_BIT); + mask &= ((w[46] ^ w[47]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_43_0_BIT + | DV_I_50_0_BIT + | DV_II_47_0_BIT + | DV_II_48_0_BIT + | DV_II_52_0_BIT + | DV_II_53_0_BIT); + mask &= ((w[45] >> 4 ^ w[48] >> 29) & 1).wrapping_sub(1) + | !(DV_I_45_0_BIT + | DV_I_47_0_BIT + | DV_I_49_0_BIT + | DV_I_51_0_BIT + | DV_II_49_0_BIT + | DV_II_54_0_BIT); + mask &= ((w[45] ^ w[46]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_49_0_BIT + | DV_I_52_0_BIT + | DV_II_46_0_BIT + | DV_II_47_0_BIT + | DV_II_51_0_BIT + | DV_II_52_0_BIT); + mask &= ((w[44] >> 4 ^ w[47] >> 29) & 1).wrapping_sub(1) + | !(DV_I_44_0_BIT + | DV_I_46_0_BIT + | DV_I_48_0_BIT + | DV_I_50_0_BIT + | DV_II_48_0_BIT + | DV_II_53_0_BIT); + mask &= ((w[43] >> 4 ^ w[46] >> 29) & 1).wrapping_sub(1) + | !(DV_I_43_0_BIT + | DV_I_45_0_BIT + | DV_I_47_0_BIT + | DV_I_49_0_BIT + | DV_II_47_0_BIT + | DV_II_52_0_BIT); + mask &= ((w[43] ^ w[44]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_47_0_BIT + | DV_I_50_0_BIT + | DV_I_51_0_BIT + | DV_II_45_0_BIT + | DV_II_49_0_BIT + | DV_II_50_0_BIT); + mask &= ((w[42] >> 4 ^ w[45] >> 29) & 1).wrapping_sub(1) + | !(DV_I_44_0_BIT + | DV_I_46_0_BIT + | DV_I_48_0_BIT + | DV_I_52_0_BIT + | DV_II_46_0_BIT + | DV_II_51_0_BIT); + mask &= ((w[41] >> 4 ^ w[44] >> 29) & 1).wrapping_sub(1) + | !(DV_I_43_0_BIT + | DV_I_45_0_BIT + | DV_I_47_0_BIT + | DV_I_51_0_BIT + | DV_II_45_0_BIT + | DV_II_50_0_BIT); + mask &= ((w[40] ^ w[41]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_44_0_BIT + | DV_I_47_0_BIT + | DV_I_48_0_BIT + | DV_II_46_0_BIT + | DV_II_47_0_BIT + | DV_II_56_0_BIT); + mask &= ((w[54] ^ w[55]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_51_0_BIT | DV_II_47_0_BIT | DV_II_50_0_BIT | DV_II_55_0_BIT | DV_II_56_0_BIT); + mask &= ((w[53] ^ w[54]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_50_0_BIT | DV_II_46_0_BIT | DV_II_49_0_BIT | DV_II_54_0_BIT | DV_II_55_0_BIT); + mask &= ((w[52] ^ w[53]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_49_0_BIT | DV_II_45_0_BIT | DV_II_48_0_BIT | DV_II_53_0_BIT | DV_II_54_0_BIT); + mask &= ((w[50] ^ w[53] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_I_50_0_BIT | DV_I_52_0_BIT | DV_II_46_0_BIT | DV_II_48_0_BIT | DV_II_54_0_BIT); + mask &= ((w[50] ^ w[51]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_47_0_BIT | DV_II_46_0_BIT | DV_II_51_0_BIT | DV_II_52_0_BIT | DV_II_56_0_BIT); + mask &= ((w[49] ^ w[52] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_I_49_0_BIT | DV_I_51_0_BIT | DV_II_45_0_BIT | DV_II_47_0_BIT | DV_II_53_0_BIT); + mask &= ((w[48] ^ w[51] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_I_48_0_BIT | DV_I_50_0_BIT | DV_I_52_0_BIT | DV_II_46_0_BIT | DV_II_52_0_BIT); + mask &= ((w[42] ^ w[43]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_46_0_BIT | DV_I_49_0_BIT | DV_I_50_0_BIT | DV_II_48_0_BIT | DV_II_49_0_BIT); + mask &= ((w[41] ^ w[42]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_45_0_BIT | DV_I_48_0_BIT | DV_I_49_0_BIT | DV_II_47_0_BIT | DV_II_48_0_BIT); + mask &= ((w[40] >> 4 ^ w[43] >> 29) & 1).wrapping_sub(1) + | !(DV_I_44_0_BIT | DV_I_46_0_BIT | DV_I_50_0_BIT | DV_II_49_0_BIT | DV_II_56_0_BIT); + mask &= ((w[39] >> 4 ^ w[42] >> 29) & 1).wrapping_sub(1) + | !(DV_I_43_0_BIT | DV_I_45_0_BIT | DV_I_49_0_BIT | DV_II_48_0_BIT | DV_II_55_0_BIT); + if mask & (DV_I_44_0_BIT | DV_I_48_0_BIT | DV_II_47_0_BIT | DV_II_54_0_BIT | DV_II_56_0_BIT) + != 0 + { + mask &= ((w[38] >> 4 ^ w[41] >> 29) & 1).wrapping_sub(1) + | !(DV_I_44_0_BIT | DV_I_48_0_BIT | DV_II_47_0_BIT | DV_II_54_0_BIT | DV_II_56_0_BIT) + } + mask &= ((w[37] >> 4 ^ w[40] >> 29) & 1).wrapping_sub(1) + | !(DV_I_43_0_BIT | DV_I_47_0_BIT | DV_II_46_0_BIT | DV_II_53_0_BIT | DV_II_55_0_BIT); + if mask & (DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_51_0_BIT | DV_II_56_0_BIT) != 0 { + mask &= ((w[55] ^ w[56]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_51_0_BIT | DV_II_56_0_BIT) + } + if mask & (DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_50_0_BIT | DV_II_56_0_BIT) != 0 { + mask &= ((w[52] ^ w[55] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_50_0_BIT | DV_II_56_0_BIT) + } + if mask & (DV_I_51_0_BIT | DV_II_47_0_BIT | DV_II_49_0_BIT | DV_II_55_0_BIT) != 0 { + mask &= ((w[51] ^ w[54] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_I_51_0_BIT | DV_II_47_0_BIT | DV_II_49_0_BIT | DV_II_55_0_BIT) + } + if mask & (DV_I_48_0_BIT | DV_II_47_0_BIT | DV_II_52_0_BIT | DV_II_53_0_BIT) != 0 { + mask &= ((w[51] ^ w[52]) >> 29 & 1).wrapping_sub(1) + | !(DV_I_48_0_BIT | DV_II_47_0_BIT | DV_II_52_0_BIT | DV_II_53_0_BIT) + } + if mask & (DV_I_46_0_BIT | DV_I_49_0_BIT | DV_II_45_0_BIT | DV_II_48_0_BIT) != 0 { + mask &= ((w[36] >> 4 ^ w[40] >> 29) & 1).wrapping_sub(1) + | !(DV_I_46_0_BIT | DV_I_49_0_BIT | DV_II_45_0_BIT | DV_II_48_0_BIT) + } + if mask & (DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_49_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[53] ^ w[56]) >> 29 & 1) + | !(DV_I_52_0_BIT | DV_II_48_0_BIT | DV_II_49_0_BIT) + } + if mask & (DV_I_50_0_BIT | DV_II_46_0_BIT | DV_II_47_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[51] ^ w[54]) >> 29 & 1) + | !(DV_I_50_0_BIT | DV_II_46_0_BIT | DV_II_47_0_BIT) + } + if mask & (DV_I_49_0_BIT | DV_I_51_0_BIT | DV_II_45_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[50] ^ w[52]) >> 29 & 1) + | !(DV_I_49_0_BIT | DV_I_51_0_BIT | DV_II_45_0_BIT) + } + if mask & (DV_I_48_0_BIT | DV_I_50_0_BIT | DV_I_52_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[49] ^ w[51]) >> 29 & 1) + | !(DV_I_48_0_BIT | DV_I_50_0_BIT | DV_I_52_0_BIT) + } + if mask & (DV_I_47_0_BIT | DV_I_49_0_BIT | DV_I_51_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[48] ^ w[50]) >> 29 & 1) + | !(DV_I_47_0_BIT | DV_I_49_0_BIT | DV_I_51_0_BIT) + } + if mask & (DV_I_46_0_BIT | DV_I_48_0_BIT | DV_I_50_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[47] ^ w[49]) >> 29 & 1) + | !(DV_I_46_0_BIT | DV_I_48_0_BIT | DV_I_50_0_BIT) + } + if mask & (DV_I_45_0_BIT | DV_I_47_0_BIT | DV_I_49_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[46] ^ w[48]) >> 29 & 1) + | !(DV_I_45_0_BIT | DV_I_47_0_BIT | DV_I_49_0_BIT) + } + mask &= ((w[45] ^ w[47]) & (1 << 6)).wrapping_sub(1 << 6) + | !(DV_I_47_2_BIT | DV_I_49_2_BIT | DV_I_51_2_BIT); + if mask & (DV_I_44_0_BIT | DV_I_46_0_BIT | DV_I_48_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[45] ^ w[47]) >> 29 & 1) + | !(DV_I_44_0_BIT | DV_I_46_0_BIT | DV_I_48_0_BIT) + } + mask &= ((w[44] ^ w[46]) >> 6 & 1).wrapping_sub(1) + | !(DV_I_46_2_BIT | DV_I_48_2_BIT | DV_I_50_2_BIT); + if mask & (DV_I_43_0_BIT | DV_I_45_0_BIT | DV_I_47_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[44] ^ w[46]) >> 29 & 1) + | !(DV_I_43_0_BIT | DV_I_45_0_BIT | DV_I_47_0_BIT) + } + mask &= (0u32).wrapping_sub((w[41] ^ w[42] >> 5) & (1 << 1)) + | !(DV_I_48_2_BIT | DV_II_46_2_BIT | DV_II_51_2_BIT); + mask &= (0u32).wrapping_sub((w[40] ^ w[41] >> 5) & (1 << 1)) + | !(DV_I_47_2_BIT | DV_I_51_2_BIT | DV_II_50_2_BIT); + if mask & (DV_I_44_0_BIT | DV_I_46_0_BIT | DV_II_56_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[40] ^ w[42]) >> 4 & 1) + | !(DV_I_44_0_BIT | DV_I_46_0_BIT | DV_II_56_0_BIT) + } + mask &= (0u32).wrapping_sub((w[39] ^ w[40] >> 5) & (1 << 1)) + | !(DV_I_46_2_BIT | DV_I_50_2_BIT | DV_II_49_2_BIT); + if mask & (DV_I_43_0_BIT | DV_I_45_0_BIT | DV_II_55_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[39] ^ w[41]) >> 4 & 1) + | !(DV_I_43_0_BIT | DV_I_45_0_BIT | DV_II_55_0_BIT) + } + if mask & (DV_I_44_0_BIT | DV_II_54_0_BIT | DV_II_56_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[38] ^ w[40]) >> 4 & 1) + | !(DV_I_44_0_BIT | DV_II_54_0_BIT | DV_II_56_0_BIT) + } + if mask & (DV_I_43_0_BIT | DV_II_53_0_BIT | DV_II_55_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[37] ^ w[39]) >> 4 & 1) + | !(DV_I_43_0_BIT | DV_II_53_0_BIT | DV_II_55_0_BIT) + } + mask &= (0u32).wrapping_sub((w[36] ^ w[37] >> 5) & (1 << 1)) + | !(DV_I_47_2_BIT | DV_I_50_2_BIT | DV_II_46_2_BIT); + if mask & (DV_I_45_0_BIT | DV_I_48_0_BIT | DV_II_47_0_BIT) != 0 { + mask &= ((w[35] >> 4 ^ w[39] >> 29) & 1).wrapping_sub(1) + | !(DV_I_45_0_BIT | DV_I_48_0_BIT | DV_II_47_0_BIT) + } + if mask & (DV_I_48_0_BIT | DV_II_48_0_BIT) != 0 { + mask &= + (0u32).wrapping_sub((w[63] ^ w[64] >> 5) & (1 << 0)) | !(DV_I_48_0_BIT | DV_II_48_0_BIT) + } + if mask & (DV_I_45_0_BIT | DV_II_45_0_BIT) != 0 { + mask &= + (0u32).wrapping_sub((w[63] ^ w[64] >> 5) & (1 << 1)) | !(DV_I_45_0_BIT | DV_II_45_0_BIT) + } + if mask & (DV_I_47_0_BIT | DV_II_47_0_BIT) != 0 { + mask &= + (0u32).wrapping_sub((w[62] ^ w[63] >> 5) & (1 << 0)) | !(DV_I_47_0_BIT | DV_II_47_0_BIT) + } + if mask & (DV_I_46_0_BIT | DV_II_46_0_BIT) != 0 { + mask &= + (0u32).wrapping_sub((w[61] ^ w[62] >> 5) & (1 << 0)) | !(DV_I_46_0_BIT | DV_II_46_0_BIT) + } + mask &= + (0u32).wrapping_sub((w[61] ^ w[62] >> 5) & (1 << 2)) | !(DV_I_46_2_BIT | DV_II_46_2_BIT); + if mask & (DV_I_45_0_BIT | DV_II_45_0_BIT) != 0 { + mask &= + (0u32).wrapping_sub((w[60] ^ w[61] >> 5) & (1 << 0)) | !(DV_I_45_0_BIT | DV_II_45_0_BIT) + } + if mask & (DV_II_51_0_BIT | DV_II_54_0_BIT) != 0 { + mask &= ((w[58] ^ w[59]) >> 29 & 1).wrapping_sub(1) | !(DV_II_51_0_BIT | DV_II_54_0_BIT) + } + if mask & (DV_II_50_0_BIT | DV_II_53_0_BIT) != 0 { + mask &= ((w[57] ^ w[58]) >> 29 & 1).wrapping_sub(1) | !(DV_II_50_0_BIT | DV_II_53_0_BIT) + } + if mask & (DV_II_52_0_BIT | DV_II_54_0_BIT) != 0 { + mask &= ((w[56] ^ w[59] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_II_52_0_BIT | DV_II_54_0_BIT) + } + if mask & (DV_II_51_0_BIT | DV_II_52_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[56] ^ w[59]) >> 29 & 1) | !(DV_II_51_0_BIT | DV_II_52_0_BIT) + } + if mask & (DV_II_49_0_BIT | DV_II_52_0_BIT) != 0 { + mask &= ((w[56] ^ w[57]) >> 29 & 1).wrapping_sub(1) | !(DV_II_49_0_BIT | DV_II_52_0_BIT) + } + if mask & (DV_II_51_0_BIT | DV_II_53_0_BIT) != 0 { + mask &= ((w[55] ^ w[58] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_II_51_0_BIT | DV_II_53_0_BIT) + } + if mask & (DV_II_50_0_BIT | DV_II_52_0_BIT) != 0 { + mask &= ((w[54] ^ w[57] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_II_50_0_BIT | DV_II_52_0_BIT) + } + if mask & (DV_II_49_0_BIT | DV_II_51_0_BIT) != 0 { + mask &= ((w[53] ^ w[56] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_II_49_0_BIT | DV_II_51_0_BIT) + } + mask &= + ((w[51] ^ w[50] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_I_50_2_BIT | DV_II_46_2_BIT); + mask &= ((w[48] ^ w[50]) & (1 << 6)).wrapping_sub(1 << 6) | !(DV_I_50_2_BIT | DV_II_46_2_BIT); + if mask & (DV_I_51_0_BIT | DV_I_52_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[48] ^ w[55]) >> 29 & 1) | !(DV_I_51_0_BIT | DV_I_52_0_BIT) + } + mask &= ((w[47] ^ w[49]) & (1 << 6)).wrapping_sub(1 << 6) | !(DV_I_49_2_BIT | DV_I_51_2_BIT); + mask &= + ((w[48] ^ w[47] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_I_47_2_BIT | DV_II_51_2_BIT); + mask &= ((w[46] ^ w[48]) & (1 << 6)).wrapping_sub(1 << 6) | !(DV_I_48_2_BIT | DV_I_50_2_BIT); + mask &= + ((w[47] ^ w[46] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_I_46_2_BIT | DV_II_50_2_BIT); + mask &= + (0u32).wrapping_sub((w[44] ^ w[45] >> 5) & (1 << 1)) | !(DV_I_51_2_BIT | DV_II_49_2_BIT); + mask &= ((w[43] ^ w[45]) & (1 << 6)).wrapping_sub(1 << 6) | !(DV_I_47_2_BIT | DV_I_49_2_BIT); + mask &= ((w[42] ^ w[44]) >> 6 & 1).wrapping_sub(1) | !(DV_I_46_2_BIT | DV_I_48_2_BIT); + mask &= + ((w[43] ^ w[42] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_II_46_2_BIT | DV_II_51_2_BIT); + mask &= + ((w[42] ^ w[41] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_I_51_2_BIT | DV_II_50_2_BIT); + mask &= + ((w[41] ^ w[40] >> 5) & (1 << 1)).wrapping_sub(1 << 1) | !(DV_I_50_2_BIT | DV_II_49_2_BIT); + if mask & (DV_I_52_0_BIT | DV_II_51_0_BIT) != 0 { + mask &= ((w[39] ^ w[43] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_I_52_0_BIT | DV_II_51_0_BIT) + } + if mask & (DV_I_51_0_BIT | DV_II_50_0_BIT) != 0 { + mask &= ((w[38] ^ w[42] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_I_51_0_BIT | DV_II_50_0_BIT) + } + if mask & (DV_I_48_2_BIT | DV_I_51_2_BIT) != 0 { + mask &= + (0u32).wrapping_sub((w[37] ^ w[38] >> 5) & (1 << 1)) | !(DV_I_48_2_BIT | DV_I_51_2_BIT) + } + if mask & (DV_I_50_0_BIT | DV_II_49_0_BIT) != 0 { + mask &= ((w[37] ^ w[41] >> 25) & (1 << 4)).wrapping_sub(1 << 4) + | !(DV_I_50_0_BIT | DV_II_49_0_BIT) + } + if mask & (DV_II_52_0_BIT | DV_II_54_0_BIT) != 0 { + mask &= (0u32).wrapping_sub((w[36] ^ w[38]) & (1 << 4)) | !(DV_II_52_0_BIT | DV_II_54_0_BIT) + } + mask &= (0u32).wrapping_sub((w[35] ^ w[36] >> 5) & (1 << 1)) | !(DV_I_46_2_BIT | DV_I_49_2_BIT); + if mask & (DV_I_51_0_BIT | DV_II_47_0_BIT) != 0 { + mask &= ((w[35] ^ w[39] >> 25) & (1 << 3)).wrapping_sub(1 << 3) + | !(DV_I_51_0_BIT | DV_II_47_0_BIT) + } + if mask != 0 { + if mask & DV_I_43_0_BIT != 0 + && ((w[61] ^ w[62] >> 5) & (1 << 1) == 0 + || (w[59] ^ w[63] >> 25) & (1 << 5) != 0 + || (w[58] ^ w[63] >> 30) & (1 << 0) == 0) + { + mask &= !DV_I_43_0_BIT + } + if mask & DV_I_44_0_BIT != 0 + && ((w[62] ^ w[63] >> 5) & (1 << 1) == 0 + || (w[60] ^ w[64] >> 25) & (1 << 5) != 0 + || (w[59] ^ w[64] >> 30) & (1 << 0) == 0) + { + mask &= !DV_I_44_0_BIT + } + if mask & DV_I_46_2_BIT != 0 { + mask &= !((w[40] ^ w[42]) >> 2) | !DV_I_46_2_BIT + } + if mask & DV_I_47_2_BIT != 0 + && ((w[62] ^ w[63] >> 5) & (1 << 2) == 0 || (w[41] ^ w[43]) & (1 << 6) != 0) + { + mask &= !DV_I_47_2_BIT + } + if mask & DV_I_48_2_BIT != 0 + && ((w[63] ^ w[64] >> 5) & (1 << 2) == 0 || (w[48] ^ w[49] << 5) & (1 << 6) != 0) + { + mask &= !DV_I_48_2_BIT + } + if mask & DV_I_49_2_BIT != 0 + && ((w[49] ^ w[50] << 5) & (1 << 6) != 0 + || (w[42] ^ w[50]) & (1 << 1) == 0 + || (w[39] ^ w[40] << 5) & (1 << 6) != 0 + || (w[38] ^ w[40]) & (1 << 1) == 0) + { + mask &= !DV_I_49_2_BIT + } + if mask & DV_I_50_0_BIT != 0 { + mask &= (w[36] ^ w[37]) << 7 | !DV_I_50_0_BIT + } + if mask & DV_I_50_2_BIT != 0 { + mask &= (w[43] ^ w[51]) << 11 | !DV_I_50_2_BIT + } + if mask & DV_I_51_0_BIT != 0 { + mask &= (w[37] ^ w[38]) << 9 | !DV_I_51_0_BIT + } + if mask & DV_I_51_2_BIT != 0 + && ((w[51] ^ w[52] << 5) & (1 << 6) != 0 + || (w[49] ^ w[51]) & (1 << 6) != 0 + || (w[37] ^ w[37] >> 5) & (1 << 1) != 0 + || (w[35] ^ w[39] >> 25) & (1 << 5) != 0) + { + mask &= !DV_I_51_2_BIT + } + if mask & DV_I_52_0_BIT != 0 { + mask &= (w[38] ^ w[39]) << 11 | !DV_I_52_0_BIT + } + if mask & DV_II_46_2_BIT != 0 { + mask &= (w[47] ^ w[51]) << 17 | !DV_II_46_2_BIT + } + if mask & DV_II_48_0_BIT != 0 + && ((w[36] ^ w[40] >> 25) & (1 << 3) != 0 || (w[35] ^ w[40] << 2) & (1 << 30) == 0) + { + mask &= !DV_II_48_0_BIT + } + if mask & DV_II_49_0_BIT != 0 + && ((w[37] ^ w[41] >> 25) & (1 << 3) != 0 || (w[36] ^ w[41] << 2) & (1 << 30) == 0) + { + mask &= !DV_II_49_0_BIT + } + if mask & DV_II_49_2_BIT != 0 + && ((w[53] ^ w[54] << 5) & (1 << 6) != 0 + || (w[51] ^ w[53]) & (1 << 6) != 0 + || (w[50] ^ w[54]) & (1 << 1) == 0 + || (w[45] ^ w[46] << 5) & (1 << 6) != 0 + || (w[37] ^ w[41] >> 25) & (1 << 5) != 0 + || (w[36] ^ w[41] >> 30) & (1 << 0) == 0) + { + mask &= !DV_II_49_2_BIT + } + if mask & DV_II_50_0_BIT != 0 + && ((w[55] ^ w[58]) & (1 << 29) == 0 + || (w[38] ^ w[42] >> 25) & (1 << 3) != 0 + || (w[37] ^ w[42] << 2) & (1 << 30) == 0) + { + mask &= !DV_II_50_0_BIT + } + if mask & DV_II_50_2_BIT != 0 + && ((w[54] ^ w[55] << 5) & (1 << 6) != 0 + || (w[52] ^ w[54]) & (1 << 6) != 0 + || (w[51] ^ w[55]) & (1 << 1) == 0 + || (w[45] ^ w[47]) & (1 << 1) == 0 + || (w[38] ^ w[42] >> 25) & (1 << 5) != 0 + || (w[37] ^ w[42] >> 30) & (1 << 0) == 0) + { + mask &= !DV_II_50_2_BIT + } + if mask & DV_II_51_0_BIT != 0 + && ((w[39] ^ w[43] >> 25) & (1 << 3) != 0 || (w[38] ^ w[43] << 2) & (1 << 30) == 0) + { + mask &= !DV_II_51_0_BIT + } + if mask & DV_II_51_2_BIT != 0 + && ((w[55] ^ w[56] << 5) & (1 << 6) != 0 + || (w[53] ^ w[55]) & (1 << 6) != 0 + || (w[52] ^ w[56]) & (1 << 1) == 0 + || (w[46] ^ w[48]) & (1 << 1) == 0 + || (w[39] ^ w[43] >> 25) & (1 << 5) != 0 + || (w[38] ^ w[43] >> 30) & (1 << 0) == 0) + { + mask &= !DV_II_51_2_BIT + } + if mask & DV_II_52_0_BIT != 0 + && ((w[59] ^ w[60]) & (1 << 29) != 0 + || (w[40] ^ w[44] >> 25) & (1 << 3) != 0 + || (w[40] ^ w[44] >> 25) & (1 << 4) != 0 + || (w[39] ^ w[44] << 2) & (1 << 30) == 0) + { + mask &= !DV_II_52_0_BIT + } + if mask & DV_II_53_0_BIT != 0 + && ((w[58] ^ w[61]) & (1 << 29) == 0 + || (w[57] ^ w[61] >> 25) & (1 << 4) != 0 + || (w[41] ^ w[45] >> 25) & (1 << 3) != 0 + || (w[41] ^ w[45] >> 25) & (1 << 4) != 0) + { + mask &= !DV_II_53_0_BIT + } + if mask & DV_II_54_0_BIT != 0 + && ((w[58] ^ w[62] >> 25) & (1 << 4) != 0 + || (w[42] ^ w[46] >> 25) & (1 << 3) != 0 + || (w[42] ^ w[46] >> 25) & (1 << 4) != 0) + { + mask &= !DV_II_54_0_BIT + } + if mask & DV_II_55_0_BIT != 0 + && ((w[59] ^ w[63] >> 25) & (1 << 4) != 0 + || (w[57] ^ w[59] >> 25) & (1 << 4) != 0 + || (w[43] ^ w[47] >> 25) & (1 << 3) != 0 + || (w[43] ^ w[47] >> 25) & (1 << 4) != 0) + { + mask &= !DV_II_55_0_BIT + } + if mask & DV_II_56_0_BIT != 0 + && ((w[60] ^ w[64] >> 25) & (1 << 4) != 0 + || (w[44] ^ w[48] >> 25) & (1 << 3) != 0 + || (w[44] ^ w[48] >> 25) & (1 << 4) != 0) + { + mask &= !DV_II_56_0_BIT + } + } + mask +} diff --git a/sha1-checked/tests/data/sha-mbles-1.bin b/sha1-checked/tests/data/sha-mbles-1.bin new file mode 100644 index 00000000..5a7c30e9 Binary files /dev/null and b/sha1-checked/tests/data/sha-mbles-1.bin differ diff --git a/sha1-checked/tests/data/sha-mbles-2.bin b/sha1-checked/tests/data/sha-mbles-2.bin new file mode 100644 index 00000000..fe391784 Binary files /dev/null and b/sha1-checked/tests/data/sha-mbles-2.bin differ diff --git a/sha1-checked/tests/data/sha1.blb b/sha1-checked/tests/data/sha1.blb new file mode 100644 index 00000000..e8dc4916 Binary files /dev/null and b/sha1-checked/tests/data/sha1.blb differ diff --git a/sha1-checked/tests/data/sha1_reducedsha_coll.bin b/sha1-checked/tests/data/sha1_reducedsha_coll.bin new file mode 100644 index 00000000..46233362 --- /dev/null +++ b/sha1-checked/tests/data/sha1_reducedsha_coll.bin @@ -0,0 +1 @@ +~9:pऄޥVZ-kqpDx$ . (8<+sC>NM]{$,+0ThEC !R6+f^j@,9|<r \ No newline at end of file diff --git a/sha1-checked/tests/data/shattered-1.pdf b/sha1-checked/tests/data/shattered-1.pdf new file mode 100644 index 00000000..ba9aaa14 Binary files /dev/null and b/sha1-checked/tests/data/shattered-1.pdf differ diff --git a/sha1-checked/tests/data/shattered-2.pdf b/sha1-checked/tests/data/shattered-2.pdf new file mode 100644 index 00000000..b621eecc Binary files /dev/null and b/sha1-checked/tests/data/shattered-2.pdf differ diff --git a/sha1-checked/tests/mod.rs b/sha1-checked/tests/mod.rs new file mode 100644 index 00000000..79af7e18 --- /dev/null +++ b/sha1-checked/tests/mod.rs @@ -0,0 +1,159 @@ +use digest::dev::{feed_rand_16mib, fixed_reset_test}; +use hex_literal::hex; +use sha1_checked::{Digest, Sha1}; + +digest::new_test!(sha1_checked_main, "sha1", Sha1, fixed_reset_test); + +#[test] +fn sha1_rand() { + let mut h = Sha1::new(); + feed_rand_16mib(&mut h); + assert_eq!( + &h.finalize()[..], + hex!("7e565a25a8b123e9881addbcedcd927b23377a78"), + ); +} + +#[test] +fn sha1_collision_rand() { + let mut h = Sha1::new(); + feed_rand_16mib(&mut h); + assert_eq!( + &h.finalize()[..], + hex!("7e565a25a8b123e9881addbcedcd927b23377a78"), + ); +} + +#[cfg(feature = "std")] +#[test] +fn shambles_1() { + collision_test( + "./data/sha-mbles-1.bin", + hex!("8ac60ba76f1999a1ab70223f225aefdc78d4ddc0"), + hex!("4f3d9be4a472c4dae83c6314aa6c36a064c1fd14"), + None, + false, + false, + ); +} + +#[cfg(feature = "std")] +#[test] +fn shambles_2() { + collision_test( + "./data/sha-mbles-2.bin", + hex!("8ac60ba76f1999a1ab70223f225aefdc78d4ddc0"), + hex!("9ed5d77a4f48be1dbf3e9e15650733eb850897f2"), + None, + false, + false, + ); +} + +#[cfg(feature = "std")] +#[test] +fn shattered_1() { + collision_test( + "./data/shattered-1.pdf", + hex!("38762cf7f55934b34d179ae6a4c80cadccbb7f0a"), + hex!("16e96b70000dd1e7c85b8368ee197754400e58ec"), + Some(hex!("d3a1d09969c3b57113fd17b23e01dd3de74a99bb")), + false, + true, + ); +} + +#[cfg(feature = "std")] +#[test] +fn shattered_2() { + collision_test( + "./data/shattered-2.pdf", + hex!("38762cf7f55934b34d179ae6a4c80cadccbb7f0a"), + hex!("e1761773e6a35916d99f891b77663e6405313587"), + Some(hex!("92246b0b718f4c704d37bb025717cbc66babf102")), + false, + true, + ); +} + +#[cfg(feature = "std")] +#[test] +fn reducedsha_coll() { + collision_test( + "./data/sha1_reducedsha_coll.bin", + hex!("a56374e1cf4c3746499bc7c0acb39498ad2ee185"), + hex!("dd39885a2a5d8f59030b451e00cb45da9f9d3828"), + Some(hex!("dd39885a2a5d8f59030b451e00cb45da9f9d3828")), + true, + false, + ); +} + +#[cfg(feature = "std")] +fn collision_test( + input_path: &str, + hash: [u8; 20], + mitigated_hash: [u8; 20], + reduced_rounds_mitigated: Option<[u8; 20]>, + reduced_rounds: bool, + allow_skip: bool, +) { + let p = std::env::current_dir() + .unwrap() + .join("tests") + .join(input_path); + + if !p.exists() && allow_skip { + eprintln!("SKIPPING TEST, data not available"); + return; + } + + let input = std::fs::read(p).unwrap(); + let has_collision = true; + + // No detection. + let mut ctx = Sha1::builder().detect_collision(false).build(); + ctx.update(&input); + let d = ctx.try_finalize(); + assert!(!d.has_collision()); + assert_eq!(&d.hash()[..], hash,); + + // No mitigation. + let mut ctx = Sha1::builder() + .safe_hash(false) + .reduced_round_collision(reduced_rounds) + .build(); + ctx.update(&input); + + let d = ctx.try_finalize(); + assert_eq!(d.has_collision(), has_collision); + assert_eq!(&d.hash()[..], hash); + + // No mitigation, no optimization. + let mut ctx = Sha1::builder() + .safe_hash(false) + .use_ubc(false) + .reduced_round_collision(reduced_rounds) + .build(); + ctx.update(&input); + let d = ctx.try_finalize(); + assert_eq!(d.has_collision(), has_collision); + assert_eq!(&d.hash()[..], hash); + + // With mitigation. + let mut ctx = Sha1::builder() + .reduced_round_collision(reduced_rounds) + .build(); + ctx.update(&input); + let d = ctx.try_finalize(); + assert_eq!(d.has_collision(), has_collision); + assert_eq!(&d.hash()[..], mitigated_hash); + + if let Some(rr) = reduced_rounds_mitigated { + let mut ctx = Sha1::builder().reduced_round_collision(true).build(); + ctx.update(&input); + let d = ctx.try_finalize(); + assert_eq!(d.has_collision(), has_collision); + assert_eq!(&d.hash()[..], rr); + } +} diff --git a/sha1/README.md b/sha1/README.md index 785a31ec..85e3ade3 100644 --- a/sha1/README.md +++ b/sha1/README.md @@ -17,6 +17,9 @@ unsuitable for further use in any security critical capacity, as it is We provide this crate for legacy interoperability purposes only. +If possible use the [sha1-checked] crate, while slower it provides the ability to +detect potential collisions, as well as generate alternative safe hashes. + ## Examples ### One-shot API @@ -89,3 +92,4 @@ dual licensed as above, without any additional terms or conditions. [SHA-1]: https://en.wikipedia.org/wiki/SHA-1 [1]: https://sha-mbles.github.io/ [examples section]: https://github.com/RustCrypto/hashes#Examples +[sha1-checked]: https://crates.io/crates/sha1-checked