aes-soft-0.6.4/.cargo_vcs_info.json0000644000000001121375455342500126310ustar { "git": { "sha1": "43a7bceb3f125a18bdc7fcaefbe13a718e630865" } } aes-soft-0.6.4/CHANGELOG.md010064400007650000024000000051361375455263400132550ustar 00000000000000# 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). ## 0.6.4 (2020-11-16) ### Changed - Rework of xor_columns ([#197]) - Implement semi-fixsliced support under `semi_fixslice` Cargo feature ([#195]) [#197]: https://github.com/RustCrypto/block-ciphers/pull/197 [#195]: https://github.com/RustCrypto/block-ciphers/pull/195 ## 0.6.3 (2020-11-01) ### Changed - Comprehensive refactoring of fixslice code ([#192]) - Forbid `unsafe` ([#190]) - Re-order (`inv`)`_sbox` using custom scheduler ([#189]) [#192]: https://github.com/RustCrypto/block-ciphers/pull/192 [#190]: https://github.com/RustCrypto/block-ciphers/pull/190 [#189]: https://github.com/RustCrypto/block-ciphers/pull/189 ## 0.6.2 (2020-10-28) ### Added - 64-bit fixsliced AES implementation ([#180]) ### Changed - Fixsliced AES decryption ([#185]) - Improved AES fixsliced MixColumns algorithms ([#184]) [#185]: https://github.com/RustCrypto/block-ciphers/pull/185 [#184]: https://github.com/RustCrypto/block-ciphers/pull/184 [#180]: https://github.com/RustCrypto/block-ciphers/pull/180 ## 0.6.1 (2020-10-26) ### Changed - Use fixslicing for AES encryption - 3X performance boost ([#174], [#176], [#177]) - Additional bitslicing performance optimizations ([#171], [#175]) [#177]: https://github.com/RustCrypto/block-ciphers/pull/177 [#176]: https://github.com/RustCrypto/block-ciphers/pull/176 [#175]: https://github.com/RustCrypto/block-ciphers/pull/175 [#174]: https://github.com/RustCrypto/block-ciphers/pull/174 [#171]: https://github.com/RustCrypto/block-ciphers/pull/171 ## 0.6.0 (2020-10-16) ### Changed - Replace `block-cipher`/`stream-cipher` with `cipher` crate ([#167]) - Performance improvements ([#166]) [#167]: https://github.com/RustCrypto/block-ciphers/pull/167 [#166]: https://github.com/RustCrypto/block-ciphers/pull/166 ## 0.5.0 (2020-08-07) ### Changed - Bump `block-cipher` dependency to v0.8 ([#138]) - Bump `opaque-debug` dependency to v0.3 ([#140]) [#138]: https://github.com/RustCrypto/block-ciphers/pull/138 [#140]: https://github.com/RustCrypto/block-ciphers/pull/140 ## 0.4.0 (2020-06-05) ### Changed - Bump `block-cipher` dependency to v0.7 ([#86], [#122]) - Update to Rust 2018 edition ([#86]) [#122]: https://github.com/RustCrypto/block-ciphers/pull/122 [#86]: https://github.com/RustCrypto/block-ciphers/pull/86 ## 0.3.3 (2018-12-23) ## 0.3.2 (2018-10-04) ## 0.3.1 (2018-10-03) ## 0.3.0 (2018-10-03) ## 0.2.0 (2018-07-27) ## 0.1.0 (2018-03-04) aes-soft-0.6.4/Cargo.toml0000644000000021131375455342500106320ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "aes-soft" version = "0.6.4" authors = ["RustCrypto Developers"] description = "AES (Rijndael) block ciphers bit-sliced implementation" documentation = "https://docs.rs/aes-soft" keywords = ["crypto", "aes", "rijndael", "block-cipher"] categories = ["cryptography", "no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/RustCrypto/block-ciphers" [dependencies.cipher] version = "0.2" [dependencies.opaque-debug] version = "0.3" [dev-dependencies.cipher] version = "0.2" features = ["dev"] [features] semi_fixslice = [] aes-soft-0.6.4/Cargo.toml.orig010064400007650000024000000010471375455233600143270ustar 00000000000000[package] name = "aes-soft" version = "0.6.4" description = "AES (Rijndael) block ciphers bit-sliced implementation" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" edition = "2018" documentation = "https://docs.rs/aes-soft" repository = "https://github.com/RustCrypto/block-ciphers" keywords = ["crypto", "aes", "rijndael", "block-cipher"] categories = ["cryptography", "no-std"] [dependencies] cipher = "0.2" opaque-debug = "0.3" [dev-dependencies] cipher = { version = "0.2", features = ["dev"] } [features] semi_fixslice = [] aes-soft-0.6.4/LICENSE-APACHE010064400007650000024000000251411374627362100133630ustar 00000000000000 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. aes-soft-0.6.4/LICENSE-MIT010064400007650000024000000021621374627362100130710ustar 00000000000000Copyright (c) 2006-2009 Graydon Hoare Copyright (c) 2009-2013 Mozilla Foundation Copyright (c) 2018 Artyom Pavlov 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. aes-soft-0.6.4/benches/aes128.rs010064400007650000024000000027011375324124100144030ustar 00000000000000#![feature(test)] extern crate test; use aes_soft::cipher::{BlockCipher, NewBlockCipher}; use aes_soft::Aes128; #[bench] pub fn aes128_new(bh: &mut test::Bencher) { bh.iter(|| { let cipher = Aes128::new(&Default::default()); test::black_box(&cipher); }); } #[bench] pub fn aes128_encrypt(bh: &mut test::Bencher) { let cipher = Aes128::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.encrypt_block(&mut input); test::black_box(&input); }); bh.bytes = input.len() as u64; } #[bench] pub fn aes128_decrypt(bh: &mut test::Bencher) { let cipher = Aes128::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.decrypt_block(&mut input); test::black_box(&input); }); bh.bytes = input.len() as u64; } #[bench] pub fn aes128_encrypt8(bh: &mut test::Bencher) { let cipher = Aes128::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.encrypt_blocks(&mut input); test::black_box(&input); }); bh.bytes = (input[0].len() * input.len()) as u64; } #[bench] pub fn aes128_decrypt8(bh: &mut test::Bencher) { let cipher = Aes128::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.decrypt_blocks(&mut input); test::black_box(&input); }); bh.bytes = (input[0].len() * input.len()) as u64; } aes-soft-0.6.4/benches/aes192.rs010064400007650000024000000027011375324124100144040ustar 00000000000000#![feature(test)] extern crate test; use aes_soft::cipher::{BlockCipher, NewBlockCipher}; use aes_soft::Aes192; #[bench] pub fn aes192_new(bh: &mut test::Bencher) { bh.iter(|| { let cipher = Aes192::new(&Default::default()); test::black_box(&cipher); }); } #[bench] pub fn aes192_encrypt(bh: &mut test::Bencher) { let cipher = Aes192::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.encrypt_block(&mut input); test::black_box(&input); }); bh.bytes = input.len() as u64; } #[bench] pub fn aes192_decrypt(bh: &mut test::Bencher) { let cipher = Aes192::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.decrypt_block(&mut input); test::black_box(&input); }); bh.bytes = input.len() as u64; } #[bench] pub fn aes192_encrypt8(bh: &mut test::Bencher) { let cipher = Aes192::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.encrypt_blocks(&mut input); test::black_box(&input); }); bh.bytes = (input[0].len() * input.len()) as u64; } #[bench] pub fn aes192_decrypt8(bh: &mut test::Bencher) { let cipher = Aes192::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.decrypt_blocks(&mut input); test::black_box(&input); }); bh.bytes = (input[0].len() * input.len()) as u64; } aes-soft-0.6.4/benches/aes256.rs010064400007650000024000000027011375324124100144050ustar 00000000000000#![feature(test)] extern crate test; use aes_soft::cipher::{BlockCipher, NewBlockCipher}; use aes_soft::Aes256; #[bench] pub fn aes256_new(bh: &mut test::Bencher) { bh.iter(|| { let cipher = Aes256::new(&Default::default()); test::black_box(&cipher); }); } #[bench] pub fn aes256_encrypt(bh: &mut test::Bencher) { let cipher = Aes256::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.encrypt_block(&mut input); test::black_box(&input); }); bh.bytes = input.len() as u64; } #[bench] pub fn aes256_decrypt(bh: &mut test::Bencher) { let cipher = Aes256::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.decrypt_block(&mut input); test::black_box(&input); }); bh.bytes = input.len() as u64; } #[bench] pub fn aes256_encrypt8(bh: &mut test::Bencher) { let cipher = Aes256::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.encrypt_blocks(&mut input); test::black_box(&input); }); bh.bytes = (input[0].len() * input.len()) as u64; } #[bench] pub fn aes256_decrypt8(bh: &mut test::Bencher) { let cipher = Aes256::new(&Default::default()); let mut input = Default::default(); bh.iter(|| { cipher.decrypt_blocks(&mut input); test::black_box(&input); }); bh.bytes = (input[0].len() * input.len()) as u64; } aes-soft-0.6.4/src/fixslice32.rs010064400007650000024000001136651375324177600145640ustar 00000000000000//! Fixsliced implementations of AES-128, AES-192 and AES-256 //! adapted from the C implementation. //! //! All implementations are fully bitsliced and do not rely on any //! Look-Up Table (LUT). //! //! See the paper at for more details. //! //! # Author (original C code) //! //! Alexandre Adomnicai, Nanyang Technological University, Singapore //! //! //! Originally licensed MIT. Relicensed as Apache 2.0+MIT with permission. use crate::Block; use cipher::{ consts::{U16, U24, U32}, generic_array::GenericArray, }; use core::convert::TryInto; /// AES block batch size for this implementation pub(crate) const FIXSLICE_BLOCKS: usize = 2; /// AES-128 round keys pub(crate) type FixsliceKeys128 = [u32; 88]; /// AES-192 round keys pub(crate) type FixsliceKeys192 = [u32; 104]; /// AES-256 round keys pub(crate) type FixsliceKeys256 = [u32; 120]; /// 256-bit internal state type State = [u32; 8]; /// Fully bitsliced AES-128 key schedule to match the fully-fixsliced representation. pub(crate) fn aes128_key_schedule(key: &GenericArray) -> FixsliceKeys128 { // TODO(tarcieri): use `::default()` after MSRV 1.47+ let mut rkeys = [0u32; 88]; bitslice(&mut rkeys[..8], key, key); let mut rk_off = 0; for rcon in 0..10 { memshift32(&mut rkeys, rk_off); rk_off += 8; sub_bytes(&mut rkeys[rk_off..(rk_off + 8)]); sub_bytes_nots(&mut rkeys[rk_off..(rk_off + 8)]); if rcon < 8 { add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon); } else { add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 8); add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 7); add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 5); add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 4); } xor_columns(&mut rkeys, rk_off, 8, ror_distance(1, 3)); } // Adjust to match fixslicing format #[cfg(feature = "semi_fixslice")] { for i in (8..88).step_by(16) { inv_shift_rows_1(&mut rkeys[i..(i + 8)]); } } #[cfg(not(feature = "semi_fixslice"))] { for i in (8..72).step_by(32) { inv_shift_rows_1(&mut rkeys[i..(i + 8)]); inv_shift_rows_2(&mut rkeys[(i + 8)..(i + 16)]); inv_shift_rows_3(&mut rkeys[(i + 16)..(i + 24)]); } inv_shift_rows_1(&mut rkeys[72..80]); } // Account for NOTs removed from sub_bytes for i in 1..11 { sub_bytes_nots(&mut rkeys[(i * 8)..(i * 8 + 8)]); } rkeys } /// Fully bitsliced AES-192 key schedule to match the fully-fixsliced representation. pub(crate) fn aes192_key_schedule(key: &GenericArray) -> FixsliceKeys192 { // TODO(tarcieri): use `::default()` after MSRV 1.47+ let mut rkeys = [0u32; 104]; let mut tmp = [0u32; 8]; bitslice(&mut rkeys[..8], &key[..16], &key[..16]); bitslice(&mut tmp, &key[8..], &key[8..]); let mut rcon = 0; let mut rk_off = 8; loop { for i in 0..8 { rkeys[rk_off + i] = (0x0f0f0f0f & (tmp[i] >> 4)) | (0xf0f0f0f0 & (rkeys[(rk_off - 8) + i] << 4)); } sub_bytes(&mut tmp); sub_bytes_nots(&mut tmp); add_round_constant_bit(&mut tmp, rcon); rcon += 1; for i in 0..8 { let mut ti = rkeys[rk_off + i]; ti ^= 0x30303030 & ror(tmp[i], ror_distance(1, 1)); ti ^= 0xc0c0c0c0 & (ti << 2); tmp[i] = ti; } rkeys[rk_off..(rk_off + 8)].copy_from_slice(&tmp); rk_off += 8; for i in 0..8 { let ui = tmp[i]; let mut ti = (0x0f0f0f0f & (rkeys[(rk_off - 16) + i] >> 4)) | (0xf0f0f0f0 & (ui << 4)); ti ^= 0x03030303 & (ui >> 6); tmp[i] = ti ^ (0xfcfcfcfc & (ti << 2)) ^ (0xf0f0f0f0 & (ti << 4)) ^ (0xc0c0c0c0 & (ti << 6)); } rkeys[rk_off..(rk_off + 8)].copy_from_slice(&tmp); rk_off += 8; sub_bytes(&mut tmp); sub_bytes_nots(&mut tmp); add_round_constant_bit(&mut tmp, rcon); rcon += 1; for i in 0..8 { let mut ti = (0x0f0f0f0f & (rkeys[(rk_off - 16) + i] >> 4)) | (0xf0f0f0f0 & (rkeys[(rk_off - 8) + i] << 4)); ti ^= 0x03030303 & ror(tmp[i], ror_distance(1, 3)); rkeys[rk_off + i] = ti ^ (0xfcfcfcfc & (ti << 2)) ^ (0xf0f0f0f0 & (ti << 4)) ^ (0xc0c0c0c0 & (ti << 6)); } rk_off += 8; if rcon >= 8 { break; } for i in 0..8 { let ui = rkeys[(rk_off - 8) + i]; let mut ti = rkeys[(rk_off - 16) + i]; ti ^= 0x30303030 & (ui >> 2); ti ^= 0xc0c0c0c0 & (ti << 2); tmp[i] = ti; } } // Adjust to match fixslicing format #[cfg(feature = "semi_fixslice")] { for i in (8..104).step_by(16) { inv_shift_rows_1(&mut rkeys[i..(i + 8)]); } } #[cfg(not(feature = "semi_fixslice"))] { for i in (0..96).step_by(32) { inv_shift_rows_1(&mut rkeys[(i + 8)..(i + 16)]); inv_shift_rows_2(&mut rkeys[(i + 16)..(i + 24)]); inv_shift_rows_3(&mut rkeys[(i + 24)..(i + 32)]); } } // Account for NOTs removed from sub_bytes for i in 1..13 { sub_bytes_nots(&mut rkeys[(i * 8)..(i * 8 + 8)]); } rkeys } /// Fully bitsliced AES-256 key schedule to match the fully-fixsliced representation. pub(crate) fn aes256_key_schedule(key: &GenericArray) -> FixsliceKeys256 { // TODO(tarcieri): use `::default()` after MSRV 1.47+ let mut rkeys = [0u32; 120]; bitslice(&mut rkeys[..8], &key[..16], &key[..16]); bitslice(&mut rkeys[8..16], &key[16..], &key[16..]); let mut rk_off = 8; let mut rcon = 0; loop { memshift32(&mut rkeys, rk_off); rk_off += 8; sub_bytes(&mut rkeys[rk_off..(rk_off + 8)]); sub_bytes_nots(&mut rkeys[rk_off..(rk_off + 8)]); add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon); xor_columns(&mut rkeys, rk_off, 16, ror_distance(1, 3)); rcon += 1; if rcon == 7 { break; } memshift32(&mut rkeys, rk_off); rk_off += 8; sub_bytes(&mut rkeys[rk_off..(rk_off + 8)]); sub_bytes_nots(&mut rkeys[rk_off..(rk_off + 8)]); xor_columns(&mut rkeys, rk_off, 16, ror_distance(0, 3)); } // Adjust to match fixslicing format #[cfg(feature = "semi_fixslice")] { for i in (8..120).step_by(16) { inv_shift_rows_1(&mut rkeys[i..(i + 8)]); } } #[cfg(not(feature = "semi_fixslice"))] { for i in (8..104).step_by(32) { inv_shift_rows_1(&mut rkeys[i..(i + 8)]); inv_shift_rows_2(&mut rkeys[(i + 8)..(i + 16)]); inv_shift_rows_3(&mut rkeys[(i + 16)..(i + 24)]); } inv_shift_rows_1(&mut rkeys[104..112]); } // Account for NOTs removed from sub_bytes for i in 1..15 { sub_bytes_nots(&mut rkeys[(i * 8)..(i * 8 + 8)]); } rkeys } /// Fully-fixsliced AES-128 decryption (the InvShiftRows is completely omitted). /// /// Decrypts four blocks in-place and in parallel. pub(crate) fn aes128_decrypt(rkeys: &FixsliceKeys128, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1]); add_round_key(&mut state, &rkeys[80..]); inv_sub_bytes(&mut state); #[cfg(not(feature = "semi_fixslice"))] { inv_shift_rows_2(&mut state); } let mut rk_off = 72; loop { #[cfg(feature = "semi_fixslice")] { inv_shift_rows_2(&mut state); } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_1(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; if rk_off == 0 { break; } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_0(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; #[cfg(not(feature = "semi_fixslice"))] { add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_3(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_2(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; } } add_round_key(&mut state, &rkeys[..8]); inv_bitslice(&mut state, blocks); } /// Fully-fixsliced AES-128 encryption (the ShiftRows is completely omitted). /// /// Encrypts four blocks in-place and in parallel. pub(crate) fn aes128_encrypt(rkeys: &FixsliceKeys128, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1]); add_round_key(&mut state, &rkeys[..8]); let mut rk_off = 8; loop { sub_bytes(&mut state); mix_columns_1(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; #[cfg(feature = "semi_fixslice")] { shift_rows_2(&mut state); } if rk_off == 80 { break; } #[cfg(not(feature = "semi_fixslice"))] { sub_bytes(&mut state); mix_columns_2(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; sub_bytes(&mut state); mix_columns_3(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } sub_bytes(&mut state); mix_columns_0(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } #[cfg(not(feature = "semi_fixslice"))] { shift_rows_2(&mut state); } sub_bytes(&mut state); add_round_key(&mut state, &rkeys[80..]); inv_bitslice(&mut state, blocks); } /// Fully-fixsliced AES-192 decryption (the InvShiftRows is completely omitted). /// /// Decrypts four blocks in-place and in parallel. pub(crate) fn aes192_decrypt(rkeys: &FixsliceKeys192, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1]); add_round_key(&mut state, &rkeys[96..]); inv_sub_bytes(&mut state); let mut rk_off = 88; loop { #[cfg(feature = "semi_fixslice")] { inv_shift_rows_2(&mut state); } #[cfg(not(feature = "semi_fixslice"))] { add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_3(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_2(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_1(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; if rk_off == 0 { break; } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_0(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; } add_round_key(&mut state, &rkeys[..8]); inv_bitslice(&mut state, blocks); } /// Fully-fixsliced AES-192 encryption (the ShiftRows is completely omitted). /// /// Encrypts four blocks in-place and in parallel. pub(crate) fn aes192_encrypt(rkeys: &FixsliceKeys192, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1]); add_round_key(&mut state, &rkeys[..8]); let mut rk_off = 8; loop { sub_bytes(&mut state); mix_columns_1(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; #[cfg(feature = "semi_fixslice")] { shift_rows_2(&mut state); } #[cfg(not(feature = "semi_fixslice"))] { sub_bytes(&mut state); mix_columns_2(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; sub_bytes(&mut state); mix_columns_3(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } if rk_off == 96 { break; } sub_bytes(&mut state); mix_columns_0(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } sub_bytes(&mut state); add_round_key(&mut state, &rkeys[96..]); inv_bitslice(&mut state, blocks); } /// Fully-fixsliced AES-256 decryption (the InvShiftRows is completely omitted). /// /// Decrypts four blocks in-place and in parallel. pub(crate) fn aes256_decrypt(rkeys: &FixsliceKeys256, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1]); add_round_key(&mut state, &rkeys[112..]); inv_sub_bytes(&mut state); #[cfg(not(feature = "semi_fixslice"))] { inv_shift_rows_2(&mut state); } let mut rk_off = 104; loop { #[cfg(feature = "semi_fixslice")] { inv_shift_rows_2(&mut state); } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_1(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; if rk_off == 0 { break; } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_0(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; #[cfg(not(feature = "semi_fixslice"))] { add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_3(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_2(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; } } add_round_key(&mut state, &rkeys[..8]); inv_bitslice(&mut state, blocks); } /// Fully-fixsliced AES-256 encryption (the ShiftRows is completely omitted). /// /// Encrypts four blocks in-place and in parallel. pub(crate) fn aes256_encrypt(rkeys: &FixsliceKeys256, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1]); add_round_key(&mut state, &rkeys[..8]); let mut rk_off = 8; loop { sub_bytes(&mut state); mix_columns_1(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; #[cfg(feature = "semi_fixslice")] { shift_rows_2(&mut state); } if rk_off == 112 { break; } #[cfg(not(feature = "semi_fixslice"))] { sub_bytes(&mut state); mix_columns_2(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; sub_bytes(&mut state); mix_columns_3(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } sub_bytes(&mut state); mix_columns_0(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } #[cfg(not(feature = "semi_fixslice"))] { shift_rows_2(&mut state); } sub_bytes(&mut state); add_round_key(&mut state, &rkeys[112..]); inv_bitslice(&mut state, blocks); } /// Note that the 4 bitwise NOT (^= 0xffffffff) are accounted for here so that it is a true /// inverse of 'sub_bytes'. fn inv_sub_bytes(state: &mut [u32]) { debug_assert_eq!(state.len(), 8); // Scheduled using https://github.com/Ko-/aes-armcortexm/tree/public/scheduler // Inline "stack" comments reflect suggested stores and loads (ARM Cortex-M3 and M4) let u7 = state[0]; let u6 = state[1]; let u5 = state[2]; let u4 = state[3]; let u3 = state[4]; let u2 = state[5]; let u1 = state[6]; let u0 = state[7]; let t23 = u0 ^ u3; let t8 = u1 ^ t23; let m2 = t23 & t8; let t4 = u4 ^ t8; let t22 = u1 ^ u3; let t2 = u0 ^ u1; let t1 = u3 ^ u4; // t23 -> stack let t9 = u7 ^ t1; // t8 -> stack let m7 = t22 & t9; // t9 -> stack let t24 = u4 ^ u7; // m7 -> stack let t10 = t2 ^ t24; // u4 -> stack let m14 = t2 & t10; let r5 = u6 ^ u7; // m2 -> stack let t3 = t1 ^ r5; // t2 -> stack let t13 = t2 ^ r5; let t19 = t22 ^ r5; // t3 -> stack let t17 = u2 ^ t19; // t4 -> stack let t25 = u2 ^ t1; let r13 = u1 ^ u6; // t25 -> stack let t20 = t24 ^ r13; // t17 -> stack let m9 = t20 & t17; // t20 -> stack let r17 = u2 ^ u5; // t22 -> stack let t6 = t22 ^ r17; // t13 -> stack let m1 = t13 & t6; let y5 = u0 ^ r17; let m4 = t19 & y5; let m5 = m4 ^ m1; let m17 = m5 ^ t24; let r18 = u5 ^ u6; let t27 = t1 ^ r18; let t15 = t10 ^ t27; // t6 -> stack let m11 = t1 & t15; let m15 = m14 ^ m11; let m21 = m17 ^ m15; // t1 -> stack // t4 <- stack let m12 = t4 & t27; let m13 = m12 ^ m11; let t14 = t10 ^ r18; let m3 = t14 ^ m1; // m2 <- stack let m16 = m3 ^ m2; let m20 = m16 ^ m13; // u4 <- stack let r19 = u2 ^ u4; let t16 = r13 ^ r19; // t3 <- stack let t26 = t3 ^ t16; let m6 = t3 & t16; let m8 = t26 ^ m6; // t10 -> stack // m7 <- stack let m18 = m8 ^ m7; let m22 = m18 ^ m13; let m25 = m22 & m20; let m26 = m21 ^ m25; let m10 = m9 ^ m6; let m19 = m10 ^ m15; // t25 <- stack let m23 = m19 ^ t25; let m28 = m23 ^ m25; let m24 = m22 ^ m23; let m30 = m26 & m24; let m39 = m23 ^ m30; let m48 = m39 & y5; let m57 = m39 & t19; // m48 -> stack let m36 = m24 ^ m25; let m31 = m20 & m23; let m27 = m20 ^ m21; let m32 = m27 & m31; let m29 = m28 & m27; let m37 = m21 ^ m29; // m39 -> stack let m42 = m37 ^ m39; let m52 = m42 & t15; // t27 -> stack // t1 <- stack let m61 = m42 & t1; let p0 = m52 ^ m61; let p16 = m57 ^ m61; // m57 -> stack // t20 <- stack let m60 = m37 & t20; // p16 -> stack // t17 <- stack let m51 = m37 & t17; let m33 = m27 ^ m25; let m38 = m32 ^ m33; let m43 = m37 ^ m38; let m49 = m43 & t16; let p6 = m49 ^ m60; let p13 = m49 ^ m51; let m58 = m43 & t3; // t9 <- stack let m50 = m38 & t9; // t22 <- stack let m59 = m38 & t22; // p6 -> stack let p1 = m58 ^ m59; let p7 = p0 ^ p1; let m34 = m21 & m22; let m35 = m24 & m34; let m40 = m35 ^ m36; let m41 = m38 ^ m40; let m45 = m42 ^ m41; // t27 <- stack let m53 = m45 & t27; let p8 = m50 ^ m53; let p23 = p7 ^ p8; // t4 <- stack let m62 = m45 & t4; let p14 = m49 ^ m62; let s6 = p14 ^ p23; // t10 <- stack let m54 = m41 & t10; let p2 = m54 ^ m62; let p22 = p2 ^ p7; let s0 = p13 ^ p22; let p17 = m58 ^ p2; let p15 = m54 ^ m59; // t2 <- stack let m63 = m41 & t2; // m39 <- stack let m44 = m39 ^ m40; // p17 -> stack // t6 <- stack let m46 = m44 & t6; let p5 = m46 ^ m51; // p23 -> stack let p18 = m63 ^ p5; let p24 = p5 ^ p7; // m48 <- stack let p12 = m46 ^ m48; let s3 = p12 ^ p22; // t13 <- stack let m55 = m44 & t13; let p9 = m55 ^ m63; // p16 <- stack let s7 = p9 ^ p16; // t8 <- stack let m47 = m40 & t8; let p3 = m47 ^ m50; let p19 = p2 ^ p3; let s5 = p19 ^ p24; let p11 = p0 ^ p3; let p26 = p9 ^ p11; // t23 <- stack let m56 = m40 & t23; let p4 = m48 ^ m56; // p6 <- stack let p20 = p4 ^ p6; let p29 = p15 ^ p20; let s1 = p26 ^ p29; // m57 <- stack let p10 = m57 ^ p4; let p27 = p10 ^ p18; // p23 <- stack let s4 = p23 ^ p27; let p25 = p6 ^ p10; let p28 = p11 ^ p25; // p17 <- stack let s2 = p17 ^ p28; state[0] = s7; state[1] = s6; state[2] = s5; state[3] = s4; state[4] = s3; state[5] = s2; state[6] = s1; state[7] = s0; } /// Bitsliced implementation of the AES Sbox based on Boyar, Peralta and Calik. /// /// See: /// /// Note that the 4 bitwise NOT (^= 0xffffffff) are moved to the key schedule. fn sub_bytes(state: &mut [u32]) { debug_assert_eq!(state.len(), 8); // Scheduled using https://github.com/Ko-/aes-armcortexm/tree/public/scheduler // Inline "stack" comments reflect suggested stores and loads (ARM Cortex-M3 and M4) let u7 = state[0]; let u6 = state[1]; let u5 = state[2]; let u4 = state[3]; let u3 = state[4]; let u2 = state[5]; let u1 = state[6]; let u0 = state[7]; let y14 = u3 ^ u5; let y13 = u0 ^ u6; let y12 = y13 ^ y14; let t1 = u4 ^ y12; let y15 = t1 ^ u5; let t2 = y12 & y15; let y6 = y15 ^ u7; let y20 = t1 ^ u1; // y12 -> stack let y9 = u0 ^ u3; // y20 -> stack let y11 = y20 ^ y9; // y9 -> stack let t12 = y9 & y11; // y6 -> stack let y7 = u7 ^ y11; let y8 = u0 ^ u5; let t0 = u1 ^ u2; let y10 = y15 ^ t0; // y15 -> stack let y17 = y10 ^ y11; // y14 -> stack let t13 = y14 & y17; let t14 = t13 ^ t12; // y17 -> stack let y19 = y10 ^ y8; // y10 -> stack let t15 = y8 & y10; let t16 = t15 ^ t12; let y16 = t0 ^ y11; // y11 -> stack let y21 = y13 ^ y16; // y13 -> stack let t7 = y13 & y16; // y16 -> stack let y18 = u0 ^ y16; let y1 = t0 ^ u7; let y4 = y1 ^ u3; // u7 -> stack let t5 = y4 & u7; let t6 = t5 ^ t2; let t18 = t6 ^ t16; let t22 = t18 ^ y19; let y2 = y1 ^ u0; let t10 = y2 & y7; let t11 = t10 ^ t7; let t20 = t11 ^ t16; let t24 = t20 ^ y18; let y5 = y1 ^ u6; let t8 = y5 & y1; let t9 = t8 ^ t7; let t19 = t9 ^ t14; let t23 = t19 ^ y21; let y3 = y5 ^ y8; // y6 <- stack let t3 = y3 & y6; let t4 = t3 ^ t2; // y20 <- stack let t17 = t4 ^ y20; let t21 = t17 ^ t14; let t26 = t21 & t23; let t27 = t24 ^ t26; let t31 = t22 ^ t26; let t25 = t21 ^ t22; // y4 -> stack let t28 = t25 & t27; let t29 = t28 ^ t22; let z14 = t29 & y2; let z5 = t29 & y7; let t30 = t23 ^ t24; let t32 = t31 & t30; let t33 = t32 ^ t24; let t35 = t27 ^ t33; let t36 = t24 & t35; let t38 = t27 ^ t36; let t39 = t29 & t38; let t40 = t25 ^ t39; let t43 = t29 ^ t40; // y16 <- stack let z3 = t43 & y16; let tc12 = z3 ^ z5; // tc12 -> stack // y13 <- stack let z12 = t43 & y13; let z13 = t40 & y5; let z4 = t40 & y1; let tc6 = z3 ^ z4; let t34 = t23 ^ t33; let t37 = t36 ^ t34; let t41 = t40 ^ t37; // y10 <- stack let z8 = t41 & y10; let z17 = t41 & y8; let t44 = t33 ^ t37; // y15 <- stack let z0 = t44 & y15; // z17 -> stack // y12 <- stack let z9 = t44 & y12; let z10 = t37 & y3; let z1 = t37 & y6; let tc5 = z1 ^ z0; let tc11 = tc6 ^ tc5; // y4 <- stack let z11 = t33 & y4; let t42 = t29 ^ t33; let t45 = t42 ^ t41; // y17 <- stack let z7 = t45 & y17; let tc8 = z7 ^ tc6; // y14 <- stack let z16 = t45 & y14; // y11 <- stack let z6 = t42 & y11; let tc16 = z6 ^ tc8; // z14 -> stack // y9 <- stack let z15 = t42 & y9; let tc20 = z15 ^ tc16; let tc1 = z15 ^ z16; let tc2 = z10 ^ tc1; let tc21 = tc2 ^ z11; let tc3 = z9 ^ tc2; let s0 = tc3 ^ tc16; let s3 = tc3 ^ tc11; let s1 = s3 ^ tc16; let tc13 = z13 ^ tc1; // u7 <- stack let z2 = t33 & u7; let tc4 = z0 ^ z2; let tc7 = z12 ^ tc4; let tc9 = z8 ^ tc7; let tc10 = tc8 ^ tc9; // z14 <- stack let tc17 = z14 ^ tc10; let s5 = tc21 ^ tc17; let tc26 = tc17 ^ tc20; // z17 <- stack let s2 = tc26 ^ z17; // tc12 <- stack let tc14 = tc4 ^ tc12; let tc18 = tc13 ^ tc14; let s6 = tc10 ^ tc18; let s7 = z12 ^ tc18; let s4 = tc14 ^ s3; state[0] = s7; state[1] = s6; state[2] = s5; state[3] = s4; state[4] = s3; state[5] = s2; state[6] = s1; state[7] = s0; } /// NOT operations that are omitted in S-box #[inline] fn sub_bytes_nots(state: &mut [u32]) { debug_assert_eq!(state.len(), 8); state[0] ^= 0xffffffff; state[1] ^= 0xffffffff; state[5] ^= 0xffffffff; state[6] ^= 0xffffffff; } /// Computation of the MixColumns transformation in the fixsliced representation, with different /// rotations used according to the round number mod 4. /// /// Based on Käsper-Schwabe, similar to https://github.com/Ko-/aes-armcortexm. macro_rules! define_mix_columns { ( $name:ident, $name_inv:ident, $first_rotate:path, $second_rotate:path ) => { #[rustfmt::skip] fn $name(state: &mut State) { let (a0, a1, a2, a3, a4, a5, a6, a7) = ( state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7] ); let (b0, b1, b2, b3, b4, b5, b6, b7) = ( $first_rotate(a0), $first_rotate(a1), $first_rotate(a2), $first_rotate(a3), $first_rotate(a4), $first_rotate(a5), $first_rotate(a6), $first_rotate(a7), ); let (c0, c1, c2, c3, c4, c5, c6, c7) = ( a0 ^ b0, a1 ^ b1, a2 ^ b2, a3 ^ b3, a4 ^ b4, a5 ^ b5, a6 ^ b6, a7 ^ b7, ); state[0] = b0 ^ c7 ^ $second_rotate(c0); state[1] = b1 ^ c0 ^ c7 ^ $second_rotate(c1); state[2] = b2 ^ c1 ^ $second_rotate(c2); state[3] = b3 ^ c2 ^ c7 ^ $second_rotate(c3); state[4] = b4 ^ c3 ^ c7 ^ $second_rotate(c4); state[5] = b5 ^ c4 ^ $second_rotate(c5); state[6] = b6 ^ c5 ^ $second_rotate(c6); state[7] = b7 ^ c6 ^ $second_rotate(c7); } #[rustfmt::skip] fn $name_inv(state: &mut State) { let (a0, a1, a2, a3, a4, a5, a6, a7) = ( state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7] ); let (b0, b1, b2, b3, b4, b5, b6, b7) = ( $first_rotate(a0), $first_rotate(a1), $first_rotate(a2), $first_rotate(a3), $first_rotate(a4), $first_rotate(a5), $first_rotate(a6), $first_rotate(a7), ); let (c0, c1, c2, c3, c4, c5, c6, c7) = ( a0 ^ b0, a1 ^ b1, a2 ^ b2, a3 ^ b3, a4 ^ b4, a5 ^ b5, a6 ^ b6, a7 ^ b7, ); let (d0, d1, d2, d3, d4, d5, d6, d7) = ( a0 ^ c7, a1 ^ c0 ^ c7, a2 ^ c1, a3 ^ c2 ^ c7, a4 ^ c3 ^ c7, a5 ^ c4, a6 ^ c5, a7 ^ c6, ); let (e0, e1, e2, e3, e4, e5, e6, e7) = ( c0 ^ d6, c1 ^ d6 ^ d7, c2 ^ d0 ^ d7, c3 ^ d1 ^ d6, c4 ^ d2 ^ d6 ^ d7, c5 ^ d3 ^ d7, c6 ^ d4, c7 ^ d5, ); state[0] = d0 ^ e0 ^ $second_rotate(e0); state[1] = d1 ^ e1 ^ $second_rotate(e1); state[2] = d2 ^ e2 ^ $second_rotate(e2); state[3] = d3 ^ e3 ^ $second_rotate(e3); state[4] = d4 ^ e4 ^ $second_rotate(e4); state[5] = d5 ^ e5 ^ $second_rotate(e5); state[6] = d6 ^ e6 ^ $second_rotate(e6); state[7] = d7 ^ e7 ^ $second_rotate(e7); } } } define_mix_columns!( mix_columns_0, inv_mix_columns_0, rotate_rows_1, rotate_rows_2 ); define_mix_columns!( mix_columns_1, inv_mix_columns_1, rotate_rows_and_columns_1_1, rotate_rows_and_columns_2_2 ); #[cfg(not(feature = "semi_fixslice"))] define_mix_columns!( mix_columns_2, inv_mix_columns_2, rotate_rows_and_columns_1_2, rotate_rows_2 ); #[cfg(not(feature = "semi_fixslice"))] define_mix_columns!( mix_columns_3, inv_mix_columns_3, rotate_rows_and_columns_1_3, rotate_rows_and_columns_2_2 ); #[inline] fn delta_swap_1(a: &mut u32, shift: u32, mask: u32) { let t = (*a ^ ((*a) >> shift)) & mask; *a ^= t ^ (t << shift); } #[inline] fn delta_swap_2(a: &mut u32, b: &mut u32, shift: u32, mask: u32) { let t = (*a ^ ((*b) >> shift)) & mask; *a ^= t; *b ^= t << shift; } /// Applies ShiftRows once on an AES state (or key). #[cfg(not(feature = "semi_fixslice"))] #[inline] fn shift_rows_1(state: &mut [u32]) { debug_assert_eq!(state.len(), 8); for x in state.iter_mut() { delta_swap_1(x, 4, 0x0c0f0300); delta_swap_1(x, 2, 0x33003300); } } /// Applies ShiftRows twice on an AES state (or key). #[inline] fn shift_rows_2(state: &mut [u32]) { debug_assert_eq!(state.len(), 8); for x in state.iter_mut() { delta_swap_1(x, 4, 0x0f000f00); } } /// Applies ShiftRows three times on an AES state (or key). #[inline] fn shift_rows_3(state: &mut [u32]) { debug_assert_eq!(state.len(), 8); for x in state.iter_mut() { delta_swap_1(x, 4, 0x030f0c00); delta_swap_1(x, 2, 0x33003300); } } #[inline(always)] fn inv_shift_rows_1(state: &mut [u32]) { shift_rows_3(state); } #[inline(always)] fn inv_shift_rows_2(state: &mut [u32]) { shift_rows_2(state); } #[cfg(not(feature = "semi_fixslice"))] #[inline(always)] fn inv_shift_rows_3(state: &mut [u32]) { shift_rows_1(state); } /// XOR the columns after the S-box during the key schedule round function. /// /// The `idx_xor` parameter refers to the index of the previous round key that is /// involved in the XOR computation (should be 8 and 16 for AES-128 and AES-256, /// respectively). /// /// The `idx_ror` parameter refers to the rotation value, which varies between the /// different key schedules. fn xor_columns(rkeys: &mut [u32], offset: usize, idx_xor: usize, idx_ror: u32) { for i in 0..8 { let off_i = offset + i; let rk = rkeys[off_i - idx_xor] ^ (0x03030303 & ror(rkeys[off_i], idx_ror)); rkeys[off_i] = rk ^ (0xfcfcfcfc & (rk << 2)) ^ (0xf0f0f0f0 & (rk << 4)) ^ (0xc0c0c0c0 & (rk << 6)); } } /// Bitslice two 128-bit input blocks input0, input1 into a 256-bit internal state. fn bitslice(output: &mut [u32], input0: &[u8], input1: &[u8]) { debug_assert_eq!(output.len(), 8); debug_assert_eq!(input0.len(), 16); debug_assert_eq!(input1.len(), 16); // Bitslicing is a bit index manipulation. 256 bits of data means each bit is positioned at an // 8-bit index. AES data is 2 blocks, each one a 4x4 column-major matrix of bytes, so the // index is initially ([b]lock, [c]olumn, [r]ow, [p]osition): // b0 c1 c0 r1 r0 p2 p1 p0 // // The desired bitsliced data groups first by bit position, then row, column, block: // p2 p1 p0 r1 r0 c1 c0 b0 // Interleave the columns on input (note the order of input) // b0 c1 c0 __ __ __ __ __ => c1 c0 b0 __ __ __ __ __ let mut t0 = u32::from_le_bytes(input0[0x00..0x04].try_into().unwrap()); let mut t2 = u32::from_le_bytes(input0[0x04..0x08].try_into().unwrap()); let mut t4 = u32::from_le_bytes(input0[0x08..0x0c].try_into().unwrap()); let mut t6 = u32::from_le_bytes(input0[0x0c..0x10].try_into().unwrap()); let mut t1 = u32::from_le_bytes(input1[0x00..0x04].try_into().unwrap()); let mut t3 = u32::from_le_bytes(input1[0x04..0x08].try_into().unwrap()); let mut t5 = u32::from_le_bytes(input1[0x08..0x0c].try_into().unwrap()); let mut t7 = u32::from_le_bytes(input1[0x0c..0x10].try_into().unwrap()); // Bit Index Swap 5 <-> 0: // __ __ b0 __ __ __ __ p0 => __ __ p0 __ __ __ __ b0 let m0 = 0x55555555; delta_swap_2(&mut t1, &mut t0, 1, m0); delta_swap_2(&mut t3, &mut t2, 1, m0); delta_swap_2(&mut t5, &mut t4, 1, m0); delta_swap_2(&mut t7, &mut t6, 1, m0); // Bit Index Swap 6 <-> 1: // __ c0 __ __ __ __ p1 __ => __ p1 __ __ __ __ c0 __ let m1 = 0x33333333; delta_swap_2(&mut t2, &mut t0, 2, m1); delta_swap_2(&mut t3, &mut t1, 2, m1); delta_swap_2(&mut t6, &mut t4, 2, m1); delta_swap_2(&mut t7, &mut t5, 2, m1); // Bit Index Swap 7 <-> 2: // c1 __ __ __ __ p2 __ __ => p2 __ __ __ __ c1 __ __ let m2 = 0x0f0f0f0f; delta_swap_2(&mut t4, &mut t0, 4, m2); delta_swap_2(&mut t5, &mut t1, 4, m2); delta_swap_2(&mut t6, &mut t2, 4, m2); delta_swap_2(&mut t7, &mut t3, 4, m2); // Final bitsliced bit index, as desired: // p2 p1 p0 r1 r0 c1 c0 b0 output[0] = t0; output[1] = t1; output[2] = t2; output[3] = t3; output[4] = t4; output[5] = t5; output[6] = t6; output[7] = t7; } /// Un-bitslice a 256-bit internal state into two 128-bit blocks of output. fn inv_bitslice(input: &mut [u32], output: &mut [Block]) { debug_assert_eq!(input.len(), 8); debug_assert_eq!(output.len(), 2); // Unbitslicing is a bit index manipulation. 256 bits of data means each bit is positioned at // an 8-bit index. AES data is 2 blocks, each one a 4x4 column-major matrix of bytes, so the // desired index for the output is ([b]lock, [c]olumn, [r]ow, [p]osition): // b0 c1 c0 r1 r0 p2 p1 p0 // // The initially bitsliced data groups first by bit position, then row, column, block: // p2 p1 p0 r1 r0 c1 c0 b0 let mut t0 = input[0]; let mut t1 = input[1]; let mut t2 = input[2]; let mut t3 = input[3]; let mut t4 = input[4]; let mut t5 = input[5]; let mut t6 = input[6]; let mut t7 = input[7]; // TODO: these bit index swaps are identical to those in 'packing' // Bit Index Swap 5 <-> 0: // __ __ p0 __ __ __ __ b0 => __ __ b0 __ __ __ __ p0 let m0 = 0x55555555; delta_swap_2(&mut t1, &mut t0, 1, m0); delta_swap_2(&mut t3, &mut t2, 1, m0); delta_swap_2(&mut t5, &mut t4, 1, m0); delta_swap_2(&mut t7, &mut t6, 1, m0); // Bit Index Swap 6 <-> 1: // __ p1 __ __ __ __ c0 __ => __ c0 __ __ __ __ p1 __ let m1 = 0x33333333; delta_swap_2(&mut t2, &mut t0, 2, m1); delta_swap_2(&mut t3, &mut t1, 2, m1); delta_swap_2(&mut t6, &mut t4, 2, m1); delta_swap_2(&mut t7, &mut t5, 2, m1); // Bit Index Swap 7 <-> 2: // p2 __ __ __ __ c1 __ __ => c1 __ __ __ __ p2 __ __ let m2 = 0x0f0f0f0f; delta_swap_2(&mut t4, &mut t0, 4, m2); delta_swap_2(&mut t5, &mut t1, 4, m2); delta_swap_2(&mut t6, &mut t2, 4, m2); delta_swap_2(&mut t7, &mut t3, 4, m2); // De-interleave the columns on output (note the order of output) // c1 c0 b0 __ __ __ __ __ => b0 c1 c0 __ __ __ __ __ output[0][0x00..0x04].copy_from_slice(&t0.to_le_bytes()); output[0][0x04..0x08].copy_from_slice(&t2.to_le_bytes()); output[0][0x08..0x0c].copy_from_slice(&t4.to_le_bytes()); output[0][0x0c..0x10].copy_from_slice(&t6.to_le_bytes()); output[1][0x00..0x04].copy_from_slice(&t1.to_le_bytes()); output[1][0x04..0x08].copy_from_slice(&t3.to_le_bytes()); output[1][0x08..0x0c].copy_from_slice(&t5.to_le_bytes()); output[1][0x0c..0x10].copy_from_slice(&t7.to_le_bytes()); // Final AES bit index, as desired: // b0 c1 c0 r1 r0 p2 p1 p0 } /// Copy 32-bytes within the provided slice to an 8-byte offset fn memshift32(buffer: &mut [u32], src_offset: usize) { debug_assert_eq!(src_offset % 8, 0); let dst_offset = src_offset + 8; debug_assert!(dst_offset + 8 <= buffer.len()); for i in (0..8).rev() { buffer[dst_offset + i] = buffer[src_offset + i]; } } /// XOR the round key to the internal state. The round keys are expected to be /// pre-computed and to be packed in the fixsliced representation. #[inline] fn add_round_key(state: &mut State, rkey: &[u32]) { debug_assert_eq!(rkey.len(), 8); for (a, b) in state.iter_mut().zip(rkey) { *a ^= b; } } #[inline(always)] fn add_round_constant_bit(state: &mut [u32], bit: usize) { state[bit] ^= 0x0000c000; } #[inline(always)] fn ror(x: u32, y: u32) -> u32 { x.rotate_right(y) } #[inline(always)] fn ror_distance(rows: u32, cols: u32) -> u32 { (rows << 3) + (cols << 1) } #[inline(always)] fn rotate_rows_1(x: u32) -> u32 { ror(x, ror_distance(1, 0)) } #[inline(always)] fn rotate_rows_2(x: u32) -> u32 { ror(x, ror_distance(2, 0)) } #[inline(always)] #[rustfmt::skip] fn rotate_rows_and_columns_1_1(x: u32) -> u32 { (ror(x, ror_distance(1, 1)) & 0x3f3f3f3f) | (ror(x, ror_distance(0, 1)) & 0xc0c0c0c0) } #[cfg(not(feature = "semi_fixslice"))] #[inline(always)] #[rustfmt::skip] fn rotate_rows_and_columns_1_2(x: u32) -> u32 { (ror(x, ror_distance(1, 2)) & 0x0f0f0f0f) | (ror(x, ror_distance(0, 2)) & 0xf0f0f0f0) } #[cfg(not(feature = "semi_fixslice"))] #[inline(always)] #[rustfmt::skip] fn rotate_rows_and_columns_1_3(x: u32) -> u32 { (ror(x, ror_distance(1, 3)) & 0x03030303) | (ror(x, ror_distance(0, 3)) & 0xfcfcfcfc) } #[inline(always)] #[rustfmt::skip] fn rotate_rows_and_columns_2_2(x: u32) -> u32 { (ror(x, ror_distance(2, 2)) & 0x0f0f0f0f) | (ror(x, ror_distance(1, 2)) & 0xf0f0f0f0) } aes-soft-0.6.4/src/fixslice64.rs010064400007650000024000001173661375324177600145730ustar 00000000000000//! Fixsliced implementations of AES-128, AES-192 and AES-256 //! adapted from the C implementation. //! //! All implementations are fully bitsliced and do not rely on any //! Look-Up Table (LUT). //! //! See the paper at for more details. //! //! # Author (original C code) //! //! Alexandre Adomnicai, Nanyang Technological University, Singapore //! //! //! Originally licensed MIT. Relicensed as Apache 2.0+MIT with permission. use crate::Block; use cipher::{ consts::{U16, U24, U32}, generic_array::GenericArray, }; /// AES block batch size for this implementation pub(crate) const FIXSLICE_BLOCKS: usize = 4; /// AES-128 round keys pub(crate) type FixsliceKeys128 = [u64; 88]; /// AES-192 round keys pub(crate) type FixsliceKeys192 = [u64; 104]; /// AES-256 round keys pub(crate) type FixsliceKeys256 = [u64; 120]; /// 512-bit internal state type State = [u64; 8]; /// Fully bitsliced AES-128 key schedule to match the fully-fixsliced representation. pub(crate) fn aes128_key_schedule(key: &GenericArray) -> FixsliceKeys128 { // TODO(tarcieri): use `::default()` after MSRV 1.47+ let mut rkeys = [0u64; 88]; bitslice(&mut rkeys[..8], key, key, key, key); let mut rk_off = 0; for rcon in 0..10 { memshift32(&mut rkeys, rk_off); rk_off += 8; sub_bytes(&mut rkeys[rk_off..(rk_off + 8)]); sub_bytes_nots(&mut rkeys[rk_off..(rk_off + 8)]); if rcon < 8 { add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon); } else { add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 8); add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 7); add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 5); add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon - 4); } xor_columns(&mut rkeys, rk_off, 8, ror_distance(1, 3)); } // Adjust to match fixslicing format #[cfg(feature = "semi_fixslice")] { for i in (8..88).step_by(16) { inv_shift_rows_1(&mut rkeys[i..(i + 8)]); } } #[cfg(not(feature = "semi_fixslice"))] { for i in (8..72).step_by(32) { inv_shift_rows_1(&mut rkeys[i..(i + 8)]); inv_shift_rows_2(&mut rkeys[(i + 8)..(i + 16)]); inv_shift_rows_3(&mut rkeys[(i + 16)..(i + 24)]); } inv_shift_rows_1(&mut rkeys[72..80]); } // Account for NOTs removed from sub_bytes for i in 1..11 { sub_bytes_nots(&mut rkeys[(i * 8)..(i * 8 + 8)]); } rkeys } /// Fully bitsliced AES-192 key schedule to match the fully-fixsliced representation. pub(crate) fn aes192_key_schedule(key: &GenericArray) -> FixsliceKeys192 { // TODO(tarcieri): use `::default()` after MSRV 1.47+ let mut rkeys = [0u64; 104]; let mut tmp = [0u64; 8]; bitslice( &mut rkeys[..8], &key[..16], &key[..16], &key[..16], &key[..16], ); bitslice(&mut tmp, &key[8..], &key[8..], &key[8..], &key[8..]); let mut rcon = 0; let mut rk_off = 8; loop { for i in 0..8 { rkeys[rk_off + i] = (0x00ff00ff00ff00ff & (tmp[i] >> 8)) | (0xff00ff00ff00ff00 & (rkeys[(rk_off - 8) + i] << 8)); } sub_bytes(&mut tmp); sub_bytes_nots(&mut tmp); add_round_constant_bit(&mut tmp, rcon); rcon += 1; for i in 0..8 { let mut ti = rkeys[rk_off + i]; ti ^= 0x0f000f000f000f00 & ror(tmp[i], ror_distance(1, 1)); ti ^= 0xf000f000f000f000 & (ti << 4); tmp[i] = ti; } rkeys[rk_off..(rk_off + 8)].copy_from_slice(&tmp); rk_off += 8; for i in 0..8 { let ui = tmp[i]; let mut ti = (0x00ff00ff00ff00ff & (rkeys[(rk_off - 16) + i] >> 8)) | (0xff00ff00ff00ff00 & (ui << 8)); ti ^= 0x000f000f000f000f & (ui >> 12); tmp[i] = ti ^ (0xfff0fff0fff0fff0 & (ti << 4)) ^ (0xff00ff00ff00ff00 & (ti << 8)) ^ (0xf000f000f000f000 & (ti << 12)); } rkeys[rk_off..(rk_off + 8)].copy_from_slice(&tmp); rk_off += 8; sub_bytes(&mut tmp); sub_bytes_nots(&mut tmp); add_round_constant_bit(&mut tmp, rcon); rcon += 1; for i in 0..8 { let mut ti = (0x00ff00ff00ff00ff & (rkeys[(rk_off - 16) + i] >> 8)) | (0xff00ff00ff00ff00 & (rkeys[(rk_off - 8) + i] << 8)); ti ^= 0x000f000f000f000f & ror(tmp[i], ror_distance(1, 3)); rkeys[rk_off + i] = ti ^ (0xfff0fff0fff0fff0 & (ti << 4)) ^ (0xff00ff00ff00ff00 & (ti << 8)) ^ (0xf000f000f000f000 & (ti << 12)); } rk_off += 8; if rcon >= 8 { break; } for i in 0..8 { let ui = rkeys[(rk_off - 8) + i]; let mut ti = rkeys[(rk_off - 16) + i]; ti ^= 0x0f000f000f000f00 & (ui >> 4); ti ^= 0xf000f000f000f000 & (ti << 4); tmp[i] = ti; } } // Adjust to match fixslicing format #[cfg(feature = "semi_fixslice")] { for i in (8..104).step_by(16) { inv_shift_rows_1(&mut rkeys[i..(i + 8)]); } } #[cfg(not(feature = "semi_fixslice"))] { for i in (0..96).step_by(32) { inv_shift_rows_1(&mut rkeys[(i + 8)..(i + 16)]); inv_shift_rows_2(&mut rkeys[(i + 16)..(i + 24)]); inv_shift_rows_3(&mut rkeys[(i + 24)..(i + 32)]); } } // Account for NOTs removed from sub_bytes for i in 1..13 { sub_bytes_nots(&mut rkeys[(i * 8)..(i * 8 + 8)]); } rkeys } /// Fully bitsliced AES-256 key schedule to match the fully-fixsliced representation. pub(crate) fn aes256_key_schedule(key: &GenericArray) -> FixsliceKeys256 { // TODO(tarcieri): use `::default()` after MSRV 1.47+ let mut rkeys = [0u64; 120]; bitslice( &mut rkeys[..8], &key[..16], &key[..16], &key[..16], &key[..16], ); bitslice( &mut rkeys[8..16], &key[16..], &key[16..], &key[16..], &key[16..], ); let mut rk_off = 8; let mut rcon = 0; loop { memshift32(&mut rkeys, rk_off); rk_off += 8; sub_bytes(&mut rkeys[rk_off..(rk_off + 8)]); sub_bytes_nots(&mut rkeys[rk_off..(rk_off + 8)]); add_round_constant_bit(&mut rkeys[rk_off..(rk_off + 8)], rcon); xor_columns(&mut rkeys, rk_off, 16, ror_distance(1, 3)); rcon += 1; if rcon == 7 { break; } memshift32(&mut rkeys, rk_off); rk_off += 8; sub_bytes(&mut rkeys[rk_off..(rk_off + 8)]); sub_bytes_nots(&mut rkeys[rk_off..(rk_off + 8)]); xor_columns(&mut rkeys, rk_off, 16, ror_distance(0, 3)); } // Adjust to match fixslicing format #[cfg(feature = "semi_fixslice")] { for i in (8..120).step_by(16) { inv_shift_rows_1(&mut rkeys[i..(i + 8)]); } } #[cfg(not(feature = "semi_fixslice"))] { for i in (8..104).step_by(32) { inv_shift_rows_1(&mut rkeys[i..(i + 8)]); inv_shift_rows_2(&mut rkeys[(i + 8)..(i + 16)]); inv_shift_rows_3(&mut rkeys[(i + 16)..(i + 24)]); } inv_shift_rows_1(&mut rkeys[104..112]); } // Account for NOTs removed from sub_bytes for i in 1..15 { sub_bytes_nots(&mut rkeys[(i * 8)..(i * 8 + 8)]); } rkeys } /// Fully-fixsliced AES-128 decryption (the InvShiftRows is completely omitted). /// /// Decrypts four blocks in-place and in parallel. pub(crate) fn aes128_decrypt(rkeys: &FixsliceKeys128, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); add_round_key(&mut state, &rkeys[80..]); inv_sub_bytes(&mut state); #[cfg(not(feature = "semi_fixslice"))] { inv_shift_rows_2(&mut state); } let mut rk_off = 72; loop { #[cfg(feature = "semi_fixslice")] { inv_shift_rows_2(&mut state); } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_1(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; if rk_off == 0 { break; } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_0(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; #[cfg(not(feature = "semi_fixslice"))] { add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_3(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_2(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; } } add_round_key(&mut state, &rkeys[..8]); inv_bitslice(&mut state, blocks); } /// Fully-fixsliced AES-128 encryption (the ShiftRows is completely omitted). /// /// Encrypts four blocks in-place and in parallel. pub(crate) fn aes128_encrypt(rkeys: &FixsliceKeys128, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); add_round_key(&mut state, &rkeys[..8]); let mut rk_off = 8; loop { sub_bytes(&mut state); mix_columns_1(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; #[cfg(feature = "semi_fixslice")] { shift_rows_2(&mut state); } if rk_off == 80 { break; } #[cfg(not(feature = "semi_fixslice"))] { sub_bytes(&mut state); mix_columns_2(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; sub_bytes(&mut state); mix_columns_3(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } sub_bytes(&mut state); mix_columns_0(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } #[cfg(not(feature = "semi_fixslice"))] { shift_rows_2(&mut state); } sub_bytes(&mut state); add_round_key(&mut state, &rkeys[80..]); inv_bitslice(&mut state, blocks); } /// Fully-fixsliced AES-192 decryption (the InvShiftRows is completely omitted). /// /// Decrypts four blocks in-place and in parallel. pub(crate) fn aes192_decrypt(rkeys: &FixsliceKeys192, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); add_round_key(&mut state, &rkeys[96..]); inv_sub_bytes(&mut state); let mut rk_off = 88; loop { #[cfg(feature = "semi_fixslice")] { inv_shift_rows_2(&mut state); } #[cfg(not(feature = "semi_fixslice"))] { add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_3(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_2(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_1(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; if rk_off == 0 { break; } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_0(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; } add_round_key(&mut state, &rkeys[..8]); inv_bitslice(&mut state, blocks); } /// Fully-fixsliced AES-192 encryption (the ShiftRows is completely omitted). /// /// Encrypts four blocks in-place and in parallel. pub(crate) fn aes192_encrypt(rkeys: &FixsliceKeys192, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); add_round_key(&mut state, &rkeys[..8]); let mut rk_off = 8; loop { sub_bytes(&mut state); mix_columns_1(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; #[cfg(feature = "semi_fixslice")] { shift_rows_2(&mut state); } #[cfg(not(feature = "semi_fixslice"))] { sub_bytes(&mut state); mix_columns_2(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; sub_bytes(&mut state); mix_columns_3(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } if rk_off == 96 { break; } sub_bytes(&mut state); mix_columns_0(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } sub_bytes(&mut state); add_round_key(&mut state, &rkeys[96..]); inv_bitslice(&mut state, blocks); } /// Fully-fixsliced AES-256 decryption (the InvShiftRows is completely omitted). /// /// Decrypts four blocks in-place and in parallel. pub(crate) fn aes256_decrypt(rkeys: &FixsliceKeys256, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); add_round_key(&mut state, &rkeys[112..]); inv_sub_bytes(&mut state); #[cfg(not(feature = "semi_fixslice"))] { inv_shift_rows_2(&mut state); } let mut rk_off = 104; loop { #[cfg(feature = "semi_fixslice")] { inv_shift_rows_2(&mut state); } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_1(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; if rk_off == 0 { break; } add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_0(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; #[cfg(not(feature = "semi_fixslice"))] { add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_3(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); inv_mix_columns_2(&mut state); inv_sub_bytes(&mut state); rk_off -= 8; } } add_round_key(&mut state, &rkeys[..8]); inv_bitslice(&mut state, blocks); } /// Fully-fixsliced AES-256 encryption (the ShiftRows is completely omitted). /// /// Encrypts four blocks in-place and in parallel. pub(crate) fn aes256_encrypt(rkeys: &FixsliceKeys256, blocks: &mut [Block]) { debug_assert_eq!(blocks.len(), FIXSLICE_BLOCKS); let mut state = State::default(); bitslice(&mut state, &blocks[0], &blocks[1], &blocks[2], &blocks[3]); add_round_key(&mut state, &rkeys[..8]); let mut rk_off = 8; loop { sub_bytes(&mut state); mix_columns_1(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; #[cfg(feature = "semi_fixslice")] { shift_rows_2(&mut state); } if rk_off == 112 { break; } #[cfg(not(feature = "semi_fixslice"))] { sub_bytes(&mut state); mix_columns_2(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; sub_bytes(&mut state); mix_columns_3(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } sub_bytes(&mut state); mix_columns_0(&mut state); add_round_key(&mut state, &rkeys[rk_off..(rk_off + 8)]); rk_off += 8; } #[cfg(not(feature = "semi_fixslice"))] { shift_rows_2(&mut state); } sub_bytes(&mut state); add_round_key(&mut state, &rkeys[112..]); inv_bitslice(&mut state, blocks); } /// Note that the 4 bitwise NOT (^= 0xffffffffffffffff) are accounted for here so that it is a true /// inverse of 'sub_bytes'. fn inv_sub_bytes(state: &mut [u64]) { debug_assert_eq!(state.len(), 8); // Scheduled using https://github.com/Ko-/aes-armcortexm/tree/public/scheduler // Inline "stack" comments reflect suggested stores and loads (ARM Cortex-M3 and M4) let u7 = state[0]; let u6 = state[1]; let u5 = state[2]; let u4 = state[3]; let u3 = state[4]; let u2 = state[5]; let u1 = state[6]; let u0 = state[7]; let t23 = u0 ^ u3; let t8 = u1 ^ t23; let m2 = t23 & t8; let t4 = u4 ^ t8; let t22 = u1 ^ u3; let t2 = u0 ^ u1; let t1 = u3 ^ u4; // t23 -> stack let t9 = u7 ^ t1; // t8 -> stack let m7 = t22 & t9; // t9 -> stack let t24 = u4 ^ u7; // m7 -> stack let t10 = t2 ^ t24; // u4 -> stack let m14 = t2 & t10; let r5 = u6 ^ u7; // m2 -> stack let t3 = t1 ^ r5; // t2 -> stack let t13 = t2 ^ r5; let t19 = t22 ^ r5; // t3 -> stack let t17 = u2 ^ t19; // t4 -> stack let t25 = u2 ^ t1; let r13 = u1 ^ u6; // t25 -> stack let t20 = t24 ^ r13; // t17 -> stack let m9 = t20 & t17; // t20 -> stack let r17 = u2 ^ u5; // t22 -> stack let t6 = t22 ^ r17; // t13 -> stack let m1 = t13 & t6; let y5 = u0 ^ r17; let m4 = t19 & y5; let m5 = m4 ^ m1; let m17 = m5 ^ t24; let r18 = u5 ^ u6; let t27 = t1 ^ r18; let t15 = t10 ^ t27; // t6 -> stack let m11 = t1 & t15; let m15 = m14 ^ m11; let m21 = m17 ^ m15; // t1 -> stack // t4 <- stack let m12 = t4 & t27; let m13 = m12 ^ m11; let t14 = t10 ^ r18; let m3 = t14 ^ m1; // m2 <- stack let m16 = m3 ^ m2; let m20 = m16 ^ m13; // u4 <- stack let r19 = u2 ^ u4; let t16 = r13 ^ r19; // t3 <- stack let t26 = t3 ^ t16; let m6 = t3 & t16; let m8 = t26 ^ m6; // t10 -> stack // m7 <- stack let m18 = m8 ^ m7; let m22 = m18 ^ m13; let m25 = m22 & m20; let m26 = m21 ^ m25; let m10 = m9 ^ m6; let m19 = m10 ^ m15; // t25 <- stack let m23 = m19 ^ t25; let m28 = m23 ^ m25; let m24 = m22 ^ m23; let m30 = m26 & m24; let m39 = m23 ^ m30; let m48 = m39 & y5; let m57 = m39 & t19; // m48 -> stack let m36 = m24 ^ m25; let m31 = m20 & m23; let m27 = m20 ^ m21; let m32 = m27 & m31; let m29 = m28 & m27; let m37 = m21 ^ m29; // m39 -> stack let m42 = m37 ^ m39; let m52 = m42 & t15; // t27 -> stack // t1 <- stack let m61 = m42 & t1; let p0 = m52 ^ m61; let p16 = m57 ^ m61; // m57 -> stack // t20 <- stack let m60 = m37 & t20; // p16 -> stack // t17 <- stack let m51 = m37 & t17; let m33 = m27 ^ m25; let m38 = m32 ^ m33; let m43 = m37 ^ m38; let m49 = m43 & t16; let p6 = m49 ^ m60; let p13 = m49 ^ m51; let m58 = m43 & t3; // t9 <- stack let m50 = m38 & t9; // t22 <- stack let m59 = m38 & t22; // p6 -> stack let p1 = m58 ^ m59; let p7 = p0 ^ p1; let m34 = m21 & m22; let m35 = m24 & m34; let m40 = m35 ^ m36; let m41 = m38 ^ m40; let m45 = m42 ^ m41; // t27 <- stack let m53 = m45 & t27; let p8 = m50 ^ m53; let p23 = p7 ^ p8; // t4 <- stack let m62 = m45 & t4; let p14 = m49 ^ m62; let s6 = p14 ^ p23; // t10 <- stack let m54 = m41 & t10; let p2 = m54 ^ m62; let p22 = p2 ^ p7; let s0 = p13 ^ p22; let p17 = m58 ^ p2; let p15 = m54 ^ m59; // t2 <- stack let m63 = m41 & t2; // m39 <- stack let m44 = m39 ^ m40; // p17 -> stack // t6 <- stack let m46 = m44 & t6; let p5 = m46 ^ m51; // p23 -> stack let p18 = m63 ^ p5; let p24 = p5 ^ p7; // m48 <- stack let p12 = m46 ^ m48; let s3 = p12 ^ p22; // t13 <- stack let m55 = m44 & t13; let p9 = m55 ^ m63; // p16 <- stack let s7 = p9 ^ p16; // t8 <- stack let m47 = m40 & t8; let p3 = m47 ^ m50; let p19 = p2 ^ p3; let s5 = p19 ^ p24; let p11 = p0 ^ p3; let p26 = p9 ^ p11; // t23 <- stack let m56 = m40 & t23; let p4 = m48 ^ m56; // p6 <- stack let p20 = p4 ^ p6; let p29 = p15 ^ p20; let s1 = p26 ^ p29; // m57 <- stack let p10 = m57 ^ p4; let p27 = p10 ^ p18; // p23 <- stack let s4 = p23 ^ p27; let p25 = p6 ^ p10; let p28 = p11 ^ p25; // p17 <- stack let s2 = p17 ^ p28; state[0] = s7; state[1] = s6; state[2] = s5; state[3] = s4; state[4] = s3; state[5] = s2; state[6] = s1; state[7] = s0; } /// Bitsliced implementation of the AES Sbox based on Boyar, Peralta and Calik. /// /// See: /// /// Note that the 4 bitwise NOT (^= 0xffffffffffffffff) are moved to the key schedule. fn sub_bytes(state: &mut [u64]) { debug_assert_eq!(state.len(), 8); // Scheduled using https://github.com/Ko-/aes-armcortexm/tree/public/scheduler // Inline "stack" comments reflect suggested stores and loads (ARM Cortex-M3 and M4) let u7 = state[0]; let u6 = state[1]; let u5 = state[2]; let u4 = state[3]; let u3 = state[4]; let u2 = state[5]; let u1 = state[6]; let u0 = state[7]; let y14 = u3 ^ u5; let y13 = u0 ^ u6; let y12 = y13 ^ y14; let t1 = u4 ^ y12; let y15 = t1 ^ u5; let t2 = y12 & y15; let y6 = y15 ^ u7; let y20 = t1 ^ u1; // y12 -> stack let y9 = u0 ^ u3; // y20 -> stack let y11 = y20 ^ y9; // y9 -> stack let t12 = y9 & y11; // y6 -> stack let y7 = u7 ^ y11; let y8 = u0 ^ u5; let t0 = u1 ^ u2; let y10 = y15 ^ t0; // y15 -> stack let y17 = y10 ^ y11; // y14 -> stack let t13 = y14 & y17; let t14 = t13 ^ t12; // y17 -> stack let y19 = y10 ^ y8; // y10 -> stack let t15 = y8 & y10; let t16 = t15 ^ t12; let y16 = t0 ^ y11; // y11 -> stack let y21 = y13 ^ y16; // y13 -> stack let t7 = y13 & y16; // y16 -> stack let y18 = u0 ^ y16; let y1 = t0 ^ u7; let y4 = y1 ^ u3; // u7 -> stack let t5 = y4 & u7; let t6 = t5 ^ t2; let t18 = t6 ^ t16; let t22 = t18 ^ y19; let y2 = y1 ^ u0; let t10 = y2 & y7; let t11 = t10 ^ t7; let t20 = t11 ^ t16; let t24 = t20 ^ y18; let y5 = y1 ^ u6; let t8 = y5 & y1; let t9 = t8 ^ t7; let t19 = t9 ^ t14; let t23 = t19 ^ y21; let y3 = y5 ^ y8; // y6 <- stack let t3 = y3 & y6; let t4 = t3 ^ t2; // y20 <- stack let t17 = t4 ^ y20; let t21 = t17 ^ t14; let t26 = t21 & t23; let t27 = t24 ^ t26; let t31 = t22 ^ t26; let t25 = t21 ^ t22; // y4 -> stack let t28 = t25 & t27; let t29 = t28 ^ t22; let z14 = t29 & y2; let z5 = t29 & y7; let t30 = t23 ^ t24; let t32 = t31 & t30; let t33 = t32 ^ t24; let t35 = t27 ^ t33; let t36 = t24 & t35; let t38 = t27 ^ t36; let t39 = t29 & t38; let t40 = t25 ^ t39; let t43 = t29 ^ t40; // y16 <- stack let z3 = t43 & y16; let tc12 = z3 ^ z5; // tc12 -> stack // y13 <- stack let z12 = t43 & y13; let z13 = t40 & y5; let z4 = t40 & y1; let tc6 = z3 ^ z4; let t34 = t23 ^ t33; let t37 = t36 ^ t34; let t41 = t40 ^ t37; // y10 <- stack let z8 = t41 & y10; let z17 = t41 & y8; let t44 = t33 ^ t37; // y15 <- stack let z0 = t44 & y15; // z17 -> stack // y12 <- stack let z9 = t44 & y12; let z10 = t37 & y3; let z1 = t37 & y6; let tc5 = z1 ^ z0; let tc11 = tc6 ^ tc5; // y4 <- stack let z11 = t33 & y4; let t42 = t29 ^ t33; let t45 = t42 ^ t41; // y17 <- stack let z7 = t45 & y17; let tc8 = z7 ^ tc6; // y14 <- stack let z16 = t45 & y14; // y11 <- stack let z6 = t42 & y11; let tc16 = z6 ^ tc8; // z14 -> stack // y9 <- stack let z15 = t42 & y9; let tc20 = z15 ^ tc16; let tc1 = z15 ^ z16; let tc2 = z10 ^ tc1; let tc21 = tc2 ^ z11; let tc3 = z9 ^ tc2; let s0 = tc3 ^ tc16; let s3 = tc3 ^ tc11; let s1 = s3 ^ tc16; let tc13 = z13 ^ tc1; // u7 <- stack let z2 = t33 & u7; let tc4 = z0 ^ z2; let tc7 = z12 ^ tc4; let tc9 = z8 ^ tc7; let tc10 = tc8 ^ tc9; // z14 <- stack let tc17 = z14 ^ tc10; let s5 = tc21 ^ tc17; let tc26 = tc17 ^ tc20; // z17 <- stack let s2 = tc26 ^ z17; // tc12 <- stack let tc14 = tc4 ^ tc12; let tc18 = tc13 ^ tc14; let s6 = tc10 ^ tc18; let s7 = z12 ^ tc18; let s4 = tc14 ^ s3; state[0] = s7; state[1] = s6; state[2] = s5; state[3] = s4; state[4] = s3; state[5] = s2; state[6] = s1; state[7] = s0; } /// NOT operations that are omitted in S-box #[inline] fn sub_bytes_nots(state: &mut [u64]) { debug_assert_eq!(state.len(), 8); state[0] ^= 0xffffffffffffffff; state[1] ^= 0xffffffffffffffff; state[5] ^= 0xffffffffffffffff; state[6] ^= 0xffffffffffffffff; } /// Computation of the MixColumns transformation in the fixsliced representation, with different /// rotations used according to the round number mod 4. /// /// Based on Käsper-Schwabe, similar to https://github.com/Ko-/aes-armcortexm. macro_rules! define_mix_columns { ( $name:ident, $name_inv:ident, $first_rotate:path, $second_rotate:path ) => { #[rustfmt::skip] fn $name(state: &mut State) { let (a0, a1, a2, a3, a4, a5, a6, a7) = ( state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7] ); let (b0, b1, b2, b3, b4, b5, b6, b7) = ( $first_rotate(a0), $first_rotate(a1), $first_rotate(a2), $first_rotate(a3), $first_rotate(a4), $first_rotate(a5), $first_rotate(a6), $first_rotate(a7), ); let (c0, c1, c2, c3, c4, c5, c6, c7) = ( a0 ^ b0, a1 ^ b1, a2 ^ b2, a3 ^ b3, a4 ^ b4, a5 ^ b5, a6 ^ b6, a7 ^ b7, ); state[0] = b0 ^ c7 ^ $second_rotate(c0); state[1] = b1 ^ c0 ^ c7 ^ $second_rotate(c1); state[2] = b2 ^ c1 ^ $second_rotate(c2); state[3] = b3 ^ c2 ^ c7 ^ $second_rotate(c3); state[4] = b4 ^ c3 ^ c7 ^ $second_rotate(c4); state[5] = b5 ^ c4 ^ $second_rotate(c5); state[6] = b6 ^ c5 ^ $second_rotate(c6); state[7] = b7 ^ c6 ^ $second_rotate(c7); } #[rustfmt::skip] fn $name_inv(state: &mut State) { let (a0, a1, a2, a3, a4, a5, a6, a7) = ( state[0], state[1], state[2], state[3], state[4], state[5], state[6], state[7] ); let (b0, b1, b2, b3, b4, b5, b6, b7) = ( $first_rotate(a0), $first_rotate(a1), $first_rotate(a2), $first_rotate(a3), $first_rotate(a4), $first_rotate(a5), $first_rotate(a6), $first_rotate(a7), ); let (c0, c1, c2, c3, c4, c5, c6, c7) = ( a0 ^ b0, a1 ^ b1, a2 ^ b2, a3 ^ b3, a4 ^ b4, a5 ^ b5, a6 ^ b6, a7 ^ b7, ); let (d0, d1, d2, d3, d4, d5, d6, d7) = ( a0 ^ c7, a1 ^ c0 ^ c7, a2 ^ c1, a3 ^ c2 ^ c7, a4 ^ c3 ^ c7, a5 ^ c4, a6 ^ c5, a7 ^ c6, ); let (e0, e1, e2, e3, e4, e5, e6, e7) = ( c0 ^ d6, c1 ^ d6 ^ d7, c2 ^ d0 ^ d7, c3 ^ d1 ^ d6, c4 ^ d2 ^ d6 ^ d7, c5 ^ d3 ^ d7, c6 ^ d4, c7 ^ d5, ); state[0] = d0 ^ e0 ^ $second_rotate(e0); state[1] = d1 ^ e1 ^ $second_rotate(e1); state[2] = d2 ^ e2 ^ $second_rotate(e2); state[3] = d3 ^ e3 ^ $second_rotate(e3); state[4] = d4 ^ e4 ^ $second_rotate(e4); state[5] = d5 ^ e5 ^ $second_rotate(e5); state[6] = d6 ^ e6 ^ $second_rotate(e6); state[7] = d7 ^ e7 ^ $second_rotate(e7); } } } define_mix_columns!( mix_columns_0, inv_mix_columns_0, rotate_rows_1, rotate_rows_2 ); define_mix_columns!( mix_columns_1, inv_mix_columns_1, rotate_rows_and_columns_1_1, rotate_rows_and_columns_2_2 ); #[cfg(not(feature = "semi_fixslice"))] define_mix_columns!( mix_columns_2, inv_mix_columns_2, rotate_rows_and_columns_1_2, rotate_rows_2 ); #[cfg(not(feature = "semi_fixslice"))] define_mix_columns!( mix_columns_3, inv_mix_columns_3, rotate_rows_and_columns_1_3, rotate_rows_and_columns_2_2 ); #[inline] fn delta_swap_1(a: &mut u64, shift: u32, mask: u64) { let t = (*a ^ ((*a) >> shift)) & mask; *a ^= t ^ (t << shift); } #[inline] fn delta_swap_2(a: &mut u64, b: &mut u64, shift: u32, mask: u64) { let t = (*a ^ ((*b) >> shift)) & mask; *a ^= t; *b ^= t << shift; } /// Applies ShiftRows once on an AES state (or key). #[cfg(not(feature = "semi_fixslice"))] #[inline] fn shift_rows_1(state: &mut [u64]) { debug_assert_eq!(state.len(), 8); for x in state.iter_mut() { delta_swap_1(x, 8, 0x00f000ff000f0000); delta_swap_1(x, 4, 0x0f0f00000f0f0000); } } /// Applies ShiftRows twice on an AES state (or key). #[inline] fn shift_rows_2(state: &mut [u64]) { debug_assert_eq!(state.len(), 8); for x in state.iter_mut() { delta_swap_1(x, 8, 0x00ff000000ff0000); } } /// Applies ShiftRows three times on an AES state (or key). #[inline] fn shift_rows_3(state: &mut [u64]) { debug_assert_eq!(state.len(), 8); for x in state.iter_mut() { delta_swap_1(x, 8, 0x000f00ff00f00000); delta_swap_1(x, 4, 0x0f0f00000f0f0000); } } #[inline(always)] fn inv_shift_rows_1(state: &mut [u64]) { shift_rows_3(state); } #[inline(always)] fn inv_shift_rows_2(state: &mut [u64]) { shift_rows_2(state); } #[cfg(not(feature = "semi_fixslice"))] #[inline(always)] fn inv_shift_rows_3(state: &mut [u64]) { shift_rows_1(state); } /// XOR the columns after the S-box during the key schedule round function. /// /// The `idx_xor` parameter refers to the index of the previous round key that is /// involved in the XOR computation (should be 8 and 16 for AES-128 and AES-256, /// respectively). /// /// The `idx_ror` parameter refers to the rotation value, which varies between the /// different key schedules. fn xor_columns(rkeys: &mut [u64], offset: usize, idx_xor: usize, idx_ror: u32) { for i in 0..8 { let off_i = offset + i; let rk = rkeys[off_i - idx_xor] ^ (0x000f000f000f000f & ror(rkeys[off_i], idx_ror)); rkeys[off_i] = rk ^ (0xfff0fff0fff0fff0 & (rk << 4)) ^ (0xff00ff00ff00ff00 & (rk << 8)) ^ (0xf000f000f000f000 & (rk << 12)); } } /// Bitslice four 128-bit input blocks input0, input1, input2, input3 into a 512-bit internal state. fn bitslice(output: &mut [u64], input0: &[u8], input1: &[u8], input2: &[u8], input3: &[u8]) { debug_assert_eq!(output.len(), 8); debug_assert_eq!(input0.len(), 16); debug_assert_eq!(input1.len(), 16); debug_assert_eq!(input2.len(), 16); debug_assert_eq!(input3.len(), 16); // Bitslicing is a bit index manipulation. 512 bits of data means each bit is positioned at a // 9-bit index. AES data is 4 blocks, each one a 4x4 column-major matrix of bytes, so the // index is initially ([b]lock, [c]olumn, [r]ow, [p]osition): // b1 b0 c1 c0 r1 r0 p2 p1 p0 // // The desired bitsliced data groups first by bit position, then row, column, block: // p2 p1 p0 r1 r0 c1 c0 b1 b0 #[rustfmt::skip] fn read_reordered(input: &[u8]) -> u64 { (u64::from(input[0x0]) ) | (u64::from(input[0x1]) << 0x10) | (u64::from(input[0x2]) << 0x20) | (u64::from(input[0x3]) << 0x30) | (u64::from(input[0x8]) << 0x08) | (u64::from(input[0x9]) << 0x18) | (u64::from(input[0xa]) << 0x28) | (u64::from(input[0xb]) << 0x38) } // Reorder each block's bytes on input // __ __ c1 c0 r1 r0 __ __ __ => __ __ c0 r1 r0 c1 __ __ __ // Reorder by relabeling (note the order of input) // b1 b0 c0 __ __ __ __ __ __ => c0 b1 b0 __ __ __ __ __ __ let mut t0 = read_reordered(&input0[0x00..0x0c]); let mut t4 = read_reordered(&input0[0x04..0x10]); let mut t1 = read_reordered(&input1[0x00..0x0c]); let mut t5 = read_reordered(&input1[0x04..0x10]); let mut t2 = read_reordered(&input2[0x00..0x0c]); let mut t6 = read_reordered(&input2[0x04..0x10]); let mut t3 = read_reordered(&input3[0x00..0x0c]); let mut t7 = read_reordered(&input3[0x04..0x10]); // Bit Index Swap 6 <-> 0: // __ __ b0 __ __ __ __ __ p0 => __ __ p0 __ __ __ __ __ b0 let m0 = 0x5555555555555555; delta_swap_2(&mut t1, &mut t0, 1, m0); delta_swap_2(&mut t3, &mut t2, 1, m0); delta_swap_2(&mut t5, &mut t4, 1, m0); delta_swap_2(&mut t7, &mut t6, 1, m0); // Bit Index Swap 7 <-> 1: // __ b1 __ __ __ __ __ p1 __ => __ p1 __ __ __ __ __ b1 __ let m1 = 0x3333333333333333; delta_swap_2(&mut t2, &mut t0, 2, m1); delta_swap_2(&mut t3, &mut t1, 2, m1); delta_swap_2(&mut t6, &mut t4, 2, m1); delta_swap_2(&mut t7, &mut t5, 2, m1); // Bit Index Swap 8 <-> 2: // c0 __ __ __ __ __ p2 __ __ => p2 __ __ __ __ __ c0 __ __ let m2 = 0x0f0f0f0f0f0f0f0f; delta_swap_2(&mut t4, &mut t0, 4, m2); delta_swap_2(&mut t5, &mut t1, 4, m2); delta_swap_2(&mut t6, &mut t2, 4, m2); delta_swap_2(&mut t7, &mut t3, 4, m2); // Final bitsliced bit index, as desired: // p2 p1 p0 r1 r0 c1 c0 b1 b0 output[0] = t0; output[1] = t1; output[2] = t2; output[3] = t3; output[4] = t4; output[5] = t5; output[6] = t6; output[7] = t7; } /// Un-bitslice a 512-bit internal state into four 128-bit blocks of output. fn inv_bitslice(input: &mut [u64], output: &mut [Block]) { debug_assert_eq!(input.len(), 8); debug_assert_eq!(output.len(), 4); // Unbitslicing is a bit index manipulation. 512 bits of data means each bit is positioned at // a 9-bit index. AES data is 4 blocks, each one a 4x4 column-major matrix of bytes, so the // desired index for the output is ([b]lock, [c]olumn, [r]ow, [p]osition): // b1 b0 c1 c0 r1 r0 p2 p1 p0 // // The initially bitsliced data groups first by bit position, then row, column, block: // p2 p1 p0 r1 r0 c1 c0 b1 b0 let mut t0 = input[0]; let mut t1 = input[1]; let mut t2 = input[2]; let mut t3 = input[3]; let mut t4 = input[4]; let mut t5 = input[5]; let mut t6 = input[6]; let mut t7 = input[7]; // TODO: these bit index swaps are identical to those in 'packing' // Bit Index Swap 6 <-> 0: // __ __ p0 __ __ __ __ __ b0 => __ __ b0 __ __ __ __ __ p0 let m0 = 0x5555555555555555; delta_swap_2(&mut t1, &mut t0, 1, m0); delta_swap_2(&mut t3, &mut t2, 1, m0); delta_swap_2(&mut t5, &mut t4, 1, m0); delta_swap_2(&mut t7, &mut t6, 1, m0); // Bit Index Swap 7 <-> 1: // __ p1 __ __ __ __ __ b1 __ => __ b1 __ __ __ __ __ p1 __ let m1 = 0x3333333333333333; delta_swap_2(&mut t2, &mut t0, 2, m1); delta_swap_2(&mut t3, &mut t1, 2, m1); delta_swap_2(&mut t6, &mut t4, 2, m1); delta_swap_2(&mut t7, &mut t5, 2, m1); // Bit Index Swap 8 <-> 2: // p2 __ __ __ __ __ c0 __ __ => c0 __ __ __ __ __ p2 __ __ let m2 = 0x0f0f0f0f0f0f0f0f; delta_swap_2(&mut t4, &mut t0, 4, m2); delta_swap_2(&mut t5, &mut t1, 4, m2); delta_swap_2(&mut t6, &mut t2, 4, m2); delta_swap_2(&mut t7, &mut t3, 4, m2); #[rustfmt::skip] fn write_reordered(columns: u64, output: &mut [u8]) { output[0x0] = (columns ) as u8; output[0x1] = (columns >> 0x10) as u8; output[0x2] = (columns >> 0x20) as u8; output[0x3] = (columns >> 0x30) as u8; output[0x8] = (columns >> 0x08) as u8; output[0x9] = (columns >> 0x18) as u8; output[0xa] = (columns >> 0x28) as u8; output[0xb] = (columns >> 0x38) as u8; } // Reorder by relabeling (note the order of output) // c0 b1 b0 __ __ __ __ __ __ => b1 b0 c0 __ __ __ __ __ __ // Reorder each block's bytes on output // __ __ c0 r1 r0 c1 __ __ __ => __ __ c1 c0 r1 r0 __ __ __ write_reordered(t0, &mut output[0][0x00..0x0c]); write_reordered(t4, &mut output[0][0x04..0x10]); write_reordered(t1, &mut output[1][0x00..0x0c]); write_reordered(t5, &mut output[1][0x04..0x10]); write_reordered(t2, &mut output[2][0x00..0x0c]); write_reordered(t6, &mut output[2][0x04..0x10]); write_reordered(t3, &mut output[3][0x00..0x0c]); write_reordered(t7, &mut output[3][0x04..0x10]); // Final AES bit index, as desired: // b1 b0 c1 c0 r1 r0 p2 p1 p0 } /// Copy 32-bytes within the provided slice to an 8-byte offset fn memshift32(buffer: &mut [u64], src_offset: usize) { debug_assert_eq!(src_offset % 8, 0); let dst_offset = src_offset + 8; debug_assert!(dst_offset + 8 <= buffer.len()); for i in (0..8).rev() { buffer[dst_offset + i] = buffer[src_offset + i]; } } /// XOR the round key to the internal state. The round keys are expected to be /// pre-computed and to be packed in the fixsliced representation. #[inline] fn add_round_key(state: &mut State, rkey: &[u64]) { debug_assert_eq!(rkey.len(), 8); for (a, b) in state.iter_mut().zip(rkey) { *a ^= b; } } #[inline(always)] fn add_round_constant_bit(state: &mut [u64], bit: usize) { state[bit] ^= 0x00000000f0000000; } #[inline(always)] fn ror(x: u64, y: u32) -> u64 { x.rotate_right(y) } #[inline(always)] fn ror_distance(rows: u32, cols: u32) -> u32 { (rows << 4) + (cols << 2) } #[inline(always)] fn rotate_rows_1(x: u64) -> u64 { ror(x, ror_distance(1, 0)) } #[inline(always)] fn rotate_rows_2(x: u64) -> u64 { ror(x, ror_distance(2, 0)) } #[inline(always)] #[rustfmt::skip] fn rotate_rows_and_columns_1_1(x: u64) -> u64 { (ror(x, ror_distance(1, 1)) & 0x0fff0fff0fff0fff) | (ror(x, ror_distance(0, 1)) & 0xf000f000f000f000) } #[cfg(not(feature = "semi_fixslice"))] #[inline(always)] #[rustfmt::skip] fn rotate_rows_and_columns_1_2(x: u64) -> u64 { (ror(x, ror_distance(1, 2)) & 0x00ff00ff00ff00ff) | (ror(x, ror_distance(0, 2)) & 0xff00ff00ff00ff00) } #[cfg(not(feature = "semi_fixslice"))] #[inline(always)] #[rustfmt::skip] fn rotate_rows_and_columns_1_3(x: u64) -> u64 { (ror(x, ror_distance(1, 3)) & 0x000f000f000f000f) | (ror(x, ror_distance(0, 3)) & 0xfff0fff0fff0fff0) } #[inline(always)] #[rustfmt::skip] fn rotate_rows_and_columns_2_2(x: u64) -> u64 { (ror(x, ror_distance(2, 2)) & 0x00ff00ff00ff00ff) | (ror(x, ror_distance(1, 2)) & 0xff00ff00ff00ff00) } aes-soft-0.6.4/src/impls.rs010064400007650000024000000052731374763121200137170ustar 00000000000000pub use cipher::{BlockCipher, NewBlockCipher}; use cipher::{ consts::{U16, U24, U32, U8}, generic_array::GenericArray, }; use crate::{ fixslice::{self, FixsliceKeys128, FixsliceKeys192, FixsliceKeys256, FIXSLICE_BLOCKS}, Block, ParBlocks, }; macro_rules! define_aes_impl { ( $name:ident, $key_size:ty, $fixslice_keys:ty, $fixslice_key_schedule:path, $fixslice_decrypt:path, $fixslice_encrypt:path, $doc:expr ) => { #[doc=$doc] #[derive(Clone)] pub struct $name { keys: $fixslice_keys, } impl NewBlockCipher for $name { type KeySize = $key_size; #[inline] fn new(key: &GenericArray) -> Self { Self { keys: $fixslice_key_schedule(key) } } } impl BlockCipher for $name { type BlockSize = U16; type ParBlocks = U8; #[inline] fn encrypt_block(&self, block: &mut Block) { let mut blocks = [Block::default(); FIXSLICE_BLOCKS]; blocks[0].copy_from_slice(block); $fixslice_encrypt(&self.keys, &mut blocks); block.copy_from_slice(&blocks[0]); } #[inline] fn decrypt_block(&self, block: &mut Block) { let mut blocks = [Block::default(); FIXSLICE_BLOCKS]; blocks[0].copy_from_slice(block); $fixslice_decrypt(&self.keys, &mut blocks); block.copy_from_slice(&blocks[0]); } #[inline] fn encrypt_blocks(&self, blocks: &mut ParBlocks) { for chunk in blocks.chunks_mut(FIXSLICE_BLOCKS) { $fixslice_encrypt(&self.keys, chunk); } } #[inline] fn decrypt_blocks(&self, blocks: &mut ParBlocks) { for chunk in blocks.chunks_mut(FIXSLICE_BLOCKS) { $fixslice_decrypt(&self.keys, chunk); } } } opaque_debug::implement!($name); } } define_aes_impl!( Aes128, U16, FixsliceKeys128, fixslice::aes128_key_schedule, fixslice::aes128_decrypt, fixslice::aes128_encrypt, "AES-128 block cipher instance" ); define_aes_impl!( Aes192, U24, FixsliceKeys192, fixslice::aes192_key_schedule, fixslice::aes192_decrypt, fixslice::aes192_encrypt, "AES-192 block cipher instance" ); define_aes_impl!( Aes256, U32, FixsliceKeys256, fixslice::aes256_key_schedule, fixslice::aes256_decrypt, fixslice::aes256_encrypt, "AES-256 block cipher instance" ); aes-soft-0.6.4/src/lib.rs010064400007650000024000000041741375324177600133510ustar 00000000000000//! AES block cipher constant-time implementation. //! //! The `aes-soft` crate implements the AES algorithm completely in software //! without using any table lookups or other timing dependant mechanisms. //! //! The encryption implementation is based on a technique called [fixslicing][1], //! while the decryption implementation is heavily based on `aessafe` [module][2], //! from the original `rust-crypto` crate. //! //! # Usage example //! ``` //! use aes_soft::cipher::generic_array::GenericArray; //! use aes_soft::cipher::{BlockCipher, NewBlockCipher}; //! use aes_soft::Aes128; //! //! let key = GenericArray::from_slice(&[0u8; 16]); //! let mut block = GenericArray::clone_from_slice(&[0u8; 16]); //! let mut block8 = GenericArray::clone_from_slice(&[block; 8]); //! // Initialize cipher //! let cipher = aes_soft::Aes128::new(&key); //! //! let block_copy = block.clone(); //! // Encrypt block in-place //! cipher.encrypt_block(&mut block); //! // And decrypt it back //! cipher.decrypt_block(&mut block); //! assert_eq!(block, block_copy); //! //! // We can encrypt 8 blocks simultaneously using //! // instruction-level parallelism //! let block8_copy = block8.clone(); //! cipher.encrypt_blocks(&mut block8); //! cipher.decrypt_blocks(&mut block8); //! assert_eq!(block8, block8_copy); //! ``` //! //! [1]: https://eprint.iacr.org/2020/1123.pdf //! [2]: https://github.com/DaGenix/rust-crypto/blob/master/src/aessafe.rs #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" )] #![forbid(unsafe_code)] #![warn(missing_docs, rust_2018_idioms)] #[cfg_attr(not(target_pointer_width = "64"), path = "fixslice32.rs")] #[cfg_attr(target_pointer_width = "64", path = "fixslice64.rs")] mod fixslice; mod impls; pub use crate::impls::{Aes128, Aes192, Aes256}; pub use cipher; /// 128-bit AES block pub type Block = cipher::generic_array::GenericArray; /// 8 x 128-bit AES blocks to be processed in parallel pub type ParBlocks = cipher::generic_array::GenericArray; aes-soft-0.6.4/tests/data/aes128.blb010064400007650000024000000654321374627362100152050ustar 00000000000000\\\\\\\\\\\\\\\\8888888888888888@@@@@@@@@@@@@@@@****************@ tttttttttttttttt3333333333333333[[[[[[[[[[[[[[[[   CCCCCCCCCCCCCCCCmmmmmmmmmmmmmmmm9999999999999999""""""""""""""""cccccccccccccccc%%%%%%%%%%%%%%%% vvvvvvvvvvvvvvvv aaaaaaaaaaaaaaaa@@ DDDDDDDDDDDDDDDD================oooooooooooooooo````````````````<<<<<<<<<<<<<<<<zzzzzzzzzzzzzzzzQQQQQQQQQQQQQQQQGGGGGGGGGGGGGGGG @dddddddddddddddd@LLLLLLLLLLLLLLLLrrrrrrrrrrrrrrrr7777777777777777@////////////////1111111111111111YYYYYYYYYYYYYYYYVVVVVVVVVVVVVVVV::::::::::::::::................yyyyyyyyyyyyyyyyeeeeeeeeeeeeeeee++++++++++++++++qqqqqqqqqqqqqqqqxxxxxxxxxxxxxxxx(((((((((((((((({{{{{{{{{{{{{{{{ssssssssssssssssPPPPPPPPPPPPPPPPhhhhhhhhhhhhhhhh~~~~~~~~~~~~~~~~2222222222222222ppppppppppppppppOOOOOOOOOOOOOOOObbbbbbbbbbbbbbbb@ IIIIIIIIIIIIIIIIJJJJJJJJJJJJJJJJ>>>>>>>>>>>>>>>>HHHHHHHHHHHHHHHH5555555555555555@BBBBBBBBBBBBBBBBNNNNNNNNNNNNNNNN]]]]]]]]]]]]]]]]ffffffffffffffff}}}}}}}}}}}}}}}}MMMMMMMMMMMMMMMMllllllllllllllll''''''''''''''''AAAAAAAAAAAAAAAA @@wwwwwwwwwwwwwwwwiiiiiiiiiiiiiiii4444444444444444@$$$$$$$$$$$$$$$$@@RRRRRRRRRRRRRRRR----------------nnnnnnnnnnnnnnnn@WWWWWWWWWWWWWWWW^^^^^^^^^^^^^^^^@&&&&&&&&&&&&&&&&@;;;;;;;;;;;;;;;;________________????????????????TTTTTTTTTTTTTTTT   gggggggggggggggg   !!!!!!!!!!!!!!!!kkkkkkkkkkkkkkkk ZZZZZZZZZZZZZZZZ,,,,,,,,,,,,,,,,################SSSSSSSSSSSSSSSSKKKKKKKKKKKKKKKK6666666666666666||||||||||||||||  0000000000000000 )))))))))))))))) jjjjjjjjjjjjjjjj XXXXXXXXXXXXXXXXuuuuuuuuuuuuuuuuFFFFFFFFFFFFFFFFEEEEEEEEEEEEEEEEUUUUUUUUUUUUUUUU G\MG\M"3DUfw+Eų,IHH 3!FE[غȀ7 ]cJwOR"g ;|5C#]e? NNUQcAq …(yMQx쑋?A R[2<߀1 `~7z66n>C ~˒QΣ1S' 7(Vťnr; ZOɡS Nn+9=>4k ln!I_ ay 5@݅7 Q,Vj  6HCD @:n(] -ޘ\v\WYA;m ?87O,kw BR=LA!C 5 ,ڐۦ=)Vq[ ԕ[AYWI  \vXg2IK kF=tF^ZѬ  24`y -Kb9py !Τ5,MXj_- n%!&4M&6#' *gU%)  V~x r2YJ}b x,݁s /Ʉ0C r@cEH˙ do虜|! &HZ0@ZzW6)$P Em|6cC*=o _H uI8~O 6[} ?M{m uj]`LC0H pKˎiF%u n!ש+ Uw n"JiE ~2޸i`{ / KqwmBY &ݑ\L:+k f直S U 3;M kYEf& wFz y0ͨ%ұ9Q zq:S4[ЁW J+Fb 2,-I% .|p|t{|~= kƤj`ś1I) H=2gL# 1 k//mv[ Z(R) ¼} CeDYg"g ؄U R]>K&; \.G1;[m B[ߔ ? \D u2 5 S9@F.(SI 4vqD8Ly  #?=a.XEɖU 7NRhgnDu)?U BL"3X/ '+N9 󾞣 sdQф7 $Hj0HWȂw gV[h=w{= o"_oL .gy"m ] x~gEg~&69 <\VU/A}= gC zO u@8Gw(TG:oc ~4j LKH1} ^Q36Ȣ+ }'U,ń# ^U7C tUf;x8C44 }Sr^:8R!] $ h+S\r#:Σk \v+ e`P  th8GT) |k1ڌiVP4[ xQ1Hee g0UxKs <>SV :I# s >벍q1 0)C2 ]arIhF~g cO8ζq]MK Zɰ)eH} W, eԍ-%9 ~bU 7? ԺM(!1q C AhX}Ni ^3nY&Ei S)A3P/~/ %)?s #1óa }gV3HBQ wXW[{Ade; sWƇѴr = eOvB?\N! Q b=+NPjbW_ tF W" 4`Q k _}Wfқ]nFB;؀+ "_Œ?TYA ]Aj_,U J͠1%E>^I. SK:W M>u@Hi c@T6wQgq- dڮGRy.+2  K"]QZ*GS J"}G;>YnA n5 OS_Po 4>NضD2y G\$g 9 I% e 1wGd"TȀ p926h+(Fy :׎rl+~+#47 Ep}) Mߺ/ g rt5%nI7[? -'>[YV;q ftJB6ufA fPnU#ɇ1 H%aXnC 5x]*}' OMq7; zK̿g9US ]x }wSlwY vxpN _ AS癍?7 *E6w0v ֠TJV )5] #ϐ][7 eF"m g9 nSE-\CȏKUQ }EqY?T}e;W &(bwI6]_I !i YLWZ= e]} u') 4?!D!xc5IB:1 V: dƅJ[ 4}(sj} K/B`a_uU | ryGϴqF z +esi}m hFoCԱ~t_ \qx VT5 Y9N&W%I $KQ )b,hkI[U -eOzIU d+PAY>/ -mw+ k Qx(>aX7 -gR6w %AU Elj[!c= M!OX }I4|ȑj7] $r;u=M9 m!(;i4 ^f= >D# fnzO J͢AC&^kc a:}P7\t@A} |9E3 [+ '# # Dy1ȀכDC PӦR|r h8(] ,ٰ ^0OW] (`nFDE aK کQhp#&bK >H]x5UuX- E.,yB[G vꭀ6$bO e h w )O B8SnX\sk 4!ދNvs9 xs.!T`) g5-9=S[ 3)PaS_Nb,e N3vCm=us 'ȡ[>w7s jKzwa Ӳ%1 h f<6ى GqoY+g  IyXK Tob'sVO{} F+̶m@9 BEK!jس֐? =>UL-7+q )CBoyl(i !_tN)D5xaY TTBeQ/ {t}3s P P a p߾@ic;/Q R_߃2ǁH7; j:iDW*d= yuzB\ZPQ KĖ p,6my_  C"/VtpND} H4>Rxrk H4VЬi+ "鱽s,brA 4s)PY"0U    [YO9 K2W !v Q% J1DRʊ6TB6C- ett",ƖT%  #QĨH"oS S H BA rS[w\~-o 4#e};\cy Qdf?<]YX e 9fh G &AVqy y;c\BJI fK,;LY4+. ^w埏4AI_N{{ %V4%όpv)2L99 s.#1m ҁ e -%Nc%% `J?8uu Rd(`]_G%% bLtcc UdĕE{Jq]s__ *8妕_δhVԄ K>g 933 qcqr/oG}^GG ӤD!ʎaa Y _ }Е 'ծJKdр o].xXy,HȁAA hmh% 0hNsrƯEII ^C5|T&!! _];Z5?ԃ-- :oF9mlii l)I ן,G%ee q S)rFSaa F\N0edw|55 }DD낫p i-&m LPP|f+vYԀ 5rWX޳pe e<>=RP33 #h1 Rb '' k 6"մd֘x̪11 uZ])4Gkk % r76bD C#K2y11 ds4 oo r&&Z;N;U [}>Ł "yVS5w'Wee h[VЂ j08KWrYY ZQМՋ '+ AgU`ӃII n8.\.=Z, CY _a e++ XI:DU'v#Y^SS P\Hءuu )UcDG|}}} _|yw`k>nB UEd*e,碃 )HȜ:KIԙ11 u{Z kIX!! ~)~b`kV؁SS #3hL_#;; vJ4Qځ _fkw0 #l  -|aU5x45W!! 3l ؑ'Eq> 爃 mUø\Qaa LUǝY;; =}(e77 /ڑqSz@gB$MM I#ٹbi뇮֣,.5 WZksԂqq Ħ !A.Z33 nP%YQ *qq 0WgABw WEol I// )m'+NbU;؀gg vr^c+' )=XKT,܄ss |:Radmm ҕC'%MaEE Hldj97 wh 91ww +k|o8Bgg ;l>2:S.QQ k:U?gnc:YY lTJ;8Zpii )00$<%h xrx4<2E ͌ւWW c{ܘޠ>LJt*qq +N` b%[€GG Cx}VQ4UU VY$a)M77 :L;J32]] Q_ۇ~r)) qWŘdk}ǀcc |Ix|r":6ii 2{X%|;" L Y/?)qp_a'' eJ sރKP 2\wr''  iK1SZ>!;с}} +\vIGyikk БGKRrmcM## Nϐ{Y99 KX:>9Ś4C|{{ !4Z:B+#// ur?44899 u)ƨoփQQ TiP ?__ j˶qZO(55 r4P%'l)CC 0;NV ,)u8ۜ S\ݿ}Bs]5ee wwBcy 9ܮ7gg —z!Tw{NS__ qF&M׬։5 teR II vG ~¢P0 V|Æ=// N`4"t\^8 wExlaa 7ؐK]%*| {]] AVM"$8;555 r]h F a] >cc V.vj{C~gai ss /97j655 +!n  8$!bYV@i!! ߐq\cNA!7  zyꤸ ND9!Bkk f{ǟ-Daee =oO}ԯ 䫩 ݚfGG {;hGRE[%% V _`:N>yy is)6Q̢6)YMM ۵<)feZ[[ | v1y[[ 2 64}̿uu zS(Qȹ=jcXEE +6npj9:UU !|0QpR:y)) E=P`Le^ zk@i:>s܀ j8:dx7yy ++n>?_ b4Prcc U" ^4 #ieh.&t++ ?D"j26c+ SIp-KK F8 <~%% Ȅ:s~. }} ωI5o_easLռWW Fu׸s@9'w.-- =<i*Әyy h p>& A}Gj]OO ˟=&^ '' i;l%d"vnɟt 7+ ,1M w#{&I@@u~ S2Y@t%iuO{{ M ZLb<ii G|8kG[1AA \k+"w3mm H=Y.r Haɤ肠;; 66b9e33 '* C~:cii ؊ xHwޙ݁ww RH˸T3-- hjaWD[VMM 3:S-7I68j## PExAX^II AB\-e*ww cSNuh== + WD ǜgQ33 #!s}S7[~ w!)C z&ot !@ē'%}dYЁcc <yk.i6EE =ѐʠZ BJb%% Gq% \.EE ˡ[Q &X VzSDv(>$[EE ElH Uѹ BQ? e7*=F: yy fP%̾MM Rp=X)ҹ̄oo +{s*fOPtJ)) kc d@m@uu K^C}gp)`OIYY >Zj-\EAK[[ nsl#s{++ ܷ. =\jAA (E y:UCћ҂// cCҋeݲG UV~c+Wk CC %Y2":Ձmm d|*1.]-g\G## Һ3/I7[:L鼀%% Y6 Sz M ™]gY7'' V?aa λ2AEaX`_O.{{ x6Fmqq II]c.à &,O/\gg ;(`&% goo N2j|CC +so`? !" o 77 e6LeW<| (Ttf#kW!! xN˸Լ#e gmZB5:;?? =d|hE7b& .b[\;D.b"uu QGK"B^SQQ Liرh3c jSS xjPb'3貈 ij{0ͷpZ )jS} hp_ܺʙa7 XÀUBYg 3hDNX ? ՠtoڟ|+hq sP`3k֨A HfKj1 5126pBC o#BJW-6-' ?Yw~$-&i; >v[x}hS ' FJ{IM\0 6Mw'CkN_ nlsr &7 <ѯC%B3{ 32cԍ|KB] (ޟz0.em `vð.ϛ A/w 0+(N~I} 5  :Qn-GG[ +qn}F50 |P <=N K ˘חyeb mblj`}Ghy qW%AY,1- i32XDS; w"KBT‡d) )KM. VT܇m]nZxFs rʡ ,+… \Ru _\SGjTw /Ttmvb ZZE G ۓȷ1c{ X嗤\X.6ѺY rS"-Lgk 9x0BY ]m X)n(ҎLY/U J6֖ :Y9)%u\Q %cGfp@iiW CVU!āq+ J_^;85L= yx{"+%) 𫋊Sk4?9z=b1 VeZ.-+[ $f_ЦO ک@bgkqO ;yYDF}iN9k C &b5 mtdn9/) DZ9Бq$[ qǣWR17<e SE؇!.9v s <)! mVAs +|9ɗ]!1 I%Lkd5hy Ie[B%Ig . <`1^&K ]Jo1!4;;} LRQ^9 >U=+d? zC}tvq 5$ZΘJO^i ^Hh6Z)i" TUM6ep@+ / _[AU|(sg+s AeQ63xB|a q|ELݩqUQ >U^/׊; bHDaE7bj D= Z+$a "vTdoQ }%㩬SLNoy$j_ ~@OGpCN6 aQO Ek ls cUImb+ ڧ0{jsb knA aS?މ.6U &$&'n< 1"AKwO)`W Ttn¥t )Zq?dn- Gga oO3咍 bH-oF ^Ȉ{S kGT[*_A 8JD{m o $ b@^/y Ƴ/]{<e "Zr+ɷHBw9 yǬP{  v6Rן? lh>4n7 !~g ?$Ī#޶py? l֞?{+埁q )5jYd-7{MA  EerM1 ]v]"2xNC >fO < ' +RA>7; lwU_b_ZS @@&  ~*)6'`QI_ L]c.j7 =;r qJCp  |˅o>\_@ ] x/p« km u Al w 5>r5 >w%Ƒe[ 6)|uӶ>1ep  ܶ>\=Kg ߏK ,g^]8iZ$l  AaZmy <SzZY- _ GY{*A 2X vLūd/Nc;U) yߵGV  EҪotYR@ˁs DY #{x>SqUS A`Q! lZuؤZ5ի܄ OIt֖vF= Ԯ(J-p|hį) 7 ys1 8lca}}[ r&yK VG} %@wYE_EU -1b :* `݂('2m U]<:"_F-w 36"Y4,UF5 iFDVG[I ]SRe*5t  Z_URU o͸5Xځ"/~}U 4V;vMmh/ GHOuY6: d8^{t#7(mu7 d# *w zBwoatj= ^$3i (B.=C>] 1:%~eƋΗ9 Af(Jl7= [zYֹ}O z_VGX]b zc -d9{f?<} J볳S3bؽ(+ Q|*DS}# կaA\.5~C Qpp OwMU,C8] E9FQMqDC.3] uE&!Q!SCVG>T Kt@E %ʲK } HP/xߗR- Bud#>Ѧ/OG d] ulm,| &O x q;M.aS!O +Dۯ>\)U4ۂk qכڵdIawPT A y.) nL܆q[ F{5NA34夃e -Zv4 s V hA!(s }E+A1 .x.?i*# X T Ln_LbX퀁g Rhwۊ<(jK pɣ[1W0p} 0ۋv6AdF~˃9 z8ٴJF=(^? %W|ui4 8q D~SʢhhwuHi j&cҼNb FmjU鮃/ ȌM {ms )?y3a ; [oQ ٰ# ?X7B; nWDǷie = jez2oREQ N\+T!q? /_ l^/`L8 |߫n΢?? k -Z$h5z-+ U ޮ#A FydgU @.A\:[/̂ %Ԝ̓W ?ٺK  mb~C s+- CyՈP],Ί  |Ϙ >"?ES ݅ǽ^@:7o[A UćU$!bo ">y j+xɜ& e OuލoMjC "=yXw: n+#f׳֦ { 3$Mk /Y9~{9 #wĔ_9%+LP9 /Lvĕ>8Y}7% d/Q B+s%u ThLر 1u% I'A$88๹X%c +WS!c_ kOZ-_ {D5 <3 ݋wƀJy٦؂3G ͥcAg(Om{Ga Ava0؍a ;ryz& LWs(Mw5s A ryOKRk'.߁A y=zixб[I C+]5\I! 9II6h~[>?!- [*Ș aq-i ҭ_cAxSk[ie "܌^k6!p$ea .=gka5 +Byq-l)5 ^~LCe  Ջ0u+ d, 8?h< yQi=eez43 ^Аk0jB3' IT8 ΂'1 B 1܇Υ?x1k 5)7[*E'k XH 3KKq1 CL8u5k~1o ѽE{qw轃o P^<4-E  (uT@s s!e 1V H FYhe [e5y Y fgHA )SY >MN`iUfłI 5D] {JI @LϒЄA>+ w[Zq+S SbubVgV?Su #pbŒ$pYZK_Au} NdP&d5} ~ R.[{PU D'vTX%kZ~1 95ʉĒ*̄1 2H5`x&n! osmu@= !S _;}&JS; qD㆚_̅; ?-egR = T"oW}ɓP|! i r6\ʼ! ٌ@+fk6ja !zoǾ$lqaAa; ZX6}$p⒰*;7 ؈S?YV7M ="9cRHa\&M #{Ҟu Âq L$MTnƩQL"q3  V]NRts)ʀ3q s$>ExƖ:7yq Α9`أr癟^/ }@WDXB/g KA@-͸!S)LgW = G"qjyx۩xW+ +{K2`+K iK{Ɂ 4..KY 85Nv9YO ~Z|BQ )bd\OS Fh:/*hGSG {r>]mG? UYHf$!$>Ä?o b;Cu@:gqo FbV ɂ# PK^[M#9 \6xD6 =093 L²2%S7*K%73# մF"4fb&k#W q*xEuXW v[/sn  jGg \ @l -upX -  4Zgft޵2= isc.+= \!0C)u|? F݀LΜ ~݁?? -Ueăgm? S s@G cspBQBסG ٴ;cUM rc%uTd֐MM -Aj^ sѻrӓMC ,A"C%Ӏ`ԯC ұh&G@s v *\ qDsm rce5#r>WemE B|xc*vIZuME LD0 շ w n[3 ^&2wg LUU5d gQ aŒH`/kEjV6"4' llt@Z)' M?flhȌ0{ꖂ ' pupBrsK'} &fӆ T7n}k ^n]B˙Z^ k# FH/#;ߧ#9 MyLz^To-Zqˁ9{ rgyϤ{/ w?Ӡ /hM;/I pJp7hҤ7I_ H*yjݶs_Y G&A@V~?$YK +|Mt{*K 5|kf5ɒ{ UvcpDۑ{ rDklV#>d HA(DĀ í&oU 9 h^#p9Q !*ɊeЋQ_ jZ/5q =ּ_5 LM|-#fJ55C pKשpBᮃC lܚTE@c}d a6#6|sO e +bDj8"{Zeg (e4j+Y΄g_ z'$zudm|_ &L % [I >yѺ}FOI !@Yv-k?/ B}XS~t/ ǣ+=0$̵ a (\mO`a] Cm%^ HnЃ]5 GI`/NPp/jE5 QIq**U;4 c ϗ,`44 cs ֱ3,˵&`[ ̀s5 UT9UA@xRxV]b5 N])ZG! :'9{:oˣ! Ki)3 zʄk S;3h)e&H݄ke }Ba2ue ޟj4*hG CZp?oG% ٨ 쌢Jk5Ã%y %-ȀR$Lp9\Wss̃M[ 8YPs'|([[ Th}*<[[u Owun q* 6uE ˪a`DaEU H-0 "kWVɂU) ]aY֬RWh) liN{>NMq zP-5ZvE@ʧӀy /h. I~u y r":,F!#-c p$vyI!c Hh L*ɂ#7FV+ M%sQMܶ+ CכM! K [`.acg'fK% HX9 Ab52%} ]LS׳Jq/Ă}W ِXEPe;*W- ~֜iumEB-; \TJy FWe R;y l ? ; vy u.f .zHO ɌE;o蜓7O' {n3k6_v#' 'a !ĚLPsLZla{ eZqp,{q \UrTQ8vaq cNq(g `tPiJXڪgo x*"<;oC ᮧh,C sEKLzkvu7 fFDu%2dbp7 * 3n! M{~ha! 2(D*ymK'? jܟ%\؈&ك? غ YQpI |c u ;bYuQ /EqgWڒQS ӑ7v~)8wS v*Z )ۙCG؅ 铈abFgaes-soft-0.6.4/tests/data/aes192.blb010064400007650000024000001205521374627362100152010ustar 00000000000000D """""""""""""""""""""""" @uuuuuuuuuuuuuuuu@qqqqqqqqqqqqqqqqYYYYYYYYYYYYYYYYYYYYYYYY@WWWWWWWWWWWWWWWWWWWWWWWWYYYYYYYYYYYYYYYYLLLLLLLLLLLLLLLLLLLLLLLL]]]]]]]]]]]]]]]]]]]]]]]]@ ----------------ZZZZZZZZZZZZZZZZZZZZZZZZ VVVVVVVVVVVVVVVVVVVVVVVVdddddddddddddddd@HHHHHHHHHHHHHHHHHHHHHHHH@ ||||||||||||||||||||||||888888888888888888888888\\\\\\\\\\\\\\\\\\\\\\\\@qqqqqqqqqqqqqqqqqqqqqqqq gggggggggggggggg7777777777777777bbbbbbbbbbbbbbbb,,,,,,,,,,,,,,,,,,,,,,,,^^^^^^^^^^^^^^^^yyyyyyyyyyyyyyyyyyyyyyyy  @wwwwwwwwwwwwwwwwwwwwwwww FFFFFFFFFFFFFFFF555555555555555555555555 @BBBBBBBBBBBBBBBB99999999999999991111111111111111@::::::::::::::::  ssssssssssssssssTTTTTTTTTTTTTTTT666666666666666666666666  vvvvvvvvvvvvvvvvMMMMMMMMMMMMMMMMMMMMMMMM;;;;;;;;;;;;;;;;````````````````````````wwwwwwwwwwwwwwww222222222222222222222222++++++++++++++++++++++++ +Eų,IHH+Eų IIIIIIIIIIIIIIIIIIIIIIII 5555555555555555oooooooooooooooooooooooofffffffffffffffffffffffftttttttttttttttttttttttt8888888888888888000000000000000000000000llllllllllllllllHHHHHHHHHHHHHHHHkkkkkkkkkkkkkkkkNNNNNNNNNNNNNNNNNNNNNNNN[[[[[[[[[[[[[[[[[[[[[[[[UUUUUUUUUUUUUUUUUUUUUUUUAAAAAAAAAAAAAAAAAAAAAAAA@444444444444444444444444  999999999999999999999999 @hhhhhhhhhhhhhhhhbbbbbbbbbbbbbbbbbbbbbbbbQQQQQQQQQQQQQQQQpppppppppppppppppppppppppppppppppppppppp++++++++++++++++{{{{{{{{{{{{{{{{ddddddddddddddddddddddddcccccccccccccccc@UUUUUUUUUUUUUUUU@@@>>>>>>>>>>>>>>>>>>>>>>>>||||||||||||||||________________<<<<<<<<<<<<<<<<NNNNNNNNNNNNNNNNrrrrrrrrrrrrrrrr------------------------   @XXXXXXXXXXXXXXXX @@@@@@@@@@@@@@@@@@@@@@@@EEEEEEEEEEEEEEEEEEEEEEEE@"3DUfw777777777777777777777777WWWWWWWWWWWWWWWWCCCCCCCCCCCCCCCCnnnnnnnnnnnnnnnnKKKKKKKKKKKKKKKK((((((((((((((((~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@zzzzzzzzzzzzzzzzzzzzzzzzaaaaaaaaaaaaaaaa @;;;;;;;;;;;;;;;;;;;;;;;;eeeeeeeeeeeeeeee6666666666666666****************########################@eeeeeeeeeeeeeeeeeeeeeeeeGGGGGGGGGGGGGGGGGGGGGGGG************************  iiiiiiiiiiiiiiii&&&&&&&&&&&&&&&&G\MG\MaaaaaaaaaaaaaaaaaaaaaaaaLLLLLLLLLLLLLLLLjjjjjjjjjjjjjjjjjjjjjjjjiiiiiiiiiiiiiiiiiiiiiiiiGGGGGGGGGGGGGGGG@jjjjjjjjjjjjjjjjVVVVVVVVVVVVVVVV@ xxxxxxxxxxxxxxxxxxxxxxxx$$$$$$$$$$$$$$$$uuuuuuuuuuuuuuuuuuuuuuuu {{{{{{{{{{{{{{{{{{{{{{{{@ssssssssssssssssssssssss@@::::::::::::::::::::::::%%%%%%%%%%%%%%%%%%%%%%%%========================________________________================ cccccccccccccccccccccccc AAAAAAAAAAAAAAAA""""""""""""""""mmmmmmmmmmmmmmmm0000000000000000@@@@QQQQQQQQQQQQQQQQQQQQQQQQOOOOOOOOOOOOOOOO))))))))))))))))))))))))SSSSSSSSSSSSSSSSSSSSSSSS>>>>>>>>>>>>>>>>FFFFFFFFFFFFFFFFFFFFFFFFDDDDDDDDDDDDDDDDDDDDDDDD////////////////////////kkkkkkkkkkkkkkkkkkkkkkkk @[[[[[[[[[[[[[[[[llllllllllllllllllllllll  ''''''''''''''''''''''''<<<<<<<<<<<<<<<<<<<<<<<<oooooooooooooooo}}}}}}}}}}}}}}}}RRRRRRRRRRRRRRRRRRRRRRRR@PPPPPPPPPPPPPPPPPPPPPPPPZZZZZZZZZZZZZZZZMMMMMMMMMMMMMMMM  ,,,,,,,,,,,,,,,,nnnnnnnnnnnnnnnnnnnnnnnn````````````````EEEEEEEEEEEEEEEE&&&&&&&&&&&&&&&&&&&&&&&&........................  ))))))))))))))))$$$$$$$$$$$$$$$$$$$$$$$$JJJJJJJJJJJJJJJJ^^^^^^^^^^^^^^^^^^^^^^^^111111111111111111111111!!!!!!!!!!!!!!!!????????????????????????DDDDDDDDDDDDDDDD@ 333333333333333333333333KKKKKKKKKKKKKKKKKKKKKKKKvvvvvvvvvvvvvvvvvvvvvvvvhhhhhhhhhhhhhhhhhhhhhhhh zzzzzzzzzzzzzzzz################JJJJJJJJJJJJJJJJJJJJJJJJ//////////////// yyyyyyyyyyyyyyyy4444444444444444................ @gggggggggggggggggggggggg''''''''''''''''OOOOOOOOOOOOOOOOOOOOOOOO   CCCCCCCCCCCCCCCCCCCCCCCCmmmmmmmmmmmmmmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrSSSSSSSSSSSSSSSS}}}}}}}}}}}}}}}}}}}}}}}}@ \\\\\\\\\\\\\\\\%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@  @ @xxxxxxxxxxxxxxxxTTTTTTTTTTTTTTTTTTTTTTTT ((((((((((((((((((((((((!!!!!!!!!!!!!!!!!!!!!!!!PPPPPPPPPPPPPPPPRRRRRRRRRRRRRRRR]]]]]]]]]]]]]]]] 3333333333333333XXXXXXXXXXXXXXXXXXXXXXXX BBBBBBBBBBBBBBBBBBBBBBBB tttttttttttttttt2222222222222222????????????????ffffffffffffffff@@@IIIIIIIIIIIIIIII ވ]ZY@,,i IOg?Ҫ205 prc%G*}tPm 4r']7̈Ë t}&^`Fy uBmE#c+ nrtJKOQ H)+&6s o]_Slx1<9 khOӿV }9Y#ewpJq[ Ɇ)Kb_ =؂]:: 5q:~1':K $0M#lq }lӞAO+,͆Y yuc{>e ey\U+R~W +vìK ! *t=Fk M^JԽƸ1  ~S8N51 0?5o ˆ? C$@V.2} Nނ%GǴCU] [$!f} pHz[ ?PK+ DlxEߩ*o) D^hnnĒWa vYumKstX (\Q;v@Hrƒi WBqP?{5Y tf;6/jk -9 n;5΃ rC?K 9'.1{Ub2 >] K6yIni5  V++qÒ1 Ha_%'jNM 8Xz/* DIOg ]+xX'U K x06m !yC$#jUE! 1<IoQ z[G@3zX: _y=BOˇ?  - *h9!2ny; 9b1 (}Y ?򲇜 -cC  9\uW w "EcvP]xc eb;|OtnC݅S Ջ&aZtW Y:-> <3  o=~]& v.IE"' xT+:X li]Ckc g 1i*{POщO mX Xe/= _W;{]jT`  %3n4羗,A C"֓O7 9GYxyN/ %:89 N35Ia0e[W O wiB^3-$5 ^u2-)9qTu m{c >h(Ui# MgHUd Y  .4M>>q:U 1Yٮ0b;2*do Np:pr d3)4){ń  ǜK05E9S% _ѯv=kv 3 e jM pZJ%Ԅ  4\Z =TsXR} N`, (A) mtQUc=×C' lO1y݌5G qkQFO#j ģ=B*P] I]9ԥS%*{; {{@񂨒Ug% 򔲏s$8~ uD j\ IIQ nU]6mi O - s`B"{YyAy bp l7k,M$} |,8J~!.iCF Iʿ_^z}ށ= GYIFUI'RW hZﯛU* ы} cmTh yp0a !kƟO$ ee ۹[s$L\E Ԕcȹ%65W ɨs@M@=oAgx[ :J|w!ݝ'] \6iR)W &Є-7ӅW^ ^_. )KuF)g *>8yr[۔; wqN9LQq WjGٞE; +@ۧ# PQb/Uc |K)P τY 6B-?d' ,`k,a\7 he*zy g,꣹vf ceo\a [ެh{{R; {nbsc Kq !e s ֬;v^o- j?BZu49Hyv paT7傈q ugYygF )I^{n) L=Ԋ,R ? hH?x~ L {4# ̫ (m8<3 (s }{lȃ% ZA2w{  .hYo/ ؓ U'h6 W  AEۛ̃ MTIrU#f$F% XA|}(^-ja `MK @ZRMvO xV#-zs  ZÞD,{<]a +|Z]y u c};9 Y䋁k 8/1~>[ =Ɛ Tk3=Ʌ g{^ iO H#su&ܝMH'{ 9i1 ẇI J5x\ .,y% s}}Ir 9 ;ϲ3)řU*  ƹ9z)c\-# J)Ɠ]_/ Q&QXA / 0!#{OFgw k}$'w *% ZiW@ 뭢!,# :&KY*k5 ㊂\qoۢHi nps1 Š@m"{ uBbK|59C }\Pp j[%sؽ-_C)={ >,ɮQeŇ9lw hǔ"0'7 A=e=kso .V.ݜQ l%ܘkJz` g B='rVګ!))M KQHP l:F$=,' 5=L|[\% =1Zq0X-U ʀ𞥭\qO  I$)r"́- m" kdCclo? p$A1Z { #[C+;NS 7c{AY8$[Oe ~m[HT} 3et>~3U7 T{Oofmr+ 3Bm _ !p"DE !%/ t-]/ Xāߩ?g $Tf9TƀT} PmA|/9UyД! y@gvV}1|~Nk ;/\eQ'9# fYo&d5 \62чFW@(I ߫:yOm~XC lڱ r}qv[V19 6[@%wit؀B .k'!/ Y l9.TZcQ Px~'X yT҅pו#ci !=`%ʰ"P' Fe+?gy(u)# (=5 j<ќ8 hG4xlu ՙ ,lLC v,ay->yg f~)(A %օHm"wgw X q}o̰ 鱫G uJ ,+ bZ;t(/A&# I+.&f2ҝ|7 lbgKKV {5q1loY -h= 1 _h~#<]i W,|^LAᆐ\ `[ iI"-d)2Y 7*"l{J( 3 z(5&Z 08O (P% W-q)3ۣZy y{}x äe! C(I]@tOB) ޿AAM7,W 8H٤U46ɄJ IN{M;LƒG 2‰z׷_ u.(+ ni!sI8` .+D>gٰ!\J`A |Hd&"@+ ڪ-V.~ ~j ёmx_ ޟFCkyJe{ hǔmGj 6gK63 A m^hꌬQL HwY}|I f^b2`[Ӿ4޾Q AY[PS+i c3 ZJ-NxHiO jE%kS 78RZ? /8:b"9 hpDO 7]' 75hgyP= 1|pJgzIݍQ ~ln@)w{/ݚƻzm N?6~C#e= 6>J@t= ći9@{ ~Q]`Vj=c zucWzΐג i2U5 ˄AE~([6 0ma =PS @h.AK ]4ek=|݁go '[ma"_B({C 1((deL */38"%6ʶȇ+} ShzEXG6yW ro(^Wh;) w!Vb[p^3.7y z4]JO;^z ÁeE ^ , F Wc Z5c#*" HG&:gNyT}7 ~3_,ŀ .?a>CmS ͒*_fk_k D6O ro) ԵS R]0ـA; JP?`YoE tA]:֞^"Xdd^Wu -.OGmካ@؀!1 O`+Kx Zń3 HP)Nk!ʴ{i 0AM{d+q ȣm I ^"CQe6xS@XlH%- E4mL=sY iCD&*h@Y:,m em&' {qRysd 0/! 9MvO;B㥃Oc e`ChJhƈE 7/iQS 'T,FGUU= J25xV&#=ыCU ҕHpޅ5Ōi᱃'[ P~~^мTw= EC/S} rB8{_ ]j<+rlCI %obE1۱΍jc$Sc= `w"c>JXE˲|6}M +2H?]|6x5S ǀ.;6[|ɀ7e W1!LUϋ]E 5޿hf~O= rf۱b{lPK?݆[ c5/3 [Q;?dnۀ9) KұsVlznkM 5,k/avc } _ u26hAgae dQyܗ &u׈)g ͕Onn^Sw /o@P]s kx'^㩑M{ W]wAM BVU` ?%WI [B]6ܙ 3 5?HwuIk =eɫc_*uW D|W٩ hu7ow pB`)+z. І wy~t0 K:ԂEua zQ= 0İ5M; X$QaHߗG [J n!:a5 ۻ`|&x~&YM#yk_ !I#`u#4 5U+ CڨлYv;wq jlc}:uc? >_NOivoY්SE uX"πc Wnؕ;>YЄ= n^Qv]u9 m'tTs #7}_ZKMۃ/= l'D%j%) >D6<~.S_ š 7O[xo c}_D*FKm 85. ~̞mk# ,^P=r[(9K ;l0?Kuم+_ n6 )>x^+K KsfPr$;}\r7; W50& b}+ Em%bǞYwqq Ku 1 cNU_ ?h[,Пx1G 2m `sɞIAM L #[߿{gpw ( z<)! q ΅o Ȧ^iy v:_%qV4K7 }83R6htR3y xwu I&׳_6=C%w :BU6Яqa 0!woXjF&Iu B=Ā9 :wއG ^6( o _7,M'GE &43T[VS5 ~C>赪bvG' 3UHaړ"WB[|% 8u5f MZ_daQ 7i̺ { 'zy>:&fEg b˜ ~n7y: 릀& |8t21c vlg+?[ݼ5O &Ȥ s5A=y [C(>.A f`dZkBdqo )h֋zSzG q;wS%őg\*W? pgr[S5 ReX |_e0kI /6 $9s0O[ "䏯NH/e!} `^\~] &FBS G '8p2\e[ 8{ułZZMo .d'1LLc y?No (J$~?uQbS? F`Ro,^j#EK @:(,bu + H<("x̢|&iO ݲ)}RI%Mޅ 1 (|cCOx] E !d\ZGEK yO*#"yI#GY M'Ѳ Bm3 %#B;yW[G .|q0'@W]# axx )Y4)Ks A:}_'Fm"oe .B:#!_ 5w'n>|D_ &Z)pN/A c&nGM5SA JaZU'Y CqԱ`u4EK C 9θ+:h7A $R@7N.aU xLJQb}iJ{+ ^vV mN&y]! MvXkgXxiw' 12a1Ԋ+ ;i}@*n/) ?ue<\1y +?,= aЄ X'A[5">vc H8}o赨3[ Ս)|IކdMEYJ.;_ $ʌGJPCg FUl.G \-gVada o SLo%gci QW^B-EcC _evw( +g TzMD,t>Dq!q QF?h#CbZgѮqC fSOw5j/ ^)h#Dwȃ= pN)q6tw ]1jm6C1 Q5J`C{q AqiXQ Q%s Պ`hs F5 ~"= 08'U  HO "Y>rKY1 N±2eT_zBD[ B5LldHj@e .|͘Ԇ S 3v`<7L{ Mp8ZzLjG] Ld.m) YHIJ/56% 1ƃ4:鏇;Q W,oA>M m ᄬ"S|^@[Ig [L4{d3 03ႀu 68xQ_IDAA ]h؇a99 zNi~[JB7- !bϦ}_{[ jO@ ~NYq lPwt^=@ Ut7I '&{ɨcd&P\Eg *VY8|rs7 #罿+~;u)3 *dOȉ8iSY HD0H 9]5g SҳG/fS 6gE@>P]KF=so Fe9L)9i DA#@wdK y ogt:IA7 Zn0KAcTW$ U ; њxC) ̈́"ʠ6\# r ĥ V^z:GcAik BF39 xȵmA syr[/ǂM `'b^ЋOg AJѧ`w P[mu;)5k P" D} ش' N]M -p>Y@|.Z) 0G`11o*7;_ E )S"˛#+  4X[ 2sK 6l0JmiJ(UU @W-p) 5AA2w dԦD F3' %I)QQ y"8Oh毭ֆ!! <|M ;5a/9 [>ꐪ|lraWK35 (N˥Ib ™S \ת3,fʉVJ?q 9&P΀~I ݩ|Lnp qM- ]wΓlor JOv[3ai  hp5 %05sJi1hhGvm A~t%q>A :J@x]wDSy wPUU:+ 4e}]y:bBQ .'޽JW)s z@+8ȸ9 fnĥ97ӶdVL %|גڱ#>GUK q2O`/q fׂ?x-MV5Y ~pe.o@e ui#2 8W .HǠM ! ˍ*h-o`s J:~{pӟ1 Qp\Qm֦=;`  @taN v CdTfZ w }uHP%~L7F= `MGM%PFk j7Ïs 7!,z[ ߆F`- LN&V;lĺ-'[! z’Ԙuz + 3{Ij1袽( bq۴[m? B)f_- `1d'򀘖(; :ps؈j0dY RRkZG >ỴC :;/_]g< D;;y IH`vئa yk aX. p&; uS>+?@e +d_;20+([I- UX2Ty+  vZH՗pUq L;̇i( wM(!(w“Qr H_`03#_9 ? d;~cEtA]W /@3\Ed@ # qf $H \'IG# Y6I5_U[/ k.de ϯ3/ z=[*8J.~ qRтҹ/2% ]BA# ysr7sMT5 O VwBi $EgmXmm{ U =;:`cC 1~8_gwB ,uw0Cy݇{ K #vr.0ll Ew H3p 7 bY+KѽtC4o A*܊8 K߮YvEcrQ 5zKkZp2g tuY]WEʹLM .J;RjQtc, v8f-P6ڦ r*^7WU7"U jw-sUi*vO d C - szCSF c? ~V|Lˊ{ ;+fۋװ+1ˀa 5'z@KJۉe 5͈@|0:  e˭DD; M _pE-ei%y )*G'~S yϒ53Y Hh[ޫ>3g?m ɓ _ aLe ?yJUwws s^'C&,B/ )vN:0G O=:1Tj~vt' bhCUc \  E~FMQW,. 7᝛Z$s- #a)5R2d9 މm?_>͋? *]Lw=X[f1 <_:,r< 5@5fRk !TG*ƌm bE2_7фQ /TI%S˘e/ Xf~bni k?B&W4! ]l!^jޯe W^ٺr˩  ]E ۾}x7 uu-o5^h1+ Ącyٜ_ M;VD_ZĦ9 Y}// pWPIÊg ;I{AH} $br=6,d! \ Gf~xok |8,5yOHU# YՄ4 ~0+65 h䙫!Ȟ<|I # Yhb̈́C tߟJ`9 m snoVz9 }TN, 0/ a7 & ̉dQ7 GHɦݍ7~̓Y sr'Շ ʘMH߰o9Si IM k  jjMb16e W4.x{w ж-_mũ- Noq⡾u O=&-wSu Np1=qpQ U_ aق I}kv͉m 5ڀ?c' и51}n 'H/- J]>dPջ'[ Xf'ɀhV>ԇY b-4T?3 I|x#OQO tU_(ݕtq򇹁% Ny &db\)Jy gC=aF☂! VD1 1,Oڲ) v `siW 3$3UvRw#zԃ W ]?iG =.&_\  Bn4kǒ) Nd5ha4>US T uOuᵙ   5÷r~(5,+ F̉521&Ӆ (X4#Ivi_ V^B{Ps;ψ{ C3LaS  scA{ޭ 1G HyµL TI 8C _ӁQ &B}[wby S$/ٚKO )Gdz̋ Vi|u"06v? k۱Iv!D cy9 GT\ZRF' B5itI@= #Hgs>ЇσQ PQ 6M S]`4CH__U 9ɴDMeGJ5m {"w{~a $Rf~Kg OpnfE5uoC IH޽j< _YœjVGA gG=ۅ[*Q!? =b7Mxy O7UkK {dBs\O+ r,&ҋTP?}y s}qI% QA/?Ppb-+D-s \eg>4Y ᧧'fyߛgm ]a>3_Uբ@:'/ %ϒi,NU;*;!O P$' 9#8cUcE jmٮ@lԃ pU|=_ .[2[*)ZC {T \!2jIc | 䦗^Yu=} AҜB;htM5 W9!a@""S7 ӣ*S^EՆe] _7}R OSEO ~l .lej= brb߈A#qX [/ mE ak:}39 ,3s*J#)k 7 E\a鴌M X9p:#Kg_a JIg kdߊe) @DK+3>UM Aagw 9;Џ<i$ PM"k9fsq\s }wj5TwA56{M [G3#W2W j SyЈVYI x77X}.Cs3I %\;֞WEYdku ϗ)-g<Wo =}0@ފVbtʊw @0zaB;8բu ٌiiT2niVaM 6WZ]acK+u; #_6Y(?\a ⲍ#;f:5k -_Q[_1Kq!_+ *yraB) dNT. p—/ L-!zAN`l$= ?1:(}؁D e0kC AηANq' ѭUYI @Lbo-Q *I@P)S D-H]nq_ %UM@6Wom ,▊LN HZ1) *jkK!jr#9 Bυ(%K+ /'4b(_ Oq׌meivK7 vk}ny L24vas$@uAq =op~yK{o \ˢ$2EW v~C ^E٦ ? $4o2 J44A5I ӊH2Y >iO l߲{ 7ӧb[} 8F4}JB'aF pQGVXXEYZ|w0]G ,~M~0 x̅e #dtc۫m [o "`׹bNlhfHo V٭iDS =yCi _g?E =8㿂lÃK 򢚣_oW\X+i # ?d" H O ,2h2z[Dt!1E q)m7su[Tt HSV(p VKG et WQZ$Ym VWm>'ѡj%+3[ 1O-m!P !G] HlHO~q9#K ΏYcUHJZss Y P5pve! ?cNp_ p_1q$!_/ "CXx L٥AS LnNr-?AY FpwЍW 6 E `Iu9[$D)c&K7 sQw+HF^KA @)%^cvx,U{ h {g"V+] \4h*h@ 2!w P VoB'+ P2t |/ 5@c/amS݆)1 GR!?b+l%WAy [`<n5J f,`֡Հc3 )7#[; _VWW2K a_C KD ~=b-ѽgG |4P @"3P I? ,=nuc-i H`ܸhdF$igc ߄Ҿ0[MτtCg icWVWCݼq ! $#Qb Uu&.VqC ]*v݆ isZ5/ ߎ2CUw'\\= j[eƦw&g w vGhiq?:{ C zJg r%-BDx?1 #|MNc% Ӯ@[g陴s5 e ɋ' oLשAu_UY +j4v 1 TOI2[ Vws>!NS߅3e {$U_ ArS{ d6[M+6G D^;{B vcх] $^Fm+(Pv) K;5[TrO*Ͱ 湉3S u C"hY .!g ^uzbΏbk s 7Wc=L6wo9 S=Rf}"cvgUi  /p:HgX穀yA d'_D:7U /2C iSFAM) JoѡWXt`ҵ؄; Ez;c'hxi_ f3kUB;Pdi+s \~R~"KU F 4]0 U lQNtJ)w OSg<ͳ3 l8aapEڋ"O'Q Y?2uFmmV#! +d,BG1W3&b;!9 Vgҗ3 zF| &jB5S E[>~z؀? ʓn1qI 3i낗65mhw$ǐM ZYa(F-aes-soft-0.6.4/tests/data/aes256.blb010064400007650000024000001406721374627362100152070ustar 00000000000000   @WWWWWWWWWWWWWWWW  IIIIIIIIIIIIIIII   vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv@<<<<<<<<<<<<<<<< ================   )))))))))))))))) 11111111111111111111111111111111  pppppppppppppppprrrrrrrrrrrrrrrr NNNNNNNNNNNNNNNNEEEEEEEEEEEEEEEE   }}}}}}}}}}}}}}}} !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!FFFFFFFFFFFFFFFF @   llllllllllllllllllllllllllllllll////////////////  @ WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW 66666666666666666666666666666666 [[[[[[[[[[[[[[[[@  ''''''''''''''''     YYYYYYYYYYYYYYYY xxxxxxxxxxxxxxxx nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ    --------------------------------  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  VVVVVVVVVVVVVVVV   SSSSSSSSSSSSSSSS     pppppppppppppppppppppppppppppppp  @    @ @ MMMMMMMMMMMMMMMM VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq@ @ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaKKKKKKKKKKKKKKKK    @ @   @ @   CCCCCCCCCCCCCCCC  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ;;;;;;;;;;;;;;;;    {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{iiiiiiiiiiiiiiiinnnnnnnnnnnnnnnn@ AAAAAAAAAAAAAAAA iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   ---------------- ================================  aaaaaaaaaaaaaaaa NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN ++++++++++++++++++++++++++++++++{{{{{{{{{{{{{{{{ 22222222222222222222222222222222  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< dddddddddddddddddddddddddddddddd kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk ((((((((((((((((((((((((((((((((     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% :::::::::::::::: ,,,,,,,,,,,,,,,, GGGGGGGGGGGGGGGG  00000000000000000000000000000000 CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  ssssssssssssssss @@@@@@@@@@@@@@@@ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB     @  GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG  PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP oooooooooooooooooooooooooooooooo @  +Eų,IHH+Eų,IHH   @ ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ ''''''''''''''''''''''''''''''''   TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT    6666666666666666 ******************************** @ RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR4444444444444444   ||||||||||||||||????????????????   mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 0000000000000000   ```````````````` 2222222222222222  ffffffffffffffffffffffffffffffff $$$$$$$$$$$$$$$$  llllllllllllllll  ................................    ################################ qqqqqqqqqqqqqqqq  OOOOOOOOOOOOOOOO RRRRRRRRRRRRRRRR  @hhhhhhhhhhhhhhhh  uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu ))))))))))))))))))))))))))))))))  PPPPPPPPPPPPPPPP ++++++++++++++++  wwwwwwwwwwwwwwww @ZZZZZZZZZZZZZZZZ        77777777777777777777777777777777 """"""""""""""""""""""""""""""""  UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU @  ||||||||||||||||||||||||||||||||yyyyyyyyyyyyyyyy AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDdddddddddddddddd   @  @    cccccccccccccccccccccccccccccccc________________          $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ////////////////////////////////    3333333333333333  !!!!!!!!!!!!!!!!  hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE    ****************tttttttttttttttt  @ mmmmmmmmmmmmmmmm @ @@""""""""""""""""kkkkkkkkkkkkkkkk    rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr 7777777777777777uuuuuuuuuuuuuuuu   KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK5555555555555555 gggggggggggggggggggggggggggggggg  ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]  vvvvvvvvvvvvvvvv    @ [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[  @ @ jjjjjjjjjjjjjjjj  ffffffffffffffff@   @   :::::::::::::::::::::::::::::::: SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS~~~~~~~~~~~~~~~~ ssssssssssssssssssssssssssssssss XXXXXXXXXXXXXXXX1111111111111111   \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\   88888888888888888888888888888888  zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz  LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL  @  tttttttttttttttttttttttttttttttt^^^^^^^^^^^^^^^^BBBBBBBBBBBBBBBB      bbbbbbbbbbbbbbbb   44444444444444444444444444444444 @  @ @ YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYG\MG\M @ MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM    gggggggggggggggg     cccccccccccccccc   JJJJJJJJJJJJJJJJ  zzzzzzzzzzzzzzzz>>>>>>>>>>>>>>>>9999999999999999  ((((((((((((((((   &&&&&&&&&&&&&&&&################ QQQQQQQQQQQQQQQQ @ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF    33333333333333333333333333333333 @   UUUUUUUUUUUUUUUU  jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj  @   %%%%%%%%%%%%%%%%  HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH  OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO@  JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ   LLLLLLLLLLLLLLLL................ 55555555555555555555555555555555 TTTTTTTTTTTTTTTT   @  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ]]]]]]]]]]]]]]]]  oooooooooooooooo }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}  ________________________________ HHHHHHHHHHHHHHHH  eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ????????????????????????????????  @ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    99999999999999999999999999999999"3DUfw IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII eeeeeeeeeeeeeeee @ \\\\\\\\\\\\\\\\   yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy    @ ```````````````````````````````` 8888888888888888 @  DDDDDDDDDDDDDDDD @   wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww  Zm+WYa Pu@[v/U4| M $=k { U{gά6c(+ 4V(tvy΋; M%=!3XGEٌK e>܎4{y rpW:Ze R(`muo) ݲu,Uln Dǎq@\fQ @Vm</bjM lKBRg&$̂ RM$*971 WeD ,Z@k ϧL@b`=ȪS ΢Ի=   UBu"z8e .X v# O/ 7ChhVUc c*s gY<]جYi 1pq[Wa$ a3Nfl.ّ m֊FWg%x՚ 4EFb7Cc]ouG SH==rB_,C ,Շ0j׌kY g` bm ̂U?vM }$~ } PWiΓ!M1 X`cKʡ >f! C 4ec AP5K(xԄ  {y [<{ [[_g.)Z5]' Z0D1q?o ҄k P/!2F%w4g "}}Z :B i_ c0QOgwQK- ԼޟKm5gJ{ mZp;=  &n7;B u2R ̬-0MP $e4bai*/ վ!GG :CRY o=F&T*[v3 W^poVC׳J{ 龳s@،y%7 N=o&(_ Gw9/^K F9to5INy P^Ugiz3Pw c |^_…) QArGsr${ fS@/4 a=] AOCvJ]/.1}! [@8#K u2y 3BhHL^CS8 R9Uc o'|U6/  M^i̓ =F7 ir'h14g ު9$AxGM} ƴf6f-  ,k|cY  -ljճq Q;3~qa`^ b4QqXJ5 E`ыP; A Brq$έH! Y/UfRTxF3Mv)y 2 bFc  ė˟ `r% 'F0D$i  ^7(%  =EZ a 챍pwDmM  E` ı  -*} ;Gaٜ m ;zT| &=[c! tŐH]CdSJq y1B>t ir 1aT ]Ӑȋ] ͩ$(˕!Mji [ 44ﱨ 6bE~ YU jDhy y =)+&!_@  hc0&e o>:ag-[/ p'Tq,LzK(x_ |;Ү#[ L!oJ8R7S  ݙ+Vؔ.i ΘĨv^L& Iσ<6D{ L̳}WhP{ K YQҔ;1 8{ 0iE]R5 jӒkƾD w +)!5f;J#~~ t:f$U)* 8Ceb#lŏjߖ/ *YɩG柆 ! AH!;~-\"a ٕ:.M )e )SG7JQM PV% %w\qW f=)$ IߕDZ}y3Ӈw M^nx>_+[ Kֱ~B:tL< nexGt2U {6;{Lw5Fi> F3(*yȉX# "e:-\Ǧ; TOmBaށ S|Ϋl 9J7 + qn8Np/ [CL)h͆9 uHOm-躅  nmV}0U 'XZwdզφ  > ̂"u PU=e^ODžo =k2qXi  R6*MN0T3  50$15O- 7٢J$~] sEw2XL\[S n)m$pZ$p  wog0pO% ie3c HN 6 %3JO)  "r{d[M eJD3a={ 3*zQ΀#7# 9)%b2o ^?:p"\vb5 ;8sZx(8 6H5  ;)0]%YɇU D!Y v ؄ Ɏ)W(õVS '] j/''Ga  z]Ay6WA1 `_{ ,V-p)00r7ITW A; 5!ʈ3 Mf€\y<^ WB|ŽKH|ˍ  m_ևM>E ? `BI\a˾% [$s5>Hzq eн].! s6AJ0F&; kl bcc)/&G mnQ1nʸcgq 8VŵWh01Wς n|M/cp7DЉ# l=EU4mKτ  9mw a !C [_3b6I wdmh߯K ȡi= u Lf$J!b xEӢUPˢX} xϷ_Da- Bji(jݵ Q ur([8ޭE  qznCR}j65 UB)#oF | 5oFW7}q k1|}b7H$"y E6l%τ1 N~&Mi1Q[  jXӻe GkWV%D$,n9 A3ָ e ;6&dyh]ǀc 6N 4ԍŠpω_ JKYi?^d,qчA ,C)glP6k w|h6QW #L7!y7O qG nތY 3~`Z,m t-Ũ8?dY մ1~oodđ6= vsXmj*P=_z  W̭ʿN\C ·A!҈p U\dd5U7 Y-jiq Ro3p5k =D*XM3Fu- Txpy_Z; nKyR9 tSP'vfd8L1 4/W]q]͋  ?,܂H[O R\$uw5Ό zKS-? R:W# :*|{Zqe zohS t([=}SBQG #!3:Vt! ZJ f؁e ?rMAz/ rCW~b-$̈5 :> k"I7цk D#)VʨЄȽv -r) 0d D$ { R&>H`*ޢU עގ\sFY L( FFռ 1q ]\* )U0o 13\d/i"^m" >(_&bY d&7W W@ײAHex4CC C;AxsZW 5:+iay  Jzٱ~>q?w /B#U)0J<= ^صlm{΁q bxJuA{YG *Pb`IOz,Åm Y5Q7  D)GMoNjTY ϖAN +S I|x<~=:o n8 A ;AUԀk 5+Ix,e Jk&`P;2HhPYO }V1Mz QLt9qU 3RP˹[_kI? jJ0z\k wXf>y61 ?ӑ#Ǫ$`' Zj Ik%"9E /_["tp.m  i>/ P2D5bB pG~@Ru M=Sl :toQnJ3 1k<73*3 q{Ufٵ*_ # pA ŏ8ჟfw *?P@P.@-k ]'6GPX;mz xGAWǵkk u:h"=}5 H <K 0֡&q󈌃2O H޳Vn X = {Lz+o3 B.s %踵$C 2qKÀP0vv_ IF{u`{.p#LO P' .ZBөً/ Q$8c`ĥ?nq0 F(k0tj c 6Igz:Վ>t7  t6/ޢ} L.JRohu J`Px-'5 (`y=3wCU ohs6JP؝xoG O?0_u mu< Dߡ?&u9yvK O)X?+H B]dPVi}·M 1G',wä(:o Zq`Exغr5 |^tMD4Xs Hm=syD/ _ ^MN;UǦc[ ওMAa؞7_ 2*f+xKL_ g}IMs\/u * #gQ* uQ  ^[3y#ĂΌ$j} n1yS 5 FDba1. ܕx@H  ƴaH9+ >f 6dǐ o/ O#|LMԘ- s*?*[°9)օ) Хګa"@so ,-cwd4M 8C85# ϯ4&T\ w# _i!,}R>ւqS ֆ0襘eY-}! K{X΋\7Fu? OOTrc9e Ӏ.sZ-{j!C% {lyp KW{i Tt}<%XL O W^K:U>;B։#Ł37 Ȩ氇oz]S _m!ll~pMI? ~k.;׊ 1 kq%[7DSe 43-Z[k x# k ۮtY*9q */j4hO^8}/ jzSoMy:s8cA +tɴ_ _ HpfK' vp]v;0h w 5|'D.e6!] `F%[ tHֈfEo gmg *x5s`/aE J±o+$߉i ߞtH$6A%ԃwW #PRED{%~قGC v3?&os5 t |AgA -:K𔾽]J<=I |pR۬OԈca 7z"m)ˇuQ ^\#Ojͣ_)! }3P?ęG u0F,U^R ;xRFv9N~-C7 mxv$Iwc-K n9c8m!s Me9}Z~¡~G# ;Xgtg O&רDYQ ".\a{I„IG /$o2p` ] {ƁUu_ _^ڈu }EQ8vo]AC #I ϫIV߈^҆C j?7to9X+3 7BK=G&P8O} 'n ?T~̉; .` f˦QIc[+ vNKK(I:yE Zr$^9x2AyS =nFRB>`(#k 4!7}b hgk U XMɱ[= |G忎b8{ o ɟmݾ;c# rbu|#mҌGc : wzZ=z(:A 2/T(- [ۧJ8:s;qw5gQ s4WކRSIH_ -PȊ|6^=u1[5) }А'^1B)K; qt13,$}-b;Q A$PH0 `! LZ)+&y35 :Q-ny' $DpVC.=w{ YZx`Y}ȿK; If.췃/ q i3fQ9*"9i -_z.Ż΋) r=4foP3? k) e՜= rdogx@+ ^mJiexrZWMs ܞo ]q L #d\<=Q 'Ɵk6)8Be S>ķTڣS})'Y DR-І@MӠI lV佦i~UmC{ D)TS[j7=- [O9Twa a%x 5uAބs FXۆv y17Ɓ/+ ,-TIX+' DQN&G(E>ƀ}u !JӥƷ gY N]_6Q Gi eQ^AI6 M1E# g:l(OSn  %VP~= r!0k÷ c 2#I_"߅T}? |n:/̟7 򙹠I v1Pъw Xzbv Ll)] J.NDl?0B!H3 :20l9V+Gm 8)|M$øC XIS#rKIY rMϠŪ(b[= 'of6;|6ao gW-Che9 .yK˭I] X9ZUR7e 9I JYDys !*8m$' vZo U68P}sbX;A  Mt# @$Kh+ks RZ(^8J+ R*v4@c8 g_ 5n"@nQY4 zȦZʢc {r3m+I*uA n4D4tt`[w v̳()\]GE  @fFHG61H- :tz{Ql&e+ǀq{ 'i /b!vQ) -wW8h7m 3F)h}"E1S Qo$CY:jT=u T$mny?uo /6ᷮy(?{ XL|*'9O TrxQ`-1d}9 e~Jknn_Rԁ Wr؋: )? [Fn&yۚu #DzK1VHI3 {S,-հ>+e @P~|Ȕ"o}+ +4cY+5! vBOv 駅1 Hx^ZFY eiU!iI @t :Uw 3Ħ:UʀEO 7BNd[,qN8g! ZAe&Bim 9()9uǵNԓ) 1L K/ψOA IAg+ys D2=@o'n)r]q O ȣ28+;1v3Y 2hbVAHPDGE EL $NzRҤmo =m30#b1 \mG{P1|΄%g e`݃S1 Pna`tJAҢY} r P`8޹W M`]lY;Eh W ;a3xHqO|Y} }A׬rS7'/ҋM kvʅ 7վOi 5H_5ݝ_*O :,gT̹[33 W&5 T|ݓNzu NQ/\I#  j]΅h') 1 .ʗ&% ) q\gHՆM[ ڂ*} $"s' o0{i)ԅWC Æ ~^$9 ?/ nExk4a<[k ^jdl\Ug1 hf; ިWA GrҪf?{`{'A ԃ㯑Դ+.&Em{ ۮ4H$)9Xƃ% % eDEU i@f9P,i(1E OzxSjb~i .(1C˵eqU +.JVԴP3S 55eu)̓0OCo J̠ZZa%= MJ:o4c Ra8e[bmg 'G;|V}&! xhZw (lֈ? 2'RM 7 W\,n"5 n &D`\)*m+ ^C5W[;7E/ P+ ԇTi-s 9udFv&#hF8!] kF[9xٗ2[VdU[ p]3^땈O=m b )+(9%k |] MxF{ cizsNZ"% l:)4n. j/ !`BBT(mE 0޹r[_m)? ŚC|W\a㳠S% #lv8UW 5L0]1XA Ug>WU"vI- __TӟQ=^ua lvXg5O:ɀG7 I:KFfLY/QE z0ywz}ڈAq %bbL@Vԥr#I L ٨4|i 4_w0X׷쟓b+g '~1  jv ($ 0yS _UWbzI9 `n֪LfCN&܄cY g2Ρ@ɢw n1^ \ObP v[ Q$Ǎ_; p]7%hyc Z_@j'/o77 INERMsQ ;)bQw_ `+ÚQ}m|/ z"ZF/#v c u.XO3مi3DLi sw]jISrX "I:8Ò BRB4fҼ-] (qORdOG X](½'C !fGʂi[Y ѥWbv&i-m # 4ez/M 5w/X\Ӛ} &ԝC0z1 ZGe`ss%$ P⁙f0}Lc I)wCuxR3Y kkJԥ 1O{ `VfhrVgI' )X4?k n猃Ztg n&C&47 ԕ.v- DxaJ{ 䙤e<2-|tl 6W(Ňg| 1Dk`  .%RQѴ͘3w/ Ģꍝa}I{G q x PU[ߧs)3 t2<_dJJX{ `xq^uZ*'7 \̯ZF*d=_ I m˅zVewK (bjJLVH&C~y OF mc սi0F4d`OsU) ?dsg hĉdZ @]/#] h:M*؈MQT! Fb5](R BD-j} <;o yz{y yR1 o c ceIw;,40ِR 7Dח\7 FNfn7]2g 鐧iNpyEᶶ aqi '5 ;M"D \ L![/8 @pJHכ V 7y S=95SW#%  P*ݓq!P$z66% ,9jk.7zrst#K Ŵ /ˋdH3u RLQTh])G z0J ZURp$M 3l_˵ƕ~B,X `@E3a^;m ߶`.6"=?Q'r! hlǏ7KЋ Esq :b2@  !ղ=Ҩ] ިj 4-NPi @ډu" cȧ-ۉK3I~U Q%d%t6y 6bC[m }x5MzMRe B] AM0^/ 7l~jkԲR$a_ 訲VFvq|[<2Y Fܗ*W2h xJtBQ1i BV Gw U~y|.{ QxII[ X߃K F'ْ'KU{ _B?ѠvL5 5PG\1]Jw &,7٪R 88 \[0 Fwwjɥ/ ̪E~>7olei A3 Kpa :j1Pikb* V"' PM [&%봏Kx% yd܎1kg;W CFyr_ Y/KU.w N2+$fgDuNx5[ ( g>Su K 5{dP]6&(^]U LOmom>Bz, /F'|jn4# :k?#6ghc; tUL=%ZF  I1W{' Us,+ [2B^TIs3 o\| {G8DS9 QB>Ci w.s K_0ЄA(U d`%vX5|m "|qi.'iSu IP]2sGaIo ѿs܈_$쮳x -6K9% E >„^\hҎ4- t[o%5pmCP g 7uv|0XS FfD>Nf h_SUP= [% ۇ1S=`2: M_{U  CA *}vpH~k鍯M o)wU.% IYF0N.?l !<^\Ko ^鷎AAU-5 Б^r"f bb9_"! U !@o=ײQ  CTiS c}o/~e_ /ANSM1  E> dp&uos:K 9b^SK- zZSYޠ[ t|۫nq9 Ta%~e?F 3&Ӭ ^9; 2) 05'xV>) 4M-X^->R ]>"ZS9 |`$Y T z}w–Ȩi MR7iYsgcy b~tOE> `XA}YfSmS] '?:YB!(Q cИ{%]:4 \Q /;^4ћ W ɡwƹR3 `!sҎ3OVpnG <$Vlőf冷 ]kĔh? ۻcHA % *7ǝIS->q A˟7ILA! U]Őw wbȸ; AV=:NG ]p~Ft)qq:Vq [n$?7  :TɒiuM# :eq$~Wӓ m/Tc{mC &vq/. 8!dI G8Y ?2K HФ Ѭ}X2Uu #HL%J O _~i*u} ܥ   X - %akl6,߫Q [Af 3nm} X/KO!5 sܒA]1]u$ `jɳN`P}q @=`dЄmg+)3Iy Ns2rSkAJ^1 -o=dz9b<[^  _X4ǔ|e @Dp?^*9 G3OHpu k Ij""c w($)5< [_ ~cv5pA yy gga7O|C Pz&BDF`:CHϏI 0UF%3$}n%ss XxTl`D)M> )by^pLoFOe7 .X8a5q nҕMyFdF5k D(i/- y!ES{$; Ƌ0(6t+0`z(9 D]b)nC1 i:|syU6 eQK,o O +$~ ՟`SC |Z18m P[fS ҹ0 `$h퀀 @rWwe Zͤ;_iZAcTU =~ L XyI iZ% 1gU +ϭL4}{RY ܦ F3 QN q db%.*uo  bqْMh ڔC6'~W E\"![gFMjXM } j7^c)3W ߲(hDgw xKA=U(jesw 9 = 'o#tq ^O[C)G [N`Xs"m gI_/\R._ 92N6f+xLY ?Tbn/C>1S g˔*׷4⻏o ELix-Rw0Dk OT B W4-+K̎<Є) LJ y؇7 9kqF~t]]T  'w6XT >A _]>TI1PkՀ? hEՊLjva pDz@#քa ( W{ -y!g 3 nMŃU HxqBf? !9X∇1 rXOݜ1 - Rmr' 7'STɼyE #Dqj9ӤDq'm 9Otl:9/ eq*ʪ Q  Sk=<& Y  k Fw 9wٌL6۴ YȔTЬ_ 43sAV}q {GJz l6yL)FC  " ) @:E Kq~8͵2:.VJM{ ͞vNHQ% ic}?`3kbF 1g3P_ Sj>}}b; [ Y4as+ !U m^1Iu@# ؕJV.Ax7 Yj E]塔O  \ O$Lr5f喊] 8@C]|jB' y mIʜ&v:!g Yʃx:1q a# 76?o 5-?g\糄K HH :[,+O ")44h 8N= x\\~bc H !IVnЉC XtQn{E.to_ ;Zd  8oQf Ǵf8l5 ggf1 |\sCQ8Km9 BhLg:X+o %d cd_Řү%X,q} fU'Hֲ/  +=~2AK RsDI`"'w e\oqr8! 8, f"ya#]% *iKڝ}[m wqZ&g L(17Ei rGН3! iY&w *U` $WG b$dl(R Cs V*Pn`MT5g xJM k%A= O^2@J#8RIc juuh2 ׁGau C TgJbsln%Q) Pbh|1-Nz! e΀FO2{,2G KPGPـC 1'Yy/|I7- 8zvs>K r3 zms# Nfl tی ZcW%a&ֽY /f oL.z3LG܀QI %q/c-%NׄG v@ *]u ب{<gdA kM"9݊rC 0Z.cdMC ZыQY|SkQ3O /0 M)}; idDy|@ME塃[ #?^HV+y ׈O-" CEy `#x@ˑ&S# XSYC"TV]kg eǻnj+l%fk[ $qrגً= Nx:{ǹ"ZNϩo# 6NI 0 aO G YS`kࢊc b i-. PZOϗA 2?tiGig Q$?w">BQ 9s{vj_# oMo@ nhh+ t"yRt^hoI'w +uC n Ma T7\~tv2x ? Ķv_~?%%݁g g1G&TwH!)K *,֯ 2Q=;; .m&7$5Q! }7aCnOm i?Pq`5y ~iܚ$Qk'{ Q,[j  K :6ߥuKʆ; 9bY+zl$q9 hǵ#Ai s0akKa[EPr)3 @oE)9U? ")$(ֵ == "yU*qtg`⥄+s sN`" g-DMn(*$%= qߚ?U[.L= Qe 8FfV_ ' b(ʶIv4{\YI n:)Bʧ`uU{ 0m(w3 -A= 5٪6m/_ *̢8)7(c +9c#gcC0hu dJOV A[ p%l?ԌwE 7ȳRs{ &nQ諚jƜ%m˄-q ִyaM$H"!{ Ty[S,s!ˆ7)Q \ZiZԪ7 Mi݁m/褃w 8[ n>kϏb93 S{dg!Q靋Uk ׶)Ykhi|҈}' Xo Ɇ8euW ؕԇo PbE O /e.r=Ę7 'rߐ m "k Ӈ"AS= h}8'Ye]]5>uo , ^NjXX !? mSu2NB{9 6{9ι CbO9 K3zݶs;M& :/>3/{) {0!LSd7OIR? .3}jb6I\uI bV3}"`_M֋3+ CQu)orߎΈe} /+j| ,+5 JP|~5 ! m0EsŢ8~1Y \OMNN j̀i TWW<9T[Iw k"1xr3 5ԈE a{VBZiɜڄOg e/јYҊg*T!i tp7< eSm 2g4Ȁ;0oj)O @0vNXs#ˆ]_Ay n2B}0}As] ۫M6&X[Cq3 %B:L_sYE HN K?gxłm aKdb ߠ V?o1 !v-. z& % JBHwՊgS 4_ہˠr1Y I.;} ?b( ӇO3 Kc' .͇׆3u Z~{9Ij6 lyaW˕š _!1L1 v?AFBWD%M f/Mo|X?[s pif73^%N'W OT4P@1|C? :?1e,!>V䎇/[ o's(0}Hqk1 ࣀlN`KVΣlW ?.(,ā2A' fRx*Qv0A{ uRe<3w|% I rbIOPʼnq9E ճEk1Qگ$U1 dGp8ԊEi Bi{OU ANTcUw.' 3 WRM;prȞSC kӌj_]1c-muo Uszy9{ ~^= A@^t ǒpӳcm )Q`%g! 75\L#E!!2mz? c `(ew7 A7CnYz3  GjBfmk A 2h e 㤁fK{% s,y/ Yp`_%BX/m }ikE .V1FO 0˧?S }ihW'7 )k?%U |Ʋ|W :XA`"xA \x"Q dO-u 97AjRdHlaG _+kJ꠽7Q B öwЫ> EA v,U ]q# lFyÆJ)H-?I e (3i+ U\`dՖy=g ,#~t` ٢쏑*y `X יeR˶SI 蘤ZX Iጫ9c #3-9k?Y -_ hn-̖ow @;C|j_ PIhݷUҤ;y / mK<Ag{c7 cUa?2np s 7GM djFPhQ_ lR]UsQ|C y{<ĂO P 4?  (!%O 9{-_|s>Uc 괇-($u{b# •J0%OdQoKaes-soft-0.6.4/tests/lib.rs010064400007650000024000000004551374763301300137120ustar 00000000000000//! Test vectors are from NESSIE: //! https://www.cosic.esat.kuleuven.be/nessie/testvectors/ cipher::block_cipher_test!(aes128_test, "aes128", aes_soft::Aes128); cipher::block_cipher_test!(aes192_test, "aes192", aes_soft::Aes192); cipher::block_cipher_test!(aes256_test, "aes256", aes_soft::Aes256);