diff --git a/README.md b/README.md
index 76333e836..08a9a3cfa 100644
--- a/README.md
+++ b/README.md
@@ -397,7 +397,7 @@ yours to keep:
✅ |
-❌ |
+✅ |
❌ |
diff --git a/bench/benches/primitives/main.rs b/bench/benches/primitives/main.rs
index 410085f86..92ffdd997 100644
--- a/bench/benches/primitives/main.rs
+++ b/bench/benches/primitives/main.rs
@@ -45,6 +45,7 @@ mod sha224;
mod sha256;
mod sha3;
mod sha512;
+mod triple_des_ecb;
mod x25519;
mod x448;
@@ -212,6 +213,7 @@ const BENCHES: &[Bench] = &[
(pbkdf2_sha512::USES, pbkdf2_sha512::bench),
(poly1305::USES, poly1305::bench),
(rc2_cbc::USES, rc2_cbc::bench),
+ (triple_des_ecb::USES, triple_des_ecb::bench),
(scrypt::USES, scrypt::bench),
(sha1::USES, sha1::bench),
(sha224::USES, sha224::bench),
diff --git a/bench/benches/primitives/triple_des_ecb.rs b/bench/benches/primitives/triple_des_ecb.rs
new file mode 100644
index 000000000..a7d2a4f25
--- /dev/null
+++ b/bench/benches/primitives/triple_des_ecb.rs
@@ -0,0 +1,63 @@
+//! Triple DES ECB, including key expansion and in-place encryption/decryption.
+
+use criterion::Criterion;
+
+/// The library modules whose code these benchmarks run.
+pub const USES: &[&str] = &["triple_des_ecb", "triple_des"];
+
+#[cfg(target_arch = "x86_64")]
+pub fn bench(c: &mut Criterion) {
+ use std::hint::black_box;
+
+ use criterion::{BenchmarkId, Throughput};
+ use openssl::nid::Nid;
+ use openssl::symm::{Cipher, Crypter, Mode};
+ use verified_garbage::triple_des_ecb::TripleDesEcb;
+
+ use crate::{OPENSSL, SIZES, VG};
+
+ let key: Vec<_> = (0..24).map(|i| (17 * i + 3) as u8).collect();
+ for (key_len, cipher) in [
+ (16, Cipher::from_nid(Nid::DES_EDE_ECB).unwrap()),
+ (24, Cipher::des_ede3_ecb()),
+ ] {
+ for (operation, encrypt, mode) in [
+ ("encrypt", true, Mode::Encrypt),
+ ("decrypt", false, Mode::Decrypt),
+ ] {
+ let mut group = c.benchmark_group(format!("3des-ecb-{operation}-{key_len}"));
+ for size in SIZES {
+ group.throughput(Throughput::Bytes(size as u64));
+ let data = vec![0x5a; size];
+ let mut buffer = vec![0; size];
+ group.bench_function(BenchmarkId::new(VG, size), |b| {
+ b.iter(|| {
+ let ctx = TripleDesEcb::new(black_box(&key[..key_len])).unwrap();
+ buffer.copy_from_slice(black_box(&data));
+ if encrypt {
+ ctx.encrypt(black_box(&mut buffer)).unwrap();
+ } else {
+ ctx.decrypt(black_box(&mut buffer)).unwrap();
+ }
+ black_box(&buffer);
+ })
+ });
+ let mut output = vec![0; size + 8];
+ group.bench_function(BenchmarkId::new(OPENSSL, size), |b| {
+ b.iter(|| {
+ let mut ctx =
+ Crypter::new(cipher, mode, black_box(&key[..key_len]), None).unwrap();
+ ctx.pad(false);
+ let n = ctx.update(black_box(&data), &mut output).unwrap();
+ let n = n + ctx.finalize(&mut output[n..]).unwrap();
+ black_box(&output[..n]);
+ })
+ });
+ }
+ group.finish();
+ }
+ }
+}
+
+#[cfg(not(target_arch = "x86_64"))]
+pub fn bench(_: &mut Criterion) {}
diff --git a/lean/VerifiedGarbage/Artifacts/TripleDes/X86_64.lean b/lean/VerifiedGarbage/Artifacts/TripleDes/X86_64.lean
new file mode 100644
index 000000000..50bd06ee3
--- /dev/null
+++ b/lean/VerifiedGarbage/Artifacts/TripleDes/X86_64.lean
@@ -0,0 +1,56 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.VerifiedBlock
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Verified
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.Verified
+
+namespace VG.Artifacts.TripleDes.X86_64
+
+def artifacts : List Artifact := [
+ { Spec.TripleDes.expandKeyApi with
+ target := X86_64.target
+ doc := Spec.TripleDes.expandKeyApi.doc
+ (notes := ["Baseline x86-64 scalar key expansion with fixed permutations and public round-count branches."])
+ code := Impl.TripleDes.X86_64.Key.expandKey
+ contract := Spec.TripleDes.expandKeyContract X86_64.abi
+ stack := 0
+ verified := Proof.TripleDes.X86_64.Key.verified
+ spSafe := Code.all_of_allInstrs (by lit_decide) },
+ { Spec.TripleDes.encryptBlockApi with
+ target := X86_64.target
+ doc := Spec.TripleDes.encryptBlockApi.doc
+ (notes := ["Baseline x86-64 scalar Boolean S-box circuits; IP and FP shared across all three DES passes."])
+ code := Impl.TripleDes.X86_64.encryptBlock
+ contract := Spec.TripleDes.encryptBlockContract X86_64.abi
+ stack := 0
+ verified := Proof.TripleDes.X86_64.encrypt_verified
+ spSafe := Code.all_of_allInstrs (by lit_decide) },
+ { Spec.TripleDes.decryptBlockApi with
+ target := X86_64.target
+ doc := Spec.TripleDes.decryptBlockApi.doc
+ (notes := ["Baseline x86-64 scalar Boolean S-box circuits with reverse EDE key order."])
+ code := Impl.TripleDes.X86_64.decryptBlock
+ contract := Spec.TripleDes.decryptBlockContract X86_64.abi
+ stack := 0
+ verified := Proof.TripleDes.X86_64.decrypt_verified
+ spSafe := Code.all_of_allInstrs (by lit_decide) },
+ { Spec.TripleDes.ecbEncryptApi with
+ target := X86_64.target
+ doc := Spec.TripleDes.ecbEncryptApi.doc
+ (notes := ["Baseline x86-64, calling the verified Triple DES block primitive for each complete block."])
+ code := Impl.TripleDes.X86_64.Ecb.encrypt
+ contract := Spec.TripleDes.ecbEncryptContract X86_64.abi 8
+ stack := 8
+ ofSig := ⟨_, _, _, by unfold Spec.TripleDes.ecbEncryptContract Spec.TripleDes.ecbContract; rfl⟩
+ verified := Proof.TripleDes.X86_64.Ecb.encrypt_verified
+ spSafe := Code.all_of_allInstrs (by lit_decide) },
+ { Spec.TripleDes.ecbDecryptApi with
+ target := X86_64.target
+ doc := Spec.TripleDes.ecbDecryptApi.doc
+ (notes := ["Baseline x86-64, calling the verified Triple DES block primitive for each complete block."])
+ code := Impl.TripleDes.X86_64.Ecb.decrypt
+ contract := Spec.TripleDes.ecbDecryptContract X86_64.abi 8
+ stack := 8
+ ofSig := ⟨_, _, _, by unfold Spec.TripleDes.ecbDecryptContract Spec.TripleDes.ecbContract; rfl⟩
+ verified := Proof.TripleDes.X86_64.Ecb.decrypt_verified
+ spSafe := Code.all_of_allInstrs (by lit_decide) }]
+
+end VG.Artifacts.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Impl/TripleDes/Circuit.lean b/lean/VerifiedGarbage/Impl/TripleDes/Circuit.lean
new file mode 100644
index 000000000..6db5ad797
--- /dev/null
+++ b/lean/VerifiedGarbage/Impl/TripleDes/Circuit.lean
@@ -0,0 +1,312 @@
+import VerifiedGarbage.Impl.Aes.Circuit
+
+/-!
+# DES Boolean S-box circuits
+
+Untrusted. These circuits are synthesized from the specification's S-boxes
+using Davio decomposition and shared subexpressions. Inputs 0–5 and outputs
+0–3 are numbered least significant bit first. The proof checks all 64
+inputs against FIPS 46-3, and checks the allocated machine code independently.
+The existing AES circuit gate representation and allocator are reused;
+no cryptographic AES operation is called.
+-/
+
+namespace VG.Impl.TripleDes.Circuit
+
+open VG.Impl.Aes.Circuit
+
+def box0 : List Gate := [
+ xor 6 0 0, xnor 8 0 6, and 9 4 8,
+ xor 10 0 4, and 11 1 10, xor 12 9 11,
+ xor 13 8 9, and 14 1 13, xor 15 0 14,
+ and 16 5 15, xor 17 12 16, and 18 4 0,
+ xnor 19 18 6, and 20 1 19, xor 21 18 20,
+ xnor 22 4 6, xor 23 22 20, and 24 5 23,
+ xor 25 21 24, and 26 3 25, xor 27 17 26,
+ and 28 1 4, xor 29 19 28, and 30 1 22,
+ xor 31 8 30, and 32 5 31, xor 33 29 32,
+ and 34 1 8, xor 35 13 34, and 36 5 35,
+ and 37 3 36, xor 38 33 37, and 39 2 38,
+ xor 40 27 39, xor 41 8 18, xor 42 41 30,
+ xnor 43 9 6, and 44 1 41, xor 45 43 44,
+ and 46 5 45, xor 47 42 46, xnor 48 13 6,
+ xor 49 48 30, and 50 1 9, xor 51 9 50,
+ and 52 5 51, xor 53 49 52, and 54 3 53,
+ xor 55 47 54, xor 56 45 52, and 57 1 0,
+ xor 58 43 57, and 59 5 58, xor 60 13 59,
+ and 61 3 60, xor 62 56 61, and 63 2 62,
+ xor 64 55 63, xor 65 13 57, and 66 5 49,
+ xor 67 65 66, xor 68 19 34, and 69 1 48,
+ xor 70 43 69, and 71 5 70, xor 72 68 71,
+ and 73 3 72, xor 74 67 73, and 75 5 20,
+ xor 76 49 75, xor 77 0 57, xor 78 77 59,
+ and 79 3 78, xor 80 76 79, and 81 2 80,
+ xor 82 74 81, xnor 83 10 6, xor 84 83 1,
+ xnor 85 20 6, and 86 5 85, xor 87 84 86,
+ xnor 88 23 6, and 89 5 88, xor 90 22 89,
+ and 91 3 90, xor 92 87 91, xor 93 13 28,
+ and 94 5 93, xor 95 57 94, xor 96 13 1,
+ and 97 5 96, xor 98 84 97, and 99 3 98,
+ xor 100 95 99, and 101 2 100, xor 102 92 101]
+
+def outputs0 : List Nat := [40, 64, 82, 102]
+
+def box1 : List Gate := [
+ xor 6 0 0, xnor 7 0 0, xnor 8 5 6,
+ and 9 1 5, xor 10 5 9, and 11 0 10,
+ xor 12 8 11, xnor 13 9 6, and 14 0 13,
+ xor 15 10 14, and 16 4 15, xor 17 12 16,
+ and 18 1 8, xor 19 8 18, xnor 20 10 6,
+ and 21 0 20, xor 22 19 21, xnor 23 19 6,
+ and 24 0 23, xor 25 1 24, and 26 4 25,
+ xor 27 22 26, and 28 3 27, xor 29 17 28,
+ and 30 0 18, xor 31 7 30, xor 32 5 1,
+ and 33 0 32, xor 34 1 33, and 35 4 34,
+ xor 36 31 35, and 37 2 36, xor 38 29 37,
+ xnor 39 32 6, and 40 0 9, xor 41 39 40,
+ xor 42 20 33, and 43 4 42, xor 44 41 43,
+ xor 45 23 16, and 46 3 45, xor 47 44 46,
+ and 48 0 19, xor 49 5 48, and 50 4 49,
+ xor 51 13 50, and 52 0 8, xor 53 19 52,
+ and 54 4 5, xor 55 53 54, and 56 3 55,
+ xor 57 51 56, and 58 2 57, xor 59 47 58,
+ xor 60 39 0, xor 61 60 4, xor 62 13 40,
+ and 63 4 62, xor 64 0 63, and 65 3 64,
+ xor 66 61 65, and 67 0 1, xor 68 7 67,
+ xor 69 13 14, and 70 4 69, xor 71 68 70,
+ and 72 3 67, xor 73 71 72, and 74 2 73,
+ xor 75 66 74, xor 76 39 14, and 77 4 21,
+ xor 78 76 77, xnor 79 40 6, xor 80 8 52,
+ and 81 4 80, xor 82 79 81, and 83 3 82,
+ xor 84 78 83, xor 85 18 40, xnor 86 85 6,
+ and 87 4 86, xor 88 85 87, and 89 2 88,
+ xor 90 84 89]
+
+def outputs1 : List Nat := [38, 59, 75, 90]
+
+def box2 : List Gate := [
+ xor 6 0 0, xnor 7 0 0, xnor 8 5 6,
+ and 9 4 8, xor 10 5 9, and 11 4 5,
+ xor 12 8 11, and 13 0 12, xor 14 10 13,
+ xnor 15 12 6, and 16 0 11, xor 17 15 16,
+ and 18 1 17, xor 19 14 18, and 20 1 12,
+ xor 21 17 20, and 22 3 21, xor 23 19 22,
+ and 24 0 5, xor 25 7 24, and 26 1 8,
+ xor 27 25 26, and 28 3 16, xor 29 27 28,
+ and 30 2 29, xor 31 23 30, xor 32 8 4,
+ xor 33 32 13, xnor 34 9 6, and 35 0 9,
+ xor 36 34 35, and 37 1 36, xor 38 33 37,
+ xnor 39 4 6, and 40 0 39, xor 41 4 40,
+ and 42 0 8, xor 43 8 42, and 44 1 43,
+ xor 45 41 44, and 46 3 45, xor 47 38 46,
+ xnor 48 14 6, xnor 49 33 6, and 50 1 49,
+ xor 51 48 50, xnor 52 10 6, and 53 0 52,
+ xor 54 34 53, xnor 55 42 6, and 56 1 55,
+ xor 57 54 56, and 58 3 57, xor 59 51 58,
+ and 60 2 59, xor 61 47 60, and 62 0 34,
+ xor 63 15 62, xnor 64 36 6, and 65 1 64,
+ xor 66 63 65, xor 67 36 37, and 68 3 67,
+ xor 69 66 68, xor 70 9 40, xor 71 70 56,
+ and 72 1 24, xor 73 9 72, and 74 3 73,
+ xor 75 71 74, and 76 2 75, xor 77 69 76,
+ xor 78 34 24, xor 79 78 1, xnor 80 32 6,
+ and 81 0 80, xor 82 39 81, and 83 1 82,
+ xor 84 12 83, and 85 3 84, xor 86 79 85,
+ xor 87 10 42, xor 88 52 53, and 89 1 88,
+ xor 90 87 89, and 91 1 42, xor 92 52 91,
+ and 93 3 92, xor 94 90 93, and 95 2 94,
+ xor 96 86 95]
+
+def outputs2 : List Nat := [31, 61, 77, 96]
+
+def box3 : List Gate := [
+ xor 6 0 0, xnor 7 0 0, xnor 8 3 6,
+ and 9 1 3, xor 10 8 9, and 11 5 10,
+ xor 12 8 11, xor 13 3 1, xnor 14 13 6,
+ and 15 5 14, xor 16 13 15, and 17 4 16,
+ xor 18 12 17, xnor 19 1 6, xor 20 1 15,
+ and 21 4 20, xor 22 19 21, and 23 2 22,
+ xor 24 18 23, xnor 25 10 6, and 26 5 25,
+ xor 27 14 26, and 28 4 27, xor 29 20 28,
+ xnor 30 9 6, and 31 1 8, xor 32 7 31,
+ and 33 5 32, xor 34 30 33, and 35 4 13,
+ xor 36 34 35, and 37 2 36, xor 38 29 37,
+ and 39 0 38, xor 40 24 39, and 41 5 31,
+ xor 42 14 41, xnor 43 33 6, and 44 4 43,
+ xor 45 42 44, xor 46 31 33, xor 47 3 15,
+ and 48 4 47, xor 49 46 48, and 50 2 49,
+ xor 51 45 50, xnor 52 38 6, and 53 0 52,
+ xor 54 51 53, xor 55 10 33, and 56 4 8,
+ xor 57 55 56, xor 58 1 48, and 59 2 58,
+ xor 60 57 59, xnor 61 42 6, xor 62 32 41,
+ and 63 4 62, xor 64 61 63, xor 65 19 11,
+ xor 66 65 35, and 67 2 66, xor 68 64 67,
+ and 69 0 68, xor 70 60 69, xor 71 31 5,
+ xor 72 3 31, xor 73 72 41, and 74 4 73,
+ xor 75 71 74, xnor 76 11 6, xor 77 76 21,
+ and 78 2 77, xor 79 75 78, xnor 80 68 6,
+ and 81 0 80, xor 82 79 81]
+
+def outputs3 : List Nat := [40, 54, 70, 82]
+
+def box4 : List Gate := [
+ xor 6 0 0, xnor 7 0 0, xnor 8 3 6,
+ and 9 8 5, xor 10 7 9, xnor 11 0 6,
+ and 12 11 10, xor 13 5 12, xnor 14 5 6,
+ and 15 8 14, xor 16 14 15, xnor 17 4 6,
+ and 18 17 16, xor 19 13 18, xor 20 14 9,
+ and 21 17 20, xor 22 3 21, xnor 23 2 6,
+ and 24 23 22, xor 25 19 24, and 26 11 14,
+ xor 27 8 26, xor 28 5 8, and 29 11 9,
+ xor 30 28 29, and 31 17 30, xor 32 27 31,
+ xnor 33 16 6, and 34 11 33, xor 35 14 11,
+ and 36 17 35, xor 37 34 36, and 38 23 37,
+ xor 39 32 38, xnor 40 1 6, and 41 40 39,
+ xor 42 25 41, and 43 11 16, xor 44 10 43,
+ xor 45 44 17, xnor 46 15 6, and 47 11 46,
+ xor 48 7 47, and 49 11 15, and 50 17 49,
+ xor 51 48 50, and 52 23 51, xor 53 45 52,
+ xor 54 20 49, and 55 17 54, xor 56 3 55,
+ and 57 11 5, xor 58 14 57, and 59 17 58,
+ xor 60 47 59, and 61 23 60, xor 62 56 61,
+ and 63 40 62, xor 64 53 63, xor 65 16 11,
+ xor 66 65 17, xor 67 46 43, xor 68 28 47,
+ and 69 17 68, xor 70 67 69, and 71 23 70,
+ xor 72 66 71, xnor 73 28 6, and 74 11 73,
+ xor 75 16 74, and 76 23 75, xor 77 10 76,
+ and 78 40 77, xor 79 72 78, xor 80 8 47,
+ and 81 17 13, xor 82 80 81, xor 83 20 11,
+ and 84 17 83, xor 85 58 84, and 86 23 85,
+ xor 87 82 86, xor 88 73 12, and 89 11 3,
+ xor 90 28 89, and 91 17 90, xor 92 88 91,
+ xnor 93 20 6, xor 94 93 74, xnor 95 57 6,
+ and 96 17 95, xor 97 94 96, and 98 23 97,
+ xor 99 92 98, and 100 40 99, xor 101 87 100]
+
+def outputs4 : List Nat := [42, 64, 79, 101]
+
+def box5 : List Gate := [
+ xor 6 0 0, xnor 7 0 0, xnor 8 4 6,
+ and 9 3 8, xor 10 9 1, xor 11 4 9,
+ and 12 1 3, xor 13 11 12, and 14 2 13,
+ xor 15 10 14, xnor 16 12 6, xnor 17 3 6,
+ and 18 1 17, xor 19 3 18, and 20 2 19,
+ xor 21 16 20, and 22 5 21, xor 23 15 22,
+ xor 24 8 3, and 25 1 24, xor 26 9 25,
+ and 27 2 26, and 28 3 4, xor 29 8 28,
+ xnor 30 24 6, xor 31 30 25, and 32 2 31,
+ xor 33 29 32, and 34 5 33, xor 35 27 34,
+ and 36 0 35, xor 37 23 36, and 38 1 9,
+ xor 39 28 38, and 40 1 4, xor 41 7 40,
+ and 42 2 41, xor 43 39 42, xor 44 11 18,
+ and 45 2 40, xor 46 44 45, and 47 5 46,
+ xor 48 43 47, and 49 2 1, xor 50 41 49,
+ xor 51 17 38, and 52 1 8, and 53 2 52,
+ xor 54 51 53, and 55 5 54, xor 56 50 55,
+ and 57 0 56, xor 58 48 57, xor 59 24 18,
+ xor 60 8 12, and 61 2 60, xor 62 59 61,
+ xnor 63 9 6, and 64 1 28, xor 65 63 64,
+ and 66 2 25, xor 67 65 66, and 68 5 67,
+ xor 69 62 68, xnor 70 45 6, xor 71 9 38,
+ xor 72 28 1, and 73 2 72, xor 74 71 73,
+ and 75 5 74, xor 76 70 75, and 77 0 76,
+ xor 78 69 77, xor 79 29 1, xor 80 79 20,
+ and 81 5 19, xor 82 80 81, xor 83 63 18,
+ and 84 2 83, xor 85 19 84, and 86 1 63,
+ xor 87 63 86, xor 88 29 52, and 89 2 88,
+ xor 90 87 89, and 91 5 90, xor 92 85 91,
+ and 93 0 92, xor 94 82 93]
+
+def outputs5 : List Nat := [37, 58, 78, 94]
+
+def box6 : List Gate := [
+ xor 6 0 0, xnor 7 0 0, xor 8 5 0,
+ and 9 0 5, and 10 2 9, xor 11 8 10,
+ xnor 12 9 6, and 13 2 12, xor 14 7 13,
+ and 15 3 14, xor 16 11 15, xnor 17 5 6,
+ and 18 0 17, and 19 2 18, xor 20 7 19,
+ and 21 3 12, xor 22 20 21, and 23 4 22,
+ xor 24 16 23, and 25 3 13, xor 26 14 25,
+ and 27 2 0, xor 28 9 27, and 29 4 28,
+ xor 30 26 29, and 31 1 30, xor 32 24 31,
+ xor 33 9 2, xnor 34 8 6, xor 35 34 19,
+ and 36 3 35, xor 37 33 36, and 38 2 5,
+ xor 39 7 38, xor 40 5 9, xor 41 40 19,
+ and 42 3 41, xor 43 39 42, and 44 4 43,
+ xor 45 37 44, xor 46 17 18, xnor 47 0 6,
+ and 48 2 47, xor 49 46 48, xor 50 49 42,
+ and 51 2 34, and 52 3 40, xor 53 51 52,
+ and 54 4 53, xor 55 50 54, and 56 1 55,
+ xor 57 45 56, xnor 58 40 6, and 59 2 17,
+ xor 60 58 59, and 61 3 5, xor 62 60 61,
+ xor 63 34 13, xor 64 12 38, and 65 3 64,
+ xor 66 63 65, and 67 4 66, xor 68 62 67,
+ and 69 2 8, and 70 3 69, xor 71 7 70,
+ and 72 4 19, xor 73 71 72, and 74 1 73,
+ xor 75 68 74, xor 76 18 38, xor 77 76 21,
+ xor 78 5 59, and 79 2 46, xor 80 46 79,
+ and 81 3 80, xor 82 78 81, and 83 4 82,
+ xor 84 77 83, xor 85 58 10, xor 86 5 79,
+ and 87 3 86, xor 88 85 87, xor 89 38 61,
+ and 90 4 89, xor 91 88 90, and 92 1 91,
+ xor 93 84 92]
+
+def outputs6 : List Nat := [32, 57, 75, 93]
+
+def box7 : List Gate := [
+ xor 6 0 0, xnor 7 0 0, xnor 8 0 6,
+ xor 9 5 8, xnor 10 3 6, xor 11 9 10,
+ xnor 12 1 6, xor 13 11 12, and 14 10 0,
+ and 15 8 5, and 16 10 15, xor 17 8 16,
+ and 18 12 17, xor 19 14 18, xnor 20 4 6,
+ and 21 20 19, xor 22 13 21, xnor 23 5 6,
+ and 24 8 23, xor 25 7 24, xor 26 25 14,
+ and 27 12 26, xor 28 8 27, xor 29 5 15,
+ and 30 10 29, xor 31 7 30, and 32 12 23,
+ xor 33 31 32, and 34 20 33, xor 35 28 34,
+ xnor 36 2 6, and 37 36 35, xor 38 22 37,
+ xnor 39 15 6, xor 40 39 30, xnor 41 29 6,
+ and 42 10 41, xor 43 23 42, and 44 12 43,
+ xor 45 40 44, xnor 46 16 6, and 47 12 16,
+ xor 48 46 47, and 49 20 48, xor 50 45 49,
+ xor 51 5 24, xor 52 51 14, and 53 12 9,
+ xor 54 52 53, xnor 55 52 6, xnor 56 51 6,
+ and 57 12 56, xor 58 55 57, and 59 20 58,
+ xor 60 54 59, and 61 36 60, xor 62 50 61,
+ xor 63 24 16, and 64 10 39, xor 65 5 64,
+ and 66 12 65, xor 67 63 66, xor 68 39 42,
+ and 69 20 68, xor 70 67 69, xor 71 39 32,
+ xor 72 15 16, xor 73 72 32, and 74 20 73,
+ xor 75 71 74, and 76 36 75, xor 77 70 76,
+ and 78 12 46, xor 79 65 78, and 80 10 24,
+ xor 81 15 80, xor 82 0 30, and 83 12 82,
+ xor 84 81 83, and 85 20 84, xor 86 79 85,
+ xor 87 25 53, xnor 88 81 6, and 89 12 41,
+ xor 90 88 89, and 91 20 90, xor 92 87 91,
+ and 93 36 92, xor 94 86 93]
+
+def outputs7 : List Nat := [38, 62, 77, 94]
+
+def gates (i : Nat) : List Gate :=
+ match i with
+ | 0 => box0
+ | 1 => box1
+ | 2 => box2
+ | 3 => box3
+ | 4 => box4
+ | 5 => box5
+ | 6 => box6
+ | _ => box7
+
+def outputs (i : Nat) : List Nat :=
+ match i with
+ | 0 => outputs0
+ | 1 => outputs1
+ | 2 => outputs2
+ | 3 => outputs3
+ | 4 => outputs4
+ | 5 => outputs5
+ | 6 => outputs6
+ | _ => outputs7
+
+end VG.Impl.TripleDes.Circuit
diff --git a/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Block.lean b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Block.lean
new file mode 100644
index 000000000..3248ed18d
--- /dev/null
+++ b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Block.lean
@@ -0,0 +1,96 @@
+import VerifiedGarbage.Impl.TripleDes.X86_64.Common
+import VerifiedGarbage.Impl.TripleDes.X86_64.Sbox
+
+/-!
+# Scalar Triple DES blocks on x86-64
+
+Two 32-bit Feistel halves stay in `r12` and `r13`. S-box input bits are
+formed with fixed shifts and XORs with the round key, passed through Boolean
+circuits, and XORed directly into their P-permuted destinations. The three
+passes share IP and FP. Round counters and key addresses are public.
+Scratch slots 0–5 save callee-saved registers, 6 saves the schedule pointer,
+7 holds the round counter, and 8–55 are the S-box's fixed spills.
+-/
+
+namespace VG.Impl.TripleDes.X86_64
+
+open VG.X86_64
+open VG.Spec.TripleDes (Direction)
+
+def savedRegs : List Reg := [.rbx, .rbp, .r12, .r13, .r14, .r15]
+
+def blockSave : List Instr :=
+ (savedRegs.zipIdx.map fun (r, i) => .store (memOp .rdx (8 * i)) r) ++
+ [.store (memOp .rdx 48) .rdi]
+
+def blockRestore : List Instr :=
+ (savedRegs.zipIdx.map fun (r, i) => .mov r (.mem (memOp .rdx (8 * i)))) ++
+ [.mov .rdi (.mem (memOp .rdx 48))]
+
+def blockLoad : List Instr :=
+ ([.mov .rax (.mem (memOp .rsi 0)), .bswap .rax] : List Instr) ++
+ permuteCode Spec.TripleDes.ip 64 .rbx .rax .rbp ++
+ [rr .r12 .rbx, .shift .shr .r12 32, .mov32 .r13 (.reg .rbx)]
+
+/-- Six inputs, least significant first, for public S-box number `i`.
+The source R bit comes directly from E; the key's upper sixteen bits are
+never read as cipher bits. -/
+def sboxInputs (i : Nat) : List Instr :=
+ ([.mov .rbx (.mem (memOp .rdi 0))] : List Instr) ++ (List.range 6).flatMap fun j =>
+ let k := 6 * i + 5 - j
+ [rr (q j) .r13] ++ shr (q j) (32 - Spec.TripleDes.expansion.getD k 1) ++
+ [rr .rbp .rbx] ++ shr .rbp (47 - k) ++
+ [.alu .xor (q j) (.reg .rbp), .alu .and (q j) (.imm 1)]
+
+/-- Deposit each output's low bit directly into its destination in L.
+The P table contains all 32 positions, so each destination is unique. -/
+def sboxOutputs (i : Nat) : List Instr :=
+ (List.range 4).flatMap fun j =>
+ let position := 4 * i + 4 - j
+ let dst := (Spec.TripleDes.p.toList.findIdx? (· == position)).getD 0
+ [.alu .and (q j) (.imm 1)] ++ placeBit (q j) (31 - dst) ++
+ ([.alu .xor .r12 (.reg (q j))] : List Instr)
+
+def box (i : Nat) : List Instr := sboxInputs i ++ sboxCode i ++ sboxOutputs i
+
+def swapHalves : List Instr := [rr .rax .r12, rr .r12 .r13, rr .r13 .rax]
+
+def roundBody : List Instr := (List.range 8).flatMap box ++ swapHalves
+
+def roundCountAdvance : List Instr :=
+ [.mov .rax (.mem (memOp .rdx 56)), .alu .sub .rax (.imm 1),
+ .store (memOp .rdx 56) .rax]
+
+def roundAdvance (direction : Direction) : List Instr :=
+ ([.alu (if direction = .encrypt then .add else .sub) .rdi (.imm 8)] : List Instr) ++
+ roundCountAdvance
+
+def passStart (component : Nat) (direction : Direction) : List Instr :=
+ [.mov .rdi (.mem (memOp .rdx 48)),
+ .alu .add .rdi (.imm (BitVec.ofNat 32 (128 * component +
+ if direction = .encrypt then 0 else 120))),
+ imm .rax 16, .store (memOp .rdx 56) .rax]
+
+def pass (component : Nat) (direction : Direction) : Prog isa :=
+ .seq (.block (passStart component direction))
+ (.seq (.loop (.block (roundBody ++ roundAdvance direction)) .ne) (.block swapHalves))
+
+def blockStore : List Instr :=
+ [rr .rax .r12, .shift .ror .rax 32, .alu .xor .rax (.reg .r13)] ++
+ permuteCode Spec.TripleDes.fp 64 .rbx .rax .rbp ++
+ [.bswap .rbx, rr .rax .rbx]
+
+def blockBody (direction : Direction) : Prog isa :=
+ match direction with
+ | .encrypt => .seq (pass 0 .encrypt) (.seq (pass 1 .decrypt) (pass 2 .encrypt))
+ | .decrypt => .seq (pass 2 .decrypt) (.seq (pass 1 .encrypt) (pass 0 .decrypt))
+
+def block (direction : Direction) : Prog isa :=
+ .seq (.block (blockSave ++ blockLoad))
+ (.seq (blockBody direction) (.block (blockStore ++ blockRestore ++
+ ([.store (memOp .rsi 0) .rax] : List Instr))))
+
+def encryptBlock : Prog isa := block .encrypt
+def decryptBlock : Prog isa := block .decrypt
+
+end VG.Impl.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Common.lean b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Common.lean
new file mode 100644
index 000000000..9fa3ae627
--- /dev/null
+++ b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Common.lean
@@ -0,0 +1,26 @@
+import VerifiedGarbage.Spec.TripleDes
+import VerifiedGarbage.TCB.X86_64.Isa
+
+namespace VG.Impl.TripleDes.X86_64
+
+open VG.X86_64
+
+def memOp (base : Reg) (offset : Nat) : MemOp := { base, disp := Int.ofNat offset }
+def rr (d s : Reg) : Instr := .mov d (.reg s)
+def imm (d : Reg) (n : Nat) : Instr := .mov d (.imm (BitVec.ofNat 32 n))
+
+def shr (r : Reg) (n : Nat) : List Instr := if n = 0 then [] else [.shift .shr r n]
+/-- A left shift of an isolated bit, using a rotate on its zero-filled word. -/
+def placeBit (r : Reg) (n : Nat) : List Instr :=
+ if n = 0 then [] else [.shift .ror r (64 - n)]
+
+/-- Fixed FIPS permutation. Source and temporary are distinct from output.
+Every address and instruction is independent of the input word. -/
+def permuteCode {m : Nat} (positions : Vector Nat m) (n : Nat)
+ (dst src tmp : Reg) : List Instr :=
+ [imm dst 0] ++ (List.range m).flatMap fun i =>
+ [rr tmp src] ++ shr tmp (n - positions.getD i 1) ++
+ ([.alu .and tmp (.imm 1)] : List Instr) ++ placeBit tmp (m - 1 - i) ++
+ ([.alu .xor dst (.reg tmp)] : List Instr)
+
+end VG.Impl.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Ecb.lean b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Ecb.lean
new file mode 100644
index 000000000..f07530492
--- /dev/null
+++ b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Ecb.lean
@@ -0,0 +1,37 @@
+import VerifiedGarbage.Impl.TripleDes.X86_64.Block
+
+/-!
+# Triple DES ECB on x86-64
+
+The block functions preserve all three pointers and callee-saved registers.
+The ECB caller keeps the remaining count in rbp, outside the block's
+512-byte scratch region. It accepts empty input, calls the block operation
+once per block, and never adds or removes padding.
+-/
+
+namespace VG.Impl.TripleDes.X86_64.Ecb
+
+open VG.X86_64 VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction)
+
+def save : List Instr := [.store (memOp .rcx 512) .rbp]
+def setup : List Instr :=
+ [rr .rbp .rdx, rr .rdx .rcx, .alu .cmp .rbp (.imm 0)]
+def restore : List Instr := [.mov .rbp (.mem (memOp .rdx 512))]
+
+def blockCall (direction : Direction) : Prog isa :=
+ match direction with
+ | .encrypt => .call "vg_triple_des_encrypt_block" encryptBlock
+ | .decrypt => .call "vg_triple_des_decrypt_block" decryptBlock
+
+def advance : List Instr := [.alu .add .rsi (.imm 8), .alu .sub .rbp (.imm 1)]
+
+def ecb (direction : Direction) : Prog isa :=
+ .seq (.block (save ++ setup))
+ (.seq (.ite .e (.block []) (.loop (.seq (blockCall direction) (.block advance)) .ne))
+ (.block restore))
+
+def encrypt : Prog isa := ecb .encrypt
+def decrypt : Prog isa := ecb .decrypt
+
+end VG.Impl.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Impl/TripleDes/X86_64/ExpandKey.lean b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/ExpandKey.lean
new file mode 100644
index 000000000..ed6003794
--- /dev/null
+++ b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/ExpandKey.lean
@@ -0,0 +1,67 @@
+import VerifiedGarbage.Impl.TripleDes.X86_64.Common
+
+/-!
+# Scalar Triple DES key expansion on x86-64
+
+PC-1 and PC-2 use fixed permutations. The only branches depend on key
+length or the public round counter. The sixteen 28-bit rotations are
+selected by FIPS 46-3's schedule; no secret-indexed table is read. Registers
+r12/r13 hold C/D; r14 is the round counter and r15 the output pointer.
+The three schedules are stored in the specification's canonical layout.
+-/
+
+namespace VG.Impl.TripleDes.X86_64.Key
+
+open VG.X86_64 VG.Impl.TripleDes.X86_64
+
+def savedRegs : List Reg := [.rbx, .rbp, .r12, .r13, .r14, .r15]
+
+def save : List Instr :=
+ savedRegs.zipIdx.map fun (r, i) => .store (memOp .rcx (8 * i)) r
+
+def restore : List Instr :=
+ savedRegs.zipIdx.map fun (r, i) => .mov r (.mem (memOp .rcx (8 * i)))
+
+def load (offset component : Nat) : List Instr :=
+ ([.mov .rax (.mem (memOp .rdi offset)), .bswap .rax] : List Instr) ++
+ permuteCode Spec.TripleDes.pc1 64 .rbx .rax .rbp ++
+ [rr .r12 .rbx, .shift .shr .r12 28, rr .r13 .rbx,
+ .alu .and .r13 (.imm 0x0fffffff), imm .r14 0, rr .r15 .rdx,
+ .alu .add .r15 (.imm (BitVec.ofNat 32 (128 * component)))]
+
+def rotate28 (r : Reg) (n : Nat) : List Instr :=
+ [rr .rax r, .shift .shr .rax (28 - n), .shift .ror r (64 - n),
+ .alu .xor r (.reg .rax), .alu .and r (.imm 0x0fffffff)]
+
+def rotate (n : Nat) : Prog isa := .block (rotate28 .r12 n ++ rotate28 .r13 n)
+
+/-- Rounds 1, 2, 9 and 16 rotate by one; the other rounds by two. -/
+def rotation : Prog isa :=
+ .seq (.block [.alu .cmp .r14 (.imm 2)])
+ (.ite .b (rotate 1)
+ (.seq (.block [.alu .cmp .r14 (.imm 8)])
+ (.ite .e (rotate 1)
+ (.seq (.block [.alu .cmp .r14 (.imm 15)]) (.ite .e (rotate 1) (rotate 2))))))
+
+def storeRound : List Instr :=
+ [rr .rax .r12, .shift .ror .rax 36, .alu .xor .rax (.reg .r13)] ++
+ permuteCode Spec.TripleDes.pc2 56 .rbx .rax .rbp ++
+ [.store (memOp .r15 0) .rbx, .alu .add .r15 (.imm 8),
+ .alu .add .r14 (.imm 1), .alu .cmp .r14 (.imm 16)]
+
+def component (offset index : Nat) : Prog isa :=
+ .seq (.block (load offset index)) (.loop (.seq rotation (.block storeRound)) .ne)
+
+/-- EDE2 reuses the first schedule rather than expanding K1 again. -/
+def copyThird : List Instr :=
+ (List.range 16).flatMap fun j =>
+ [.mov .rax (.mem (memOp .rdx (8 * j))), .store (memOp .rdx (256 + 8 * j)) .rax]
+
+def expandKey : Prog isa :=
+ .seq (.block save)
+ (.seq (component 0 0)
+ (.seq (component 8 1)
+ (.seq (.block [.alu .cmp .rsi (.imm 16)])
+ (.seq (.ite .e (.block copyThird) (component 16 2)) (.block restore)))))
+
+end VG.Impl.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Permutation.lean b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Permutation.lean
new file mode 100644
index 000000000..4f3a44029
--- /dev/null
+++ b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Permutation.lean
@@ -0,0 +1,12 @@
+import VerifiedGarbage.Impl.TripleDes.X86_64.Common
+
+namespace VG.Impl.TripleDes.X86_64
+
+open VG.X86_64
+
+def initialPermutation : Prog isa := .block (permuteCode Spec.TripleDes.ip 64 .rbx .rax .rbp)
+def finalPermutation : Prog isa := .block (permuteCode Spec.TripleDes.fp 64 .rbx .rax .rbp)
+def keyPermutation1 : Prog isa := .block (permuteCode Spec.TripleDes.pc1 64 .rbx .rax .rbp)
+def keyPermutation2 : Prog isa := .block (permuteCode Spec.TripleDes.pc2 56 .rbx .rax .rbp)
+
+end VG.Impl.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Sbox.lean b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Sbox.lean
new file mode 100644
index 000000000..26215371a
--- /dev/null
+++ b/lean/VerifiedGarbage/Impl/TripleDes/X86_64/Sbox.lean
@@ -0,0 +1,39 @@
+import VerifiedGarbage.Impl.TripleDes.Circuit
+import VerifiedGarbage.Impl.Aes.X86_64.Alloc
+
+/-!
+# Constant-time scalar DES S-boxes on x86-64
+
+Six input planes are in `q 0 … q 5`; the four output planes are returned
+in `q 0 … q 3`. These are general-purpose registers, so this is scalar
+code. It computes the S-box independently at all 64 bit positions. Scratch
+slots 8–55 are fixed spill locations; slots 0–7 are reserved for the block
+function's saved registers and intermediate state. Left and right Feistel
+halves (`r12`, `r13`) and argument pointers are preserved.
+-/
+
+namespace VG.Impl.TripleDes.X86_64
+
+open VG.X86_64
+
+def q : Nat → Reg
+ | 0 => .rax | 1 => .rcx | 2 => .r8 | 3 => .r9 | 4 => .r10 | _ => .r11
+
+def sboxIns : List (Nat × Reg) := (List.range 6).map fun i => (i, q i)
+def sboxOuts (i : Nat) : List (Nat × Reg) :=
+ (List.range 4).map fun j => ((Circuit.outputs i).getD j 0, q j)
+
+def sboxCode (i : Nat) : List Instr :=
+ VG.Impl.Aes.X86_64.compile .rdx (Circuit.gates i) sboxIns (sboxOuts i)
+ [.rbx, .rbp, .r14, .r15] 8 (List.range' 9 47)
+
+def sbox0 : Prog isa := .block (sboxCode 0)
+def sbox1 : Prog isa := .block (sboxCode 1)
+def sbox2 : Prog isa := .block (sboxCode 2)
+def sbox3 : Prog isa := .block (sboxCode 3)
+def sbox4 : Prog isa := .block (sboxCode 4)
+def sbox5 : Prog isa := .block (sboxCode 5)
+def sbox6 : Prog isa := .block (sboxCode 6)
+def sbox7 : Prog isa := .block (sboxCode 7)
+
+end VG.Impl.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/Bytes.lean b/lean/VerifiedGarbage/Proof/TripleDes/Bytes.lean
new file mode 100644
index 000000000..fba9708ac
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/Bytes.lean
@@ -0,0 +1,43 @@
+import VerifiedGarbage.Spec.TripleDes
+import VerifiedGarbage.Proof.Framework.Mem
+
+namespace VG.Proof.TripleDes
+
+open VG.Spec.TripleDes
+
+def catBlock (b : Block) : BitVec 64 :=
+ b[0] ++ b[1] ++ b[2] ++ b[3] ++ b[4] ++ b[5] ++ b[6] ++ b[7]
+
+theorem block_list (b : Block) : b.toList = List.ofFn (fun i : Fin 8 => b[i.val]) := by
+ simpa only [Vector.toList_ofFn] using
+ (congrArg (fun v : Block => v.toList) (Vector.ofFn_getElem (xs := b))).symm
+
+theorem decodeBlock_cat (b : Block) : decodeBlock b = catBlock b := by
+ unfold decodeBlock
+ rw [block_list]
+ simp only [List.ofFn_succ, List.ofFn_zero, List.foldl_cons, List.foldl_nil]
+ have h : (catBlock b).setWidth 64 = catBlock b := by simp
+ rw [← h]
+ simp only [catBlock, BitVec.setWidth_append_eq_shiftLeft_setWidth_or]
+ simp
+ rfl
+
+
+theorem blockAt_eq_of_frame {rs : List VG.Region} {m m' : VG.Mem} (p : VG.Addr)
+ (hf : VG.Frame rs m m')
+ (hd : ∀ r ∈ rs, (⟨p, 8⟩ : VG.Region).Disjoint r) : blockAt m' p = blockAt m p := by
+ apply Vector.ext
+ intro i hi
+ simp only [blockAt, Vector.getElem_ofFn]
+ exact hf.bytes hd (by change 8 ≤ 2 ^ 64; decide) hi
+
+theorem bytesAt_eq_of_frame {rs : List VG.Region} {m m' : VG.Mem} (p : VG.Addr) (n : Nat)
+ (hf : VG.Frame rs m m') (hn : n ≤ 2 ^ 64)
+ (hd : ∀ r ∈ rs, (⟨p, n⟩ : VG.Region).Disjoint r) : bytesAt m' p n = bytesAt m p n := by
+ unfold bytesAt
+ apply List.map_congr_left
+ intro i hi
+ exact hf.bytes hd hn (List.mem_range.mp hi)
+
+
+end VG.Proof.TripleDes
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/Core.lean b/lean/VerifiedGarbage/Proof/TripleDes/Core.lean
new file mode 100644
index 000000000..87a8e4f7a
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/Core.lean
@@ -0,0 +1,87 @@
+import VerifiedGarbage.Proof.TripleDes.Permutation
+
+namespace VG.Proof.TripleDes
+
+open VG.Spec.TripleDes
+
+theorem ip_bounds : ∀ k < 64, 1 ≤ ip.getD k 1 ∧ ip.getD k 1 ≤ 64 := by decide
+theorem fp_bounds : ∀ k < 64, 1 ≤ fp.getD k 1 ∧ fp.getD k 1 ≤ 64 := by decide
+
+theorem ip_fp_positions : ∀ j < 64,
+ 64 - fp.getD (64 - 1 - (64 - ip.getD (64 - 1 - j) 1)) 1 = j := by decide
+
+theorem fp_ip_positions : ∀ j < 64,
+ 64 - ip.getD (64 - 1 - (64 - fp.getD (64 - 1 - j) 1)) 1 = j := by decide
+
+theorem ip_fp (x : BitVec 64) : permute ip (permute fp x) = x := by
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ have hj' : 64 - 1 - j < 64 := by omega
+ obtain ⟨lo, hi⟩ := ip_bounds _ hj'
+ have hk : 64 - ip.getD (64 - 1 - j) 1 < 64 := by omega
+ rw [permute_bit ip _ (by decide) j hj,
+ permute_bit fp _ (by decide) _ hk, ip_fp_positions j hj]
+
+theorem fp_ip (x : BitVec 64) : permute fp (permute ip x) = x := by
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ have hj' : 64 - 1 - j < 64 := by omega
+ obtain ⟨lo, hi⟩ := fp_bounds _ hj'
+ have hk : 64 - fp.getD (64 - 1 - j) 1 < 64 := by omega
+ rw [permute_bit fp _ (by decide) j hj,
+ permute_bit ip _ (by decide) _ hk, fp_ip_positions j hj]
+
+def feistelStep (k : BitVec 48) (state : BitVec 32 × BitVec 32) : BitVec 32 × BitVec 32 :=
+ (state.2, state.1 ^^^ roundFunction state.2 k)
+
+/-- DES between IP and FP, including its final half swap. -/
+def desCore (keys : DesSchedule) (direction : Direction) (input : BitVec 64) : BitVec 64 :=
+ let (l, r) := (List.range 16).foldl (fun state j =>
+ feistelStep (keys.getD (if direction = .encrypt then j else 15 - j) 0) state)
+ ((input >>> 32).setWidth 32, input.setWidth 32)
+ r ++ l
+
+theorem des_eq_core (keys : DesSchedule) (direction : Direction) (input : BitVec 64) :
+ des keys direction input = permute fp (desCore keys direction (permute ip input)) := rfl
+
+theorem encryptBlock_eq_cores (k : Schedule) (b : Block) :
+ encryptBlock k b = encodeBlock (permute fp
+ (desCore (componentSchedule k 2) .encrypt
+ (desCore (componentSchedule k 1) .decrypt
+ (desCore (componentSchedule k 0) .encrypt (permute ip (decodeBlock b)))))) := by
+ unfold encryptBlock
+ rw [des_eq_core, des_eq_core, des_eq_core, ip_fp, ip_fp]
+
+theorem decryptBlock_eq_cores (k : Schedule) (b : Block) :
+ decryptBlock k b = encodeBlock (permute fp
+ (desCore (componentSchedule k 0) .decrypt
+ (desCore (componentSchedule k 1) .encrypt
+ (desCore (componentSchedule k 2) .decrypt (permute ip (decodeBlock b)))))) := by
+ unfold decryptBlock
+ rw [des_eq_core, des_eq_core, des_eq_core, ip_fp, ip_fp]
+
+def roundKey (keys : DesSchedule) (direction : Direction) (j : Nat) : BitVec 48 :=
+ keys.getD (if direction = .encrypt then j else 15 - j) 0
+
+def roundPrefix (keys : DesSchedule) (direction : Direction) (n : Nat)
+ (v : BitVec 32 × BitVec 32) : BitVec 32 × BitVec 32 :=
+ (List.range n).foldl (fun state j => feistelStep (roundKey keys direction j) state) v
+
+theorem roundPrefix_zero (keys : DesSchedule) (direction : Direction)
+ (v : BitVec 32 × BitVec 32) : roundPrefix keys direction 0 v = v := rfl
+
+theorem roundPrefix_succ (keys : DesSchedule) (direction : Direction) (n : Nat)
+ (v : BitVec 32 × BitVec 32) :
+ roundPrefix keys direction (n + 1) v =
+ feistelStep (roundKey keys direction n) (roundPrefix keys direction n v) := by
+ unfold roundPrefix
+ rw [List.range_succ, List.foldl_append]
+ simp only [List.foldl_cons, List.foldl_nil]
+
+theorem desCore_roundPrefix (keys : DesSchedule) (direction : Direction)
+ (v : BitVec 64) :
+ desCore keys direction v =
+ let halves := roundPrefix keys direction 16 ((v >>> 32).setWidth 32, v.setWidth 32)
+ halves.2 ++ halves.1 := rfl
+
+end VG.Proof.TripleDes
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/EcbMemory.lean b/lean/VerifiedGarbage/Proof/TripleDes/EcbMemory.lean
new file mode 100644
index 000000000..f04688fba
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/EcbMemory.lean
@@ -0,0 +1,30 @@
+import VerifiedGarbage.Proof.TripleDes.Bytes
+import VerifiedGarbage.Proof.Framework.Offset
+
+namespace VG.Proof.TripleDes
+
+open VG
+
+theorem blocksAt_cons (m : Mem) (p : Addr) (n : Nat) :
+ Spec.TripleDes.blocksAt m p (n + 1) = Spec.TripleDes.blockAt m p :: Spec.TripleDes.blocksAt m (p + 8) n := by
+ rw [Spec.TripleDes.blocksAt, List.range_succ_eq_map, List.map_cons, List.map_map]
+ simp only [Nat.mul_zero, BitVec.ofNat_eq_ofNat, BitVec.add_zero, List.cons.injEq, true_and]
+ apply List.map_congr_left
+ intro i _
+ apply congrArg (Spec.TripleDes.blockAt m)
+ rw [BitVec.add_assoc, ← BitVec.ofNat_add]
+ exact congrArg (fun j => p + BitVec.ofNat 64 j) (by omega)
+
+theorem blocksAt_frame {rs : List Region} {m m' : Mem} (hf : Frame rs m m') (p : Addr) (n : Nat)
+ (hd : ∀ r ∈ rs, (Region.mk p (8 * n)).Disjoint r) :
+ Spec.TripleDes.blocksAt m' p n = Spec.TripleDes.blocksAt m p n := by
+ unfold Spec.TripleDes.blocksAt
+ apply List.map_congr_left
+ intro i hi
+ apply blockAt_eq_of_frame _ hf
+ intro r hr
+ exact (hd r hr).sub_left (Offset.sub_base p (by
+ have h := List.mem_range.mp hi
+ omega))
+
+end VG.Proof.TripleDes
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/KeyMemory.lean b/lean/VerifiedGarbage/Proof/TripleDes/KeyMemory.lean
new file mode 100644
index 000000000..0402efde0
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/KeyMemory.lean
@@ -0,0 +1,60 @@
+import VerifiedGarbage.Proof.TripleDes.Schedule
+import VerifiedGarbage.Proof.TripleDes.Bytes
+
+namespace VG.Proof.TripleDes
+
+open VG VG.Spec.TripleDes
+
+def componentOffset (n c : Nat) : Nat := if c = 2 ∧ n = 16 then 0 else 8 * c
+
+def componentKeys (m : Mem) (p : Addr) (n c : Nat) : DesSchedule :=
+ expandDesKey (decodeBlock (blockAt m (p + BitVec.ofNat 64 (componentOffset n c))))
+
+def expandedMemory (m : Mem) (p : Addr) (n : Nat) : Schedule :=
+ Vector.ofFn fun i => ((if i.val < 16 then componentKeys m p n 0 else
+ if i.val < 32 then componentKeys m p n 1 else componentKeys m p n 2).getD (i.val % 16) 0).setWidth 64
+
+theorem bytesAt_length (m : Mem) (p : Addr) (n : Nat) : (bytesAt m p n).length = n := by
+ simp only [bytesAt, List.length_map, List.length_range]
+
+theorem bytesAt_getD (m : Mem) (p : Addr) (n i : Nat) (hi : i < n) :
+ (bytesAt m p n).getD i 0 = m (p + BitVec.ofNat 64 i) := by
+ simp only [bytesAt, List.getD_eq_getElem?_getD, List.getElem?_map, List.getElem?_range hi,
+ Option.map_some, Option.getD_some]
+
+theorem bytesAt_component (m : Mem) (p : Addr) (n offset : Nat) (hi : offset + 8 ≤ n) :
+ (Vector.ofFn fun j : Fin 8 => (bytesAt m p n).getD (offset + j.val) 0) =
+ blockAt m (p + BitVec.ofNat 64 offset) := by
+ apply Vector.ext
+ intro j hj
+ simp only [Vector.getElem_ofFn, blockAt]
+ rw [bytesAt_getD m p n _ (by omega), Offset.add_ofNat_add_ofNat]
+
+theorem componentOffset_bound (n c : Nat) (hn : validKey n) (hc : c < 3) :
+ componentOffset n c + 8 ≤ n := by
+ rcases hn with rfl | rfl <;> unfold componentOffset
+ · by_cases h : c = 2
+ · rw [ite_eq_left (by simp only [h, and_self])]; decide
+ · rw [ite_eq_right (by simp only [h, false_and, not_false_eq_true])]; omega
+ · rw [ite_eq_right (by simp only [show ¬(24 : Nat) = 16 by decide, and_false, not_false_eq_true])]
+ omega
+
+theorem expandKey_memory (m : Mem) (p : Addr) (n : Nat) (hn : validKey n) :
+ expandKey (bytesAt m p n) = expandedMemory m p n := by
+ have component (c : Nat) (hc : c < 3) :
+ expandDesKey (decodeBlock (Vector.ofFn fun j : Fin 8 =>
+ (bytesAt m p n).getD ((if c = 2 ∧ (bytesAt m p n).length = 16 then 0 else 8 * c) + j.val) 0)) =
+ componentKeys m p n c := by
+ rw [bytesAt_length]
+ unfold componentKeys
+ exact congrArg (fun b => expandDesKey (decodeBlock b))
+ (bytesAt_component m p n (componentOffset n c) (componentOffset_bound n c hn hc))
+ have third := component 2 (by decide)
+ simp only [true_and] at third
+ apply Vector.ext
+ intro i hi
+ simp only [expandKey, expandedMemory, Vector.getElem_ofFn,
+ component 0 (by decide), component 1 (by decide)]
+ simp only [true_and, third]
+
+end VG.Proof.TripleDes
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/KeySchedule.lean b/lean/VerifiedGarbage/Proof/TripleDes/KeySchedule.lean
new file mode 100644
index 000000000..8907d9449
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/KeySchedule.lean
@@ -0,0 +1,35 @@
+import VerifiedGarbage.Spec.TripleDes
+import VerifiedGarbage.Proof.Framework.Mem
+
+namespace VG.Proof.TripleDes
+
+open VG.Spec.TripleDes
+
+abbrev KeyState := BitVec 28 × BitVec 28 × DesSchedule
+
+def keyStep (state : KeyState) (j : Nat) : KeyState :=
+ let c := state.1.rotateLeft (rotations.getD j 0)
+ let d := state.2.1.rotateLeft (rotations.getD j 0)
+ (c, d, state.2.2.set! j (permute pc2 (c ++ d)))
+
+def keyInitial (key : BitVec 64) : KeyState :=
+ let selected := permute pc1 key
+ ((selected >>> 28).setWidth 28, selected.setWidth 28, Vector.replicate 16 0)
+
+def keyPrefix (key : BitVec 64) (n : Nat) : KeyState :=
+ (List.range n).foldl keyStep (keyInitial key)
+
+theorem keyPrefix_zero (key : BitVec 64) : keyPrefix key 0 = keyInitial key := rfl
+
+theorem keyPrefix_succ (key : BitVec 64) (n : Nat) :
+ keyPrefix key (n + 1) = keyStep (keyPrefix key n) n := by
+ simp only [keyPrefix, List.range_succ, List.foldl_append, List.foldl_cons, List.foldl_nil]
+
+theorem expandDesKey_prefix (key : BitVec 64) : expandDesKey key = (keyPrefix key 16).2.2 := by
+ simp only [expandDesKey, List.forIn_pure_yield_eq_foldl]
+ rfl
+
+theorem rotation_value : ∀ j < 16,
+ rotations.getD j 0 = if j < 2 ∨ j = 8 ∨ j = 15 then 1 else 2 := by decide
+
+end VG.Proof.TripleDes
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/Permutation.lean b/lean/VerifiedGarbage/Proof/TripleDes/Permutation.lean
new file mode 100644
index 000000000..b00fa4b2f
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/Permutation.lean
@@ -0,0 +1,53 @@
+import VerifiedGarbage.Spec.TripleDes
+import VerifiedGarbage.Proof.Framework.Bitslice.Table
+
+/-! Fixed permutations in the FIPS numbering convention. Untrusted. -/
+
+namespace VG.Proof.TripleDes
+
+open VG.Spec.TripleDes
+
+private theorem prefix_bit {n m : Nat} (positions : Vector Nat m) (x : BitVec n)
+ (hn : 0 < n) (k : Nat) (hk : k ≤ m) (j : Nat) (hj : j < m) :
+ ((List.range k).foldl (fun (out : BitVec m) i =>
+ (out <<< 1) ||| (((x >>> (n - positions.getD i 1)) &&& 1).setWidth m))
+ (0 : BitVec m)).getLsbD j =
+ if j < k then x.getLsbD (n - positions.getD (k - 1 - j) 1) else false := by
+ induction k generalizing j with
+ | zero => simp
+ | succ k ih =>
+ rw [List.range_succ, List.foldl_append]
+ simp only [List.foldl_cons, List.foldl_nil, BitVec.getLsbD_or,
+ BitVec.getLsbD_shiftLeft, BitVec.getLsbD_setWidth, BitVec.getLsbD_and,
+ BitVec.getLsbD_ushiftRight, hj, decide_true, Bool.true_and]
+ by_cases hzero : j = 0
+ · subst j
+ simp [hn]
+ · have hj1 : j - 1 < m := by omega
+ rw [ih (by omega) (j - 1) hj1]
+ have hge : ¬j < 1 := by omega
+ have hone : (1 : BitVec n).getLsbD j = false := by
+ change (BitVec.ofNat n 1).getLsbD j = false
+ rw [BitVec.getLsbD_ofNat]
+ have hnat : Nat.testBit 1 j = false := by
+ change Nat.testBit (2 ^ 0) j = false
+ rw [Nat.testBit_two_pow]
+ exact decide_eq_false (Ne.symm hzero)
+ rw [hnat, Bool.and_false]
+ simp only [hone, Bool.and_false, Bool.or_false, hge,
+ decide_false, Bool.not_false, Bool.true_and]
+ by_cases hlt : j < k + 1
+ · have hlt' : j - 1 < k := by omega
+ simp only [hlt, hlt', ite_true]
+ have heq : k - 1 - (j - 1) = k + 1 - 1 - j := by omega
+ rw [heq]
+ · have hlt' : ¬j - 1 < k := by omega
+ simp only [hlt, hlt', ite_false]
+
+theorem permute_bit {n m : Nat} (positions : Vector Nat m) (x : BitVec n)
+ (hn : 0 < n) (j : Nat) (hj : j < m) :
+ (permute positions x).getLsbD j = x.getLsbD (n - positions.getD (m - 1 - j) 1) := by
+ have h := prefix_bit positions x hn m (Nat.le_refl m) j hj
+ simpa only [permute, hj, ite_true] using h
+
+end VG.Proof.TripleDes
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/Round.lean b/lean/VerifiedGarbage/Proof/TripleDes/Round.lean
new file mode 100644
index 000000000..5d3b2b2f5
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/Round.lean
@@ -0,0 +1,60 @@
+import VerifiedGarbage.Proof.TripleDes.Permutation
+
+namespace VG.Proof.TripleDes
+
+open VG.Spec.TripleDes
+
+def substitutionPrefix (x : BitVec 48) (n : Nat) : BitVec 32 :=
+ (List.range n).foldl (fun out i =>
+ (out <<< 4) ||| (sBox i ((x >>> (6 * (7 - i))).setWidth 6)).zeroExtend 32) 0
+
+theorem substitutionPrefix_bit (x : BitVec 48) (n : Nat) (hn : n ≤ 8)
+ (j : Nat) (hj : j < 32) :
+ (substitutionPrefix x n).getLsbD j =
+ if j < 4 * n then
+ (sBox (n - 1 - j / 4)
+ ((x >>> (6 * (7 - (n - 1 - j / 4)))).setWidth 6)).getLsbD (j % 4)
+ else false := by
+ induction n generalizing j with
+ | zero => simp [substitutionPrefix]
+ | succ n ih =>
+ unfold substitutionPrefix
+ rw [List.range_succ, List.foldl_append]
+ simp only [List.foldl_cons, List.foldl_nil, BitVec.getLsbD_or,
+ BitVec.getLsbD_shiftLeft, BitVec.getLsbD_setWidth, hj, decide_true, Bool.true_and]
+ by_cases hlow : j < 4
+ · have hdiv : j / 4 = 0 := Nat.div_eq_of_lt hlow
+ have hmod : j % 4 = j := Nat.mod_eq_of_lt hlow
+ have hbound : j < 4 * (n + 1) := by omega
+ simp only [hlow, decide_true, Bool.not_true, Bool.false_and, Bool.false_or,
+ hbound, ite_true, hdiv, hmod, Nat.sub_zero, Nat.add_sub_cancel]
+ · have hj' : j - 4 < 32 := by omega
+ have ih' := ih (by omega) (j - 4) hj'
+ change ((!decide (j < 4) &&
+ (substitutionPrefix x n).getLsbD (j - 4)) ||
+ (sBox n ((x >>> (6 * (7 - n))).setWidth 6)).getLsbD j) = _
+ rw [BitVec.getLsbD_of_ge (sBox n ((x >>> (6 * (7 - n))).setWidth 6)) j (by omega), ih']
+ simp only [hlow, decide_false, Bool.not_false, Bool.true_and, Bool.or_false]
+ have hdiv : (j - 4) / 4 = j / 4 - 1 := by omega
+ have hmod : (j - 4) % 4 = j % 4 := by omega
+ have hidx : n - 1 - (j - 4) / 4 = n + 1 - 1 - j / 4 := by omega
+ have hbound : (j - 4 < 4 * n) ↔ (j < 4 * (n + 1)) := by omega
+ simp only [hbound, hidx, hmod]
+
+theorem roundFunction_bit (r : BitVec 32) (k : BitVec 48) (j : Nat) (hj : j < 32) :
+ (roundFunction r k).getLsbD j =
+ let t := 32 - p.getD (31 - j) 1
+ (sBox (7 - t / 4)
+ (((permute expansion r ^^^ k) >>> (6 * (7 - (7 - t / 4)))).setWidth 6)).getLsbD
+ (t % 4) := by
+ have bounds : ∀ j < 32, 1 ≤ p.getD j 1 ∧ p.getD j 1 ≤ 32 := by decide +kernel
+ obtain ⟨lo, hi⟩ := bounds (31 - j) (by omega)
+ have ht : 32 - p.getD (31 - j) 1 < 32 := by omega
+ unfold roundFunction
+ rw [permute_bit _ _ (by decide) j hj]
+ change (substitutionPrefix (permute expansion r ^^^ k) 8).getLsbD
+ (32 - p.getD (32 - 1 - j) 1) = _
+ rw [substitutionPrefix_bit _ 8 (by decide) _ ht]
+ simp only [ht, ite_true]
+
+end VG.Proof.TripleDes
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/Schedule.lean b/lean/VerifiedGarbage/Proof/TripleDes/Schedule.lean
new file mode 100644
index 000000000..2093bc0fb
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/Schedule.lean
@@ -0,0 +1,72 @@
+import VerifiedGarbage.Spec.TripleDes
+import VerifiedGarbage.Proof.Framework.Mem
+import VerifiedGarbage.Proof.Framework.Offset
+
+namespace VG.Proof.TripleDes
+
+open VG VG.Spec.TripleDes
+
+theorem reverse_or8 (a b c d e f g h : BitVec 64) :
+ a ||| b ||| c ||| d ||| e ||| f ||| g ||| h =
+ h ||| g ||| f ||| e ||| d ||| c ||| b ||| a := by ac_rfl
+
+theorem littleEndian_word (b : Nat → Byte) :
+ (List.range 8).foldl (fun out j => out ||| ((b j).zeroExtend 64 <<< (8 * j))) (0 : BitVec 64) =
+ (b 7 ++ b 6 ++ b 5 ++ b 4 ++ b 3 ++ b 2 ++ b 1 ++ b 0 : BitVec 64).setWidth 64 := by
+ simp only [List.range_succ, List.range_zero, List.foldl_append, List.foldl_cons,
+ List.foldl_nil, List.nil_append, Nat.reduceAdd, Nat.reduceMul, BitVec.shiftLeft_zero]
+ rw [BitVec.setWidth_append_eq_shiftLeft_setWidth_or,
+ BitVec.setWidth_append_eq_shiftLeft_setWidth_or,
+ BitVec.setWidth_append_eq_shiftLeft_setWidth_or,
+ BitVec.setWidth_append_eq_shiftLeft_setWidth_or,
+ BitVec.setWidth_append_eq_shiftLeft_setWidth_or,
+ BitVec.setWidth_append_eq_shiftLeft_setWidth_or,
+ BitVec.setWidth_append_eq_shiftLeft_setWidth_or]
+ have hz : (0 : BitVec 64) ||| (b 0).zeroExtend 64 = (b 0).zeroExtend 64 := BitVec.zero_or
+ rw [hz]
+ simp only [BitVec.shiftLeft_or_distrib, ← BitVec.shiftLeft_add, Nat.reduceAdd]
+ exact reverse_or8 _ _ _ _ _ _ _ _
+
+
+theorem readW64_cat (m : Mem) (p : Addr) :
+ m.readW p 64 = (m (p + BitVec.ofNat 64 7) ++ m (p + BitVec.ofNat 64 6) ++
+ m (p + BitVec.ofNat 64 5) ++ m (p + BitVec.ofNat 64 4) ++ m (p + BitVec.ofNat 64 3) ++
+ m (p + BitVec.ofNat 64 2) ++ m (p + BitVec.ofNat 64 1) ++ m p : BitVec 64).setWidth 64 := by
+ simp only [Mem.readW, Mem.read, BitVec.add_assoc]
+ rw [BitVec.zero_width_append]
+ rfl
+
+theorem scheduleAt_readW (m : Mem) (p : Addr) (i : Nat) (hi : i < 48) :
+ (scheduleAt m p)[i] = m.readW (p + BitVec.ofNat 64 (8 * i)) 64 := by
+ have h := littleEndian_word (fun j => m (p + BitVec.ofNat 64 (8 * i + j)))
+ have hread := readW64_cat m (p + BitVec.ofNat 64 (8 * i))
+ rw [Offset.add_ofNat_add_ofNat, Offset.add_ofNat_add_ofNat,
+ Offset.add_ofNat_add_ofNat, Offset.add_ofNat_add_ofNat,
+ Offset.add_ofNat_add_ofNat, Offset.add_ofNat_add_ofNat,
+ Offset.add_ofNat_add_ofNat] at hread
+ simp only [scheduleAt, Vector.getElem_ofFn]
+ exact h.trans hread.symm
+
+
+theorem vector_getD {α : Type} {n : Nat} (v : Vector α n) (i : Nat) (hi : i < n) (fallback : α) :
+ v.getD i fallback = v[i]'hi :=
+ (Array.getElem_eq_getD fallback).symm
+
+theorem componentSchedule_readW (m : Mem) (p : Addr) (c j : Nat) (hc : c < 3) (hj : j < 16) :
+ (componentSchedule (scheduleAt m p) c).getD j 0 =
+ (m.readW (p + BitVec.ofNat 64 (8 * (16 * c + j))) 64).setWidth 48 := by
+ rw [vector_getD _ j hj 0]
+ simp only [componentSchedule, Vector.getElem_ofFn]
+ rw [vector_getD _ (16 * c + j) (by omega) 0, scheduleAt_readW m p _ (by omega)]
+
+theorem scheduleAt_eq_of_frame {rs : List Region} {m m' : Mem} (p : Addr)
+ (hf : Frame rs m m')
+ (hd : ∀ r ∈ rs, (⟨p, 384⟩ : Region).Disjoint r) : scheduleAt m' p = scheduleAt m p := by
+ apply Vector.ext
+ intro i hi
+ rw [scheduleAt_readW m' p i hi, scheduleAt_readW m p i hi]
+ exact hf.readW (r := ⟨p, 384⟩)
+ (Offset.contains_base p (by omega) (by omega)) hd (by decide)
+
+
+end VG.Proof.TripleDes
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/Word.lean b/lean/VerifiedGarbage/Proof/TripleDes/Word.lean
new file mode 100644
index 000000000..bf8f77d68
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/Word.lean
@@ -0,0 +1,84 @@
+import VerifiedGarbage.Proof.Framework.Bitslice.Table
+
+namespace VG.Proof.TripleDes
+
+theorem mask28 (x : BitVec 64) : x &&& 0x0fffffff = (x.setWidth 28).setWidth 64 := by
+ apply BitVec.eq_of_toNat_eq
+ simp only [BitVec.toNat_and, BitVec.toNat_setWidth]
+ change x.toNat &&& (2 ^ 28 - 1) = x.toNat % 268435456 % 18446744073709551616
+ rw [Nat.and_two_pow_sub_one_eq_mod]
+ omega
+
+theorem rotate28_word (x : BitVec 28) (n : Nat) (hn : 1 ≤ n) (hn' : n < 28) :
+ ((x.setWidth 64).rotateRight (64 - n) ^^^ (x.setWidth 64) >>> (28 - n)) &&& 0x0fffffff =
+ (x.rotateLeft n).setWidth 64 := by
+ rw [mask28]
+ apply congrArg (BitVec.setWidth 64)
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ simp only [BitVec.getLsbD_setWidth, BitVec.getLsbD_xor, BitVec.getLsbD_rotateRight,
+ BitVec.getLsbD_ushiftRight, BitVec.getLsbD_rotateLeft]
+ have n64 : (64 - n) % 64 = 64 - n := Nat.mod_eq_of_lt (by omega)
+ have n28 : n % 28 = n := Nat.mod_eq_of_lt hn'
+ rw [n64, n28]
+ rw [show 64 - (64 - n) = n by omega]
+ by_cases h : j < n
+ · simp (disch := omega) [h, hj,
+ show j + (28 - n) < 64 by omega, BitVec.getLsbD_of_ge, Nat.add_comm]
+ · simp (disch := omega) [h, hj, show j < 64 by omega,
+ show j - n < 64 by omega, BitVec.getLsbD_of_ge]
+
+
+theorem packHalves_word (l r : BitVec 32) :
+ (l.setWidth 64).rotateRight 32 ^^^ r.setWidth 64 = l ++ r := by
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ simp only [BitVec.getLsbD_xor, BitVec.getLsbD_rotateRight, BitVec.getLsbD_setWidth,
+ BitVec.getLsbD_append]
+ by_cases h : j < 32
+ · simp (disch := omega) [h, hj, show 32 + j < 64 by omega, BitVec.getLsbD_of_ge]
+ · simp (disch := omega) [h, hj, show j - 32 < 64 by omega, BitVec.getLsbD_of_ge]
+
+
+theorem appended_left (l r : BitVec 32) : ((l ++ r) >>> 32).setWidth 32 = l := by
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ simp only [BitVec.getLsbD_setWidth, BitVec.getLsbD_ushiftRight, BitVec.getLsbD_append,
+ hj, decide_true, Bool.true_and, show ¬32 + j < 32 by omega, ite_false,
+ show 32 + j - 32 = j by omega]
+
+theorem appended_right (l r : BitVec 32) : (l ++ r).setWidth 32 = r := by
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ simp only [BitVec.getLsbD_setWidth, BitVec.getLsbD_append, hj, decide_true,
+ Bool.true_and, ite_true]
+
+theorem halves_append (x : BitVec 64) : (x >>> 32).setWidth 32 ++ x.setWidth 32 = x := by
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ simp only [BitVec.getLsbD_append, BitVec.getLsbD_setWidth, BitVec.getLsbD_ushiftRight]
+ by_cases h : j < 32
+ · simp only [h, decide_true, Bool.true_and, ite_true]
+ · simp (disch := omega) [h, show j - 32 < 32 by omega, show 32 + (j - 32) = j by omega]
+
+theorem pack28_word (c d : BitVec 28) :
+ ((c.setWidth 64).rotateRight 36 ^^^ d.setWidth 64).setWidth 56 = c ++ d := by
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ simp only [BitVec.getLsbD_setWidth, BitVec.getLsbD_xor, BitVec.getLsbD_rotateRight,
+ BitVec.getLsbD_append]
+ by_cases h : j < 28
+ · simp (disch := omega) [h, hj, show j < 64 by omega, show 36 + j < 64 by omega, BitVec.getLsbD_of_ge]
+ · simp (disch := omega) [h, hj, show j < 64 by omega, show j - 28 < 64 by omega, BitVec.getLsbD_of_ge]
+
+theorem split28_upper (x : BitVec 56) :
+ x.setWidth 64 >>> 28 = ((x >>> 28).setWidth 28).setWidth 64 := by
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ simp only [BitVec.getLsbD_setWidth, BitVec.getLsbD_ushiftRight]
+ by_cases h : j < 28
+ · simp only [h, hj, show 28 + j < 64 by omega, decide_true, Bool.true_and]
+ · simp only [h, hj, BitVec.getLsbD_of_ge x (28 + j) (by omega), decide_false, decide_true, Bool.and_false]
+
+
+end VG.Proof.TripleDes
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Block.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Block.lean
new file mode 100644
index 000000000..15d8277e4
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Block.lean
@@ -0,0 +1,83 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Head
+import VerifiedGarbage.Proof.TripleDes.X86_64.Tail
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction Schedule)
+
+def blockResult (keys : Schedule) (direction : Direction) (b : Spec.TripleDes.Block) :
+ Spec.TripleDes.Block :=
+ match direction with
+ | .encrypt => Spec.TripleDes.encryptBlock keys b
+ | .decrypt => Spec.TripleDes.decryptBlock keys b
+
+theorem blockResult_core (keys : Schedule) (direction : Direction) (b : Spec.TripleDes.Block) :
+ Spec.TripleDes.encodeBlock (Spec.TripleDes.permute Spec.TripleDes.fp
+ (blockCore (Spec.TripleDes.componentSchedule keys) direction
+ (Spec.TripleDes.permute Spec.TripleDes.ip (Spec.TripleDes.decodeBlock b)))) =
+ blockResult keys direction b := by
+ cases direction
+ · exact (VG.Proof.TripleDes.encryptBlock_eq_cores keys b).symm
+ · exact (VG.Proof.TripleDes.decryptBlock_eq_cores keys b).symm
+
+def blockRegions (s : State) : List Region := [⟨s.gpr .rsi, 8⟩, ⟨s.gpr .rdx, 512⟩]
+
+structure BlockPost (keys : Schedule) (direction : Direction) (original s : State) : Prop where
+ result : Spec.TripleDes.blockAt s.mem (original.gpr .rsi) =
+ blockResult keys direction (Spec.TripleDes.blockAt original.mem (original.gpr .rsi))
+ saved : ∀ r ∈ savedRegs ++ [Reg.rdi], s.gpr r = original.gpr r
+ rd : s.rd = original.rd
+ wr : s.wr = original.wr
+ regs : ∀ q ∈ [Reg.rsi, .rdx, .rsp], s.gpr q = original.gpr q
+ frame : Frame (blockRegions original) original.mem s.mem
+
+theorem block_ok (keys : Schedule) (base : Addr) (direction : Direction) (s : State)
+ (hp : HeadPre (Spec.TripleDes.componentSchedule keys) base s)
+ (hwrite : InRegions s.wr (s.gpr .rsi) 8) :
+ WP isa (block direction) s (BlockPost keys direction s) := by
+ apply WP.seq
+ apply WP.mono (blockHead_ok (Spec.TripleDes.componentSchedule keys) base s hp)
+ intro s₁ hs₁
+ apply WP.seq
+ apply WP.mono (blockBody_ok (Spec.TripleDes.componentSchedule keys) base s₁ _ direction hs₁.ready hs₁.word)
+ intro s₂ hs₂
+ have hregs₂ : ∀ q ∈ [Reg.rsi, .rdx, .rsp], s₂.gpr q = s.gpr q := by
+ intro q hq
+ have hkeep : ∀ r ∈ [Reg.rsi, .rdx, .rsp], r ∈ [Reg.rdi, .rsi, .rdx, .rsp] := by decide
+ exact (hs₂.2.2.regs q hq).trans (hs₁.regs q (hkeep q hq))
+ have saved₂ := hs₁.saved.congr (hs₂.2.2.regs .rdx (by decide)) hs₂.2.2.frame
+ have savedRead₂ : ∀ i < 7, InRegions (s₂.rd ++ s₂.wr) (s₂.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8 := by
+ rw [hs₂.2.2.rd, hs₂.2.2.wr, hs₁.rd, hs₁.wr, hregs₂ .rdx (by decide)]
+ exact hp.saveRead
+ have hwrite₂ : InRegions s₂.wr (s₂.gpr .rsi) 8 := by
+ rw [hs₂.2.2.wr, hs₁.wr, hregs₂ .rsi (by decide)]
+ exact hwrite
+ apply WP.mono (blockTail_ok s s₂ _ hs₂.1 saved₂ savedRead₂ hwrite₂)
+ intro s₃ hs₃
+ refine ⟨?_, hs₃.saved, hs₃.rd.trans (hs₂.2.2.rd.trans hs₁.rd),
+ hs₃.wr.trans (hs₂.2.2.wr.trans hs₁.wr),
+ fun q hq => (hs₃.regs q hq).trans (hregs₂ q hq), ?_⟩
+ · have hresult := hs₃.result
+ rw [hregs₂ .rsi (by decide)] at hresult
+ exact hresult.trans (blockResult_core keys direction _)
+ · have hf₁ : Frame (blockRegions s) s.mem s₁.mem := hs₁.frame.sub (by
+ intro r hr
+ obtain rfl := List.mem_singleton.mp hr
+ exact ⟨⟨s.gpr .rdx, 512⟩, by simp [blockRegions], Region.sub_prefix (by decide)⟩)
+ have hf₂ : Frame (blockRegions s) s₁.mem s₂.mem := hs₂.2.2.frame.sub (by
+ intro r hr
+ obtain rfl := List.mem_singleton.mp hr
+ refine ⟨⟨s.gpr .rdx, 512⟩, by simp [blockRegions], ?_⟩
+ have hbase := hs₁.regs .rdx (by decide)
+ change Region.Sub ⟨s₁.gpr .rdx + BitVec.ofNat 64 56, 392⟩ ⟨s.gpr .rdx, 512⟩
+ rw [hbase]
+ exact Offset.sub_base _ (by decide))
+ have hf₃ : Frame (blockRegions s) s₂.mem s₃.mem := hs₃.frame.sub (by
+ intro r hr
+ obtain rfl := List.mem_singleton.mp hr
+ rw [hregs₂ .rsi (by decide)]
+ exact ⟨⟨s.gpr .rsi, 8⟩, by simp [blockRegions], fun _ h => h⟩)
+ exact hf₁.trans (hf₂.trans hf₃)
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/BlockIO.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/BlockIO.lean
new file mode 100644
index 000000000..b874d5e67
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/BlockIO.lean
@@ -0,0 +1,136 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Bytes
+import VerifiedGarbage.Proof.TripleDes.X86_64.Initial
+import VerifiedGarbage.Proof.TripleDes.Core
+import VerifiedGarbage.Impl.TripleDes.X86_64.Block
+import VerifiedGarbage.Proof.Framework.X86_64.RegUpd
+import VerifiedGarbage.Proof.TripleDes.X86_64.Box
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.RegUpd VG.Impl.TripleDes.X86_64
+
+theorem readData_ok (s : State)
+ (hread : InRegions (s.rd ++ s.wr) (s.gpr .rsi) 8) :
+ ∃ s', runBlock isa
+ [.mov .rax (.mem (memOp .rsi 0)), .bswap .rax] s = some s' ∧
+ s'.gpr .rax = Spec.TripleDes.decodeBlock (Spec.TripleDes.blockAt s.mem (s.gpr .rsi)) ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .rax → s'.gpr r = s.gpr r) := by
+ have haddr : s.gpr .rsi + BitVec.ofInt 64 (Int.ofNat 0) = s.gpr .rsi :=
+ BitVec.add_zero _
+ refine ⟨_, by
+ simp only [runBlock_cons, runStep_some, runBlock_nil, exec, readSrc, State.load64,
+ State.ea, memOp, haddr, hread, ite_true, Option.map_some,
+ gpr_setReg_self]
+ rfl, ?_, ?_, ?_, ?_, ?_⟩
+ · simp only [gpr_setReg_self]
+ exact (decodeBlock_readW s.mem (s.gpr .rsi)).symm
+ · simp only [mem_setReg]
+ · simp only [rd_setReg]
+ · simp only [wr_setReg]
+ · intro r hr
+ simp only [gpr_setReg, hr, ite_false]
+
+theorem splitHalves_ok (s : State) :
+ ∃ s', runBlock isa [rr .r12 .rbx, .shift .shr .r12 32, .mov32 .r13 (.reg .rbx)] s = some s' ∧
+ s'.gpr .r12 = s.gpr .rbx >>> 32 ∧
+ s'.gpr .r13 = ((s.gpr .rbx).setWidth 32).setWidth 64 ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .r12 → r ≠ .r13 → s'.gpr r = s.gpr r) := by
+ refine ⟨_, by
+ simp only [rr, runBlock_cons, runStep_some, exec, readSrc, execShift,
+ Option.map_some, gpr_setReg, ite_true]
+ rfl, ?_, ?_, ?_, ?_, ?_, ?_⟩
+ · simp only [State.setReg32, gpr_setReg, gpr_setFlags, reduceCtorEq, ite_true, ite_false]
+ · exact gpr_setReg_self _ _ _
+ · simp only [State.setReg32, mem_setReg, mem_setFlags]
+ · simp only [State.setReg32, rd_setReg, rd_setFlags]
+ · simp only [State.setReg32, wr_setReg, wr_setFlags]
+ · intro r h12 h13
+ simp only [State.setReg32, gpr_setReg, gpr_setFlags, h12, h13, ite_false]
+
+
+theorem upperHalf_extend (x : BitVec 64) :
+ x >>> 32 = ((x >>> 32).setWidth 32).setWidth 64 := by
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ simp only [BitVec.getLsbD_setWidth, BitVec.getLsbD_ushiftRight]
+ by_cases h : j < 32
+ · simp only [h, hj, decide_true, Bool.true_and]
+ · have hz : x.getLsbD (32 + j) = false := BitVec.getLsbD_of_ge _ _ (by omega)
+ simp only [h, hj, decide_false, decide_true, Bool.false_and, Bool.true_and, hz]
+
+theorem runAppend_some (xs ys : List Instr) (s t u : State)
+ (hx : runBlock isa xs s = some t) (hy : runBlock isa ys t = some u) :
+ runBlock isa (xs ++ ys) s = some u := by
+ calc
+ runBlock isa (xs ++ ys) s = (runBlock isa xs s).bind (runBlock isa ys) :=
+ runBoxes_append xs ys s
+ _ = (some t).bind (runBlock isa ys) := congrArg (fun v => v.bind (runBlock isa ys)) hx
+ _ = runBlock isa ys t := Option.bind_some t (runBlock isa ys)
+ _ = some u := hy
+
+theorem blockLoad_run (s s₁ s₂ s₃ : State)
+ (h₁ : runBlock isa [.mov .rax (.mem (memOp .rsi 0)), .bswap .rax] s = some s₁)
+ (h₂ : runBlock isa (permuteCode Spec.TripleDes.ip 64 .rbx .rax .rbp) s₁ = some s₂)
+ (h₃ : runBlock isa [rr .r12 .rbx, .shift .shr .r12 32, .mov32 .r13 (.reg .rbx)] s₂ = some s₃) :
+ runBlock isa blockLoad s = some s₃ := by
+ have hhead := runAppend_some _ _ _ _ _ h₁ h₂
+ have htail := runAppend_some _ _ _ _ _ hhead h₃
+ have hcode : blockLoad =
+ (([.mov .rax (.mem (memOp .rsi 0)), .bswap .rax] : List Instr) ++
+ permuteCode Spec.TripleDes.ip 64 .rbx .rax .rbp) ++
+ [rr .r12 .rbx, .shift .shr .r12 32, .mov32 .r13 (.reg .rbx)] := rfl
+ exact (congrArg (fun is => runBlock isa is s) hcode).trans htail
+
+theorem blockLoad_ok (s : State)
+ (hread : InRegions (s.rd ++ s.wr) (s.gpr .rsi) 8) :
+ ∃ s', runBlock isa blockLoad s = some s' ∧
+ s'.gpr .r12 =
+ (((Spec.TripleDes.permute Spec.TripleDes.ip
+ (Spec.TripleDes.decodeBlock (Spec.TripleDes.blockAt s.mem (s.gpr .rsi)))) >>> 32).setWidth 32).setWidth 64 ∧
+ s'.gpr .r13 =
+ ((Spec.TripleDes.permute Spec.TripleDes.ip
+ (Spec.TripleDes.decodeBlock (Spec.TripleDes.blockAt s.mem (s.gpr .rsi)))).setWidth 32).setWidth 64 ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r ∈ [Reg.rdi, .rsi, .rdx, .rsp], s'.gpr r = s.gpr r) := by
+ obtain ⟨s₁, run₁, word₁, mem₁, rd₁, wr₁, regs₁⟩ := readData_ok s hread
+ obtain ⟨s₂, run₂raw, word₂, rd₂, wr₂, mem₂, regs₂⟩ := initial_raw_ok s₁
+ obtain ⟨s₃, run₃, left₃, right₃, mem₃, rd₃, wr₃, regs₃⟩ := splitHalves_ok s₂
+ have hword : s₂.gpr .rbx = Spec.TripleDes.permute Spec.TripleDes.ip
+ (Spec.TripleDes.decodeBlock (Spec.TripleDes.blockAt s.mem (s.gpr .rsi))) := by
+ exact word₂.trans (congrArg (Spec.TripleDes.permute Spec.TripleDes.ip) word₁)
+ refine ⟨s₃, ?_, ?_, ?_, mem₃.trans (mem₂.trans mem₁),
+ rd₃.trans (rd₂.trans rd₁), wr₃.trans (wr₂.trans wr₁), ?_⟩
+ · exact blockLoad_run s s₁ s₂ s₃ run₁ run₂raw run₃
+ · exact left₃.trans ((congrArg (fun x : BitVec 64 => x >>> 32) hword).trans
+ (upperHalf_extend _))
+ · exact right₃.trans (congrArg (fun x : BitVec 64 => (x.setWidth 32).setWidth 64) hword)
+ · intro r hr
+ have hdst : (instrs initialPermutation.lit).all
+ (fun op => op.dst == some Reg.rbx || op.dst == some Reg.rbp) = true := by
+ decide +kernel
+ have hneDst : r ≠ .rbx ∧ r ≠ .rbp := by
+ have hfinite : ∀ q ∈ [Reg.rdi, .rsi, .rdx, .rsp], q ≠ .rbx ∧ q ≠ .rbp := by decide
+ exact hfinite r hr
+ have hno : (instrs initialPermutation.lit).all
+ (fun op => op.dst != some r) = true := by
+ apply List.all_eq_true.mpr
+ intro op hop
+ have h := List.all_eq_true.mp hdst op hop
+ simp only [Bool.or_eq_true, beq_iff_eq] at h
+ rcases h with h | h
+ · rw [h, bne_iff_ne]
+ intro he
+ exact hneDst.1 (Option.some.inj he).symm
+ · rw [h, bne_iff_ne]
+ intro he
+ exact hneDst.2 (Option.some.inj he).symm
+ have hne : r ≠ .rax ∧ r ≠ .r12 ∧ r ≠ .r13 := by
+ have hfinite : ∀ q ∈ [Reg.rdi, .rsi, .rdx, .rsp],
+ q ≠ .rax ∧ q ≠ .r12 ∧ q ≠ .r13 := by decide
+ exact hfinite r hr
+ exact (regs₃ r hne.2.1 hne.2.2).trans ((regs₂ r hno).trans (regs₁ r hne.1))
+
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Body.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Body.lean
new file mode 100644
index 000000000..e57c75abd
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Body.lean
@@ -0,0 +1,40 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ready
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction DesSchedule)
+open VG.Proof.TripleDes (desCore)
+
+theorem threePasses_ok (keys : Nat → DesSchedule) (base : Addr) (s : State) (x : BitVec 64)
+ (c₀ c₁ c₂ : Nat) (h₀ : c₀ < 3) (h₁ : c₁ < 3) (h₂ : c₂ < 3)
+ (d₀ d₁ d₂ : Direction) (hready : Ready keys base s) (hword : WordState x s) :
+ WP isa (.seq (pass c₀ d₀) (.seq (pass c₁ d₁) (pass c₂ d₂))) s
+ (fun t => WordState (desCore (keys c₂) d₂ (desCore (keys c₁) d₁
+ (desCore (keys c₀) d₀ x))) t ∧ Ready keys base t ∧ Stable s t) := by
+ apply WP.seq
+ apply WP.mono (pass_word_ok keys base s x c₀ h₀ d₀ hready hword)
+ intro s₁ hs₁
+ apply WP.seq
+ apply WP.mono (pass_word_ok keys base s₁ _ c₁ h₁ d₁ hs₁.2.1 hs₁.1)
+ intro s₂ hs₂
+ apply WP.mono (pass_word_ok keys base s₂ _ c₂ h₂ d₂ hs₂.2.1 hs₂.1)
+ intro s₃ hs₃
+ exact ⟨hs₃.1, hs₃.2.1, hs₁.2.2.trans (hs₂.2.2.trans hs₃.2.2)⟩
+
+def blockCore (keys : Nat → DesSchedule) (direction : Direction) (x : BitVec 64) : BitVec 64 :=
+ match direction with
+ | .encrypt => desCore (keys 2) .encrypt (desCore (keys 1) .decrypt (desCore (keys 0) .encrypt x))
+ | .decrypt => desCore (keys 0) .decrypt (desCore (keys 1) .encrypt (desCore (keys 2) .decrypt x))
+
+theorem blockBody_ok (keys : Nat → DesSchedule) (base : Addr) (s : State) (x : BitVec 64)
+ (direction : Direction) (hready : Ready keys base s) (hword : WordState x s) :
+ WP isa (blockBody direction) s
+ (fun t => WordState (blockCore keys direction x) t ∧ Ready keys base t ∧ Stable s t) := by
+ cases direction
+ · exact threePasses_ok keys base s x 0 1 2 (by decide) (by decide) (by decide)
+ .encrypt .decrypt .encrypt hready hword
+ · exact threePasses_ok keys base s x 2 1 0 (by decide) (by decide) (by decide)
+ .decrypt .encrypt .decrypt hready hword
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Box.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Box.lean
new file mode 100644
index 000000000..1fb7430a3
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Box.lean
@@ -0,0 +1,55 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Round
+import VerifiedGarbage.Proof.TripleDes.X86_64.Spills
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Impl.TripleDes.X86_64
+
+theorem runBoxes_append (a b : List Instr) (s : State) :
+ runBlock isa (a ++ b) s = (runBlock isa a s).bind (runBlock isa b) := by
+ induction a generalizing s with
+ | nil => rw [List.nil_append, runBlock_nil]; rfl
+ | cons i is ih =>
+ show (isa.exec i s).bind _ = ((isa.exec i s).bind _).bind _
+ cases isa.exec i s with
+ | none => rfl
+ | some s' => exact ih s'
+
+/-- One complete DES S-box contribution, including E/key input extraction,
+the Boolean circuit, and P output placement. -/
+theorem box_ok (i : Nat) (hi : i < 8) (s : State) (hok : Ok sboxCfg s)
+ (hread : InRegions (s.rd ++ s.wr) (s.gpr .rdi) 8) :
+ ∃ s', runBlock isa (box i) s = some s' ∧
+ s'.gpr .r12 = s.gpr .r12 ^^^
+ (boxPiece i (Spec.TripleDes.sBox i
+ (roundChunk i ((s.gpr .r13).setWidth 32)
+ ((s.mem.readW (s.gpr .rdi) 64).setWidth 48)))).zeroExtend 64 ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r ∈ roundKept, s'.gpr r = s.gpr r) ∧
+ Frame [spillRegion s] s.mem s'.mem := by
+ obtain ⟨s₁, run₁, chunk, rd₁, wr₁, mem₁, keep₁⟩ := roundInput_chunk i hi s hread
+ have kept₁ : ∀ r ∈ .r12 :: roundKept, s₁.gpr r = s.gpr r :=
+ fun r hr => keep₁ r (roundInput_keep i hi r hr)
+ have hok₁ : Ok sboxCfg s₁ := hok.congr
+ (kept₁ .rdx (by decide)) (kept₁ .rdx (by decide)) rd₁ wr₁
+ obtain ⟨s₂, run₂, bits, rd₂, wr₂, keep₂, _⟩ := sbox_ok i hi hok₁
+ have hbits : ∀ j < 4, (s₂.gpr (q j)).getLsbD 0 =
+ (Spec.TripleDes.sBox i (roundChunk i ((s.gpr .r13).setWidth 32)
+ ((s.mem.readW (s.gpr .rdi) 64).setWidth 48))).getLsbD j := by
+ intro j hj
+ rw [bits j hj 0 (by decide), chunk]
+ obtain ⟨s₃, run₃, value, rd₃, wr₃, mem₃, keep₃⟩ := roundOutput_piece i hi s₂ _ hbits
+ refine ⟨s₃, ?_, ?_, rd₃.trans (rd₂.trans rd₁), wr₃.trans (wr₂.trans wr₁), ?_, ?_⟩
+ · simp only [box, runBoxes_append, run₁, Option.bind_some, run₂, run₃]
+ · rw [value, keep₂ .r12 (by decide), kept₁ .r12 (by decide)]
+ · intro r hr
+ rw [keep₃ r (roundOutput_keep i hi r hr), keep₂ r ?_, kept₁ r (List.mem_cons_of_mem _ hr)]
+ revert hr; cases r <;> decide
+ · have hf := sbox_spillFrame i hi s₁ s₂ run₂
+ have hregion : spillRegion s₁ = spillRegion s := by
+ simp only [spillRegion, kept₁ .rdx (by decide)]
+ rw [hregion, mem₁] at hf
+ rw [mem₃]
+ exact hf
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Bytes.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Bytes.lean
new file mode 100644
index 000000000..462a5d3e1
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Bytes.lean
@@ -0,0 +1,36 @@
+import VerifiedGarbage.Proof.TripleDes.Bytes
+import VerifiedGarbage.Proof.Framework.X86_64.Bswap
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.Spec.TripleDes
+
+theorem decodeBlock_readW (m : Mem) (p : Addr) :
+ decodeBlock (blockAt m p) = bswap64 (m.readW p 64) := by
+ rw [VG.Proof.TripleDes.decodeBlock_cat, bswap64_readW]
+ simp only [VG.Proof.TripleDes.catBlock, blockAt, Vector.getElem_ofFn,
+ BitVec.add_assoc, BitVec.add_zero]
+ rfl
+
+
+theorem bswap64_byte (x : BitVec 64) (i : Nat) (hi : i < 8) :
+ (bswap64 x).extractLsb' (8 * i) 8 = (x >>> (8 * (7 - i))).setWidth 8 := by
+ have hcases : ∀ k < 8, k = 0 ∨ k = 1 ∨ k = 2 ∨ k = 3 ∨
+ k = 4 ∨ k = 5 ∨ k = 6 ∨ k = 7 := by decide
+ rcases hcases i hi with rfl | rfl | rfl | rfl | rfl | rfl | rfl | rfl
+ all_goals
+ simp (disch := decide) only [bswap64, extractLsb'_append_byte_hi,
+ extractLsb'_append_byte_lo, Nat.reduceMul, Nat.reduceSub,
+ BitVec.setWidth_ushiftRight_eq_extractLsb, BitVec.extractLsb'_eq_self]
+
+
+theorem blockAt_writeW (m : Mem) (p : Addr) (x : BitVec 64) :
+ blockAt (m.writeW p (bswap64 x)) p = encodeBlock x := by
+ apply Vector.ext
+ intro i hi
+ simp only [blockAt, encodeBlock, Vector.getElem_ofFn, Mem.writeW, Mem.write,
+ Mem.sub_ofNat_toNat p (by omega : i < 2 ^ 64), BitVec.setWidth_eq,
+ hi, ite_true]
+ exact bswap64_byte x i hi
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/ConstantTime.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/ConstantTime.lean
new file mode 100644
index 000000000..5233ce33e
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/ConstantTime.lean
@@ -0,0 +1,46 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.FunctionsLit
+import VerifiedGarbage.Proof.Framework.X86_64.Taint
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+
+def PublicRegs (rs : List Reg) (s₁ s₂ : State) : Prop :=
+ ∀ r ∈ rs, s₁.gpr r = s₂.gpr r
+
+def blockTaint : X86_64.Taint.T :=
+ { regs := .ofList [.rdi, .rsi, .rdx], flags := false,
+ lens := [0, 512], bases := [(.rdx, 1, 0)] }
+
+def ecbTaint : X86_64.Taint.T :=
+ { regs := .ofList [.rdi, .rsi, .rdx, .rcx, .rsp], flags := false,
+ lens := [0, 1024], bases := [(.rcx, 1, 0)] }
+
+theorem encryptBlock_constantTime (pre : State → Prop) (pub : State → State → Prop)
+ (hagree : ∀ s t, pre s → pre t → pub s t → X86_64.Taint.Agree blockTaint s t) :
+ ConstantTime isa pre pub encryptBlock :=
+ VG.Taint.constantTime (A := taint) blockTaint hagree (by taint_decide)
+
+theorem decryptBlock_constantTime (pre : State → Prop) (pub : State → State → Prop)
+ (hagree : ∀ s t, pre s → pre t → pub s t → X86_64.Taint.Agree blockTaint s t) :
+ ConstantTime isa pre pub decryptBlock :=
+ VG.Taint.constantTime (A := taint) blockTaint hagree (by taint_decide)
+
+theorem ecbEncrypt_constantTime (pre : State → Prop) (pub : State → State → Prop)
+ (hagree : ∀ s t, pre s → pre t → pub s t → X86_64.Taint.Agree ecbTaint s t) :
+ ConstantTime isa pre pub Ecb.encrypt :=
+ VG.Taint.constantTime (A := taint) ecbTaint hagree (by taint_decide)
+
+theorem ecbDecrypt_constantTime (pre : State → Prop) (pub : State → State → Prop)
+ (hagree : ∀ s t, pre s → pre t → pub s t → X86_64.Taint.Agree ecbTaint s t) :
+ ConstantTime isa pre pub Ecb.decrypt :=
+ VG.Taint.constantTime (A := taint) ecbTaint hagree (by taint_decide)
+
+theorem expandKey_constantTime (pre : State → Prop) :
+ ConstantTime isa pre (PublicRegs [.rdi, .rsi, .rdx, .rcx]) Key.expandKey := by
+ refine VG.Taint.constantTime (A := taint) (Taint.ofRegs [.rdi, .rsi, .rdx, .rcx]) ?_
+ (by taint_decide)
+ intro s₁ s₂ _ _ hp
+ exact Taint.agree_ofRegs hp
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Body.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Body.lean
new file mode 100644
index 000000000..a8b51817c
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Body.lean
@@ -0,0 +1,56 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.Slice
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.Steps
+import VerifiedGarbage.Proof.TripleDes.EcbMemory
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64 VG.Spec.TripleDes
+
+structure BodyPost (d : Direction) (s : State) (n : Nat) (s' : State) : Prop where
+ ptr : s'.gpr .rsi = s.gpr .rsi + 8
+ count : s'.gpr .rbp = BitVec.ofNat 64 (n - 1)
+ flag : s'.zf = some (decide (n = 1))
+ reg : ∀ r ∈ kept, r ≠ .rsi → r ≠ .rbp → s'.gpr r = s.gpr r
+ callee : ∀ r ∈ calleeSaved, r ≠ .rbp → s'.gpr r = s.gpr r
+ rd : s'.rd = s.rd
+ wr : s'.wr = s.wr
+ mem : Frame ([dataR s, ⟨s.gpr .rdx, 512⟩, stackR s]) s.mem s'.mem
+ data : Spec.TripleDes.blockAt s'.mem (s.gpr .rsi) =
+ blockResult (Spec.TripleDes.scheduleAt s.mem (s.gpr .rdi)) d
+ (Spec.TripleDes.blockAt s.mem (s.gpr .rsi))
+
+theorem body_ok (d : Direction) (s : State) (n : Nat) (hn : 1 ≤ n) (bound : n < 2 ^ 64)
+ (count : s.gpr .rbp = BitVec.ofNat 64 n) (hp : StepPre s) :
+ WP isa (.seq (Impl.TripleDes.X86_64.Ecb.blockCall d) (.block Impl.TripleDes.X86_64.Ecb.advance)) s (BodyPost d s n) := by
+ apply WP.seq
+ apply WP.mono (call_ok d s hp.call)
+ intro s₁ h₁
+ obtain ⟨s₂, run₂, ptr₂, count₂, flag₂, keep₂⟩ := advance_ok s₁
+ refine WP.of_runBlock ⟨s₂, run₂, ?_⟩
+ have count' : s₁.gpr .rbp - 1 = BitVec.ofNat 64 (n - 1) := by
+ rw [h₁.reg .rbp (by decide), count]
+ exact Offset.ofNat_sub_ofNat hn
+ refine ⟨by rw [ptr₂, h₁.reg .rsi (by decide)], count₂.trans count', ?_, ?_, ?_,
+ keep₂.rd.trans h₁.rd, keep₂.wr.trans h₁.wr, ?_, ?_⟩
+ · rw [flag₂, count']
+ rw [counter_zero (n - 1) (by omega)]
+ have he : n - 1 = 0 ↔ n = 1 := by omega
+ simp only [he]
+ · intro r hr hs hb
+ exact (keep₂.reg r (by simp [hs, hb])).trans (h₁.reg r hr)
+ · intro r hr hb
+ have hs : r ≠ .rsi := by
+ have fact : ∀ r ∈ calleeSaved, r ≠ .rsi := by decide
+ exact fact r hr
+ exact (keep₂.reg r (by simp [hs, hb])).trans (h₁.callee r hr)
+ · rw [keep₂.mem]; exact h₁.mem
+ · rw [keep₂.mem]; exact h₁.output
+
+theorem BodyPost.tail {d : Direction} {s s' : State} {n : Nat}
+ (h : BodyPost d s (n + 1) s') (hp : StepPre s (n + 1)) : StepPre s' n :=
+ hp.slice (i := 1) (by omega) h.rd h.wr
+ (h.reg .rdi (by decide) (by decide) (by decide))
+ (h.reg .rdx (by decide) (by decide) (by decide))
+ (h.reg .rsp (by decide) (by decide) (by decide)) h.ptr
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Call.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Call.lean
new file mode 100644
index 000000000..d03e6884c
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Call.lean
@@ -0,0 +1,87 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.StrongBlock
+import VerifiedGarbage.Impl.TripleDes.X86_64.Ecb
+import VerifiedGarbage.Proof.Framework.X86_64.Call
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction)
+
+def kept : List Reg := [.rdi, .rsi, .rdx, .rbp, .rsp]
+
+theorem block_noSp (d : Direction) : NoSp (block d) := by
+ have h : ((block d).allInstrs fun i => !Taint.clobbers i .rsp) = true := by
+ cases d
+ · change (encryptBlock.allInstrs _) = true
+ lit_decide
+ · change (decryptBlock.allInstrs _) = true
+ lit_decide
+ intro i hi
+ rw [Code.allInstrs_eq] at h
+ simpa using List.all_eq_true.mp h i hi
+
+theorem blockCall_eq (d : Direction) : Impl.TripleDes.X86_64.Ecb.blockCall d =
+ .call (match d with | .encrypt => "vg_triple_des_encrypt_block" | .decrypt => "vg_triple_des_decrypt_block")
+ (block d) := by cases d <;> rfl
+
+theorem block_depth (d : Direction) : (block d).depth = 0 := by cases d <;> rfl
+
+structure CallPre (s : State) : Prop where
+ reads : Covers [⟨s.gpr .rdi, 384⟩, ⟨s.gpr .rsi, 8⟩, ⟨s.gpr .rdx, 512⟩] (s.rd ++ s.wr)
+ writes : Covers [⟨s.gpr .rsi, 8⟩, ⟨s.gpr .rdx, 512⟩] s.wr
+ keyScratch : (Region.mk (s.gpr .rdi) 384).Disjoint ⟨s.gpr .rdx, 512⟩
+ dataScratch : (Region.mk (s.gpr .rsi) 8).Disjoint ⟨s.gpr .rdx, 512⟩
+ stackKey : (below (s.gpr .rsp) 8).Disjoint ⟨s.gpr .rdi, 384⟩
+ stackData : (below (s.gpr .rsp) 8).Disjoint ⟨s.gpr .rsi, 8⟩
+ stackScratch : (below (s.gpr .rsp) 8).Disjoint ⟨s.gpr .rdx, 512⟩
+
+structure CallPost (d : Direction) (s s' : State) : Prop where
+ reg : ∀ r ∈ kept, s'.gpr r = s.gpr r
+ callee : ∀ r ∈ calleeSaved, s'.gpr r = s.gpr r
+ rd : s'.rd = s.rd
+ wr : s'.wr = s.wr
+ mem : Frame [⟨s.gpr .rsi, 8⟩, ⟨s.gpr .rdx, 512⟩, below (s.gpr .rsp) 8] s.mem s'.mem
+ output : Spec.TripleDes.blockAt s'.mem (s.gpr .rsi) =
+ blockResult (Spec.TripleDes.scheduleAt s.mem (s.gpr .rdi)) d
+ (Spec.TripleDes.blockAt s.mem (s.gpr .rsi))
+
+theorem call_ok (d : Direction) (s : State) (hp : CallPre s) :
+ WP isa (Impl.TripleDes.X86_64.Ecb.blockCall d) s (CallPost d s) := by
+ rw [blockCall_eq]
+ refine WP.call (k := strongBlockContract d) (strongBlock_correct d)
+ (block_noSp d) (by rw [block_depth]; decide)
+ (rd := [⟨s.gpr .rdi, 384⟩]) (wr := [⟨s.gpr .rsi, 8⟩, ⟨s.gpr .rdx, 512⟩]) ?_ hp.reads hp.writes ?_
+ · simp only [strongBlockContract, blockContract, State.withRegions_gpr,
+ State.withRegions_rd, State.withRegions_wr,
+ State.callEntry_rsp, State.callEntry_gpr _ (by decide : Reg.rdi ≠ .rsp),
+ State.callEntry_gpr _ (by decide : Reg.rsi ≠ .rsp), State.callEntry_gpr _ (by decide : Reg.rdx ≠ .rsp)]
+ exact ⟨trivial, trivial, hp.keyScratch, hp.dataScratch, hp.stackData, hp.stackScratch⟩
+ · intro s' rd wr callee frame _ ⟨s₂, mem₂, regs₂, out₂⟩
+ refine ⟨?_, callee, rd, wr, ?_, ?_⟩
+ · intro r hr
+ by_cases hsp : r = .rsp
+ · subst r
+ exact callee .rsp (by decide)
+ · have hkeep : ∀ q ∈ kept, q ∈ savedRegs ++ [Reg.rdi] ∨ q ∈ [Reg.rsi, .rdx, .rsp] := by decide
+ have hreg : s₂.gpr r = (s.callEntry.withRegions
+ [⟨s.gpr .rdi, 384⟩] [⟨s.gpr .rsi, 8⟩, ⟨s.gpr .rdx, 512⟩]).gpr r := by
+ rcases hkeep r hr with h | h
+ · exact out₂.saved r h
+ · exact out₂.regs r h
+ rw [State.withRegions_gpr, State.callEntry_gpr _ hsp] at hreg
+ exact (regs₂ r hsp).symm.trans hreg
+ · rw [block_depth] at frame
+ exact frame
+ · have stackFrame : Frame [below (s.gpr .rsp) 8] s.mem s.callEntry.mem :=
+ (Frame.refl _ _).writeW List.mem_cons_self _ (below_call _ (by decide) (by decide))
+ have key := VG.Proof.TripleDes.scheduleAt_eq_of_frame (s.gpr .rdi) stackFrame
+ (by simpa only [List.mem_singleton, forall_eq] using hp.stackKey.symm)
+ have input := VG.Proof.TripleDes.blockAt_eq_of_frame (s.gpr .rsi) stackFrame
+ (by simpa only [List.mem_singleton, forall_eq] using hp.stackData.symm)
+ have result := out₂.result
+ simp only [State.withRegions_gpr, State.withRegions_mem,
+ State.callEntry_gpr _ (by decide : Reg.rdi ≠ .rsp),
+ State.callEntry_gpr _ (by decide : Reg.rsi ≠ .rsp), key, input, mem₂] at result
+ exact result
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Contract.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Contract.lean
new file mode 100644
index 000000000..0ec48bd44
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Contract.lean
@@ -0,0 +1,72 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.IO
+import VerifiedGarbage.Proof.Framework.Contract
+import VerifiedGarbage.Spec.TripleDes.Contract
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64
+
+def contract (d : Spec.TripleDes.Direction) : Contract isa where
+ pre s :=
+ let key : Region := ⟨s.gpr .rdi, 384⟩
+ let data : Region := ⟨s.gpr .rsi, 8 * (s.gpr .rdx).toNat⟩
+ let buf : Region := ⟨s.gpr .rcx, 1024⟩
+ let ret : Region := ⟨s.gpr .rsp, 8⟩
+ let stack := below (s.gpr .rsp) 8
+ s.rd = [key] ∧ s.wr = [data, buf] ∧ key.Disjoint data ∧ key.Disjoint buf ∧
+ data.Disjoint buf ∧ ret.Disjoint data ∧ ret.Disjoint buf ∧
+ stack.Disjoint key ∧ stack.Disjoint data ∧ stack.Disjoint buf ∧
+ (s.gpr .rsi).toNat + 8 * (s.gpr .rdx).toNat ≤ 2 ^ 64
+ post s s' :=
+ Spec.TripleDes.blocksAt s'.mem (s.gpr .rsi) (s.gpr .rdx).toNat =
+ Spec.TripleDes.ecb (Spec.TripleDes.scheduleAt s.mem (s.gpr .rdi)) d
+ (Spec.TripleDes.blocksAt s.mem (s.gpr .rsi) (s.gpr .rdx).toNat)
+ pub := PublicRegs [.rdi, .rsi, .rdx, .rcx, .rsp]
+
+theorem ecbTaint_wf (d : Spec.TripleDes.Direction) (s : State) (hs : (contract d).pre s) :
+ Taint.Wf ecbTaint s := by
+ obtain ⟨_, hwr, _, _, dataSep, _, _, _, _, _, fit⟩ := hs
+ refine ⟨?_, ?_⟩
+ · intro _
+ rw [hwr]
+ refine ⟨?_, ?_, ?_⟩
+ · exact List.Forall₂.cons (by change 0 ≤ 8 * (s.gpr .rdx).toNat; omega)
+ (List.Forall₂.cons (by change 1024 ≤ 1024; decide) List.Forall₂.nil)
+ · exact List.Pairwise.cons
+ (fun r hr => by obtain rfl := List.mem_singleton.mp hr; exact dataSep)
+ (List.Pairwise.cons (by simp) List.Pairwise.nil)
+ · intro r hr
+ simp only [List.mem_cons, List.not_mem_nil, or_false] at hr
+ rcases hr with rfl | rfl
+ · change 8 * (s.gpr .rdx).toNat ≤ 2 ^ 64; omega
+ · change 1024 ≤ 2 ^ 64; decide
+ · intro p hp
+ simp only [ecbTaint, List.mem_singleton] at hp
+ subst p
+ unfold Taint.region
+ rw [hwr]
+ change s.gpr .rcx = s.gpr .rcx + (0 : BitVec 64)
+ exact (BitVec.add_zero _).symm
+
+theorem ecbTaint_agree (d : Spec.TripleDes.Direction) (s t : State)
+ (hs : (contract d).pre s) (ht : (contract d).pre t)
+ (hp : (contract d).pub s t) : X86_64.Taint.Agree ecbTaint s t := by
+ refine ⟨?_, ?_, ecbTaint_wf d s hs, ecbTaint_wf d t ht, ?_, ?_, ?_⟩
+ · constructor
+ · intro r hr
+ exact hp r (by simpa only [ecbTaint, RegSet.mem_ofList] using hr)
+ · intro h
+ change false = true at h
+ contradiction
+ · intro _
+ rw [hs.2.1, ht.2.1, hp .rsi (by decide), hp .rdx (by decide), hp .rcx (by decide)]
+ · intro slot hslot
+ change slot ∈ ([] : List (Nat × Nat × Nat)) at hslot
+ exact False.elim (List.not_mem_nil hslot)
+ · intro slot hslot
+ change slot ∈ ([] : List (Nat × Nat × Nat)) at hslot
+ exact False.elim (List.not_mem_nil hslot)
+ · intro r hr
+ simp only [ecbTaint, RegSet.not_mem_empty] at hr
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Correct.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Correct.lean
new file mode 100644
index 000000000..6b7faae6b
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Correct.lean
@@ -0,0 +1,97 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.Contract
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64
+
+theorem ecb_correct (d : Spec.TripleDes.Direction) (s : State) (hs : (contract d).pre s) :
+ WP isa (Impl.TripleDes.X86_64.Ecb.ecb d) s (fun s' => gprPreserved s s' ∧ (contract d).post s s') := by
+ obtain ⟨hrd, hwr, keyData, keyBuf, dataBuf,
+ retData, retBuf, stackKey, stackData, stackBuf, fit⟩ := hs
+ have writes (i : Nat) (hi : i + 8 ≤ 1024) : InRegions s.wr (s.gpr .rcx + BitVec.ofNat 64 i) 8 := by
+ rw [hwr]
+ exact ⟨⟨s.gpr .rcx, 1024⟩, by simp, Offset.contains_base _ hi (by omega)⟩
+ rw [Impl.TripleDes.X86_64.Ecb.ecb]
+ apply WP.seq
+ rw [WP.block_append_iff]
+ obtain ⟨s₁, run₁, keep₁⟩ := save_ok s (writes 512 (by decide))
+ refine WP.of_runBlock ⟨s₁, run₁, ?_⟩
+ obtain ⟨s₂, run₂, count₂, buf₂, flag₂, keep₂⟩ := setup_ok s₁
+ refine WP.of_runBlock ⟨s₂, run₂, ?_⟩
+ have g₁ (r : Reg) : s₁.gpr r = s.gpr r := keep₁.reg r (by simp)
+ rw [g₁] at count₂ buf₂ flag₂
+ have key₂ := (keep₂.reg .rdi (by decide)).trans (g₁ .rdi)
+ have data₂ := (keep₂.reg .rsi (by decide)).trans (g₁ .rsi)
+ have sp₂ := (keep₂.reg .rsp (by decide)).trans (g₁ .rsp)
+ have rd₂ := keep₂.rd.trans keep₁.rd
+ have wr₂ := keep₂.wr.trans keep₁.wr
+ have mem₂ : s₂.mem = savedMem s := keep₂.mem.trans keep₁.mem
+ have scratchFrame : Frame [⟨s.gpr .rcx, 1024⟩] s.mem s₂.mem := by
+ rw [mem₂]; exact savedMem_frame s
+ have initialKey := VG.Proof.TripleDes.scheduleAt_eq_of_frame (s.gpr .rdi) scratchFrame
+ (by simpa using keyBuf)
+ have initialData := VG.Proof.TripleDes.blocksAt_frame scratchFrame (s.gpr .rsi) (s.gpr .rdx).toNat
+ (by simpa using dataBuf)
+ have hp₂ : StepPre s₂ (s.gpr .rdx).toNat := by
+ constructor
+ · simp only [keyR, dataR, bufR, key₂, data₂, buf₂, rd₂, wr₂, hrd, hwr]
+ exact fun _ _ h => h
+ · simp only [dataR, bufR, data₂, buf₂, wr₂, hwr]
+ exact fun _ _ h => h
+ · simpa only [keyR, dataR, key₂, data₂] using keyData
+ · simpa only [keyR, bufR, key₂, buf₂] using keyBuf
+ · simpa only [dataR, bufR, data₂, buf₂] using dataBuf
+ · simpa only [stackR, keyR, sp₂, key₂] using stackKey
+ · simpa only [stackR, dataR, sp₂, data₂] using stackData
+ · simpa only [stackR, bufR, sp₂, buf₂] using stackBuf
+ apply WP.seq
+ apply WP.mono (maybeLoop_ok d s₂ (s.gpr .rdx).toNat (by omega) hp₂
+ (by simpa using count₂) (by rw [count₂]; exact flag₂))
+ intro s₃ h₃
+ have rd₃ := h₃.rd.trans rd₂
+ have wr₃ := h₃.wr.trans wr₂
+ have buf₃ := (h₃.reg .rdx (by decide) (by decide) (by decide)).trans buf₂
+ have readable : InRegions (s₃.rd ++ s₃.wr) (s₃.gpr .rdx + BitVec.ofNat 64 512) 8 := by
+ rw [rd₃, wr₃, buf₃]
+ obtain ⟨r, hr, hc⟩ := writes 512 (by decide)
+ exact ⟨r, List.mem_append_right _ hr, hc⟩
+ have value : s₃.mem.readW (s₃.gpr .rdx + BitVec.ofNat 64 512) 64 = s.gpr .rbp := by
+ have h := h₃.scratchRead hp₂
+ rw [buf₂, mem₂, savedMem_rbp] at h
+ rw [buf₃]; exact h
+ obtain ⟨s₄, run₄, rbp₄, keep₄⟩ := restore_ok s₃ (s.gpr .rbp) readable value
+ refine WP.of_runBlock ⟨s₄, run₄, ?_⟩
+ constructor
+ · constructor
+ · intro r hr
+ by_cases hp : r = .rbp
+ · subst r; exact rbp₄
+ · rw [keep₄.reg r (by simpa using hp), h₃.callee r hr hp]
+ have sep : ∀ r ∈ calleeSaved, r ≠ .rbp → r ∉ [.rbp, .rdx] := by decide
+ exact (keep₂.reg r (sep r hr hp)).trans (g₁ r)
+ · let rs : List Region := [⟨s.gpr .rsi, 8 * (s.gpr .rdx).toNat⟩,
+ ⟨s.gpr .rcx, 1024⟩, below (s.gpr .rsp) 8]
+ have loopFrame : Frame rs s₂.mem s₃.mem := by
+ have h := h₃.mem
+ simp only [loopWrites, dataR, stackR, data₂, buf₂, sp₂] at h
+ apply h.sub
+ intro r hr
+ simp only [List.mem_cons, List.not_mem_nil, or_false] at hr
+ rcases hr with rfl | rfl | rfl
+ · exact ⟨⟨s.gpr .rsi, 8 * (s.gpr .rdx).toNat⟩, by simp [rs], fun _ h => h⟩
+ · exact ⟨⟨s.gpr .rcx, 1024⟩, by simp [rs], Region.sub_prefix (by decide)⟩
+ · exact ⟨below (s.gpr .rsp) 8, by simp [rs], fun _ h => h⟩
+ have frame : Frame rs s.mem s₄.mem := by
+ rw [keep₄.mem]
+ exact (scratchFrame.mono (by simp [rs])).trans loopFrame
+ apply frame.readW (r := ⟨s.gpr .rsp, 8⟩) (Region.contains_self _ _) (hn := by decide)
+ have stackSep : (Region.mk (s.gpr .rsp) 8).Disjoint (below (s.gpr .rsp) 8) :=
+ Offset.base_disjoint_below _ (by decide : 8 + 8 ≤ 2 ^ 64)
+ simpa only [rs, List.mem_cons, List.not_mem_nil, or_false, forall_eq_or_imp, forall_eq] using
+ And.intro retData (And.intro retBuf stackSep)
+ · have out := h₃.data
+ rw [key₂, data₂, initialKey, initialData] at out
+ change Spec.TripleDes.blocksAt s₄.mem (s.gpr .rsi) (s.gpr .rdx).toNat = _
+ rw [keep₄.mem]; exact out
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/IO.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/IO.lean
new file mode 100644
index 000000000..dbdbdafa3
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/IO.lean
@@ -0,0 +1,75 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.Loop
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64 VG.X86_64.RegUpd VG.Impl.TripleDes.X86_64
+open VG.Proof.Rc2.X86_64 (Keep offset_nat)
+
+def savedMem (s : State) : Mem :=
+ s.mem.writeW (s.gpr .rcx + BitVec.ofNat 64 512) (s.gpr .rbp)
+
+theorem save_ok (s : State)
+ (hw : InRegions s.wr (s.gpr .rcx + BitVec.ofNat 64 512) 8) :
+ ∃ s', runBlock isa Impl.TripleDes.X86_64.Ecb.save s = some s' ∧
+ Keep [] {s with mem := savedMem s} s' := by
+ refine ⟨_, by
+ simp only [Impl.TripleDes.X86_64.Ecb.save, runBlock_cons, runStep_some, runBlock_nil,
+ memOp, exec, State.store64, State.ea, offset_nat, hw, ite_true]
+ rfl, ?_⟩
+ exact ⟨fun _ _ => rfl, rfl, rfl, rfl⟩
+
+theorem savedMem_frame (s : State) : Frame [⟨s.gpr .rcx, 1024⟩] s.mem (savedMem s) :=
+ (Frame.refl _ _).writeW List.mem_cons_self _
+ (Offset.contains_base _ (by decide : 512 + 8 ≤ 1024) (by decide))
+
+theorem savedMem_rbp (s : State) : (savedMem s).readW (s.gpr .rcx + BitVec.ofNat 64 512) 64 = s.gpr .rbp := by
+ rw [savedMem, Mem.readW_writeW_self64]
+
+theorem setup_ok (s : State) :
+ ∃ s', runBlock isa Impl.TripleDes.X86_64.Ecb.setup s = some s' ∧
+ s'.gpr .rbp = s.gpr .rdx ∧ s'.gpr .rdx = s.gpr .rcx ∧
+ s'.zf = some (s.gpr .rdx == 0) ∧ Keep [.rbp, .rdx] s s' := by
+ refine ⟨_, by
+ simp only [Impl.TripleDes.X86_64.Ecb.setup, rr, runBlock_cons, exec, readSrc]
+ rfl, ?_⟩
+ refine ⟨?_, ?_, ?_, ?_⟩
+ · simp only [gpr_arithFlags, gpr_setReg, reduceCtorEq, ite_true, ite_false]
+ · simp only [gpr_arithFlags, gpr_setReg, reduceCtorEq, ite_true, ite_false]
+ · rw [zf_arithFlags]
+ simp only [gpr_setReg, reduceCtorEq, ite_false, ite_true]
+ rw [show (0 : BitVec 32).signExtend 64 = (0 : BitVec 64) by rfl]
+ exact congrArg (fun x : BitVec 64 => some (x == 0)) (BitVec.sub_zero _)
+ · constructor
+ · intro r hr
+ simp only [List.mem_cons, List.not_mem_nil, or_false, not_or] at hr
+ simp only [gpr_setReg, gpr_arithFlags, hr.1, hr.2, ite_false]
+ · simp only [mem_setReg, mem_arithFlags]
+ · simp only [rd_setReg, rd_arithFlags]
+ · simp only [wr_setReg, wr_arithFlags]
+
+theorem restore_ok (s : State) (v : BitVec 64)
+ (hr : InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 512) 8)
+ (hv : s.mem.readW (s.gpr .rdx + BitVec.ofNat 64 512) 64 = v) :
+ ∃ s', runBlock isa Impl.TripleDes.X86_64.Ecb.restore s = some s' ∧
+ s'.gpr .rbp = v ∧ Keep [.rbp] s s' := by
+ refine ⟨_, by
+ simp only [Impl.TripleDes.X86_64.Ecb.restore, runBlock_cons, runStep_some,
+ runBlock_nil, memOp, exec, readSrc, State.load64, State.ea, offset_nat, hr, ite_true,
+ Option.map_some, hv]
+ rfl, gpr_setReg_self _ _ _, ?_⟩
+ exact ⟨fun r h => gpr_setReg_of_ne _ _ (by simpa only [List.mem_singleton] using h), rfl, rfl, rfl⟩
+
+theorem LoopPost.scratchRead {d : Spec.TripleDes.Direction} {s s' : State} {n : Nat}
+ (h : LoopPost d s n s') (hp : StepPre s n) :
+ s'.mem.readW (s.gpr .rdx + BitVec.ofNat 64 512) 64 =
+ s.mem.readW (s.gpr .rdx + BitVec.ofNat 64 512) 64 := by
+ have sub : Region.Sub ⟨s.gpr .rdx + BitVec.ofNat 64 512, 8⟩ (bufR s) :=
+ Offset.sub_base _ (by decide)
+ have sep : (Region.mk (s.gpr .rdx + BitVec.ofNat 64 512) 8).Disjoint ⟨s.gpr .rdx, 512⟩ :=
+ Offset.disjoint_base _ (by decide) (by decide)
+ apply h.mem.readW (r := ⟨s.gpr .rdx + BitVec.ofNat 64 512, 8⟩) (Region.contains_self _ _)
+ (hn := by decide)
+ simpa only [loopWrites, List.mem_cons, List.not_mem_nil, or_false, forall_eq_or_imp, forall_eq] using
+ And.intro ((hp.dataBuf.sub_right sub).symm) (And.intro sep ((hp.stackBuf.sub_right sub).symm))
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Loop.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Loop.lean
new file mode 100644
index 000000000..45801becd
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Loop.lean
@@ -0,0 +1,90 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.LoopFrame
+
+/-! # Correctness of the ECB loop on complete blocks -/
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64
+open VG.Proof.TripleDes (blocksAt_cons)
+
+structure LoopPost (d : Spec.TripleDes.Direction) (s : State) (n : Nat) (s' : State) : Prop where
+ ptr : s'.gpr .rsi = s.gpr .rsi + BitVec.ofNat 64 (8 * n)
+ count : s'.gpr .rbp = 0
+ reg : ∀ r ∈ kept, r ≠ .rsi → r ≠ .rbp → s'.gpr r = s.gpr r
+ callee : ∀ r ∈ calleeSaved, r ≠ .rbp → s'.gpr r = s.gpr r
+ rd : s'.rd = s.rd
+ wr : s'.wr = s.wr
+ mem : Frame (loopWrites s n) s.mem s'.mem
+ data : Spec.TripleDes.blocksAt s'.mem (s.gpr .rsi) n =
+ Spec.TripleDes.ecb (Spec.TripleDes.scheduleAt s.mem (s.gpr .rdi)) d
+ (Spec.TripleDes.blocksAt s.mem (s.gpr .rsi) n)
+
+theorem ecb_cons (keys : Spec.TripleDes.Schedule) (d : Spec.TripleDes.Direction)
+ (b : Spec.TripleDes.Block) (bs : List Spec.TripleDes.Block) :
+ Spec.TripleDes.ecb keys d (b :: bs) = blockResult keys d b :: Spec.TripleDes.ecb keys d bs := by
+ cases d <;> rfl
+
+theorem loop_ok (d : Spec.TripleDes.Direction) (n : Nat) :
+ ∀ s : State, 1 ≤ n → 8 * n ≤ 2 ^ 64 → StepPre s n → s.gpr .rbp = BitVec.ofNat 64 n →
+ WP isa (.loop (.seq (Impl.TripleDes.X86_64.Ecb.blockCall d) (.block Impl.TripleDes.X86_64.Ecb.advance)) .ne) s (LoopPost d s n) := by
+ induction n with
+ | zero => intro s hn; omega
+ | succ n ih =>
+ intro s hn bound hp count
+ obtain ⟨t₁, s₁, exec₁, h₁⟩ := body_ok d s (n + 1) hn (by omega) count (hp.head hn)
+ by_cases hz : n = 0
+ · subst n
+ refine ⟨_, s₁, Exec.loopExit exec₁ ?_, ?_⟩
+ · simp only [eval, h₁.flag, decide_true, Option.map_some, Bool.not_true]
+ · refine ⟨h₁.ptr, h₁.count, h₁.reg, h₁.callee, h₁.rd, h₁.wr, h₁.frame (by decide), ?_⟩
+ · rw [blocksAt_cons, blocksAt_cons, ecb_cons]
+ simp only [Spec.TripleDes.blocksAt, List.range_zero, List.map_nil,
+ Spec.TripleDes.ecb, List.map_nil]
+ exact congrArg (· :: []) h₁.data
+ · have hp₁ := h₁.tail hp
+ obtain ⟨t₂, s₂, exec₂, h₂⟩ := ih s₁ (by omega) (by omega) hp₁ (by simpa using h₁.count)
+ refine ⟨_, s₂, Exec.loopNext exec₁ ?_ exec₂, ?_⟩
+ · have he : n + 1 ≠ 1 := by omega
+ simp only [eval, h₁.flag, he, decide_false, Option.map_some, Bool.not_false]
+ · have key := h₁.schedule (hp.head hn)
+ have tail := h₁.tailData hp bound
+ have data := h₂.data
+ have ki := h₁.reg .rdi (by decide) (by decide) (by decide)
+ have bi := h₁.reg .rdx (by decide) (by decide) (by decide)
+ have sp := h₁.reg .rsp (by decide) (by decide) (by decide)
+ rw [ki, h₁.ptr, key, tail] at data
+ refine ⟨?_, h₂.count, ?_, ?_, h₂.rd.trans h₁.rd, h₂.wr.trans h₁.wr, ?_, ?_⟩
+ · rw [h₂.ptr, h₁.ptr, BitVec.add_assoc]
+ exact congrArg (s.gpr .rsi + ·) (by
+ change BitVec.ofNat 64 8 + BitVec.ofNat 64 (8 * n) = _
+ rw [← BitVec.ofNat_add]
+ exact congrArg (BitVec.ofNat 64) (by omega))
+ · intro r hr hs hb
+ exact (h₂.reg r hr hs hb).trans (h₁.reg r hr hs hb)
+ · intro r hr hb
+ exact (h₂.callee r hr hb).trans (h₁.callee r hr hb)
+ · exact (h₁.frame hn).trans (loopFrame_slice (i := 1) h₂.mem (by omega) bi sp h₁.ptr)
+ · have first := firstBlock_frame h₁ hp bound h₂.mem
+ rw [blocksAt_cons, first, h₁.data, data, blocksAt_cons, ecb_cons]
+
+theorem maybeLoop_ok (d : Spec.TripleDes.Direction) (s : State) (n : Nat) (bound : 8 * n ≤ 2 ^ 64)
+ (hp : StepPre s n) (count : s.gpr .rbp = BitVec.ofNat 64 n)
+ (flag : s.zf = some (s.gpr .rbp == 0)) :
+ WP isa (.ite .e (.block []) (.loop (.seq (Impl.TripleDes.X86_64.Ecb.blockCall d) (.block Impl.TripleDes.X86_64.Ecb.advance)) .ne)) s (LoopPost d s n) := by
+ have flag' : s.zf = some (decide (n = 0)) := by
+ rw [flag, count, counter_zero n (by omega)]
+ by_cases hz : n = 0
+ · subst n
+ apply WP.ite true (by simp only [eval, flag', decide_true])
+ · intro _
+ apply WP.block_nil
+ refine ⟨by simp, count, fun _ _ _ _ => rfl, fun _ _ _ => rfl, rfl, rfl, Frame.refl _ _, ?_⟩
+ · rfl
+ · simp
+ · apply WP.ite false (by simp only [eval, flag', hz, decide_false])
+ · simp
+ · intro _
+ exact loop_ok d n s (by omega) bound hp count
+
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/LoopFrame.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/LoopFrame.lean
new file mode 100644
index 000000000..1103f8be8
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/LoopFrame.lean
@@ -0,0 +1,73 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.Body
+
+/-! # Frames for successive ECB blocks -/
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64
+
+def stepWrites (s : State) : List Region := [dataR s, ⟨s.gpr .rdx, 512⟩, stackR s]
+
+def loopWrites (s : State) (n : Nat) : List Region := [dataR s n, ⟨s.gpr .rdx, 512⟩, stackR s]
+
+theorem loopFrame_slice {s s' : State} {n m i : Nat} {a b : Mem}
+ (h : Frame (loopWrites s' m) a b) (bound : i + m ≤ n)
+ (buf : s'.gpr .rdx = s.gpr .rdx)
+ (sp : s'.gpr .rsp = s.gpr .rsp) (ptr : s'.gpr .rsi = s.gpr .rsi + BitVec.ofNat 64 (8 * i)) :
+ Frame (loopWrites s n) a b := by
+ apply h.sub
+ intro r hr
+ simp only [loopWrites, List.mem_cons, List.not_mem_nil, or_false] at hr
+ rcases hr with rfl | rfl | rfl
+ · refine ⟨dataR s n, by simp [loopWrites], ?_⟩
+ change Region.Sub ⟨s'.gpr .rsi, 8 * m⟩ ⟨s.gpr .rsi, 8 * n⟩
+ rw [ptr]
+ exact Offset.sub_base _ (by omega)
+ · refine ⟨⟨s.gpr .rdx, 512⟩, by simp [loopWrites], ?_⟩
+ rw [buf]; exact fun _ h => h
+ · refine ⟨stackR s, by simp [loopWrites], ?_⟩
+ change Region.Sub (below (s'.gpr .rsp) 8) (below (s.gpr .rsp) 8)
+ rw [sp]; exact fun _ h => h
+
+theorem BodyPost.frame {d : Spec.TripleDes.Direction} {s s' : State} {n : Nat}
+ (h : BodyPost d s n s') (hn : 1 ≤ n) : Frame (loopWrites s n) s.mem s'.mem :=
+ loopFrame_slice (m := 1) (i := 0) h.mem hn rfl rfl (by simp)
+
+theorem BodyPost.schedule {d : Spec.TripleDes.Direction} {s s' : State} {n : Nat}
+ (h : BodyPost d s n s') (hp : StepPre s) :
+ Spec.TripleDes.scheduleAt s'.mem (s.gpr .rdi) = Spec.TripleDes.scheduleAt s.mem (s.gpr .rdi) := by
+ apply VG.Proof.TripleDes.scheduleAt_eq_of_frame _ h.mem
+ simpa only [stepWrites, List.mem_cons, List.not_mem_nil, or_false, forall_eq_or_imp, forall_eq] using
+ And.intro hp.keyData (And.intro
+ (hp.keyBuf.sub_right (Region.sub_prefix (by decide : 512 ≤ 1024))) hp.stackKey.symm)
+
+theorem BodyPost.tailData {d : Spec.TripleDes.Direction} {s s' : State} {n : Nat}
+ (h : BodyPost d s (n + 1) s') (hp : StepPre s (n + 1)) (bound : 8 * (n + 1) ≤ 2 ^ 64) :
+ Spec.TripleDes.blocksAt s'.mem (s.gpr .rsi + 8) n = Spec.TripleDes.blocksAt s.mem (s.gpr .rsi + 8) n := by
+ have sub : Region.Sub ⟨s.gpr .rsi + 8, 8 * n⟩ (dataR s (n + 1)) :=
+ Offset.sub_base _ (by change 8 + 8 * n ≤ 8 * (n + 1); omega)
+ have sep : (Region.mk (s.gpr .rsi + 8) (8 * n)).Disjoint (dataR s) :=
+ Offset.disjoint_base _ (d := 8) (n := 8 * n) (k := 8) (by decide) (by omega)
+ apply VG.Proof.TripleDes.blocksAt_frame h.mem
+ simpa only [stepWrites, List.mem_cons, List.not_mem_nil, or_false, forall_eq_or_imp, forall_eq] using
+ And.intro sep (And.intro
+ ((hp.dataBuf.sub_left sub).sub_right (Region.sub_prefix (by decide : 512 ≤ 1024)))
+ ((hp.stackData.sub_right sub).symm))
+
+theorem firstBlock_frame {d : Spec.TripleDes.Direction} {s s' : State} {n : Nat} {m : Mem}
+ (h : BodyPost d s (n + 1) s') (hp : StepPre s (n + 1)) (bound : 8 * (n + 1) ≤ 2 ^ 64)
+ (frame : Frame (loopWrites s' n) s'.mem m) :
+ Spec.TripleDes.blockAt m (s.gpr .rsi) = Spec.TripleDes.blockAt s'.mem (s.gpr .rsi) := by
+ have first : Region.Sub (dataR s) (dataR s (n + 1)) := Region.sub_prefix (by change 8 ≤ 8 * (n + 1); omega)
+ have sep : (dataR s).Disjoint ⟨s.gpr .rsi + 8, 8 * n⟩ :=
+ Offset.base_disjoint _ (e := 8) (n := 8 * n) (k := 8) (by decide) (by omega)
+ apply VG.Proof.TripleDes.blockAt_eq_of_frame _ frame
+ have buf := h.reg .rdx (by decide) (by decide) (by decide)
+ have sp := h.reg .rsp (by decide) (by decide) (by decide)
+ simpa only [loopWrites, dataR, stackR, buf, sp, h.ptr,
+ List.mem_cons, List.not_mem_nil, or_false, forall_eq_or_imp, forall_eq] using
+ And.intro sep (And.intro
+ ((hp.dataBuf.sub_left first).sub_right (Region.sub_prefix (by decide : 512 ≤ 1024)))
+ ((hp.stackData.sub_right first).symm))
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Pre.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Pre.lean
new file mode 100644
index 000000000..4ff30d9a2
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Pre.lean
@@ -0,0 +1,67 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.Call
+
+/-! # Permissions and separation for one ECB step -/
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64
+
+abbrev keyR (s : State) : Region := ⟨s.gpr .rdi, 384⟩
+abbrev dataR (s : State) (n : Nat := 1) : Region := ⟨s.gpr .rsi, 8 * n⟩
+abbrev bufR (s : State) : Region := ⟨s.gpr .rdx, 1024⟩
+abbrev stackR (s : State) : Region := below (s.gpr .rsp) 8
+
+structure StepPre (s : State) (n : Nat := 1) : Prop where
+ reads : Covers [keyR s, dataR s n, bufR s] (s.rd ++ s.wr)
+ writes : Covers [dataR s n, bufR s] s.wr
+ keyData : (keyR s).Disjoint (dataR s n)
+ keyBuf : (keyR s).Disjoint (bufR s)
+ dataBuf : (dataR s n).Disjoint (bufR s)
+ stackKey : (stackR s).Disjoint (keyR s)
+ stackData : (stackR s).Disjoint (dataR s n)
+ stackBuf : (stackR s).Disjoint (bufR s)
+
+theorem StepPre.transport {s s' : State} {n : Nat} (hp : StepPre s n)
+ (rd : s'.rd = s.rd) (wr : s'.wr = s.wr) (regs : ∀ r ∈ kept, s'.gpr r = s.gpr r) : StepPre s' n := by
+ have a := regs .rdi (by decide)
+ have c := regs .rsi (by decide)
+ have d := regs .rdx (by decide)
+ have e := regs .rsp (by decide)
+ constructor
+ · simpa only [keyR, dataR, bufR, stackR, rd, wr, a, c, d, e] using hp.reads
+ · simpa only [keyR, dataR, bufR, stackR, rd, wr, a, c, d, e] using hp.writes
+ · simpa only [keyR, dataR, bufR, stackR, rd, wr, a, c, d, e] using hp.keyData
+ · simpa only [keyR, dataR, bufR, stackR, rd, wr, a, c, d, e] using hp.keyBuf
+ · simpa only [keyR, dataR, bufR, stackR, rd, wr, a, c, d, e] using hp.dataBuf
+ · simpa only [keyR, dataR, bufR, stackR, rd, wr, a, c, d, e] using hp.stackKey
+ · simpa only [keyR, dataR, bufR, stackR, rd, wr, a, c, d, e] using hp.stackData
+ · simpa only [keyR, dataR, bufR, stackR, rd, wr, a, c, d, e] using hp.stackBuf
+
+theorem StepPre.call {s : State} (hp : StepPre s) : CallPre s := by
+ constructor
+ · have hc : Covers [⟨s.gpr .rdi, 384⟩, ⟨s.gpr .rsi, 8⟩, ⟨s.gpr .rdx, 512⟩]
+ [keyR s, dataR s, bufR s] := by
+ apply Covers.of_sub
+ intro r hr
+ simp only [List.mem_cons, List.not_mem_nil, or_false] at hr
+ rcases hr with rfl | rfl | rfl
+ · exact ⟨keyR s, by simp, 0, by simp, by simp⟩
+ · exact ⟨dataR s, by simp, 0, by simp, by simp⟩
+ · exact ⟨bufR s, by simp, 0, by simp, by simp⟩
+ exact fun a n h => hp.reads a n (hc a n h)
+ · have hc : Covers [⟨s.gpr .rsi, 8⟩, ⟨s.gpr .rdx, 512⟩] [dataR s, bufR s] := by
+ apply Covers.of_sub
+ intro r hr
+ simp only [List.mem_cons, List.not_mem_nil, or_false] at hr
+ rcases hr with rfl | rfl
+ · exact ⟨dataR s, by simp, 0, by simp, by simp⟩
+ · exact ⟨bufR s, by simp, 0, by simp, by simp⟩
+ exact fun a n h => hp.writes a n (hc a n h)
+ · exact hp.keyBuf.sub_right (Region.sub_prefix (by decide))
+ · exact hp.dataBuf.sub_right (Region.sub_prefix (by decide))
+ · exact hp.stackKey
+ · exact hp.stackData
+ · exact hp.stackBuf.sub_right (Region.sub_prefix (by decide))
+
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Slice.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Slice.lean
new file mode 100644
index 000000000..8cac280ce
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Slice.lean
@@ -0,0 +1,48 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.Pre
+
+/-! # Restricting ECB permissions to a consecutive subrange -/
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64
+
+theorem StepPre.slice {s s' : State} {n m i : Nat} (hp : StepPre s n) (bound : i + m ≤ n)
+ (rd : s'.rd = s.rd) (wr : s'.wr = s.wr)
+ (key : s'.gpr .rdi = s.gpr .rdi)
+ (buf : s'.gpr .rdx = s.gpr .rdx) (sp : s'.gpr .rsp = s.gpr .rsp)
+ (ptr : s'.gpr .rsi = s.gpr .rsi + BitVec.ofNat 64 (8 * i)) : StepPre s' m := by
+ have sub : Region.Sub (dataR s' m) (dataR s n) := by
+ change Region.Sub ⟨s'.gpr .rsi, 8 * m⟩ ⟨s.gpr .rsi, 8 * n⟩
+ rw [ptr]
+ exact Offset.sub_base _ (by omega)
+ constructor
+ · have hc : Covers [keyR s', dataR s' m, bufR s'] [keyR s, dataR s n, bufR s] := by
+ apply Covers.of_sub
+ intro r hr
+ simp only [List.mem_cons, List.not_mem_nil, or_false] at hr
+ rcases hr with rfl | rfl | rfl
+ · exact ⟨keyR s, by simp, 0, by simp [key], by simp⟩
+ · exact ⟨dataR s n, by simp, 8 * i, ptr, by change 8 * i + 8 * m ≤ 8 * n; omega⟩
+ · exact ⟨bufR s, by simp, 0, by simp [buf], by simp⟩
+ rw [rd, wr]
+ exact fun a k h => hp.reads a k (hc a k h)
+ · have hc : Covers [dataR s' m, bufR s'] [dataR s n, bufR s] := by
+ apply Covers.of_sub
+ intro r hr
+ simp only [List.mem_cons, List.not_mem_nil, or_false] at hr
+ rcases hr with rfl | rfl
+ · exact ⟨dataR s n, by simp, 8 * i, ptr, by change 8 * i + 8 * m ≤ 8 * n; omega⟩
+ · exact ⟨bufR s, by simp, 0, by simp [buf], by simp⟩
+ rw [wr]
+ exact fun a k h => hp.writes a k (hc a k h)
+ · simpa only [keyR, key] using hp.keyData.sub_right sub
+ · simpa only [keyR, bufR, key, buf] using hp.keyBuf
+ · simpa only [bufR, buf] using hp.dataBuf.sub_left sub
+ · simpa only [stackR, keyR, sp, key] using hp.stackKey
+ · simpa only [stackR, sp] using hp.stackData.sub_right sub
+ · simpa only [stackR, bufR, sp, buf] using hp.stackBuf
+
+theorem StepPre.head {s : State} {n : Nat} (hp : StepPre s n) (hn : 1 ≤ n) : StepPre s :=
+ hp.slice (i := 0) hn rfl rfl rfl rfl rfl (by simp)
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Steps.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Steps.lean
new file mode 100644
index 000000000..e04a94729
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Steps.lean
@@ -0,0 +1,44 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.Call
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64 VG.X86_64.RegUpd
+open VG.Proof.Rc2.X86_64 (Keep)
+
+theorem advance_ok (s : State) :
+ ∃ s', runBlock isa Impl.TripleDes.X86_64.Ecb.advance s = some s' ∧
+ s'.gpr .rsi = s.gpr .rsi + 8 ∧ s'.gpr .rbp = s.gpr .rbp - 1 ∧
+ s'.zf = some ((s.gpr .rbp - 1) == 0) ∧ Keep [.rsi, .rbp] s s' := by
+ refine ⟨_, by
+ simp (config := {decide := true}) only [Impl.TripleDes.X86_64.Ecb.advance,
+ runBlock_cons, runStep_some, runBlock_nil, exec, execAlu, readSrc,
+ Option.bind_some, gpr_setReg, gpr_arithFlags, ite_false]
+ rfl, ?_⟩
+ refine ⟨?_, ?_, ?_, ?_⟩
+ · simp only [gpr_setReg, gpr_arithFlags, reduceCtorEq, ite_false, ite_true]
+ rfl
+ · exact gpr_setReg_self _ _ _
+ · rw [zf_setReg, zf_arithFlags]
+ rfl
+ · constructor
+ · intro r hr
+ simp only [List.mem_cons, List.not_mem_nil, or_false, not_or] at hr
+ simp only [gpr_setReg, gpr_arithFlags, hr.1, hr.2, ite_false]
+ · simp only [mem_setReg, mem_arithFlags]
+ · simp only [rd_setReg, rd_arithFlags]
+ · simp only [wr_setReg, wr_arithFlags]
+
+theorem counter_zero (n : Nat) (hn : n < 2 ^ 64) :
+ ((BitVec.ofNat 64 n) == (0 : BitVec 64)) = decide (n = 0) := by
+ apply Bool.eq_iff_iff.mpr
+ simp only [beq_iff_eq, decide_eq_true_eq]
+ constructor
+ · intro h
+ have ht := congrArg BitVec.toNat h
+ simp only [BitVec.toNat_ofNat, Nat.mod_eq_of_lt hn] at ht
+ exact ht
+ · intro h
+ rw [h]
+ rfl
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Verified.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Verified.lean
new file mode 100644
index 000000000..a49828064
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ecb/Verified.lean
@@ -0,0 +1,51 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Ecb.Correct
+
+namespace VG.Proof.TripleDes.X86_64.Ecb
+
+open VG VG.X86_64
+
+def satState : State where
+ gpr r := match r with
+ | .rdi => 0x1000 | .rsi => 0x2000 | .rcx => 0x3000 | .rsp => 0x4000 | _ => 0
+ cf := none
+ zf := none
+ sf := none
+ of := none
+ mem _ := 0
+ rd := [⟨0x1000, 384⟩]
+ wr := [⟨0x2000, 0⟩, ⟨0x3000, 1024⟩]
+
+theorem encrypt_correct (s : State) (hs : (contract .encrypt).pre s) :
+ ∃ t s', Exec isa Impl.TripleDes.X86_64.Ecb.encrypt s t s' ∧ abiPreserved s s' ∧
+ (contract .encrypt).post s s' := by
+ obtain ⟨t, s', he, ha, hp⟩ := ecb_correct .encrypt s hs
+ change Exec isa Impl.TripleDes.X86_64.Ecb.encrypt s t s' at he
+ exact ⟨t, s', he, abiPreserved_of_exec (by lit_decide) he ha, hp⟩
+
+theorem decrypt_correct (s : State) (hs : (contract .decrypt).pre s) :
+ ∃ t s', Exec isa Impl.TripleDes.X86_64.Ecb.decrypt s t s' ∧ abiPreserved s s' ∧
+ (contract .decrypt).post s s' := by
+ obtain ⟨t, s', he, ha, hp⟩ := ecb_correct .decrypt s hs
+ change Exec isa Impl.TripleDes.X86_64.Ecb.decrypt s t s' at he
+ exact ⟨t, s', he, abiPreserved_of_exec (by lit_decide) he ha, hp⟩
+
+theorem publicRegs_five (s₁ s₂ : State) : PublicRegs [.rdi, .rsi, .rdx, .rcx, .rsp] s₁ s₂ ↔
+ s₁.gpr .rdi = s₂.gpr .rdi ∧ s₁.gpr .rsi = s₂.gpr .rsi ∧ s₁.gpr .rdx = s₂.gpr .rdx ∧
+ s₁.gpr .rcx = s₂.gpr .rcx ∧ s₁.gpr .rsp = s₂.gpr .rsp := by
+ simp [PublicRegs]
+
+theorem encrypt_verified : Verified target Impl.TripleDes.X86_64.Ecb.encrypt
+ (Spec.TripleDes.ecbEncryptContract abi 8) := by
+ refine Verified.of_correct encrypt_correct
+ (ecbEncrypt_constantTime _ _ (ecbTaint_agree .encrypt)) ?_
+ sig_implies [Spec.TripleDes.ecbEncryptContract, Spec.TripleDes.ecbContract,
+ Spec.TripleDes.ecbSig, abi, argRegs, contract, publicRegs_five] [satState] using satState
+
+theorem decrypt_verified : Verified target Impl.TripleDes.X86_64.Ecb.decrypt
+ (Spec.TripleDes.ecbDecryptContract abi 8) := by
+ refine Verified.of_correct decrypt_correct
+ (ecbDecrypt_constantTime _ _ (ecbTaint_agree .decrypt)) ?_
+ sig_implies [Spec.TripleDes.ecbDecryptContract, Spec.TripleDes.ecbContract,
+ Spec.TripleDes.ecbSig, abi, argRegs, contract, publicRegs_five] [satState] using satState
+
+end VG.Proof.TripleDes.X86_64.Ecb
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/FunctionsLit.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/FunctionsLit.lean
new file mode 100644
index 000000000..e042abb84
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/FunctionsLit.lean
@@ -0,0 +1,13 @@
+import VerifiedGarbage.Proof.Framework.X86_64.Lit
+import VerifiedGarbage.Impl.TripleDes.X86_64.ExpandKey
+import VerifiedGarbage.Impl.TripleDes.X86_64.Ecb
+
+namespace VG
+
+materialize_code Impl.TripleDes.X86_64.encryptBlock
+materialize_code Impl.TripleDes.X86_64.decryptBlock
+materialize_code Impl.TripleDes.X86_64.Key.expandKey
+materialize_code Impl.TripleDes.X86_64.Ecb.encrypt
+materialize_code Impl.TripleDes.X86_64.Ecb.decrypt
+
+end VG
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Head.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Head.lean
new file mode 100644
index 000000000..16f1f2058
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Head.lean
@@ -0,0 +1,94 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Body
+import VerifiedGarbage.Proof.TripleDes.X86_64.BlockIO
+import VerifiedGarbage.Proof.TripleDes.X86_64.Save
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction DesSchedule)
+open VG.Proof.TripleDes (roundKey)
+
+def saveRegion (s : State) : Region := ⟨s.gpr .rdx, 56⟩
+
+structure HeadPre (keys : Nat → DesSchedule) (base : Addr) (s : State) : Prop where
+ spills : Ok sboxCfg s
+ pointer : s.gpr .rdi = base
+ saveRead : ∀ i < 7, InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8
+ saveWrite : ∀ i < 7, InRegions s.wr (s.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8
+ countRead : InRegions (s.rd ++ s.wr) (countAddr s) 8
+ countWrite : InRegions s.wr (countAddr s) 8
+ dataRead : InRegions (s.rd ++ s.wr) (s.gpr .rsi) 8
+ dataSeparate : (⟨s.gpr .rsi, 8⟩ : Region).Disjoint (saveRegion s)
+ read : ∀ c < 3, ∀ d : Direction, ∀ j < 16,
+ InRegions (s.rd ++ s.wr) (keyAddr (componentBase base c) d j) 8
+ separateWork : ∀ c < 3, ∀ d : Direction, ∀ j < 16,
+ (⟨keyAddr (componentBase base c) d j, 8⟩ : Region).Disjoint (workRegion s)
+ separateSave : ∀ c < 3, ∀ d : Direction, ∀ j < 16,
+ (⟨keyAddr (componentBase base c) d j, 8⟩ : Region).Disjoint (saveRegion s)
+ values : ∀ c < 3, ∀ d : Direction, ∀ j < 16,
+ (s.mem.readW (keyAddr (componentBase base c) d j) 64).setWidth 48 = roundKey (keys c) d j
+
+structure HeadPost (keys : Nat → DesSchedule) (base : Addr) (original s : State) : Prop where
+ word : WordState (Spec.TripleDes.permute Spec.TripleDes.ip
+ (Spec.TripleDes.decodeBlock (Spec.TripleDes.blockAt original.mem (original.gpr .rsi)))) s
+ ready : Ready keys base s
+ saved : Saved original s
+ rd : s.rd = original.rd
+ wr : s.wr = original.wr
+ regs : ∀ q ∈ [Reg.rdi, .rsi, .rdx, .rsp], s.gpr q = original.gpr q
+ frame : Frame [saveRegion original] original.mem s.mem
+
+theorem ready_afterSave {keys : Nat → DesSchedule} {base : Addr} {s t : State}
+ (hp : HeadPre keys base s) (hg : t.gpr = s.gpr) (hrd : t.rd = s.rd)
+ (hwr : t.wr = s.wr) (hsaved : Saved s t) (hf : Frame [saveRegion s] s.mem t.mem) :
+ Ready keys base t := by
+ have hbase : t.gpr .rdx = s.gpr .rdx := congrFun hg .rdx
+ refine ⟨hp.spills.congr hbase hbase hrd hwr, ?_, ?_, ?_, ?_, ?_, ?_, ?_⟩
+ · exact (hsaved 6 (by decide)).trans hp.pointer
+ · rw [hrd, hwr, show savedKeyAddr t = savedKeyAddr s from congrArg (· + BitVec.ofNat 64 48) hbase]
+ exact hp.saveRead 6 (by decide)
+ · rw [hrd, hwr, show countAddr t = countAddr s from congrArg (· + BitVec.ofNat 64 56) hbase]
+ exact hp.countRead
+ · rw [hwr, show countAddr t = countAddr s from congrArg (· + BitVec.ofNat 64 56) hbase]
+ exact hp.countWrite
+ · rw [hrd, hwr]; exact hp.read
+ · rw [show workRegion t = workRegion s from
+ congrArg (fun p => (⟨p + BitVec.ofNat 64 56, 392⟩ : Region)) hbase]
+ exact hp.separateWork
+ · intro c hc d j hj
+ have hmem := hf.readW (a := keyAddr (componentBase base c) d j) (w := 64)
+ (r := ⟨keyAddr (componentBase base c) d j, 8⟩) (Region.contains_self _ _)
+ (fun q hq => by obtain rfl := List.mem_singleton.mp hq; exact hp.separateSave c hc d j hj)
+ (by decide)
+ exact (congrArg (BitVec.setWidth 48) hmem).trans (hp.values c hc d j hj)
+
+theorem blockHead_ok (keys : Nat → DesSchedule) (base : Addr) (s : State)
+ (hp : HeadPre keys base s) :
+ WP isa (.block (blockSave ++ blockLoad)) s (HeadPost keys base s) := by
+ apply WP.block_append
+ apply WP.mono (blockSave_ok s hp.saveWrite)
+ intro s₁ hs₁
+ have hready := ready_afterSave hp hs₁.1 hs₁.2.1 hs₁.2.2.1 hs₁.2.2.2.1 hs₁.2.2.2.2
+ have hread₁ : InRegions (s₁.rd ++ s₁.wr) (s₁.gpr .rsi) 8 := by
+ rw [hs₁.2.1, hs₁.2.2.1, hs₁.1]; exact hp.dataRead
+ have hdata : Spec.TripleDes.blockAt s₁.mem (s₁.gpr .rsi) =
+ Spec.TripleDes.blockAt s.mem (s.gpr .rsi) := by
+ rw [hs₁.1]
+ exact VG.Proof.TripleDes.blockAt_eq_of_frame _ hs₁.2.2.2.2
+ (fun q hq => by obtain rfl := List.mem_singleton.mp hq; exact hp.dataSeparate)
+ obtain ⟨s₂, run₂, left₂, right₂, mem₂, rd₂, wr₂, regs₂⟩ := blockLoad_ok s₁ hread₁
+ have hframe : Frame [workRegion s₁] s₁.mem s₂.mem := by
+ rw [mem₂]; exact Frame.refl _ _
+ have hinput := congrArg (fun b => Spec.TripleDes.permute Spec.TripleDes.ip
+ (Spec.TripleDes.decodeBlock b)) hdata
+ apply WP.of_runBlock
+ refine ⟨s₂, run₂, ?_, hready.congr (regs₂ .rdx (by decide)) rd₂ wr₂ hframe,
+ hs₁.2.2.2.1.congr (regs₂ .rdx (by decide)) hframe,
+ rd₂.trans hs₁.2.1, wr₂.trans hs₁.2.2.1, ?_, ?_⟩
+ · exact ⟨left₂.trans (congrArg (fun x : BitVec 64 => ((x >>> 32).setWidth 32).setWidth 64) hinput),
+ right₂.trans (congrArg (fun x : BitVec 64 => (x.setWidth 32).setWidth 64) hinput)⟩
+ · intro q hq
+ exact (regs₂ q hq).trans (congrFun hs₁.1 q)
+ · rw [mem₂]; exact hs₁.2.2.2.2
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Initial.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Initial.lean
new file mode 100644
index 000000000..6a2bf652f
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Initial.lean
@@ -0,0 +1,58 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Permutation
+import VerifiedGarbage.Proof.TripleDes.Core
+namespace VG.Proof.TripleDes.X86_64
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+
+theorem initial_ok (s : State) :
+ ∃ s', runBlock isa (instrs initialPermutation.lit) s = some s' ∧
+ s'.gpr .rbx = (Spec.TripleDes.permute Spec.TripleDes.ip
+ ((s.gpr .rax).setWidth 64)).zeroExtend 64 ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, ((instrs initialPermutation.lit).all fun op => op.dst != some r) = true →
+ s'.gpr r = s.gpr r) :=
+ fixedPermutation_ok Spec.TripleDes.ip (by decide) (by decide)
+ VG.Proof.TripleDes.ip_bounds (instrs initialPermutation.lit) initialPermutation_check s
+end VG.Proof.TripleDes.X86_64
+namespace VG.Proof.TripleDes.X86_64
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+
+theorem initial_raw_ok (s : State) :
+ ∃ s', runBlock isa (permuteCode Spec.TripleDes.ip 64 .rbx .rax .rbp) s = some s' ∧
+ s'.gpr .rbx = Spec.TripleDes.permute Spec.TripleDes.ip (s.gpr .rax) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, ((instrs initialPermutation.lit).all fun op => op.dst != some r) = true →
+ s'.gpr r = s.gpr r) := by
+ obtain ⟨s', run, word, rd, wr, mem, regs⟩ := initial_ok s
+ have hcode : permuteCode Spec.TripleDes.ip 64 .rbx .rax .rbp =
+ instrs initialPermutation.lit := congrArg instrs initialPermutation.lit_eq
+ refine ⟨s', (congrArg (fun is => runBlock isa is s) hcode).trans run, ?_, rd, wr, mem, regs⟩
+ exact word.trans ((BitVec.setWidth_eq _).trans
+ (congrArg (Spec.TripleDes.permute Spec.TripleDes.ip) (BitVec.setWidth_eq _)))
+end VG.Proof.TripleDes.X86_64
+
+namespace VG.Proof.TripleDes.X86_64
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+theorem final_ok (s : State) :
+ ∃ s', runBlock isa (instrs finalPermutation.lit) s = some s' ∧
+ s'.gpr .rbx = (Spec.TripleDes.permute Spec.TripleDes.fp
+ ((s.gpr .rax).setWidth 64)).zeroExtend 64 ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, ((instrs finalPermutation.lit).all fun op => op.dst != some r) = true →
+ s'.gpr r = s.gpr r) :=
+ fixedPermutation_ok Spec.TripleDes.fp (by decide) (by decide)
+ VG.Proof.TripleDes.fp_bounds (instrs finalPermutation.lit) finalPermutation_check s
+
+theorem final_raw_ok (s : State) :
+ ∃ s', runBlock isa (permuteCode Spec.TripleDes.fp 64 .rbx .rax .rbp) s = some s' ∧
+ s'.gpr .rbx = Spec.TripleDes.permute Spec.TripleDes.fp (s.gpr .rax) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, ((instrs finalPermutation.lit).all fun op => op.dst != some r) = true →
+ s'.gpr r = s.gpr r) := by
+ obtain ⟨s', run, word, rd, wr, mem, regs⟩ := final_ok s
+ have hcode : permuteCode Spec.TripleDes.fp 64 .rbx .rax .rbp =
+ instrs finalPermutation.lit := congrArg instrs finalPermutation.lit_eq
+ refine ⟨s', (congrArg (fun is => runBlock isa is s) hcode).trans run, ?_, rd, wr, mem, regs⟩
+ exact word.trans ((BitVec.setWidth_eq _).trans
+ (congrArg (Spec.TripleDes.permute Spec.TripleDes.fp) (BitVec.setWidth_eq _)))
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Body.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Body.lean
new file mode 100644
index 000000000..1e9c81bed
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Body.lean
@@ -0,0 +1,71 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Composition
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64 VG.X86_64.RegUpd
+open VG.Proof.Rc2.X86_64 (Keep)
+
+theorem cmpLength_ok (s : State) :
+ ∃ s', runBlock isa [.alu .cmp .rsi (.imm 16)] s = some s' ∧
+ s'.zf = some (s.gpr .rsi == 16) ∧ Keep [] s s' := by
+ refine ⟨_, by
+ simp only [runBlock_cons, runStep_some, runBlock_nil, exec, execAlu, readSrc, Option.bind_some]
+ rfl, ?_, ?_⟩
+ · rw [zf_arithFlags]
+ exact congrArg some (by
+ apply Bool.eq_iff_iff.mpr
+ simp only [beq_iff_eq]
+ change (s.gpr .rsi - (16 : BitVec 64) = (0 : BitVec 64)) ↔ s.gpr .rsi = (16 : BitVec 64)
+ bv_omega)
+ · exact ⟨fun _ _ => rfl, rfl, rfl, rfl⟩
+
+theorem Components.keep {origin s t : State} {n : Nat} (hs : Components origin s n)
+ (ht : Keep [] s t) : Components origin t n :=
+ ⟨fun c hc j hj => by rw [ht.mem]; exact hs.keys c hc j hj,
+ ht.rd.trans hs.rd, ht.wr.trans hs.wr,
+ fun r hr => (ht.reg r (by simp)).trans (hs.reg r hr), by rw [ht.mem]; exact hs.frame⟩
+
+theorem beq16_toNat (x : BitVec 64) : (x == 16) = decide (x.toNat = 16) := by
+ apply Bool.eq_iff_iff.mpr
+ simp only [beq_iff_eq, decide_eq_true_eq]
+ constructor
+ · intro h; rw [h]; rfl
+ · intro h
+ apply BitVec.eq_of_toNat_eq
+ exact h
+
+theorem body_ok (origin s : State) (hp : Permissions origin) (hs : Components origin s 0)
+ (Q : State → Prop)
+ (finish : ∀ t, Components origin t 3 → WP isa (.block Impl.TripleDes.X86_64.Key.restore) t Q) :
+ WP isa (.seq (Impl.TripleDes.X86_64.Key.component 0 0)
+ (.seq (Impl.TripleDes.X86_64.Key.component 8 1)
+ (.seq (.block [.alu .cmp .rsi (.imm 16)])
+ (.seq (.ite .e (.block Impl.TripleDes.X86_64.Key.copyThird)
+ (Impl.TripleDes.X86_64.Key.component 16 2)) (.block Impl.TripleDes.X86_64.Key.restore))))) s Q := by
+ apply WP.seq
+ apply WP.mono (componentStep_ok origin s 0 (by decide) hp hs (by rfl))
+ intro s₁ hs₁
+ apply WP.seq
+ apply WP.mono (componentStep_ok origin s₁ 1 (by decide) hp hs₁ (by rfl))
+ intro s₂ hs₂
+ apply WP.seq
+ obtain ⟨s₃, run₃, flag₃, keep₃⟩ := cmpLength_ok s₂
+ refine WP.of_runBlock ⟨s₃, run₃, ?_⟩
+ have hs₃ := hs₂.keep keep₃
+ apply WP.seq
+ apply WP.mono (Q := (Components origin · 3)) ?_
+ · intro t ht
+ exact finish t ht
+ have flag : s₃.zf = some (decide ((origin.gpr .rsi).toNat = 16)) := by
+ rw [flag₃, hs₂.reg .rsi (by decide), beq16_toNat]
+ by_cases h16 : (origin.gpr .rsi).toNat = 16
+ · apply WP.ite true (by simp only [eval, flag, h16, decide_true])
+ · intro _; exact copyThird_ok origin s₃ hp hs₃ h16
+ · simp
+ · apply WP.ite false (by simp only [eval, flag, h16, decide_false])
+ · simp
+ · intro _
+ exact componentStep_ok origin s₃ 2 (by decide) hp hs₃
+ (by simp only [VG.Proof.TripleDes.componentOffset, h16, and_false, ite_false])
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Component.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Component.lean
new file mode 100644
index 000000000..19f08a8dc
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Component.lean
@@ -0,0 +1,40 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Loop
+import VerifiedGarbage.Proof.TripleDes.Schedule
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64
+
+structure ComponentPost (keys : Spec.TripleDes.DesSchedule) (base : Addr) (s s' : State) : Prop where
+ keys : ∀ i < 16, s'.mem.readW (base + BitVec.ofNat 64 (8 * i)) 64 = (keys.getD i 0).setWidth 64
+ rd : s'.rd = s.rd
+ wr : s'.wr = s.wr
+ reg : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp], s'.gpr r = s.gpr r
+ frame : Frame [⟨base, 128⟩] s.mem s'.mem
+
+theorem component_ok (s : State) (offset component : Nat) (hc : component < 3)
+ (hr : InRegions (s.rd ++ s.wr) (s.gpr .rdi + BitVec.ofNat 64 offset) 8)
+ (hw : ∀ j < 16, InRegions s.wr
+ (s.gpr .rdx + BitVec.ofNat 64 (128 * component) + BitVec.ofNat 64 (8 * j)) 8) :
+ WP isa (Impl.TripleDes.X86_64.Key.component offset component) s
+ (ComponentPost (Spec.TripleDes.expandDesKey (Spec.TripleDes.decodeBlock
+ (Spec.TripleDes.blockAt s.mem (s.gpr .rdi + BitVec.ofNat 64 offset))))
+ (s.gpr .rdx + BitVec.ofNat 64 (128 * component)) s) := by
+ rw [Impl.TripleDes.X86_64.Key.component]
+ apply WP.seq
+ apply WP.mono (load_ok s offset component hc hr)
+ intro s₁ h₁
+ have writes : ∀ j < 16, InRegions s₁.wr
+ (s.gpr .rdx + BitVec.ofNat 64 (128 * component) + BitVec.ofNat 64 (8 * j)) 8 := by
+ rw [h₁.wr]; exact hw
+ apply WP.mono (loop_ok _ _ s₁ writes h₁.c h₁.d h₁.counter h₁.ptr)
+ intro s₂ h₂
+ refine ⟨?_, h₂.rd.trans h₁.rd, h₂.wr.trans h₁.wr,
+ fun r hr => (h₂.reg r hr).trans (h₁.reg r hr), ?_⟩
+ · intro i hi
+ rw [VG.Proof.TripleDes.expandDesKey_prefix, VG.Proof.TripleDes.vector_getD _ i hi 0]
+ exact h₂.keys i hi hi
+ · rw [← h₁.mem]
+ exact h₂.frame
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Composition.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Composition.lean
new file mode 100644
index 000000000..005aa4548
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Composition.lean
@@ -0,0 +1,150 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Copy
+import VerifiedGarbage.Proof.TripleDes.KeyMemory
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64
+open VG.Proof.TripleDes (componentKeys componentOffset)
+
+abbrev keyR (s : State) : Region := ⟨s.gpr .rdi, (s.gpr .rsi).toNat⟩
+abbrev outputR (s : State) : Region := ⟨s.gpr .rdx, 384⟩
+
+def slot (base : Addr) (c j : Nat) : Addr := base + BitVec.ofNat 64 (128 * c + 8 * j)
+
+structure Components (origin s : State) (done : Nat) : Prop where
+ keys : ∀ c < done, ∀ j < 16, s.mem.readW (slot (origin.gpr .rdx) c j) 64 =
+ ((componentKeys origin.mem (origin.gpr .rdi) (origin.gpr .rsi).toNat c).getD j 0).setWidth 64
+ rd : s.rd = origin.rd
+ wr : s.wr = origin.wr
+ reg : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp], s.gpr r = origin.gpr r
+ frame : Frame [outputR origin] origin.mem s.mem
+
+structure Permissions (s : State) : Prop where
+ reads : ∀ offset, offset + 8 ≤ (s.gpr .rsi).toNat →
+ InRegions (s.rd ++ s.wr) (s.gpr .rdi + BitVec.ofNat 64 offset) 8
+ writes : ∀ offset, offset + 8 ≤ 384 → InRegions s.wr (s.gpr .rdx + BitVec.ofNat 64 offset) 8
+ keyOutput : (keyR s).Disjoint (outputR s)
+ valid : Spec.TripleDes.validKey (s.gpr .rsi).toNat
+
+theorem componentStep_ok (origin s : State) (c : Nat) (hc : c < 3)
+ (hp : Permissions origin) (hs : Components origin s c)
+ (hoff : componentOffset (origin.gpr .rsi).toNat c = 8 * c) :
+ WP isa (Impl.TripleDes.X86_64.Key.component (8 * c) c) s
+ (Components origin · (c + 1)) := by
+ have offsetBound := VG.Proof.TripleDes.componentOffset_bound _ c hp.valid hc
+ rw [hoff] at offsetBound
+ have read : InRegions (s.rd ++ s.wr) (s.gpr .rdi + BitVec.ofNat 64 (8 * c)) 8 := by
+ rw [hs.rd, hs.wr, hs.reg .rdi (by decide)]
+ exact hp.reads _ offsetBound
+ have write : ∀ j < 16, InRegions s.wr
+ (s.gpr .rdx + BitVec.ofNat 64 (128 * c) + BitVec.ofNat 64 (8 * j)) 8 := by
+ intro j hj
+ rw [hs.wr, hs.reg .rdx (by decide), Offset.add_ofNat_add_ofNat]
+ exact hp.writes _ (by omega_using [hc, hj])
+ apply WP.mono (component_ok s (8 * c) c hc read write)
+ intro t ht
+ have frame : Frame [⟨origin.gpr .rdx + BitVec.ofNat 64 (128 * c), 128⟩] s.mem t.mem := by
+ have hf := ht.frame
+ rw [hs.reg .rdx (by decide)] at hf
+ exact hf
+ have key : Spec.TripleDes.blockAt s.mem (s.gpr .rdi + BitVec.ofNat 64 (8 * c)) =
+ Spec.TripleDes.blockAt origin.mem (origin.gpr .rdi + BitVec.ofNat 64 (8 * c)) := by
+ rw [hs.reg .rdi (by decide)]
+ apply VG.Proof.TripleDes.blockAt_eq_of_frame _ hs.frame
+ intro r hr
+ obtain rfl := List.mem_singleton.mp hr
+ exact hp.keyOutput.sub_left (Offset.sub_base _ offsetBound)
+ refine ⟨?_, ht.rd.trans hs.rd, ht.wr.trans hs.wr,
+ fun r hr => (ht.reg r hr).trans (hs.reg r hr), hs.frame.trans (frame.sub ?_)⟩
+ · intro k hk j hj
+ by_cases he : k = c
+ · subst k
+ have h := ht.keys j hj
+ rw [key, hs.reg .rdx (by decide), Offset.add_ofNat_add_ofNat] at h
+ unfold componentKeys
+ rw [hoff]
+ exact h
+ · have before : k < c := by omega_using [hk, he]
+ have sep : (Region.mk (slot (origin.gpr .rdx) k j) 8).Disjoint
+ ⟨origin.gpr .rdx + BitVec.ofNat 64 (128 * c), 128⟩ :=
+ Offset.disjoint _ (by omega_using [before, hj])
+ (by omega_using [hk, hc, hj]) (by omega_using [hc])
+ have hmem := frame.readW (a := slot (origin.gpr .rdx) k j) (w := 64) (r := ⟨slot (origin.gpr .rdx) k j, 8⟩)
+ (Region.contains_self _ _) (fun r hr => by obtain rfl := List.mem_singleton.mp hr; exact sep)
+ (by decide)
+ exact hmem.trans (hs.keys k before j hj)
+ · intro r hr
+ obtain rfl := List.mem_singleton.mp hr
+ exact ⟨outputR origin, by simp, Offset.sub_base _ (by omega_using [hc])⟩
+
+theorem copyThird_ok (origin s : State) (hp : Permissions origin)
+ (hs : Components origin s 2) (hn : (origin.gpr .rsi).toNat = 16) :
+ WP isa (.block Impl.TripleDes.X86_64.Key.copyThird) s (Components origin · 3) := by
+ have reads : ∀ i < 16, InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8 := by
+ intro i hi
+ rw [hs.rd, hs.wr, hs.reg .rdx (by decide)]
+ obtain ⟨r, hr, hc⟩ := hp.writes (8 * i) (by omega_using [hi])
+ exact ⟨r, List.mem_append_right _ hr, hc⟩
+ have writes : ∀ i < 16, InRegions s.wr (s.gpr .rdx + BitVec.ofNat 64 (256 + 8 * i)) 8 := by
+ intro i hi
+ rw [hs.wr, hs.reg .rdx (by decide)]
+ exact hp.writes _ (by omega_using [hi])
+ apply WP.mono (copy_ok s 16 (by decide) reads writes)
+ intro t ht
+ have frame : Frame [⟨origin.gpr .rdx + BitVec.ofNat 64 256, 128⟩] s.mem t.mem := by
+ have h := ht.frame
+ rw [hs.reg .rdx (by decide)] at h
+ exact h
+ refine ⟨?_, ht.rd.trans hs.rd, ht.wr.trans hs.wr, ?_, hs.frame.trans (frame.sub ?_)⟩
+ · intro c hc j hj
+ by_cases he : c = 2
+ · subst c
+ have hRepeat : componentKeys origin.mem (origin.gpr .rdi) (origin.gpr .rsi).toNat 2 =
+ componentKeys origin.mem (origin.gpr .rdi) (origin.gpr .rsi).toNat 0 := by
+ rw [hn]; rfl
+ have h := ht.keys j hj
+ rw [hs.reg .rdx (by decide)] at h
+ change t.mem.readW (origin.gpr .rdx + BitVec.ofNat 64 (256 + 8 * j)) 64 = _
+ rw [hRepeat]
+ have first := hs.keys 0 (by decide) j hj
+ simp only [slot, Nat.mul_zero, Nat.zero_add] at first
+ exact h.trans first
+ · have before : c < 2 := by omega_using [hc, he]
+ have sep : (Region.mk (slot (origin.gpr .rdx) c j) 8).Disjoint
+ ⟨origin.gpr .rdx + BitVec.ofNat 64 256, 128⟩ :=
+ Offset.disjoint _ (by omega_using [before, hj])
+ (by omega_using [before, hj]) (by decide)
+ have hmem := frame.readW (a := slot (origin.gpr .rdx) c j) (w := 64) (r := ⟨slot (origin.gpr .rdx) c j, 8⟩)
+ (Region.contains_self _ _) (fun r hr => by obtain rfl := List.mem_singleton.mp hr; exact sep)
+ (by decide)
+ exact hmem.trans (hs.keys c before j hj)
+ · intro r hr
+ have unused : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp], r ≠ .rax := by decide
+ exact (ht.reg r (unused r hr)).trans (hs.reg r hr)
+ · intro r hr
+ obtain rfl := List.mem_singleton.mp hr
+ exact ⟨outputR origin, by simp, Offset.sub_base _ (by decide)⟩
+
+def componentIndex (i : Nat) : Nat := if i < 16 then 0 else if i < 32 then 1 else 2
+
+theorem index_partition : ∀ i < 48, componentIndex i < 3 ∧ i % 16 < 16 ∧
+ 8 * i = 128 * componentIndex i + 8 * (i % 16) := by decide
+
+theorem Components.schedule {origin s : State} (h : Components origin s 3) :
+ Spec.TripleDes.scheduleAt s.mem (origin.gpr .rdx) =
+ VG.Proof.TripleDes.expandedMemory origin.mem (origin.gpr .rdi) (origin.gpr .rsi).toNat := by
+ apply Vector.ext
+ intro i hi
+ have fact := index_partition i hi
+ have keys := h.keys (componentIndex i) fact.1 (i % 16) fact.2.1
+ rw [slot, ← fact.2.2] at keys
+ rw [VG.Proof.TripleDes.scheduleAt_readW s.mem (origin.gpr .rdx) i hi]
+ simp only [VG.Proof.TripleDes.expandedMemory, Vector.getElem_ofFn]
+ by_cases h16 : i < 16
+ · simpa only [componentIndex, h16, ite_true] using keys
+ · by_cases h32 : i < 32
+ · simpa only [componentIndex, h16, h32, ite_false, ite_true] using keys
+ · simpa only [componentIndex, h16, h32, ite_false] using keys
+
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Contract.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Contract.lean
new file mode 100644
index 000000000..5202bfbe9
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Contract.lean
@@ -0,0 +1,24 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Body
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Save
+import VerifiedGarbage.Proof.TripleDes.X86_64.ConstantTime
+import VerifiedGarbage.Proof.Framework.X86_64.Abi
+import VerifiedGarbage.Spec.TripleDes.Contract
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64
+
+def contract : Contract isa where
+ pre s :=
+ let key : Region := ⟨s.gpr .rdi, (s.gpr .rsi).toNat⟩
+ let output : Region := ⟨s.gpr .rdx, 384⟩
+ let scratch : Region := ⟨s.gpr .rcx, 512⟩
+ let ret : Region := ⟨s.gpr .rsp, 8⟩
+ s.rd = [key] ∧ s.wr = [output, scratch] ∧ key.Disjoint output ∧ key.Disjoint scratch ∧
+ output.Disjoint scratch ∧ ret.Disjoint output ∧ ret.Disjoint scratch ∧
+ Spec.TripleDes.validKey (s.gpr .rsi).toNat
+ post s s' := Spec.TripleDes.scheduleAt s'.mem (s.gpr .rdx) =
+ Spec.TripleDes.expandKey (Spec.TripleDes.bytesAt s.mem (s.gpr .rdi) (s.gpr .rsi).toNat)
+ pub := PublicRegs [.rdi, .rsi, .rdx, .rcx]
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Copy.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Copy.lean
new file mode 100644
index 000000000..c3c48517f
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Copy.lean
@@ -0,0 +1,67 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Component
+import VerifiedGarbage.Proof.Rc2.X86_64.Cbc.Steps
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+
+ def copyCode (n : Nat) : List Instr :=
+ (List.range n).flatMap fun j =>
+ [.mov .rax (.mem (memOp .rdx (8 * j))), .store (memOp .rdx (256 + 8 * j)) .rax]
+
+structure CopyPost (base : Addr) (s : State) (n : Nat) (s' : State) : Prop where
+ keys : ∀ i < n, s'.mem.readW (base + BitVec.ofNat 64 (256 + 8 * i)) 64 =
+ s.mem.readW (base + BitVec.ofNat 64 (8 * i)) 64
+ rd : s'.rd = s.rd
+ wr : s'.wr = s.wr
+ reg : ∀ r, r ≠ .rax → s'.gpr r = s.gpr r
+ frame : Frame [⟨base + BitVec.ofNat 64 256, 128⟩] s.mem s'.mem
+
+theorem copy_ok (s : State) (n : Nat) (hn : n ≤ 16)
+ (hr : ∀ i < 16, InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8)
+ (hw : ∀ i < 16, InRegions s.wr (s.gpr .rdx + BitVec.ofNat 64 (256 + 8 * i)) 8) :
+ WP isa (.block (copyCode n)) s (CopyPost (s.gpr .rdx) s n) := by
+ induction n with
+ | zero =>
+ apply WP.block_nil
+ exact ⟨fun _ hi => by omega, rfl, rfl, fun _ _ => rfl, Frame.refl _ _⟩
+ | succ n ih =>
+ rw [copyCode, List.range_succ, List.flatMap_append, List.flatMap_cons, List.flatMap_nil,
+ List.append_nil, WP.block_append_iff]
+ apply WP.mono (ih (by omega))
+ intro s₁ h₁
+ have hbase : s₁.gpr .rdx = s.gpr .rdx := h₁.reg .rdx (by decide)
+ have readable : InRegions (s₁.rd ++ s₁.wr) (s₁.gpr .rdx + BitVec.ofNat 64 (8 * n)) 8 := by
+ rw [h₁.rd, h₁.wr, hbase]; exact hr n (by omega)
+ have writable : InRegions s₁.wr (s₁.gpr .rdx + BitVec.ofNat 64 (256 + 8 * n)) 8 := by
+ rw [h₁.wr, hbase]; exact hw n (by omega)
+ obtain ⟨s₂, run₂, keep₂⟩ := VG.Proof.Rc2.X86_64.Cbc.copy64_ok s₁ .rdx .rdx
+ (8 * n) (256 + 8 * n) (by decide) readable writable
+ have source : s₁.mem.readW (s.gpr .rdx + BitVec.ofNat 64 (8 * n)) 64 =
+ s.mem.readW (s.gpr .rdx + BitVec.ofNat 64 (8 * n)) 64 := by
+ apply h₁.frame.readW (r := ⟨s.gpr .rdx + BitVec.ofNat 64 (8 * n), 8⟩)
+ (Region.contains_self _ _) _ (by decide)
+ intro r h
+ obtain rfl := List.mem_singleton.mp h
+ exact Offset.disjoint (s.gpr .rdx) (by omega) (by omega) (by decide)
+ have mem₂ : s₂.mem = s₁.mem.writeW (s.gpr .rdx + BitVec.ofNat 64 (256 + 8 * n))
+ (s.mem.readW (s.gpr .rdx + BitVec.ofNat 64 (8 * n)) 64) := by
+ have hm := keep₂.mem
+ rw [hbase, source] at hm
+ exact hm
+ refine WP.of_runBlock ⟨s₂, run₂, ⟨?_, keep₂.rd.trans h₁.rd, keep₂.wr.trans h₁.wr,
+ fun r hr => (keep₂.reg r (by simpa only [List.mem_singleton] using hr)).trans (h₁.reg r hr), ?_⟩⟩
+ · intro i hi
+ rw [mem₂]
+ by_cases he : i = n
+ · subst i; exact Mem.readW_writeW_self64 _ _ _
+ · rw [Mem.readW_writeW_sep (Offset.sep (s.gpr .rdx) (by omega) (by omega) (by omega)) (by decide)]
+ exact h₁.keys i (by omega)
+ · rw [mem₂]
+ apply h₁.frame.writeW (List.mem_singleton_self _) _
+ have hc := Offset.contains_base (s.gpr .rdx + BitVec.ofNat 64 256)
+ (d := 8 * n) (n := 8) (k := 128) (by omega) (by omega)
+ rw [Offset.add_ofNat_add_ofNat] at hc
+ exact hc
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Correct.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Correct.lean
new file mode 100644
index 000000000..7bf05f8cf
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Correct.lean
@@ -0,0 +1,88 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Contract
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64
+
+ theorem expand_correct (s : State) (hs : contract.pre s) :
+ WP isa Impl.TripleDes.X86_64.Key.expandKey s (fun s' => gprPreserved s s' ∧ contract.post s s') := by
+ obtain ⟨hrd, hwr, keyOutput, keyScratch, outputScratch, retOutput, retScratch, valid⟩ := hs
+ have scratchWrites : ∀ i < 6, InRegions s.wr (s.gpr .rcx + BitVec.ofNat 64 (8 * i)) 8 := by
+ intro i hi
+ rw [hwr]
+ exact ⟨⟨s.gpr .rcx, 512⟩, by simp, Offset.contains_base _ (by omega_using [hi]) (by omega_using [hi])⟩
+ rw [Impl.TripleDes.X86_64.Key.expandKey]
+ apply WP.seq
+ apply WP.mono (save_ok s scratchWrites)
+ intro s₁ h₁
+ have g₁ (r : Reg) : s₁.gpr r = s.gpr r := congrFun h₁.1 r
+ have hp : Permissions s₁ := by
+ constructor
+ · intro offset hoff
+ rw [h₁.2.1, h₁.2.2.1, g₁, hrd, hwr]
+ exact ⟨⟨s.gpr .rdi, (s.gpr .rsi).toNat⟩, by simp,
+ Offset.contains_base _ (by simpa only [g₁] using hoff) (by
+ have bound := BitVec.isLt (s.gpr .rsi)
+ rw [g₁] at hoff
+ omega_using [hoff, bound])⟩
+ · intro offset hoff
+ rw [h₁.2.2.1, g₁, hwr]
+ exact ⟨⟨s.gpr .rdx, 384⟩, by simp, Offset.contains_base _ hoff (by omega_using [hoff])⟩
+ · simpa only [keyR, outputR, g₁] using keyOutput
+ · simpa only [g₁] using valid
+ apply body_ok s₁ s₁ hp ⟨fun _ h => by omega, rfl, rfl, fun _ _ => rfl, Frame.refl _ _⟩
+ intro s₂ h₂
+ have g₂ (r : Reg) (hr : r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp]) : s₂.gpr r = s.gpr r :=
+ (h₂.reg r hr).trans (g₁ r)
+ have frame₂ : Frame [⟨s.gpr .rdx, 384⟩] s₁.mem s₂.mem := by
+ have h := h₂.frame
+ rw [outputR, g₁] at h
+ exact h
+ have saved₂ : Saved s s₂ := by
+ intro i hi
+ have sub : Region.Sub ⟨s.gpr .rcx + BitVec.ofNat 64 (8 * i), 8⟩ ⟨s.gpr .rcx, 512⟩ :=
+ Offset.sub_base _ (by omega_using [hi])
+ have mem := frame₂.readW (a := s.gpr .rcx + BitVec.ofNat 64 (8 * i)) (w := 64)
+ (r := ⟨s.gpr .rcx + BitVec.ofNat 64 (8 * i), 8⟩) (Region.contains_self _ _)
+ (fun r hr => by obtain rfl := List.mem_singleton.mp hr; exact (outputScratch.sub_right sub).symm)
+ (by decide)
+ rw [g₂ .rcx (by decide)]
+ have saved₁ := h₁.2.2.2.1 i hi
+ rw [g₁] at saved₁
+ exact mem.trans saved₁
+ have scratchReads : ∀ i < 6, InRegions (s₂.rd ++ s₂.wr) (s₂.gpr .rcx + BitVec.ofNat 64 (8 * i)) 8 := by
+ intro i hi
+ rw [h₂.rd, h₂.wr, h₁.2.1, h₁.2.2.1, g₂ .rcx (by decide)]
+ obtain ⟨r, hr, hc⟩ := scratchWrites i hi
+ exact ⟨r, List.mem_append_right _ hr, hc⟩
+ apply WP.mono (restore_ok s s₂ saved₂ scratchReads)
+ intro s₃ h₃
+ have scratchFrame : Frame [⟨s.gpr .rcx, 512⟩] s.mem s₁.mem := h₁.2.2.2.2.sub (by
+ intro r hr
+ obtain rfl := List.mem_singleton.mp hr
+ exact ⟨⟨s.gpr .rcx, 512⟩, by simp, Region.sub_prefix (by decide)⟩)
+ have initialBytes := VG.Proof.TripleDes.bytesAt_eq_of_frame (s.gpr .rdi) (s.gpr .rsi).toNat
+ scratchFrame (Nat.le_of_lt (BitVec.isLt _)) (by simpa using keyScratch)
+ constructor
+ · constructor
+ · intro r hr
+ by_cases hrsp : r = .rsp
+ · subst r
+ exact (h₃.2.reg .rsp (by decide)).trans (g₂ .rsp (by decide))
+ · have saved : ∀ r ∈ calleeSaved, r ≠ .rsp → r ∈ Impl.TripleDes.X86_64.Key.savedRegs := by decide
+ exact h₃.1 r (saved r hr hrsp)
+ · have frame : Frame [⟨s.gpr .rdx, 384⟩, ⟨s.gpr .rcx, 512⟩] s.mem s₃.mem := by
+ rw [h₃.2.mem]
+ exact (scratchFrame.mono (by simp)).trans (frame₂.mono (by simp))
+ apply frame.readW (r := ⟨s.gpr .rsp, 8⟩) (Region.contains_self _ _) _ (by decide)
+ simpa only [List.mem_cons, List.not_mem_nil, or_false, forall_eq_or_imp, forall_eq] using
+ And.intro retOutput retScratch
+ · have result := h₂.schedule
+ simp only [g₁] at result
+ rw [← VG.Proof.TripleDes.expandKey_memory s₁.mem (s.gpr .rdi) (s.gpr .rsi).toNat valid,
+ initialBytes] at result
+ change Spec.TripleDes.scheduleAt s₃.mem (s.gpr .rdx) = _
+ rw [h₃.2.mem]
+ exact result
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Load.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Load.lean
new file mode 100644
index 000000000..529430a25
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Load.lean
@@ -0,0 +1,109 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Permutation
+import VerifiedGarbage.Proof.TripleDes.X86_64.BlockIO
+import VerifiedGarbage.Proof.TripleDes.Word
+import VerifiedGarbage.Impl.TripleDes.X86_64.ExpandKey
+import VerifiedGarbage.Proof.Rc2.X86_64.Lookup
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64 VG.X86_64.RegUpd VG.Impl.TripleDes.X86_64
+open VG.Proof.Rc2.X86_64 (offset_nat)
+
+theorem readKey_ok (s : State) (offset : Nat)
+ (hr : InRegions (s.rd ++ s.wr) (s.gpr .rdi + BitVec.ofNat 64 offset) 8) :
+ ∃ s', runBlock isa [.mov .rax (.mem (memOp .rdi offset)), .bswap .rax] s = some s' ∧
+ s'.gpr .rax = Spec.TripleDes.decodeBlock
+ (Spec.TripleDes.blockAt s.mem (s.gpr .rdi + BitVec.ofNat 64 offset)) ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .rax → s'.gpr r = s.gpr r) := by
+ refine ⟨_, by
+ simp only [runBlock_cons, runStep_some, runBlock_nil, exec, readSrc,
+ State.load64, State.ea, memOp, offset_nat, hr, ite_true, Option.map_some,
+ gpr_setReg_self]
+ rfl, ?_, ?_, ?_, ?_, ?_⟩
+ · simp only [gpr_setReg_self]
+ exact (decodeBlock_readW s.mem _).symm
+ · simp only [mem_setReg]
+ · simp only [rd_setReg]
+ · simp only [wr_setReg]
+ · intro r hr
+ simp only [gpr_setReg, hr, ite_false]
+
+def loadTail (component : Nat) : List Instr :=
+ [rr .r12 .rbx, .shift .shr .r12 28, rr .r13 .rbx,
+ .alu .and .r13 (.imm 0x0fffffff), imm .r14 0, rr .r15 .rdx,
+ .alu .add .r15 (.imm (BitVec.ofNat 32 (128 * component)))]
+
+theorem componentOffset_word : ∀ c < 3,
+ (BitVec.ofNat 32 (128 * c)).signExtend 64 = BitVec.ofNat 64 (128 * c) := by decide
+
+theorem loadTail_ok (s : State) (component : Nat) (hc : component < 3) (x : BitVec 56)
+ (hx : s.gpr .rbx = x.setWidth 64) :
+ ∃ s', runBlock isa (loadTail component) s = some s' ∧
+ s'.gpr .r12 = ((x >>> 28).setWidth 28).setWidth 64 ∧
+ s'.gpr .r13 = (x.setWidth 28).setWidth 64 ∧ s'.gpr .r14 = 0 ∧
+ s'.gpr .r15 = s.gpr .rdx + BitVec.ofNat 64 (128 * component) ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ∉ [Reg.r12, .r13, .r14, .r15] → s'.gpr r = s.gpr r) := by
+ refine ⟨_, by
+ simp only [loadTail, rr, imm, runBlock_cons, runStep_some, exec,
+ execShift, readSrc, Option.map_some, gpr_setReg, ite_true]
+ rfl, ?_, ?_, ?_, ?_, ?_, ?_, ?_, ?_⟩
+ · simp only [gpr_setReg, gpr_arithFlags, gpr_setFlags, reduceCtorEq, ite_true, ite_false]
+ rw [hx]
+ exact VG.Proof.TripleDes.split28_upper x
+ · simp only [gpr_setReg, gpr_arithFlags, gpr_setFlags, reduceCtorEq, ite_true, ite_false]
+ rw [hx]
+ change x.setWidth 64 &&& 0x0fffffff = _
+ rw [VG.Proof.TripleDes.mask28]
+ exact congrArg (BitVec.setWidth 64) (by simp only [BitVec.setWidth_setWidth_of_le x (by decide : 28 ≤ 64)])
+ · simp only [gpr_setReg, gpr_arithFlags, reduceCtorEq, ite_true, ite_false]
+ rfl
+ · simp only [gpr_setReg, gpr_arithFlags, gpr_setFlags, reduceCtorEq, ite_true, ite_false]
+ rw [componentOffset_word component hc]
+ · simp only [mem_setReg, mem_arithFlags, mem_setFlags]
+ · simp only [rd_setReg, rd_arithFlags, rd_setFlags]
+ · simp only [wr_setReg, wr_arithFlags, wr_setFlags]
+ · intro r hr
+ simp only [List.mem_cons, List.not_mem_nil, or_false, not_or] at hr
+ simp only [gpr_setReg, gpr_arithFlags, gpr_setFlags, hr.1, hr.2.1, hr.2.2.1, hr.2.2.2, ite_false]
+
+structure LoadPost (x : BitVec 56) (component : Nat) (s s' : State) : Prop where
+ c : s'.gpr .r12 = ((x >>> 28).setWidth 28).setWidth 64
+ d : s'.gpr .r13 = (x.setWidth 28).setWidth 64
+ counter : s'.gpr .r14 = 0
+ ptr : s'.gpr .r15 = s.gpr .rdx + BitVec.ofNat 64 (128 * component)
+ mem : s'.mem = s.mem
+ rd : s'.rd = s.rd
+ wr : s'.wr = s.wr
+ reg : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp], s'.gpr r = s.gpr r
+
+theorem load_ok (s : State) (offset component : Nat) (hc : component < 3)
+ (hr : InRegions (s.rd ++ s.wr) (s.gpr .rdi + BitVec.ofNat 64 offset) 8) :
+ WP isa (.block (Impl.TripleDes.X86_64.Key.load offset component)) s
+ (LoadPost (Spec.TripleDes.permute Spec.TripleDes.pc1 (Spec.TripleDes.decodeBlock
+ (Spec.TripleDes.blockAt s.mem (s.gpr .rdi + BitVec.ofNat 64 offset)))) component s) := by
+ have code : Impl.TripleDes.X86_64.Key.load offset component =
+ (([.mov .rax (.mem (memOp .rdi offset)), .bswap .rax] : List Instr) ++
+ permuteCode Spec.TripleDes.pc1 64 .rbx .rax .rbp) ++ loadTail component := rfl
+ rw [code, WP.block_append_iff, WP.block_append_iff]
+ obtain ⟨s₁, run₁, key₁, mem₁, rd₁, wr₁, reg₁⟩ := readKey_ok s offset hr
+ refine WP.of_runBlock ⟨s₁, run₁, ?_⟩
+ obtain ⟨s₂, run₂, word₂, rd₂, wr₂, mem₂, reg₂⟩ := pc1_ok s₁
+ refine WP.of_runBlock ⟨s₂, run₂, ?_⟩
+ rw [key₁] at word₂
+ obtain ⟨s₃, run₃, c₃, d₃, counter₃, ptr₃, mem₃, rd₃, wr₃, reg₃⟩ := loadTail_ok s₂ component hc _ word₂
+ refine WP.of_runBlock ⟨s₃, run₃, ⟨c₃, d₃, counter₃, ?_, mem₃.trans (mem₂.trans mem₁),
+ rd₃.trans (rd₂.trans rd₁), wr₃.trans (wr₂.trans wr₁), ?_⟩⟩
+ · have rdx₂ : s₂.gpr .rdx = s.gpr .rdx :=
+ (reg₂ .rdx (by decide +kernel)).trans (reg₁ .rdx (by decide))
+ rw [rdx₂] at ptr₃
+ exact ptr₃
+ · intro r hr
+ have unused : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp],
+ r ∉ [Reg.r12, .r13, .r14, .r15] ∧ r ≠ .rax := by decide
+ have hcheck : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp],
+ ((instrs keyPermutation1.lit).all fun op => op.dst != some r) = true := by decide +kernel
+ exact (reg₃ r (unused r hr).1).trans ((reg₂ r (hcheck r hr)).trans (reg₁ r (unused r hr).2))
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Loop.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Loop.lean
new file mode 100644
index 000000000..960082bfc
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Loop.lean
@@ -0,0 +1,116 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Rotation
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Store
+import VerifiedGarbage.Proof.Framework.Offset
+import VerifiedGarbage.Proof.Framework.Omega
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64
+open VG.Proof.TripleDes (keyPrefix keyInitial keyStep keyPrefix_succ)
+
+structure LoopState (key : BitVec 64) (base : Addr) (origin : State) (j : Nat) (s : State) : Prop where
+ c : s.gpr .r12 = (keyPrefix key j).1.setWidth 64
+ d : s.gpr .r13 = (keyPrefix key j).2.1.setWidth 64
+ counter : s.gpr .r14 = BitVec.ofNat 64 j
+ pointer : s.gpr .r15 = base + BitVec.ofNat 64 (8 * j)
+ keys : ∀ i < j, ∀ hi : i < 16, s.mem.readW (base + BitVec.ofNat 64 (8 * i)) 64 =
+ ((keyPrefix key j).2.2[i]'hi).setWidth 64
+ rd : s.rd = origin.rd
+ wr : s.wr = origin.wr
+ reg : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp], s.gpr r = origin.gpr r
+ frame : Frame [⟨base, 128⟩] origin.mem s.mem
+
+def LoopInv (key : BitVec 64) (base : Addr) (origin : State) (n : Nat) (s : State) : Prop :=
+ 1 ≤ n ∧ n ≤ 16 ∧ LoopState key base origin (16 - n) s
+
+theorem loopBody_ok (key : BitVec 64) (base : Addr) (origin : State)
+ (hw : ∀ j < 16, InRegions origin.wr (base + BitVec.ofNat 64 (8 * j)) 8)
+ (j : Nat) (hj : j < 16) (s : State) (hs : LoopState key base origin j s) :
+ WP isa (.seq Impl.TripleDes.X86_64.Key.rotation (.block Impl.TripleDes.X86_64.Key.storeRound)) s
+ (fun s' => s'.zf = some (decide (j = 15)) ∧ LoopState key base origin (j + 1) s') := by
+ apply WP.seq
+ apply WP.mono (rotation_ok s _ _ j hj hs.c hs.d hs.counter)
+ intro s₁ h₁
+ have unused : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp, .r14, .r15],
+ r ≠ .rax ∧ r ≠ .r12 ∧ r ≠ .r13 := by decide
+ have reg₁ : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp, .r14, .r15], s₁.gpr r = s.gpr r := by
+ intro r hr
+ exact h₁.reg r (unused r hr).1 (unused r hr).2.1 (unused r hr).2.2
+ have write₁ : InRegions s₁.wr (s₁.gpr .r15) 8 := by
+ rw [h₁.wr, hs.wr, reg₁ .r15 (by decide), hs.pointer]
+ exact hw j hj
+ apply WP.mono (storeRound_ok s₁ _ _ j hj h₁.c h₁.d
+ ((reg₁ .r14 (by decide)).trans hs.counter) write₁)
+ intro s₂ h₂
+ have hmem : s₂.mem = s.mem.writeW (base + BitVec.ofNat 64 (8 * j))
+ ((Spec.TripleDes.permute Spec.TripleDes.pc2
+ ((keyPrefix key j).1.rotateLeft (Spec.TripleDes.rotations.getD j 0) ++
+ (keyPrefix key j).2.1.rotateLeft (Spec.TripleDes.rotations.getD j 0))).setWidth 64) := by
+ rw [h₂.mem, h₁.mem, reg₁ .r15 (by decide), hs.pointer]
+ refine ⟨h₂.flag, ⟨?_, ?_, h₂.counter, ?_, ?_, h₂.rd.trans (h₁.rd.trans hs.rd),
+ h₂.wr.trans (h₁.wr.trans hs.wr), ?_, ?_⟩⟩
+ · rw [keyPrefix_succ]
+ exact (h₂.reg .r12 (by decide)).trans h₁.c
+ · rw [keyPrefix_succ]
+ exact (h₂.reg .r13 (by decide)).trans h₁.d
+ · rw [h₂.ptr, reg₁ .r15 (by decide), hs.pointer]
+ change base + BitVec.ofNat 64 (8 * j) + BitVec.ofNat 64 8 = _
+ rw [Offset.add_ofNat_add_ofNat]
+ exact congrArg (fun n => base + BitVec.ofNat 64 n) (by omega)
+ · intro i hi hi16
+ rw [hmem, keyPrefix_succ]
+ by_cases he : i = j
+ · subst i
+ rw [Mem.readW_writeW_self64]
+ exact congrArg (BitVec.setWidth 64) (Vector.getElem_set!_self hj).symm
+ · rw [Mem.readW_writeW_sep (Offset.sep base (by omega_using [hi, he])
+ (by omega_using [hi16]) (by omega_using [hj])) (by decide), hs.keys i (by omega_using [hi, he]) hi16]
+ exact congrArg (BitVec.setWidth 64) (Vector.getElem_set!_ne hi16 (Ne.symm he)).symm
+ · intro r hr
+ have incl : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp],
+ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp, .r12, .r13] ∧
+ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp, .r14, .r15] := by decide
+ exact (h₂.reg r (incl r hr).1).trans ((reg₁ r (incl r hr).2).trans (hs.reg r hr))
+ · rw [hmem]
+ exact hs.frame.writeW (List.mem_singleton_self _) _
+ (Offset.contains_base base (by omega_using [hj]) (by omega_using [hj]))
+
+theorem loopStep (key : BitVec 64) (base : Addr) (origin : State)
+ (hw : ∀ j < 16, InRegions origin.wr (base + BitVec.ofNat 64 (8 * j)) 8)
+ (n : Nat) (s : State) (hs : LoopInv key base origin n s) :
+ WP isa (.seq Impl.TripleDes.X86_64.Key.rotation (.block Impl.TripleDes.X86_64.Key.storeRound)) s
+ (fun s' => (isa.eval .ne s' = some false ∧ LoopState key base origin 16 s') ∨
+ (isa.eval .ne s' = some true ∧ ∃ m < n, LoopInv key base origin m s')) := by
+ apply WP.mono (loopBody_ok key base origin hw (16 - n) (by omega_using [hs.1]) s hs.2.2)
+ intro s' h
+ by_cases last : n = 1
+ · left
+ have idx : 16 - n = 15 := by omega_using [last]
+ refine ⟨?_, ?_⟩
+ · simp only [eval, h.1, idx, decide_true, Option.map_some, Bool.not_true]
+ · simpa only [idx] using h.2
+ · right
+ have idx : ¬16 - n = 15 := by omega_using [hs.1, hs.2.1, last]
+ refine ⟨?_, n - 1, by omega_using [hs.1], ?_⟩
+ · simp only [eval, h.1, idx, decide_false, Option.map_some, Bool.not_false]
+ · refine ⟨by omega_using [hs.1, last], by omega_using [hs.2.1], ?_⟩
+ have eq : 16 - n + 1 = 16 - (n - 1) := by omega_using [hs.1, hs.2.1]
+ rw [← eq]
+ exact h.2
+
+theorem loop_ok (key : BitVec 64) (base : Addr) (s : State)
+ (hw : ∀ j < 16, InRegions s.wr (base + BitVec.ofNat 64 (8 * j)) 8)
+ (hc : s.gpr .r12 = (keyInitial key).1.setWidth 64)
+ (hd : s.gpr .r13 = (keyInitial key).2.1.setWidth 64)
+ (hcount : s.gpr .r14 = 0) (hptr : s.gpr .r15 = base) :
+ WP isa (.loop (.seq Impl.TripleDes.X86_64.Key.rotation
+ (.block Impl.TripleDes.X86_64.Key.storeRound)) .ne) s (LoopState key base s 16) := by
+ apply WP.loop (M := isa) (body := .seq Impl.TripleDes.X86_64.Key.rotation
+ (.block Impl.TripleDes.X86_64.Key.storeRound)) (c := .ne)
+ (Q := LoopState key base s 16) (LoopInv key base s) (loopStep key base s hw) 16 s
+ refine ⟨by decide, by decide, hc, hd, hcount, ?_, ?_, rfl, rfl, fun _ _ => rfl, Frame.refl _ _⟩
+ · exact hptr.trans (BitVec.add_zero base).symm
+ · intro i hi
+ omega
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Permutation.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Permutation.lean
new file mode 100644
index 000000000..a333df3fb
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Permutation.lean
@@ -0,0 +1,35 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Permutation
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+
+ theorem pc1_ok (s : State) :
+ ∃ s', runBlock isa (permuteCode Spec.TripleDes.pc1 64 .rbx .rax .rbp) s = some s' ∧
+ s'.gpr .rbx = (Spec.TripleDes.permute Spec.TripleDes.pc1 (s.gpr .rax)).setWidth 64 ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, ((instrs keyPermutation1.lit).all fun op => op.dst != some r) = true →
+ s'.gpr r = s.gpr r) := by
+ obtain ⟨s', run, word, rd, wr, mem, regs⟩ :=
+ fixedPermutation_ok Spec.TripleDes.pc1 (by decide) (by decide) (by decide)
+ (instrs keyPermutation1.lit) keyPermutation1_check s
+ have hcode : permuteCode Spec.TripleDes.pc1 64 .rbx .rax .rbp = instrs keyPermutation1.lit :=
+ congrArg instrs keyPermutation1.lit_eq
+ refine ⟨s', (congrArg (fun is => runBlock isa is s) hcode).trans run, ?_, rd, wr, mem, regs⟩
+ exact word.trans (congrArg (fun x => (Spec.TripleDes.permute Spec.TripleDes.pc1 x).setWidth 64)
+ (BitVec.setWidth_eq _))
+
+theorem pc2_ok (s : State) :
+ ∃ s', runBlock isa (permuteCode Spec.TripleDes.pc2 56 .rbx .rax .rbp) s = some s' ∧
+ s'.gpr .rbx = (Spec.TripleDes.permute Spec.TripleDes.pc2 ((s.gpr .rax).setWidth 56)).setWidth 64 ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, ((instrs keyPermutation2.lit).all fun op => op.dst != some r) = true →
+ s'.gpr r = s.gpr r) := by
+ obtain ⟨s', run, word, rd, wr, mem, regs⟩ :=
+ fixedPermutation_ok Spec.TripleDes.pc2 (by decide) (by decide) (by decide)
+ (instrs keyPermutation2.lit) keyPermutation2_check s
+ have hcode : permuteCode Spec.TripleDes.pc2 56 .rbx .rax .rbp = instrs keyPermutation2.lit :=
+ congrArg instrs keyPermutation2.lit_eq
+ exact ⟨s', (congrArg (fun is => runBlock isa is s) hcode).trans run, word, rd, wr, mem, regs⟩
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Rotation.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Rotation.lean
new file mode 100644
index 000000000..40630c19f
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Rotation.lean
@@ -0,0 +1,111 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.KeySteps
+import VerifiedGarbage.Proof.TripleDes.KeySchedule
+import VerifiedGarbage.Proof.Rc2.X86_64.Lookup
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64 VG.X86_64.RegUpd VG.Impl.TripleDes.X86_64
+open VG.Proof.Rc2.X86_64 (Keep)
+
+structure RotatePost (c d : BitVec 28) (n : Nat) (s s' : State) : Prop where
+ c : s'.gpr .r12 = (c.rotateLeft n).setWidth 64
+ d : s'.gpr .r13 = (d.rotateLeft n).setWidth 64
+ mem : s'.mem = s.mem
+ rd : s'.rd = s.rd
+ wr : s'.wr = s.wr
+ reg : ∀ r, r ≠ .rax → r ≠ .r12 → r ≠ .r13 → s'.gpr r = s.gpr r
+
+theorem rotate_ok (s : State) (c d : BitVec 28)
+ (hc : s.gpr .r12 = c.setWidth 64) (hd : s.gpr .r13 = d.setWidth 64)
+ (n : Nat) (hn : 1 ≤ n) (hn' : n < 28) :
+ WP isa (Impl.TripleDes.X86_64.Key.rotate n) s (RotatePost c d n s) := by
+ rw [Impl.TripleDes.X86_64.Key.rotate, WP.block_append_iff]
+ obtain ⟨s₁, run₁, c₁, mem₁, rd₁, wr₁, reg₁⟩ := rotate28_ok s .r12 (by decide) c hc n hn hn'
+ refine WP.of_runBlock ⟨s₁, run₁, ?_⟩
+ have d₁ : s₁.gpr .r13 = d.setWidth 64 := (reg₁ .r13 (by decide) (by decide)).trans hd
+ obtain ⟨s₂, run₂, d₂, mem₂, rd₂, wr₂, reg₂⟩ := rotate28_ok s₁ .r13 (by decide) d d₁ n hn hn'
+ refine WP.of_runBlock ⟨s₂, run₂, ⟨(reg₂ .r12 (by decide) (by decide)).trans c₁, d₂,
+ mem₂.trans mem₁, rd₂.trans rd₁, wr₂.trans wr₁, ?_⟩⟩
+ intro r ha hc hd
+ exact (reg₂ r hd ha).trans (reg₁ r hc ha)
+
+theorem comparison_values : ∀ j < 16, ∀ k < 16,
+ decide ((BitVec.ofNat 64 j).toNat < ((BitVec.ofNat 32 k).signExtend 64).toNat) = decide (j < k) ∧
+ ((BitVec.ofNat 64 j - (BitVec.ofNat 32 k).signExtend 64) == (0 : BitVec 64)) = decide (j = k) := by
+ decide
+
+theorem cmp_ok (s : State) (j k : Nat) (hj : j < 16) (hk : k < 16)
+ (hv : s.gpr .r14 = BitVec.ofNat 64 j) :
+ ∃ s', runBlock isa [.alu .cmp .r14 (.imm (BitVec.ofNat 32 k))] s = some s' ∧
+ s'.cf = some (decide (j < k)) ∧ s'.zf = some (decide (j = k)) ∧ Keep [] s s' := by
+ refine ⟨_, by
+ simp only [runBlock_cons, runStep_some, runBlock_nil, exec, execAlu, readSrc, Option.bind_some]
+ rfl, ?_, ?_, ?_⟩
+ · rw [cf_arithFlags, hv]
+ exact congrArg some (comparison_values j hj k hk).1
+ · rw [zf_arithFlags, hv]
+ exact congrArg some (comparison_values j hj k hk).2
+ · exact ⟨fun _ _ => rfl, rfl, rfl, rfl⟩
+
+theorem rotation_ok (s : State) (c d : BitVec 28) (j : Nat) (hj : j < 16)
+ (hc : s.gpr .r12 = c.setWidth 64) (hd : s.gpr .r13 = d.setWidth 64)
+ (hjreg : s.gpr .r14 = BitVec.ofNat 64 j) :
+ WP isa Impl.TripleDes.X86_64.Key.rotation s
+ (RotatePost c d (Spec.TripleDes.rotations.getD j 0) s) := by
+ rw [Impl.TripleDes.X86_64.Key.rotation]
+ apply WP.seq
+ obtain ⟨s₁, run₁, cf₁, zf₁, keep₁⟩ := cmp_ok s j 2 hj (by decide) hjreg
+ refine WP.of_runBlock ⟨s₁, run₁, ?_⟩
+ have hrot (s' : State) (h : Keep [] s s') (n : Nat) (hn : 1 ≤ n) (hn' : n < 28)
+ (hv : Spec.TripleDes.rotations.getD j 0 = n) :
+ WP isa (Impl.TripleDes.X86_64.Key.rotate n) s' (RotatePost c d (Spec.TripleDes.rotations.getD j 0) s) := by
+ apply WP.mono (rotate_ok s' c d ((h.reg .r12 (by simp)).trans hc)
+ ((h.reg .r13 (by simp)).trans hd) n hn hn')
+ intro t ht
+ rw [hv]
+ exact ⟨ht.c, ht.d, ht.mem.trans h.mem, ht.rd.trans h.rd, ht.wr.trans h.wr,
+ fun r ha hc hd => (ht.reg r ha hc hd).trans (h.reg r (by simp))⟩
+ have combine {a b : State} (ha : Keep [] s a) (hb : Keep [] a b) : Keep [] s b :=
+ ⟨fun r hr => (hb.reg r hr).trans (ha.reg r hr), hb.mem.trans ha.mem,
+ hb.rd.trans ha.rd, hb.wr.trans ha.wr⟩
+ by_cases h2 : j < 2
+ · apply WP.ite true (by simp only [eval, cf₁, h2, decide_true])
+ · intro _
+ exact hrot s₁ keep₁ 1 (by decide) (by decide)
+ (by rw [VG.Proof.TripleDes.rotation_value j hj, ite_eq_left (Or.inl h2)])
+ · simp
+ · apply WP.ite false (by simp only [eval, cf₁, h2, decide_false])
+ · simp
+ · intro _
+ apply WP.seq
+ obtain ⟨s₂, run₂, cf₂, zf₂, keep₂⟩ := cmp_ok s₁ j 8 hj (by decide)
+ ((keep₁.reg .r14 (by simp)).trans hjreg)
+ refine WP.of_runBlock ⟨s₂, run₂, ?_⟩
+ have keep₂' := combine keep₁ keep₂
+ by_cases h8 : j = 8
+ · apply WP.ite true (by simp only [eval, zf₂, h8, decide_true])
+ · intro _
+ exact hrot s₂ keep₂' 1 (by decide) (by decide)
+ (by rw [VG.Proof.TripleDes.rotation_value j hj, ite_eq_left (Or.inr (Or.inl h8))])
+ · simp
+ · apply WP.ite false (by simp only [eval, zf₂, h8, decide_false])
+ · simp
+ · intro _
+ apply WP.seq
+ obtain ⟨s₃, run₃, cf₃, zf₃, keep₃⟩ := cmp_ok s₂ j 15 hj (by decide)
+ ((keep₂'.reg .r14 (by simp)).trans hjreg)
+ refine WP.of_runBlock ⟨s₃, run₃, ?_⟩
+ have keep₃' := combine keep₂' keep₃
+ by_cases h15 : j = 15
+ · apply WP.ite true (by simp only [eval, zf₃, h15, decide_true])
+ · intro _
+ exact hrot s₃ keep₃' 1 (by decide) (by decide)
+ (by rw [VG.Proof.TripleDes.rotation_value j hj, ite_eq_left (Or.inr (Or.inr h15))])
+ · simp
+ · apply WP.ite false (by simp only [eval, zf₃, h15, decide_false])
+ · simp
+ · intro _
+ exact hrot s₃ keep₃' 2 (by decide) (by decide)
+ (by rw [VG.Proof.TripleDes.rotation_value j hj, ite_eq_right (by simp only [h2, h8, h15, or_self, not_false_eq_true])])
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Save.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Save.lean
new file mode 100644
index 000000000..4ddc3c857
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Save.lean
@@ -0,0 +1,54 @@
+import VerifiedGarbage.Proof.Rc2.X86_64.Save
+import VerifiedGarbage.Impl.TripleDes.X86_64.ExpandKey
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+
+/-- The six callee-saved registers, in slot order. -/
+def savedReg (i : Nat) : Reg := (Impl.TripleDes.X86_64.Key.savedRegs).getD i .rdi
+
+theorem save_eq : Impl.TripleDes.X86_64.Key.save = VG.Proof.Rc2.X86_64.saveCode .rcx savedReg 6 := by
+ decide +kernel
+
+theorem restore_eq : Impl.TripleDes.X86_64.Key.restore = VG.Proof.Rc2.X86_64.restoreCode .rcx savedReg (List.range 6) := by
+ decide +kernel
+
+def Saved (original current : State) : Prop :=
+ ∀ i < 6, current.mem.readW (current.gpr .rcx + BitVec.ofNat 64 (8 * i)) 64 =
+ original.gpr (savedReg i)
+
+theorem save_ok (s : State)
+ (hw : ∀ i < 6, InRegions s.wr (s.gpr .rcx + BitVec.ofNat 64 (8 * i)) 8) :
+ WP isa (.block Impl.TripleDes.X86_64.Key.save) s (fun s' =>
+ s'.gpr = s.gpr ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧ Saved s s' ∧
+ Frame [⟨s.gpr .rcx, 48⟩] s.mem s'.mem) := by
+ rw [save_eq]
+ apply WP.mono (VG.Proof.Rc2.X86_64.saveCode_ok s .rcx savedReg 6 hw)
+ intro s' hs
+ refine ⟨hs.1, hs.2.1, hs.2.2.1, ?_, ?_⟩
+ · intro i hi
+ rw [hs.1, hs.2.2.2]
+ exact VG.Proof.Rc2.X86_64.saveMem_read _ _ _ 6 (by decide) i hi
+ · rw [hs.2.2.2]
+ exact VG.Proof.Rc2.X86_64.saveMem_frame _ _ _ 6 (by decide)
+
+theorem savedReg_separate : ∀ i < 6, savedReg i ≠ .rcx := by decide +kernel
+
+theorem restore_ok (original s : State) (hsaved : Saved original s)
+ (hread : ∀ i < 6, InRegions (s.rd ++ s.wr) (s.gpr .rcx + BitVec.ofNat 64 (8 * i)) 8) :
+ WP isa (.block Impl.TripleDes.X86_64.Key.restore) s (fun s' =>
+ (∀ r ∈ Impl.TripleDes.X86_64.Key.savedRegs, s'.gpr r = original.gpr r) ∧
+ VG.Proof.Rc2.X86_64.Keep (Impl.TripleDes.X86_64.Key.savedRegs) s s') := by
+ rw [restore_eq]
+ have hregs : (List.range 6).map savedReg = Impl.TripleDes.X86_64.Key.savedRegs := by decide +kernel
+ have h := VG.Proof.Rc2.X86_64.restoreCode_ok s .rcx savedReg (List.range 6) original.gpr
+ (fun i hi => savedReg_separate i (List.mem_range.mp hi))
+ (fun i hi => hread i (List.mem_range.mp hi))
+ (fun i hi => hsaved i (List.mem_range.mp hi))
+ rw [hregs] at h
+ exact h
+
+
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Store.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Store.lean
new file mode 100644
index 000000000..86db72027
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Store.lean
@@ -0,0 +1,103 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Load
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64 VG.X86_64.RegUpd VG.Impl.TripleDes.X86_64
+open VG.Proof.Rc2.X86_64 (offset_nat)
+
+def pack : List Instr := [rr .rax .r12, .shift .ror .rax 36, .alu .xor .rax (.reg .r13)]
+
+def tail : List Instr := [.store (memOp .r15 0) .rbx, .alu .add .r15 (.imm 8),
+ .alu .add .r14 (.imm 1), .alu .cmp .r14 (.imm 16)]
+
+theorem pack_ok (s : State) (c d : BitVec 28)
+ (hc : s.gpr .r12 = c.setWidth 64) (hd : s.gpr .r13 = d.setWidth 64) :
+ ∃ s', runBlock isa pack s = some s' ∧
+ (s'.gpr .rax).setWidth 56 = c ++ d ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .rax → s'.gpr r = s.gpr r) := by
+ refine ⟨_, by
+ simp only [pack, rr, runBlock_cons, runStep_some, exec, execShift,
+ readSrc, Option.map_some, gpr_setReg, ite_true]
+ rfl, ?_, ?_, ?_, ?_, ?_⟩
+ · simp only [gpr_setReg, gpr_setFlags, gpr_arithFlags, reduceCtorEq, ite_true, ite_false]
+ rw [hc, hd]
+ exact VG.Proof.TripleDes.pack28_word c d
+ · simp only [mem_setReg, mem_setFlags, mem_arithFlags]
+ · simp only [rd_setReg, rd_setFlags, rd_arithFlags]
+ · simp only [wr_setReg, wr_setFlags, wr_arithFlags]
+ · intro r hr
+ simp only [gpr_setReg, gpr_setFlags, gpr_arithFlags, hr, ite_false]
+
+theorem nextRound_values : ∀ j < 16,
+ BitVec.ofNat 64 j + 1 = BitVec.ofNat 64 (j + 1) ∧
+ ((BitVec.ofNat 64 j + 1 - (16 : BitVec 64)) == 0) = decide (j = 15) := by decide
+
+theorem tail_ok (s : State) (j : Nat) (hj : j < 16)
+ (hc : s.gpr .r14 = BitVec.ofNat 64 j)
+ (hw : InRegions s.wr (s.gpr .r15) 8) :
+ ∃ s', runBlock isa tail s = some s' ∧
+ s'.mem = s.mem.writeW (s.gpr .r15) (s.gpr .rbx) ∧
+ s'.gpr .r15 = s.gpr .r15 + 8 ∧ s'.gpr .r14 = BitVec.ofNat 64 (j + 1) ∧
+ s'.zf = some (decide (j = 15)) ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .r14 → r ≠ .r15 → s'.gpr r = s.gpr r) := by
+ have hoff : s.gpr .r15 + BitVec.ofInt 64 (Int.ofNat 0) = s.gpr .r15 := BitVec.add_zero _
+ refine ⟨_, by
+ simp only [tail, runBlock_cons, runStep_some, runBlock_nil, exec, execAlu,
+ readSrc, State.store64, State.ea, memOp, hoff, hw, ite_true, Option.bind_some,
+ gpr_setReg, gpr_arithFlags, reduceCtorEq, ite_false]
+ rfl, ?_, ?_, ?_, ?_, ?_, ?_, ?_⟩
+ · rfl
+ · simp only [gpr_setReg, gpr_arithFlags, reduceCtorEq, ite_true, ite_false]
+ rfl
+ · simp only [gpr_setReg, gpr_arithFlags, reduceCtorEq, ite_true, ite_false]
+ rw [hc]
+ exact (nextRound_values j hj).1
+ · rw [zf_arithFlags, hc]
+ exact congrArg some (nextRound_values j hj).2
+ · simp only [rd_setReg, rd_arithFlags]
+ · simp only [wr_setReg, wr_arithFlags]
+ · intro r h14 h15
+ simp only [gpr_setReg, gpr_arithFlags, h14, h15, ite_false]
+
+structure StorePost (c d : BitVec 28) (j : Nat) (s s' : State) : Prop where
+ mem : s'.mem = s.mem.writeW (s.gpr .r15) ((Spec.TripleDes.permute Spec.TripleDes.pc2 (c ++ d)).setWidth 64)
+ ptr : s'.gpr .r15 = s.gpr .r15 + 8
+ counter : s'.gpr .r14 = BitVec.ofNat 64 (j + 1)
+ flag : s'.zf = some (decide (j = 15))
+ rd : s'.rd = s.rd
+ wr : s'.wr = s.wr
+ reg : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp, .r12, .r13], s'.gpr r = s.gpr r
+
+theorem storeRound_ok (s : State) (c d : BitVec 28) (j : Nat) (hj : j < 16)
+ (hc : s.gpr .r12 = c.setWidth 64) (hd : s.gpr .r13 = d.setWidth 64)
+ (hjreg : s.gpr .r14 = BitVec.ofNat 64 j) (hw : InRegions s.wr (s.gpr .r15) 8) :
+ WP isa (.block Impl.TripleDes.X86_64.Key.storeRound) s (StorePost c d j s) := by
+ have code : Impl.TripleDes.X86_64.Key.storeRound =
+ (pack ++ permuteCode Spec.TripleDes.pc2 56 .rbx .rax .rbp) ++ tail := rfl
+ rw [code, WP.block_append_iff, WP.block_append_iff]
+ obtain ⟨s₁, run₁, word₁, mem₁, rd₁, wr₁, reg₁⟩ := pack_ok s c d hc hd
+ refine WP.of_runBlock ⟨s₁, run₁, ?_⟩
+ obtain ⟨s₂, run₂, word₂, rd₂, wr₂, mem₂, reg₂⟩ := pc2_ok s₁
+ refine WP.of_runBlock ⟨s₂, run₂, ?_⟩
+ rw [word₁] at word₂
+ have checks : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp, .r12, .r13, .r14, .r15],
+ ((instrs keyPermutation2.lit).all fun op => op.dst != some r) = true := by decide +kernel
+ have keep₂ : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp, .r12, .r13, .r14, .r15], s₂.gpr r = s.gpr r := by
+ intro r hr
+ have unused : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp, .r12, .r13, .r14, .r15], r ≠ .rax := by decide
+ exact (reg₂ r (checks r hr)).trans (reg₁ r (unused r hr))
+ have counter₂ := (keep₂ .r14 (by decide)).trans hjreg
+ have write₂ : InRegions s₂.wr (s₂.gpr .r15) 8 := by
+ rw [wr₂, wr₁, keep₂ .r15 (by decide)]; exact hw
+ obtain ⟨s₃, run₃, mem₃, ptr₃, counter₃, flag₃, rd₃, wr₃, reg₃⟩ := tail_ok s₂ j hj counter₂ write₂
+ refine WP.of_runBlock ⟨s₃, run₃, ⟨?_, ?_, counter₃, flag₃, rd₃.trans (rd₂.trans rd₁),
+ wr₃.trans (wr₂.trans wr₁), ?_⟩⟩
+ · rw [mem₃, mem₂, mem₁, keep₂ .r15 (by decide), word₂]
+ · rw [ptr₃, keep₂ .r15 (by decide)]
+ · intro r hr
+ have incl : ∀ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp, .r12, .r13],
+ r ≠ .r14 ∧ r ≠ .r15 ∧ r ∈ [Reg.rdi, .rsi, .rdx, .rcx, .rsp, .r12, .r13, .r14, .r15] := by decide
+ exact (reg₃ r (incl r hr).1 (incl r hr).2.1).trans (keep₂ r (incl r hr).2.2)
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Verified.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Verified.lean
new file mode 100644
index 000000000..4b9ddda4c
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Key/Verified.lean
@@ -0,0 +1,34 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Key.Correct
+import VerifiedGarbage.Proof.Framework.Contract
+
+namespace VG.Proof.TripleDes.X86_64.Key
+
+open VG VG.X86_64
+
+def satState : State where
+ gpr r := match r with
+ | .rdi => 0x1000 | .rsi => 16 | .rdx => 0x2000 | .rcx => 0x3000 | .rsp => 0x4000 | _ => 0
+ cf := none
+ zf := none
+ sf := none
+ of := none
+ mem _ := 0
+ rd := [⟨0x1000, 16⟩]
+ wr := [⟨0x2000, 384⟩, ⟨0x3000, 512⟩]
+
+theorem correct (s : State) (hs : contract.pre s) :
+ ∃ t s', Exec isa Impl.TripleDes.X86_64.Key.expandKey s t s' ∧ abiPreserved s s' ∧ contract.post s s' := by
+ obtain ⟨t, s', he, ha, hp⟩ := expand_correct s hs
+ exact ⟨t, s', he, abiPreserved_of_exec (by lit_decide) he ha, hp⟩
+
+theorem publicRegs_four (s₁ s₂ : State) : PublicRegs [.rdi, .rsi, .rdx, .rcx] s₁ s₂ ↔
+ s₁.gpr .rdi = s₂.gpr .rdi ∧ s₁.gpr .rsi = s₂.gpr .rsi ∧ s₁.gpr .rdx = s₂.gpr .rdx ∧
+ s₁.gpr .rcx = s₂.gpr .rcx := by simp [PublicRegs]
+
+theorem verified : Verified target Impl.TripleDes.X86_64.Key.expandKey
+ (Spec.TripleDes.expandKeyContract abi) := by
+ refine Verified.of_correct correct (expandKey_constantTime _) ?_
+ sig_implies [Spec.TripleDes.expandKeyContract, Spec.TripleDes.expandKeySig, abi, argRegs,
+ contract, publicRegs_four] [satState] using satState
+
+end VG.Proof.TripleDes.X86_64.Key
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/KeySteps.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/KeySteps.lean
new file mode 100644
index 000000000..2baee19f4
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/KeySteps.lean
@@ -0,0 +1,34 @@
+import VerifiedGarbage.Impl.TripleDes.X86_64.ExpandKey
+import VerifiedGarbage.Proof.TripleDes.Word
+import VerifiedGarbage.Proof.Framework.X86_64.Exec
+import VerifiedGarbage.Proof.Framework.X86_64.RegUpd
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.RegUpd VG.Impl.TripleDes.X86_64
+
+theorem rotate28_ok (s : State) (r : Reg) (hr : r ≠ .rax)
+ (x : BitVec 28) (hx : s.gpr r = x.setWidth 64)
+ (n : Nat) (hn : 1 ≤ n) (hn' : n < 28) :
+ ∃ s', runBlock isa (Key.rotate28 r n) s = some s' ∧
+ s'.gpr r = (x.rotateLeft n).setWidth 64 ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r', r' ≠ r → r' ≠ .rax → s'.gpr r' = s.gpr r') := by
+ have hleft : 1 ≤ 64 - n ∧ 64 - n ≤ 63 := by omega
+ have hright : 1 ≤ 28 - n ∧ 28 - n ≤ 63 := by omega
+ refine ⟨_, by
+ simp only [Key.rotate28, rr, runBlock_cons, runStep_some, runBlock_nil, exec,
+ execAlu, execShift, readSrc, hleft, hright, and_self, ite_true, hr, Ne.symm hr,
+ Option.bind_some, Option.map_some, gpr_setReg, gpr_setFlags, gpr_arithFlags,
+ ite_false]
+ rfl, ?_, ?_, ?_, ?_, ?_⟩
+ · simp only [gpr_setReg, gpr_arithFlags, gpr_setFlags, ite_true, hr, ite_false]
+ rw [hx]
+ exact VG.Proof.TripleDes.rotate28_word x n hn hn'
+ · simp only [mem_setReg, mem_arithFlags, mem_setFlags]
+ · simp only [rd_setReg, rd_arithFlags, rd_setFlags]
+ · simp only [wr_setReg, wr_arithFlags, wr_setFlags]
+ · intro r' h1 h2
+ simp only [gpr_setReg, gpr_arithFlags, gpr_setFlags, h1, h2, ite_false]
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Lit.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Lit.lean
new file mode 100644
index 000000000..188255958
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Lit.lean
@@ -0,0 +1,21 @@
+import VerifiedGarbage.Impl.TripleDes.X86_64.Sbox
+import VerifiedGarbage.Impl.TripleDes.X86_64.Permutation
+import VerifiedGarbage.Proof.Framework.X86_64.Lit
+
+namespace VG.Impl.TripleDes.X86_64
+
+materialize_code sbox0
+materialize_code sbox1
+materialize_code sbox2
+materialize_code sbox3
+materialize_code sbox4
+materialize_code sbox5
+materialize_code sbox6
+materialize_code sbox7
+
+materialize_code initialPermutation
+materialize_code finalPermutation
+materialize_code keyPermutation1
+materialize_code keyPermutation2
+
+end VG.Impl.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Loop.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Loop.lean
new file mode 100644
index 000000000..250f0ce45
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Loop.lean
@@ -0,0 +1,149 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.RoundStep
+import VerifiedGarbage.Proof.TripleDes.Core
+import VerifiedGarbage.Proof.Framework.Omega
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction DesSchedule)
+open VG.Proof.TripleDes (roundKey roundPrefix feistelStep)
+
+def keyAddr (base : Addr) (direction : Direction) (j : Nat) : Addr :=
+ base + BitVec.ofNat 64 (8 * (if direction = .encrypt then j else 15 - j))
+
+theorem keyAddr_step (base : Addr) (direction : Direction) (j : Nat) (hj : j < 15) :
+ (if direction = .encrypt then keyAddr base direction j + 8
+ else keyAddr base direction j - 8) = keyAddr base direction (j + 1) := by
+ cases direction
+ · change base + BitVec.ofNat 64 (8 * j) + BitVec.ofNat 64 8 =
+ base + BitVec.ofNat 64 (8 * (j + 1))
+ rw [Offset.add_ofNat_add_ofNat]
+ exact congrArg (fun i => base + BitVec.ofNat 64 i) (by omega)
+ · change base + BitVec.ofNat 64 (8 * (15 - j)) - BitVec.ofNat 64 8 =
+ base + BitVec.ofNat 64 (8 * (15 - (j + 1)))
+ rw [Offset.add_ofNat_sub _ (by omega)]
+ exact congrArg (fun i => base + BitVec.ofNat 64 i) (by omega)
+
+structure LoopInv (keys : DesSchedule) (direction : Direction) (base : Addr)
+ (origin : State) (v : BitVec 32 × BitVec 32) (n : Nat) (s : State) : Prop where
+ positive : 1 ≤ n
+ bounded : n ≤ 16
+ left : s.gpr .r12 = (roundPrefix keys direction (16 - n) v).1.setWidth 64
+ right : s.gpr .r13 = (roundPrefix keys direction (16 - n) v).2.setWidth 64
+ counter : s.mem.readW (countAddr s) 64 = BitVec.ofNat 64 n
+ pointer : s.gpr .rdi = keyAddr base direction (16 - n)
+ rd : s.rd = origin.rd
+ wr : s.wr = origin.wr
+ regs : ∀ q ∈ [Reg.rsi, .rdx, .rsp], s.gpr q = origin.gpr q
+ frame : Frame [workRegion origin] origin.mem s.mem
+
+structure LoopPost (keys : DesSchedule) (direction : Direction)
+ (origin : State) (v : BitVec 32 × BitVec 32) (s : State) : Prop where
+ left : s.gpr .r12 = (roundPrefix keys direction 16 v).1.setWidth 64
+ right : s.gpr .r13 = (roundPrefix keys direction 16 v).2.setWidth 64
+ counter : s.mem.readW (countAddr s) 64 = 0
+ rd : s.rd = origin.rd
+ wr : s.wr = origin.wr
+ regs : ∀ q ∈ [Reg.rsi, .rdx, .rsp], s.gpr q = origin.gpr q
+ frame : Frame [workRegion origin] origin.mem s.mem
+
+theorem loopStep (keys : DesSchedule) (direction : Direction) (base : Addr)
+ (origin : State) (v : BitVec 32 × BitVec 32)
+ (hok : Ok sboxCfg origin)
+ (hcountRead : InRegions (origin.rd ++ origin.wr) (countAddr origin) 8)
+ (hcountWrite : InRegions origin.wr (countAddr origin) 8)
+ (hread : ∀ j < 16, InRegions (origin.rd ++ origin.wr) (keyAddr base direction j) 8)
+ (hsep : ∀ j < 16, (⟨keyAddr base direction j, 8⟩ : Region).Disjoint (workRegion origin))
+ (hkeys : ∀ j < 16, (origin.mem.readW (keyAddr base direction j) 64).setWidth 48 =
+ roundKey keys direction j)
+ (n : Nat) (s : State) (hs : LoopInv keys direction base origin v n s) :
+ WP isa (.block (roundBody ++ roundAdvance direction)) s (fun s' =>
+ (isa.eval .ne s' = some false ∧ LoopPost keys direction origin v s') ∨
+ (isa.eval .ne s' = some true ∧ ∃ m < n, LoopInv keys direction base origin v m s')) := by
+ have hj : 16 - n < 16 := by omega_using [hs.positive]
+ have haddr : countAddr s = countAddr origin := by
+ simp only [countAddr, hs.regs .rdx (by decide)]
+ have hwork : workRegion s = workRegion origin := by
+ simp only [workRegion, hs.regs .rdx (by decide)]
+ have hokS : Ok sboxCfg s := hok.congr
+ (hs.regs .rdx (by decide)) (hs.regs .rdx (by decide)) hs.rd hs.wr
+ have hreadS : InRegions (s.rd ++ s.wr) (s.gpr .rdi) 8 := by
+ rw [hs.rd, hs.wr, hs.pointer]; exact hread _ hj
+ have hsepS : (⟨s.gpr .rdi, 8⟩ : Region).Disjoint (spillRegion s) := by
+ rw [hs.pointer]
+ intro a ha hb
+ apply hsep _ hj a ha
+ rw [← hwork]
+ exact spill_sub_work s a hb
+ have hreadCountS : InRegions (s.rd ++ s.wr) (countAddr s) 8 := by
+ rw [hs.rd, hs.wr, haddr]; exact hcountRead
+ have hwriteCountS : InRegions s.wr (countAddr s) 8 := by
+ rw [hs.wr, haddr]; exact hcountWrite
+ have hk : (s.mem.readW (s.gpr .rdi) 64).setWidth 48 = roundKey keys direction (16 - n) := by
+ rw [hs.pointer]
+ have hmem := hs.frame.readW (a := keyAddr base direction (16 - n)) (w := 64)
+ (r := ⟨keyAddr base direction (16 - n), 8⟩)
+ (Region.contains_self _ _) (fun q hq => by
+ obtain rfl := List.mem_singleton.mp hq
+ exact hsep _ hj) (by decide)
+ exact (congrArg (BitVec.setWidth 48) hmem).trans (hkeys _ hj)
+ obtain ⟨s', run, left, right, ptr, count, flag, rd, wr, regs, frame⟩ :=
+ roundStep_ok direction s _ _ (s.mem.readW (s.gpr .rdi) 64) n hs.positive
+ (by omega_using [hs.bounded]) hs.left hs.right rfl hokS hreadS hsepS
+ hs.counter hreadCountS hwriteCountS
+ have hidx : 16 - (n - 1) = 16 - n + 1 := by
+ omega_using [hs.positive, hs.bounded]
+ have hleft : s'.gpr .r12 = (roundPrefix keys direction (16 - (n - 1)) v).1.setWidth 64 := by
+ rw [hidx]
+ exact left.trans (congrArg (fun pair => pair.1.setWidth 64)
+ (VG.Proof.TripleDes.roundPrefix_succ keys direction (16 - n) v).symm)
+ have hright : s'.gpr .r13 = (roundPrefix keys direction (16 - (n - 1)) v).2.setWidth 64 := by
+ rw [hidx]
+ have hval := congrArg (fun key =>
+ ((roundPrefix keys direction (16 - n) v).1 ^^^
+ Spec.TripleDes.roundFunction (roundPrefix keys direction (16 - n) v).2 key).setWidth 64) hk
+ exact (right.trans hval).trans (congrArg (fun pair => pair.2.setWidth 64)
+ (VG.Proof.TripleDes.roundPrefix_succ keys direction (16 - n) v).symm)
+ have hframe : Frame [workRegion origin] origin.mem s'.mem := by
+ rw [hwork] at frame
+ exact hs.frame.trans frame
+ have hregs : ∀ q ∈ [Reg.rsi, .rdx, .rsp], s'.gpr q = origin.gpr q :=
+ fun q hq => (regs q hq).trans (hs.regs q hq)
+ refine WP.of_runBlock ⟨s', run, ?_⟩
+ by_cases hlast : n = 1
+ · left
+ refine ⟨?_, ?_⟩
+ · simpa only [hlast, ne_eq, not_true_eq_false, decide_false] using flag
+ · subst n
+ exact ⟨hleft, hright, count, rd.trans hs.rd, wr.trans hs.wr, hregs, hframe⟩
+ · right
+ refine ⟨?_, n - 1, by omega_using [hs.positive], ?_⟩
+ · simpa only [hlast, ne_eq, not_false_eq_true, decide_true] using flag
+ · refine ⟨by omega_using [hs.positive, hlast], by omega_using [hs.bounded],
+ hleft, hright, count, ?_, rd.trans hs.rd, wr.trans hs.wr, hregs, hframe⟩
+ rw [ptr, hs.pointer, keyAddr_step base direction (16 - n) (by
+ omega_using [hs.positive, hlast]), ← hidx]
+
+/-- The complete sixteen-round loop, in either key order. -/
+theorem roundsLoop_ok (keys : DesSchedule) (direction : Direction) (base : Addr)
+ (origin : State) (v : BitVec 32 × BitVec 32)
+ (hok : Ok sboxCfg origin)
+ (hl : origin.gpr .r12 = v.1.setWidth 64) (hr : origin.gpr .r13 = v.2.setWidth 64)
+ (hptr : origin.gpr .rdi = keyAddr base direction 0)
+ (hcount : origin.mem.readW (countAddr origin) 64 = BitVec.ofNat 64 16)
+ (hcountRead : InRegions (origin.rd ++ origin.wr) (countAddr origin) 8)
+ (hcountWrite : InRegions origin.wr (countAddr origin) 8)
+ (hread : ∀ j < 16, InRegions (origin.rd ++ origin.wr) (keyAddr base direction j) 8)
+ (hsep : ∀ j < 16, (⟨keyAddr base direction j, 8⟩ : Region).Disjoint (workRegion origin))
+ (hkeys : ∀ j < 16, (origin.mem.readW (keyAddr base direction j) 64).setWidth 48 =
+ roundKey keys direction j) :
+ WP isa (.loop (.block (roundBody ++ roundAdvance direction)) .ne)
+ origin (LoopPost keys direction origin v) := by
+ apply WP.loop (M := isa) (body := .block (roundBody ++ roundAdvance direction))
+ (c := .ne) (Q := LoopPost keys direction origin v) (LoopInv keys direction base origin v)
+ (loopStep keys direction base origin v hok hcountRead hcountWrite hread hsep hkeys)
+ 16 origin
+ exact ⟨by decide, by decide, hl, hr, hcount, hptr, rfl, rfl,
+ fun _ _ => rfl, Frame.refl _ _⟩
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Pass.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Pass.lean
new file mode 100644
index 000000000..2ac21a839
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Pass.lean
@@ -0,0 +1,110 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.PassStart
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction DesSchedule)
+open VG.Proof.TripleDes (roundKey roundPrefix)
+
+structure PassPost (keys : DesSchedule) (direction : Direction)
+ (origin : State) (v : BitVec 32 × BitVec 32) (s : State) : Prop where
+ left : s.gpr .r12 = (roundPrefix keys direction 16 v).2.setWidth 64
+ right : s.gpr .r13 = (roundPrefix keys direction 16 v).1.setWidth 64
+ rd : s.rd = origin.rd
+ wr : s.wr = origin.wr
+ regs : ∀ q ∈ [Reg.rsi, .rdx, .rsp], s.gpr q = origin.gpr q
+ frame : Frame [workRegion origin] origin.mem s.mem
+
+/-- The sixteen-round loop and final DES half swap. -/
+theorem roundsWithSwap_ok (keys : DesSchedule) (direction : Direction) (base : Addr)
+ (origin : State) (v : BitVec 32 × BitVec 32)
+ (hok : Ok sboxCfg origin)
+ (hl : origin.gpr .r12 = v.1.setWidth 64) (hr : origin.gpr .r13 = v.2.setWidth 64)
+ (hptr : origin.gpr .rdi = keyAddr base direction 0)
+ (hcount : origin.mem.readW (countAddr origin) 64 = BitVec.ofNat 64 16)
+ (hcountRead : InRegions (origin.rd ++ origin.wr) (countAddr origin) 8)
+ (hcountWrite : InRegions origin.wr (countAddr origin) 8)
+ (hread : ∀ j < 16, InRegions (origin.rd ++ origin.wr) (keyAddr base direction j) 8)
+ (hsep : ∀ j < 16, (⟨keyAddr base direction j, 8⟩ : Region).Disjoint (workRegion origin))
+ (hkeys : ∀ j < 16, (origin.mem.readW (keyAddr base direction j) 64).setWidth 48 =
+ roundKey keys direction j) :
+ WP isa (.seq (.loop (.block (roundBody ++ roundAdvance direction)) .ne)
+ (.block swapHalves)) origin (PassPost keys direction origin v) := by
+ apply WP.seq
+ apply WP.mono (roundsLoop_ok keys direction base origin v hok hl hr hptr hcount
+ hcountRead hcountWrite hread hsep hkeys)
+ intro s hs
+ obtain ⟨s', run, left, right, rd, wr, mem, regs⟩ := swapHalves_ok s
+ apply WP.of_runBlock
+ refine ⟨s', run, left.trans hs.right, right.trans hs.left,
+ rd.trans hs.rd, wr.trans hs.wr, ?_, ?_⟩
+ · intro q hq
+ have hkeep : ∀ r ∈ [Reg.rsi, .rdx, .rsp], r ∈ roundOuterKept := by decide
+ exact (regs q (hkeep q hq)).trans (hs.regs q hq)
+ · rw [mem]
+ exact hs.frame
+
+
+/-- A complete DES pass, including its public key-pointer and counter setup. -/
+theorem pass_ok (component : Nat) (hc : component < 3)
+ (keys : DesSchedule) (direction : Direction) (base : Addr)
+ (origin : State) (v : BitVec 32 × BitVec 32)
+ (hok : Ok sboxCfg origin)
+ (hl : origin.gpr .r12 = v.1.setWidth 64) (hr : origin.gpr .r13 = v.2.setWidth 64)
+ (hptr : origin.mem.readW (savedKeyAddr origin) 64 +
+ BitVec.ofNat 64 (passOffset component direction) = keyAddr base direction 0)
+ (hsavedRead : InRegions (origin.rd ++ origin.wr) (savedKeyAddr origin) 8)
+ (hcountRead : InRegions (origin.rd ++ origin.wr) (countAddr origin) 8)
+ (hcountWrite : InRegions origin.wr (countAddr origin) 8)
+ (hread : ∀ j < 16, InRegions (origin.rd ++ origin.wr) (keyAddr base direction j) 8)
+ (hsep : ∀ j < 16, (⟨keyAddr base direction j, 8⟩ : Region).Disjoint (workRegion origin))
+ (hkeys : ∀ j < 16, (origin.mem.readW (keyAddr base direction j) 64).setWidth 48 =
+ roundKey keys direction j) :
+ WP isa (pass component direction) origin (PassPost keys direction origin v) := by
+ obtain ⟨s, run, ptr, mem, rd, wr, regs⟩ :=
+ passStart_ok component hc direction origin hsavedRead hcountWrite
+ have hbase : s.gpr .rdx = origin.gpr .rdx := regs .rdx (by decide) (by decide)
+ have hcountAddr : countAddr s = countAddr origin := congrArg (· + BitVec.ofNat 64 56) hbase
+ have hwork : workRegion s = workRegion origin := congrArg (fun p => (⟨p + BitVec.ofNat 64 56, 392⟩ : Region)) hbase
+ have hframe : Frame [workRegion origin] origin.mem s.mem := by
+ rw [mem]
+ apply (countWrite_frame origin.mem (countAddr origin) (BitVec.ofNat 64 16)).sub
+ intro r hmem
+ obtain rfl := List.mem_singleton.mp hmem
+ exact ⟨workRegion origin, List.mem_singleton_self _, count_sub_work origin⟩
+ have hkeysS : ∀ j < 16, (s.mem.readW (keyAddr base direction j) 64).setWidth 48 =
+ roundKey keys direction j := by
+ intro j hj
+ have hmem := hframe.readW (a := keyAddr base direction j) (w := 64)
+ (r := ⟨keyAddr base direction j, 8⟩) (Region.contains_self _ _)
+ (fun q hq => by obtain rfl := List.mem_singleton.mp hq; exact hsep j hj) (by decide)
+ exact (congrArg (BitVec.setWidth 48) hmem).trans (hkeys j hj)
+ have hreadS : ∀ j < 16, InRegions (s.rd ++ s.wr) (keyAddr base direction j) 8 := by
+ rw [rd, wr]; exact hread
+ have hsepS : ∀ j < 16, (⟨keyAddr base direction j, 8⟩ : Region).Disjoint (workRegion s) := by
+ rw [hwork]; exact hsep
+ have hcountReadS : InRegions (s.rd ++ s.wr) (countAddr s) 8 := by
+ rw [rd, wr, hcountAddr]; exact hcountRead
+ have hcountWriteS : InRegions s.wr (countAddr s) 8 := by
+ rw [wr, hcountAddr]; exact hcountWrite
+ have hcount : s.mem.readW (countAddr s) 64 = BitVec.ofNat 64 16 := by
+ rw [mem, hcountAddr]
+ exact Mem.readW_writeW_self64 _ _ _
+ have htail := roundsWithSwap_ok keys direction base s v
+ (hok.congr hbase hbase rd wr)
+ ((regs .r12 (by decide) (by decide)).trans hl)
+ ((regs .r13 (by decide) (by decide)).trans hr)
+ (ptr.trans hptr) hcount hcountReadS hcountWriteS hreadS hsepS hkeysS
+ apply WP.seq
+ apply WP.of_runBlock
+ refine ⟨s, run, WP.mono htail ?_⟩
+ intro s' hs
+ refine ⟨hs.left, hs.right, hs.rd.trans rd, hs.wr.trans wr, ?_, ?_⟩
+ · intro q hq
+ have hneq : ∀ r ∈ [Reg.rsi, .rdx, .rsp], r ≠ .rax ∧ r ≠ .rdi := by decide
+ exact (hs.regs q hq).trans (regs q (hneq q hq).1 (hneq q hq).2)
+ · have hf := hs.frame
+ rw [hwork] at hf
+ exact hframe.trans hf
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/PassStart.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/PassStart.lean
new file mode 100644
index 000000000..6fe515f01
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/PassStart.lean
@@ -0,0 +1,55 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Loop
+import VerifiedGarbage.Proof.Framework.X86_64.RegUpd
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.RegUpd VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction)
+
+def savedKeyAddr (s : State) : Addr := s.gpr .rdx + BitVec.ofNat 64 48
+
+def passOffset (component : Nat) (direction : Direction) : Nat :=
+ 128 * component + if direction = .encrypt then 0 else 120
+
+theorem passOffset_signExtend (component : Nat) (hc : component < 3) (direction : Direction) :
+ (BitVec.ofNat 32 (passOffset component direction)).signExtend 64 =
+ BitVec.ofNat 64 (passOffset component direction) := by
+ have h : ∀ c < 3,
+ ((BitVec.ofNat 32 (passOffset c .encrypt)).signExtend 64 =
+ BitVec.ofNat 64 (passOffset c .encrypt)) ∧
+ ((BitVec.ofNat 32 (passOffset c .decrypt)).signExtend 64 =
+ BitVec.ofNat 64 (passOffset c .decrypt)) := by decide +kernel
+ cases direction
+ · exact (h component hc).1
+ · exact (h component hc).2
+
+theorem passStart_ok (component : Nat) (hc : component < 3) (direction : Direction)
+ (s : State) (hread : InRegions (s.rd ++ s.wr) (savedKeyAddr s) 8)
+ (hwrite : InRegions s.wr (countAddr s) 8) :
+ ∃ s', runBlock isa (passStart component direction) s = some s' ∧
+ s'.gpr .rdi = s.mem.readW (savedKeyAddr s) 64 +
+ BitVec.ofNat 64 (passOffset component direction) ∧
+ s'.mem = s.mem.writeW (countAddr s) (BitVec.ofNat 64 16) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .rax → r ≠ .rdi → s'.gpr r = s.gpr r) := by
+ unfold savedKeyAddr at hread
+ unfold countAddr at hwrite
+ have h48 : BitVec.ofInt 64 (Int.ofNat 48) = BitVec.ofNat 64 48 := rfl
+ have h56 : BitVec.ofInt 64 (Int.ofNat 56) = BitVec.ofNat 64 56 := rfl
+ refine ⟨_, by
+ simp only [passStart, imm, runBlock_cons, runStep_some, runBlock_nil, exec,
+ execAlu, readSrc, State.ea, memOp, h48, h56, State.load64, State.store64,
+ gpr_setReg, mem_setReg, rd_setReg, wr_setReg, gpr_arithFlags, mem_arithFlags,
+ rd_arithFlags, wr_arithFlags, reduceCtorEq, ite_false, ite_true,
+ hread, hwrite, Option.map_some, Option.bind_some]
+ rfl, ?_, ?_, ?_, ?_, ?_⟩
+ · simp only [gpr_setReg, gpr_arithFlags, reduceCtorEq, ite_false, ite_true]
+ exact congrArg (s.mem.readW (savedKeyAddr s) 64 + ·)
+ (passOffset_signExtend component hc direction)
+ · rfl
+ · rfl
+ · rfl
+ · intro r hrax hrdi
+ simp only [gpr_setReg, gpr_arithFlags, hrax, hrdi, ite_false]
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/PassSteps.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/PassSteps.lean
new file mode 100644
index 000000000..9bdf2dd17
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/PassSteps.lean
@@ -0,0 +1,86 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.RoundBody
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.RegUpd VG.Impl.TripleDes.X86_64
+
+def countAddr (s : State) : Addr := s.gpr .rdx + BitVec.ofNat 64 56
+
+theorem roundCountAdvance_ok (s : State)
+ (hread : InRegions (s.rd ++ s.wr) (countAddr s) 8)
+ (hwrite : InRegions s.wr (countAddr s) 8) :
+ ∃ s', runBlock isa roundCountAdvance s = some s' ∧
+ s'.mem = s.mem.writeW (countAddr s) (s.mem.readW (countAddr s) 64 - 1) ∧
+ s'.zf = some ((s.mem.readW (countAddr s) 64 - 1) == 0) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .rax → s'.gpr r = s.gpr r) := by
+ unfold countAddr at hread hwrite
+ have hoff : BitVec.ofInt 64 (Int.ofNat 56) = BitVec.ofNat 64 56 := rfl
+ refine ⟨_, by
+ simp only [roundCountAdvance, runBlock_cons, runStep_some, runBlock_nil, exec,
+ execAlu, readSrc, State.ea, memOp, hoff, State.load64, State.store64,
+ gpr_setReg, mem_setReg, rd_setReg, wr_setReg, gpr_arithFlags, mem_arithFlags,
+ rd_arithFlags, wr_arithFlags, reduceCtorEq, ite_false, ite_true,
+ hread, hwrite, Option.map_some, Option.bind_some]
+ rfl, ?_, ?_, ?_, ?_, ?_⟩
+ · rfl
+ · simp only [zf_setReg, zf_arithFlags]
+ rfl
+ · rfl
+ · rfl
+ · intro r hr
+ simp only [gpr_setReg, gpr_arithFlags, hr, ite_false]
+
+theorem pointerAdvance_ok (direction : Spec.TripleDes.Direction) (s : State) :
+ ∃ s', runBlock isa
+ [.alu (if direction = .encrypt then .add else .sub) .rdi (.imm 8)] s = some s' ∧
+ s'.gpr .rdi = (if direction = .encrypt then s.gpr .rdi + 8 else s.gpr .rdi - 8) ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .rdi → s'.gpr r = s.gpr r) := by
+ cases direction <;>
+ refine ⟨_, by
+ simp only [runBlock_cons, exec, execAlu, readSrc,
+ Option.bind_some]
+ rfl, ?_, ?_, ?_, ?_, ?_⟩
+ all_goals try exact gpr_setReg_self _ _ _
+ all_goals try simp only [mem_setReg, mem_arithFlags]
+ all_goals try simp only [rd_setReg, rd_arithFlags]
+ all_goals try simp only [wr_setReg, wr_arithFlags]
+ all_goals
+ intro r hr
+ simp only [gpr_setReg, gpr_arithFlags, hr, ite_false]
+
+theorem countDown_rules : ∀ n < 17, 1 ≤ n →
+ (BitVec.ofNat 64 n - 1 = BitVec.ofNat 64 (n - 1)) ∧
+ ((BitVec.ofNat 64 n - 1) == 0) = decide (n = 1) := by
+ decide +kernel
+
+theorem countWrite_frame (m : Mem) (p : Addr) (v : BitVec 64) :
+ Frame [⟨p, 8⟩] m (m.writeW p v) :=
+ (Frame.refl _ _).writeW (List.mem_singleton_self _) v (Region.contains_self _ _)
+
+theorem roundAdvance_ok (direction : Spec.TripleDes.Direction) (s : State)
+ (hread : InRegions (s.rd ++ s.wr) (countAddr s) 8)
+ (hwrite : InRegions s.wr (countAddr s) 8) :
+ ∃ s', runBlock isa (roundAdvance direction) s = some s' ∧
+ s'.gpr .rdi = (if direction = .encrypt then s.gpr .rdi + 8 else s.gpr .rdi - 8) ∧
+ s'.mem = s.mem.writeW (countAddr s) (s.mem.readW (countAddr s) 64 - 1) ∧
+ s'.zf = some ((s.mem.readW (countAddr s) 64 - 1) == 0) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .rax → r ≠ .rdi → s'.gpr r = s.gpr r) := by
+ obtain ⟨s₁, run₁, ptr₁, mem₁, rd₁, wr₁, keep₁⟩ := pointerAdvance_ok direction s
+ have haddr : countAddr s₁ = countAddr s := by
+ simp only [countAddr, keep₁ .rdx (by decide)]
+ have hread₁ : InRegions (s₁.rd ++ s₁.wr) (countAddr s₁) 8 := by
+ rw [rd₁, wr₁, haddr]; exact hread
+ have hwrite₁ : InRegions s₁.wr (countAddr s₁) 8 := by
+ rw [wr₁, haddr]; exact hwrite
+ obtain ⟨s₂, run₂, mem₂, flag₂, rd₂, wr₂, keep₂⟩ := roundCountAdvance_ok s₁ hread₁ hwrite₁
+ refine ⟨s₂, ?_, ?_, ?_, ?_, rd₂.trans rd₁, wr₂.trans wr₁, ?_⟩
+ · simp only [roundAdvance, runBoxes_append, run₁, Option.bind_some, run₂]
+ · exact (keep₂ .rdi (by decide)).trans ptr₁
+ · rw [mem₂, mem₁, haddr]
+ · rw [flag₂, mem₁, haddr]
+ · exact fun r hrax hrdi => (keep₂ r hrax).trans (keep₁ r hrdi)
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Permutation.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Permutation.lean
new file mode 100644
index 000000000..3b4d12a22
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Permutation.lean
@@ -0,0 +1,90 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Lit
+import VerifiedGarbage.Proof.TripleDes.Permutation
+import VerifiedGarbage.Proof.Framework.X86_64.Linear
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Bitslice VG.Impl.TripleDes.X86_64
+
+def permutationCfg : Cfg := { base := .rdx, slots := 0, ext := .rdx, exts := 0 }
+def permutationInputs : List (Reg × Nat) := [(.rax, 0)]
+
+def permutationBits {m : Nat} (positions : Vector Nat m) (n p : Nat) : List Nat :=
+ if p < m then [n - positions.getD (m - 1 - p) 1] else []
+
+def permutationOutputs {m : Nat} (positions : Vector Nat m) (n : Nat) :
+ List (Reg × (Nat → List Nat)) := [(.rbx, permutationBits positions n)]
+
+theorem initialPermutation_check :
+ check (lanes 64 6) permutationCfg (linExt 1) (instrs initialPermutation.lit)
+ (linEnv permutationInputs) (linPost 6 (permutationOutputs Spec.TripleDes.ip 64)) = true := by
+ decide +kernel
+
+theorem finalPermutation_check :
+ check (lanes 64 6) permutationCfg (linExt 1) (instrs finalPermutation.lit)
+ (linEnv permutationInputs) (linPost 6 (permutationOutputs Spec.TripleDes.fp 64)) = true := by
+ decide +kernel
+
+theorem keyPermutation1_check :
+ check (lanes 64 6) permutationCfg (linExt 1) (instrs keyPermutation1.lit)
+ (linEnv permutationInputs) (linPost 6 (permutationOutputs Spec.TripleDes.pc1 64)) = true := by
+ decide +kernel
+
+theorem keyPermutation2_check :
+ check (lanes 64 6) permutationCfg (linExt 1) (instrs keyPermutation2.lit)
+ (linEnv permutationInputs) (linPost 6 (permutationOutputs Spec.TripleDes.pc2 56)) = true := by
+ decide +kernel
+
+theorem permutationCfg_ok (s : State) : Ok permutationCfg s := by
+ refine ⟨?_, ?_, by decide, ?_⟩
+ · intro k hk; simp [permutationCfg] at hk
+ · intro k hk; simp [permutationCfg] at hk
+ · intro k hk; simp [permutationCfg] at hk
+
+theorem fixedPermutation_ok {m n : Nat} (positions : Vector Nat m)
+ (hn : 0 < n) (hn64 : n ≤ 64)
+ (bounds : ∀ k < m, 1 ≤ positions.getD k 1 ∧ positions.getD k 1 ≤ n)
+ (is : List Instr)
+ (hchk : check (lanes 64 6) permutationCfg (linExt 1) is
+ (linEnv permutationInputs) (linPost 6 (permutationOutputs positions n)) = true)
+ (s : State) :
+ ∃ s', runBlock isa is s = some s' ∧
+ s'.gpr .rbx = (Spec.TripleDes.permute positions ((s.gpr .rax).setWidth n)).zeroExtend 64 ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, (is.all fun op => op.dst != some r) = true → s'.gpr r = s.gpr r) := by
+ let W : Nat → BitVec 64 := fun _ => s.gpr .rax
+ obtain ⟨s', hs', out, rd, wr, keep, frame⟩ :=
+ linear_ok hchk (permutationCfg_ok s) W (fun r i h => by
+ simp only [permutationInputs, List.mem_singleton, Prod.mk.injEq] at h
+ obtain ⟨rfl, rfl⟩ := h
+ exact ⟨by decide, rfl⟩)
+ (fun j hj => by simp [permutationCfg] at hj)
+ refine ⟨s', hs', ?_, rd, wr, ?_, keep⟩
+ · apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ have hout := out .rbx (permutationBits positions n) (by simp [permutationOutputs]) j hj
+ change (s'.gpr .rbx).getLsbD j =
+ ((Spec.TripleDes.permute positions ((s.gpr .rax).setWidth n)).setWidth 64).getLsbD j
+ rw [BitVec.getLsbD_setWidth]
+ simp only [hj, decide_true, Bool.true_and]
+ rw [hout]
+ by_cases hjm : j < m
+ · have hk : m - 1 - j < m := by omega
+ obtain ⟨hlo, hhi⟩ := bounds _ hk
+ have hsource : n - positions.getD (m - 1 - j) 1 < n := by omega
+ have h64 : n - positions.getD (m - 1 - j) 1 < 64 := by omega
+ rw [VG.Proof.TripleDes.permute_bit positions _ hn j hjm,
+ BitVec.getLsbD_setWidth]
+ simp only [hsource, decide_true, Bool.true_and, permutationBits, hjm, ite_true,
+ xorBits, List.foldr_cons, List.foldr_nil, Bool.xor_false, bitOf,
+ Nat.mod_eq_of_lt h64, W]
+ · rw [BitVec.getLsbD_of_ge _ _ (by omega)]
+ simp only [permutationBits, hjm, ite_false, xorBits, List.foldr_nil]
+ · funext a
+ apply frame a
+ intro r hr hc
+ simp only [slotRegion, permutationCfg, List.mem_singleton] at hr
+ subst r
+ simp [Region.Contains] at hc
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Pre.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Pre.lean
new file mode 100644
index 000000000..736e8ed0e
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Pre.lean
@@ -0,0 +1,128 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Block
+import VerifiedGarbage.Proof.TripleDes.Schedule
+import VerifiedGarbage.Proof.TripleDes.X86_64.ConstantTime
+import VerifiedGarbage.Proof.Framework.X86_64.Abi
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction)
+
+def blockContract (d : Direction) : Contract isa where
+ pre s :=
+ let key : Region := ⟨s.gpr .rdi, 384⟩
+ let data : Region := ⟨s.gpr .rsi, 8⟩
+ let scratch : Region := ⟨s.gpr .rdx, 512⟩
+ let ret : Region := ⟨s.gpr .rsp, 8⟩
+ s.rd = [key] ∧ s.wr = [data, scratch] ∧ key.Disjoint scratch ∧ data.Disjoint scratch ∧
+ ret.Disjoint data ∧ ret.Disjoint scratch
+ post s s' := Spec.TripleDes.blockAt s'.mem (s.gpr .rsi) =
+ blockResult (Spec.TripleDes.scheduleAt s.mem (s.gpr .rdi)) d (Spec.TripleDes.blockAt s.mem (s.gpr .rsi))
+ pub := PublicRegs [.rdi, .rsi, .rdx]
+
+def selectedRound (d : Direction) (j : Nat) : Nat := if d = .encrypt then j else 15 - j
+
+theorem selectedRound_bound (d : Direction) (j : Nat) (hj : j < 16) : selectedRound d j < 16 := by
+ cases d <;> simp only [selectedRound, reduceCtorEq, ite_true, ite_false] <;> omega
+
+theorem keyAddr_component (base : Addr) (c : Nat) (d : Direction) (j : Nat) :
+ keyAddr (componentBase base c) d j = base + BitVec.ofNat 64 (8 * (16 * c + selectedRound d j)) := by
+ unfold keyAddr componentBase selectedRound
+ rw [Offset.add_ofNat_add_ofNat]
+ exact congrArg (fun n => base + BitVec.ofNat 64 n) (by omega)
+
+theorem headPre_of_contract (d : Direction) (s : State) (hs : (blockContract d).pre s) :
+ HeadPre (Spec.TripleDes.componentSchedule (Spec.TripleDes.scheduleAt s.mem (s.gpr .rdi)))
+ (s.gpr .rdi) s := by
+ obtain ⟨hrd, hwr, keySep, dataSep, _, _⟩ := hs
+ have scratchWrites : ∀ i < 64, InRegions s.wr (s.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8 := by
+ intro i hi
+ rw [hwr]
+ exact ⟨⟨s.gpr .rdx, 512⟩, by simp, Offset.contains_base _ (by omega) (by omega)⟩
+ have scratchReads : ∀ i < 64, InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8 := by
+ intro i hi
+ rw [hrd, hwr]
+ exact ⟨⟨s.gpr .rdx, 512⟩, by simp, Offset.contains_base _ (by omega) (by omega)⟩
+ have spills : Ok sboxCfg s := by
+ refine ⟨scratchWrites, ?_, by decide, ?_⟩
+ · intro k hk; change k < 0 at hk; omega
+ · intro k hk j hj; change j < 0 at hj; omega
+ have keyContains : ∀ c < 3, ∀ direction : Direction, ∀ j < 16,
+ (⟨s.gpr .rdi, 384⟩ : Region).Contains (keyAddr (componentBase (s.gpr .rdi) c) direction j) 8 := by
+ intro c hc direction j hj
+ rw [keyAddr_component]
+ have hindex := selectedRound_bound direction j hj
+ exact Offset.contains_base _ (by omega) (by omega)
+ have keySub : ∀ c < 3, ∀ direction : Direction, ∀ j < 16,
+ Region.Sub ⟨keyAddr (componentBase (s.gpr .rdi) c) direction j, 8⟩ ⟨s.gpr .rdi, 384⟩ := by
+ intro c hc direction j hj
+ rw [keyAddr_component]
+ have hindex := selectedRound_bound direction j hj
+ exact Offset.sub_base _ (by omega)
+ have workSub : Region.Sub (workRegion s) ⟨s.gpr .rdx, 512⟩ := Offset.sub_base _ (by decide)
+ have saveSub : Region.Sub (saveRegion s) ⟨s.gpr .rdx, 512⟩ := Region.sub_prefix (by decide)
+ refine ⟨spills, rfl, (fun i hi => scratchReads i (by omega)),
+ (fun i hi => scratchWrites i (by omega)), scratchReads 7 (by decide),
+ scratchWrites 7 (by decide), ?_, dataSep.sub_right saveSub, ?_, ?_, ?_, ?_⟩
+ · rw [hrd, hwr]
+ exact ⟨⟨s.gpr .rsi, 8⟩, by simp, Region.contains_self _ _⟩
+ · intro c hc direction j hj
+ rw [hrd, hwr]
+ exact ⟨⟨s.gpr .rdi, 384⟩, by simp, keyContains c hc direction j hj⟩
+ · intro c hc direction j hj
+ exact (keySep.sub_left (keySub c hc direction j hj)).sub_right workSub
+ · intro c hc direction j hj
+ exact (keySep.sub_left (keySub c hc direction j hj)).sub_right saveSub
+ · intro c hc direction j hj
+ rw [keyAddr_component]
+ exact (VG.Proof.TripleDes.componentSchedule_readW s.mem (s.gpr .rdi) c
+ (selectedRound direction j) hc (selectedRound_bound direction j hj)).symm
+
+
+theorem blockTaint_wf (d : Direction) (s : State) (hs : (blockContract d).pre s) :
+ Taint.Wf blockTaint s := by
+ obtain ⟨_, hwr, _, dataSep, _, _⟩ := hs
+ refine ⟨?_, ?_⟩
+ · intro _
+ rw [hwr]
+ refine ⟨?_, ?_, ?_⟩
+ · exact List.Forall₂.cons (by change 0 ≤ 8; decide)
+ (List.Forall₂.cons (by change 512 ≤ 512; decide) List.Forall₂.nil)
+ · exact List.Pairwise.cons
+ (fun r hr => by obtain rfl := List.mem_singleton.mp hr; exact dataSep)
+ (List.Pairwise.cons (by simp) List.Pairwise.nil)
+ · intro r hr
+ simp only [List.mem_cons, List.not_mem_nil, or_false] at hr
+ rcases hr with rfl | rfl
+ · change 8 ≤ 2 ^ 64; decide
+ · change 512 ≤ 2 ^ 64; decide
+ · intro p hp
+ simp only [blockTaint, List.mem_singleton] at hp
+ subst p
+ unfold Taint.region
+ rw [hwr]
+ change s.gpr .rdx = s.gpr .rdx + (0 : BitVec 64)
+ exact (BitVec.add_zero _).symm
+
+theorem blockTaint_agree (d : Direction) (s t : State)
+ (hs : (blockContract d).pre s) (ht : (blockContract d).pre t)
+ (hp : (blockContract d).pub s t) : X86_64.Taint.Agree blockTaint s t := by
+ refine ⟨?_, ?_, blockTaint_wf d s hs, blockTaint_wf d t ht, ?_, ?_, ?_⟩
+ · constructor
+ · intro r hr
+ exact hp r (by simpa only [blockTaint, RegSet.mem_ofList] using hr)
+ · intro h
+ change false = true at h
+ contradiction
+ · intro _
+ rw [hs.2.1, ht.2.1, hp .rsi (by decide), hp .rdx (by decide)]
+ · intro slot hslot
+ change slot ∈ ([] : List (Nat × Nat × Nat)) at hslot
+ exact False.elim (List.not_mem_nil hslot)
+ · intro slot hslot
+ change slot ∈ ([] : List (Nat × Nat × Nat)) at hslot
+ exact False.elim (List.not_mem_nil hslot)
+ · intro r hr
+ simp only [blockTaint, RegSet.not_mem_empty] at hr
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ready.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ready.lean
new file mode 100644
index 000000000..c45c44541
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Ready.lean
@@ -0,0 +1,99 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.WordState
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction DesSchedule)
+open VG.Proof.TripleDes (roundKey)
+
+def componentBase (base : Addr) (component : Nat) : Addr :=
+ base + BitVec.ofNat 64 (128 * component)
+
+structure Ready (keys : Nat → DesSchedule) (base : Addr) (s : State) : Prop where
+ spills : Ok sboxCfg s
+ saved : s.mem.readW (savedKeyAddr s) 64 = base
+ savedRead : InRegions (s.rd ++ s.wr) (savedKeyAddr s) 8
+ countRead : InRegions (s.rd ++ s.wr) (countAddr s) 8
+ countWrite : InRegions s.wr (countAddr s) 8
+ read : ∀ c < 3, ∀ d : Direction, ∀ j < 16,
+ InRegions (s.rd ++ s.wr) (keyAddr (componentBase base c) d j) 8
+ separate : ∀ c < 3, ∀ d : Direction, ∀ j < 16,
+ (⟨keyAddr (componentBase base c) d j, 8⟩ : Region).Disjoint (workRegion s)
+ values : ∀ c < 3, ∀ d : Direction, ∀ j < 16,
+ (s.mem.readW (keyAddr (componentBase base c) d j) 64).setWidth 48 = roundKey (keys c) d j
+
+theorem saved_work_disjoint (s : State) :
+ (⟨savedKeyAddr s, 8⟩ : Region).Disjoint (workRegion s) :=
+ Offset.disjoint (s.gpr .rdx) (by decide) (by decide) (by decide)
+
+theorem Ready.congr {keys : Nat → DesSchedule} {base : Addr} {s t : State}
+ (hs : Ready keys base s) (hbase : t.gpr .rdx = s.gpr .rdx)
+ (hrd : t.rd = s.rd) (hwr : t.wr = s.wr)
+ (hf : Frame [workRegion s] s.mem t.mem) : Ready keys base t := by
+ have hsave : savedKeyAddr t = savedKeyAddr s := congrArg (· + BitVec.ofNat 64 48) hbase
+ have hcount : countAddr t = countAddr s := congrArg (· + BitVec.ofNat 64 56) hbase
+ have hwork : workRegion t = workRegion s :=
+ congrArg (fun p => (⟨p + BitVec.ofNat 64 56, 392⟩ : Region)) hbase
+ refine ⟨hs.spills.congr hbase hbase hrd hwr, ?_, ?_, ?_, ?_, ?_, ?_, ?_⟩
+ · rw [hsave]
+ have hmem := hf.readW (a := savedKeyAddr s) (w := 64)
+ (r := ⟨savedKeyAddr s, 8⟩) (Region.contains_self _ _)
+ (fun q hq => by obtain rfl := List.mem_singleton.mp hq; exact saved_work_disjoint s) (by decide)
+ exact hmem.trans hs.saved
+ · rw [hrd, hwr, hsave]; exact hs.savedRead
+ · rw [hrd, hwr, hcount]; exact hs.countRead
+ · rw [hwr, hcount]; exact hs.countWrite
+ · rw [hrd, hwr]; exact hs.read
+ · rw [hwork]; exact hs.separate
+ · intro c hc d j hj
+ have hmem := hf.readW (a := keyAddr (componentBase base c) d j) (w := 64)
+ (r := ⟨keyAddr (componentBase base c) d j, 8⟩) (Region.contains_self _ _)
+ (fun q hq => by obtain rfl := List.mem_singleton.mp hq; exact hs.separate c hc d j hj) (by decide)
+ exact (congrArg (BitVec.setWidth 48) hmem).trans (hs.values c hc d j hj)
+
+theorem passPointer (base : Addr) (c : Nat) (d : Direction) :
+ base + BitVec.ofNat 64 (passOffset c d) = keyAddr (componentBase base c) d 0 := by
+ cases d
+ · change base + BitVec.ofNat 64 (128 * c + 0) = base + BitVec.ofNat 64 (128 * c) + (0 : BitVec 64)
+ exact (congrArg (fun n => base + BitVec.ofNat 64 n) (Nat.add_zero (128 * c))).trans
+ (BitVec.add_zero (base + BitVec.ofNat 64 (128 * c))).symm
+ · simp only [passOffset, keyAddr, componentBase, reduceCtorEq, ite_false]
+ rw [Offset.add_ofNat_add_ofNat]
+
+
+structure Stable (origin s : State) : Prop where
+ rd : s.rd = origin.rd
+ wr : s.wr = origin.wr
+ regs : ∀ q ∈ [Reg.rsi, .rdx, .rsp], s.gpr q = origin.gpr q
+ frame : Frame [workRegion origin] origin.mem s.mem
+
+theorem Stable.refl (s : State) : Stable s s :=
+ ⟨rfl, rfl, fun _ _ => rfl, Frame.refl _ _⟩
+
+theorem Stable.trans {s t u : State} (hs : Stable s t) (ht : Stable t u) : Stable s u := by
+ have hwork : workRegion t = workRegion s :=
+ congrArg (fun p => (⟨p + BitVec.ofNat 64 56, 392⟩ : Region)) (hs.regs .rdx (by decide))
+ have hf := ht.frame
+ rw [hwork] at hf
+ exact ⟨ht.rd.trans hs.rd, ht.wr.trans hs.wr,
+ fun q hq => (ht.regs q hq).trans (hs.regs q hq), hs.frame.trans hf⟩
+
+theorem pass_word_ok (keys : Nat → DesSchedule) (base : Addr) (s : State) (x : BitVec 64)
+ (c : Nat) (hc : c < 3) (d : Direction)
+ (hready : Ready keys base s) (hword : WordState x s) :
+ WP isa (pass c d) s (fun t => WordState (VG.Proof.TripleDes.desCore (keys c) d x) t ∧
+ Ready keys base t ∧ Stable s t) := by
+ have hptr : s.mem.readW (savedKeyAddr s) 64 + BitVec.ofNat 64 (passOffset c d) =
+ keyAddr (componentBase base c) d 0 := by
+ rw [hready.saved]
+ exact passPointer base c d
+ apply WP.mono (pass_ok c hc (keys c) d (componentBase base c) s
+ ((x >>> 32).setWidth 32, x.setWidth 32) hready.spills hword.left hword.right
+ hptr hready.savedRead hready.countRead hready.countWrite
+ (hready.read c hc d) (hready.separate c hc d) (hready.values c hc d))
+ intro t ht
+ exact ⟨ht.wordState,
+ hready.congr (ht.regs .rdx (by decide)) ht.rd ht.wr ht.frame,
+ ht.rd, ht.wr, ht.regs, ht.frame⟩
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Round.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Round.lean
new file mode 100644
index 000000000..97b663c4d
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Round.lean
@@ -0,0 +1,285 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.RoundLit
+import VerifiedGarbage.Proof.TripleDes.X86_64.Sbox
+import VerifiedGarbage.Proof.TripleDes.Permutation
+import VerifiedGarbage.Proof.Framework.X86_64.Linear
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Bitslice VG.Impl.TripleDes.X86_64
+
+noncomputable def sboxInputsLiterals : Array (Prog isa) :=
+ #[sboxInputs0.lit, sboxInputs1.lit, sboxInputs2.lit, sboxInputs3.lit, sboxInputs4.lit, sboxInputs5.lit, sboxInputs6.lit, sboxInputs7.lit]
+
+noncomputable def sboxInputsLiteral (i : Nat) : Prog isa :=
+ sboxInputsLiterals.getD i (.block [])
+
+noncomputable def sboxOutputsLiterals : Array (Prog isa) :=
+ #[sboxOutputs0.lit, sboxOutputs1.lit, sboxOutputs2.lit, sboxOutputs3.lit, sboxOutputs4.lit, sboxOutputs5.lit, sboxOutputs6.lit, sboxOutputs7.lit]
+
+noncomputable def sboxOutputsLiteral (i : Nat) : Prog isa :=
+ sboxOutputsLiterals.getD i (.block [])
+
+def roundInputCfg : Cfg := { base := .rdx, slots := 0, ext := .rdi, exts := 1 }
+def roundInputRegs : List (Reg × Nat) := [(.r13, 0)]
+
+def roundInputBits (i j p : Nat) : List Nat :=
+ if p = 0 then
+ let k := 6 * i + 5 - j
+ [32 - Spec.TripleDes.expansion.getD k 1, 64 + (47 - k)]
+ else []
+
+def roundInputPost (i : Nat) : List (Reg × (Nat → List Nat)) :=
+ (List.range 6).map fun j => (q j, roundInputBits i j)
+
+theorem roundInput_check : ∀ i < 8,
+ check (lanes 64 7) roundInputCfg (linExt 1) (instrs (sboxInputsLiteral i))
+ (linEnv roundInputRegs) (linPost 7 (roundInputPost i)) = true := by
+ decide +kernel
+
+def roundOutputCfg : Cfg := { base := .rdx, slots := 0, ext := .rdx, exts := 0 }
+def roundOutputRegs : List (Reg × Nat) :=
+ [(.r12, 0)] ++ (List.range 4).map fun j => (q j, j + 1)
+
+def roundOutputBits (i p : Nat) : List Nat :=
+ [p] ++ ((List.range 4).filterMap fun j =>
+ let position := 4 * i + 4 - j
+ let dst := (Spec.TripleDes.p.toList.findIdx? (· == position)).getD 0
+ if p = 31 - dst then some (64 * (j + 1)) else none)
+
+theorem roundOutput_check : ∀ i < 8,
+ check (lanes 64 9) roundOutputCfg (linExt 5) (instrs (sboxOutputsLiteral i))
+ (linEnv roundOutputRegs) (linPost 9 [(.r12, roundOutputBits i)]) = true := by
+ decide +kernel
+
+theorem sboxInputsLiteral_eq : ∀ i < 8,
+ sboxInputsLiteral i = .block (sboxInputs i)
+ | 0, _ => sboxInputs0.lit_eq.symm
+ | 1, _ => sboxInputs1.lit_eq.symm
+ | 2, _ => sboxInputs2.lit_eq.symm
+ | 3, _ => sboxInputs3.lit_eq.symm
+ | 4, _ => sboxInputs4.lit_eq.symm
+ | 5, _ => sboxInputs5.lit_eq.symm
+ | 6, _ => sboxInputs6.lit_eq.symm
+ | 7, _ => sboxInputs7.lit_eq.symm
+ | n + 8, h => by omega
+
+theorem roundInputCfg_ok (s : State)
+ (hread : InRegions (s.rd ++ s.wr) (s.gpr .rdi) 8) : Ok roundInputCfg s := by
+ refine ⟨?_, ?_, by decide, ?_⟩
+ · intro k hk; simp [roundInputCfg] at hk
+ · intro k hk
+ have hk0 : k = 0 := by simp only [roundInputCfg] at hk; omega
+ subst k
+ simpa only [roundInputCfg, wordAddr, Nat.mul_zero,
+ BitVec.add_zero] using hread
+ · intro k hk; simp [roundInputCfg] at hk
+
+/-- The extraction block reads just one round key and forms six Boolean
+input words. It does not change memory, access permissions or other registers. -/
+theorem roundInput_ok (i : Nat) (hi : i < 8) (s : State)
+ (hread : InRegions (s.rd ++ s.wr) (s.gpr .rdi) 8) :
+ ∃ s', runBlock isa (sboxInputs i) s = some s' ∧
+ (∀ j < 6, ∀ p < 64, (s'.gpr (q j)).getLsbD p =
+ xorBits (fun k => if k = 0 then s.gpr .r13
+ else s.mem.readW (s.gpr .rdi) 64) (roundInputBits i j p)) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, ((sboxInputs i).all fun op => op.dst != some r) = true →
+ s'.gpr r = s.gpr r) := by
+ have hchk := roundInput_check i hi
+ rw [sboxInputsLiteral_eq i hi] at hchk
+ let W : Nat → BitVec 64 := fun k =>
+ if k = 0 then s.gpr .r13 else s.mem.readW (s.gpr .rdi) 64
+ obtain ⟨s', hs', out, rd, wr, keep, frame⟩ := linear_ok hchk
+ (roundInputCfg_ok s hread) W (fun r k h => by
+ simp only [roundInputRegs, List.mem_singleton, Prod.mk.injEq] at h
+ obtain ⟨rfl, rfl⟩ := h
+ exact ⟨by decide, rfl⟩) (fun j hj => by
+ have hj0 : j = 0 := by simp only [roundInputCfg] at hj; omega
+ subst j
+ exact ⟨by decide, by simp [W, wordAddr, roundInputCfg]⟩)
+ refine ⟨s', hs', fun j hj p hp => ?_, rd, wr, ?_, keep⟩
+ · exact out (q j) (roundInputBits i j)
+ (List.mem_map.mpr ⟨j, List.mem_range.mpr hj, rfl⟩) p hp
+ · funext a
+ apply frame a
+ intro r hr hc
+ simp only [slotRegion, roundInputCfg, List.mem_singleton] at hr
+ subst r
+ simp [Region.Contains] at hc
+
+theorem roundInput_bounds : ∀ i < 8, ∀ j < 6,
+ 32 - Spec.TripleDes.expansion.getD (6 * i + 5 - j) 1 < 64 ∧
+ 47 - (6 * i + 5 - j) < 64 := by
+ decide +kernel
+
+theorem bitOf_low (W : Nat → BitVec 64) (a : Nat) (ha : a < 64) :
+ bitOf W a = (W 0).getLsbD a := by
+ simp only [bitOf, Nat.div_eq_of_lt ha, Nat.mod_eq_of_lt ha]
+
+theorem bitOf_next (W : Nat → BitVec 64) (a : Nat) (ha : a < 64) :
+ bitOf W (64 + a) = (W 1).getLsbD a := by
+ have hd : (64 + a) / 64 = 1 := by omega
+ simp only [bitOf, hd, Nat.add_mod_left, Nat.mod_eq_of_lt ha]
+
+def roundChunk (i : Nat) (r : BitVec 32) (k : BitVec 48) : BitVec 6 :=
+ ((Spec.TripleDes.permute Spec.TripleDes.expansion r ^^^ k) >>> (6 * (7 - i))).setWidth 6
+
+theorem roundChunk_bit (i j : Nat) (hi : i < 8) (hj : j < 6)
+ (r : BitVec 64) (k : BitVec 64) :
+ (roundChunk i (r.setWidth 32) (k.setWidth 48)).getLsbD j =
+ (r.getLsbD (32 - Spec.TripleDes.expansion.getD (6 * i + 5 - j) 1) ^^
+ k.getLsbD (47 - (6 * i + 5 - j))) := by
+ have ht : 6 * (7 - i) + j < 48 := by omega
+ have heq : 48 - 1 - (6 * (7 - i) + j) = 6 * i + 5 - j := by omega
+ have hkey : 6 * (7 - i) + j = 47 - (6 * i + 5 - j) := by omega
+ have hsource : 32 - Spec.TripleDes.expansion.getD (6 * i + 5 - j) 1 < 32 := by
+ have hb : ∀ t < 48, 1 ≤ Spec.TripleDes.expansion.getD t 1 := by decide +kernel
+ have hpos : 6 * i + 5 - j < 48 := by omega
+ have := hb _ hpos
+ omega
+ simp only [roundChunk, BitVec.getLsbD_setWidth, hj, decide_true, Bool.true_and,
+ BitVec.getLsbD_ushiftRight, BitVec.getLsbD_xor]
+ rw [VG.Proof.TripleDes.permute_bit _ _ (by decide) _ ht]
+ rw [heq]
+ simp only [BitVec.getLsbD_setWidth, hsource, ht, decide_true, Bool.true_and]
+ rw [hkey]
+
+theorem roundInput_chunk (i : Nat) (hi : i < 8) (s : State)
+ (hread : InRegions (s.rd ++ s.wr) (s.gpr .rdi) 8) :
+ ∃ s', runBlock isa (sboxInputs i) s = some s' ∧
+ inputAt s' 0 = roundChunk i ((s.gpr .r13).setWidth 32)
+ ((s.mem.readW (s.gpr .rdi) 64).setWidth 48) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, ((sboxInputs i).all fun op => op.dst != some r) = true →
+ s'.gpr r = s.gpr r) := by
+ obtain ⟨s', run, bits, rd, wr, mem, keep⟩ := roundInput_ok i hi s hread
+ refine ⟨s', run, ?_, rd, wr, mem, keep⟩
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ simp only [inputAt, getLsbD_ofBits, hj, decide_true, Bool.true_and]
+ rw [bits j hj 0 (by decide), roundChunk_bit i j hi hj]
+ obtain ⟨hr, hk⟩ := roundInput_bounds i hi j hj
+ simp only [roundInputBits, ite_true, xorBits_cons, xorBits_nil, Bool.xor_false,
+ bitOf_low _ _ hr, bitOf_next _ _ hk, ite_true]
+ rfl
+
+def boxSource (p : Nat) : Nat := Spec.TripleDes.p.getD (31 - p) 1 - 1
+
+def boxPiece (i : Nat) (b : BitVec 4) : BitVec 32 :=
+ ofBits 32 fun p => if boxSource p / 4 = i then
+ b.getLsbD (3 - boxSource p % 4) else false
+
+theorem roundOutputBits_shape : ∀ i < 8, ∀ p < 64,
+ roundOutputBits i p = [p] ++
+ (if p < 32 ∧ boxSource p / 4 = i then
+ [64 * (4 - boxSource p % 4)] else []) := by
+ decide +kernel
+
+theorem sboxOutputsLiteral_eq : ∀ i < 8,
+ sboxOutputsLiteral i = .block (sboxOutputs i)
+ | 0, _ => sboxOutputs0.lit_eq.symm
+ | 1, _ => sboxOutputs1.lit_eq.symm
+ | 2, _ => sboxOutputs2.lit_eq.symm
+ | 3, _ => sboxOutputs3.lit_eq.symm
+ | 4, _ => sboxOutputs4.lit_eq.symm
+ | 5, _ => sboxOutputs5.lit_eq.symm
+ | 6, _ => sboxOutputs6.lit_eq.symm
+ | 7, _ => sboxOutputs7.lit_eq.symm
+ | n + 8, h => by omega
+
+theorem roundOutputCfg_ok (s : State) : Ok roundOutputCfg s := by
+ refine ⟨?_, ?_, by decide, ?_⟩
+ · intro k hk; simp [roundOutputCfg] at hk
+ · intro k hk; simp [roundOutputCfg] at hk
+ · intro k hk; simp [roundOutputCfg] at hk
+
+/-- Deposit the four low S-box bits into L, at P's fixed destinations. -/
+theorem roundOutput_ok (i : Nat) (hi : i < 8) (s : State) :
+ ∃ s', runBlock isa (sboxOutputs i) s = some s' ∧
+ (∀ p < 64, (s'.gpr .r12).getLsbD p =
+ xorBits (fun k => if k = 0 then s.gpr .r12 else s.gpr (q (k - 1)))
+ (roundOutputBits i p)) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, ((sboxOutputs i).all fun op => op.dst != some r) = true →
+ s'.gpr r = s.gpr r) := by
+ have hchk := roundOutput_check i hi
+ rw [sboxOutputsLiteral_eq i hi] at hchk
+ let W : Nat → BitVec 64 := fun k =>
+ if k = 0 then s.gpr .r12 else s.gpr (q (k - 1))
+ obtain ⟨s', hs', out, rd, wr, keep, frame⟩ := linear_ok hchk
+ (roundOutputCfg_ok s) W (fun r k h => by
+ simp only [roundOutputRegs, List.mem_append, List.mem_singleton,
+ Prod.mk.injEq, List.mem_map, List.mem_range] at h
+ rcases h with ⟨rfl, rfl⟩ | ⟨j, hj, heq⟩
+ · exact ⟨by decide, rfl⟩
+ · obtain ⟨rfl, rfl⟩ := heq
+ refine ⟨by omega, ?_⟩
+ simp [W]) (fun j hj => by simp [roundOutputCfg] at hj)
+ refine ⟨s', hs', fun p hp => ?_, rd, wr, ?_, keep⟩
+ · exact out .r12 (roundOutputBits i) (by simp) p hp
+ · funext a
+ apply frame a
+ intro r hr hc
+ simp only [slotRegion, roundOutputCfg, List.mem_singleton] at hr
+ subst r
+ simp [Region.Contains] at hc
+
+theorem bitOf_word (W : Nat → BitVec 64) (j : Nat) :
+ bitOf W (64 * j) = (W j).getLsbD 0 := by
+ simp [bitOf]
+
+theorem roundOutput_piece (i : Nat) (hi : i < 8) (s : State) (b : BitVec 4)
+ (hb : ∀ j < 4, (s.gpr (q j)).getLsbD 0 = b.getLsbD j) :
+ ∃ s', runBlock isa (sboxOutputs i) s = some s' ∧
+ s'.gpr .r12 = s.gpr .r12 ^^^ (boxPiece i b).zeroExtend 64 ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ r, ((sboxOutputs i).all fun op => op.dst != some r) = true →
+ s'.gpr r = s.gpr r) := by
+ obtain ⟨s', run, bits, rd, wr, mem, keep⟩ := roundOutput_ok i hi s
+ refine ⟨s', run, ?_, rd, wr, mem, keep⟩
+ apply BitVec.eq_of_getLsbD_eq
+ intro p hp
+ rw [bits p hp, roundOutputBits_shape i hi p hp]
+ simp only [BitVec.getLsbD_xor, BitVec.zeroExtend_eq_setWidth,
+ BitVec.getLsbD_setWidth, hp, decide_true, Bool.true_and]
+ simp only [List.cons_append, List.nil_append, xorBits_cons, bitOf_low _ _ hp, ite_true]
+ by_cases h : p < 32 ∧ boxSource p / 4 = i
+ · simp only [h]
+ have hj : 3 - boxSource p % 4 < 4 := by omega
+ simp
+ rw [bitOf_word]
+ have hn : 4 - boxSource p % 4 ≠ 0 := by omega
+ have heq : 4 - boxSource p % 4 - 1 = 3 - boxSource p % 4 := by omega
+ simp only [hn, ite_false, heq]
+ rw [hb _ hj]
+ simp only [boxPiece, getLsbD_ofBits, h.1, h.2, decide_true, Bool.true_and, ite_true]
+ · simp only [h, ite_false, xorBits_nil]
+ simp only [boxPiece, getLsbD_ofBits]
+ by_cases hp32 : p < 32
+ · have hs : boxSource p / 4 ≠ i := by omega
+ simp only [hp32, decide_true, Bool.true_and, hs, ite_false]
+ · simp only [hp32, decide_false, Bool.false_and]
+
+def roundKept : List Reg := [.rdi, .rsi, .rdx, .rsp, .r13]
+
+theorem roundInput_keeps : ∀ i < 8, (.r12 :: roundKept).all
+ (fun r => (instrs (sboxInputsLiteral i)).all fun op => op.dst != some r) = true := by
+ decide +kernel
+
+theorem roundOutput_keeps : ∀ i < 8, roundKept.all
+ (fun r => (instrs (sboxOutputsLiteral i)).all fun op => op.dst != some r) = true := by
+ decide +kernel
+
+theorem roundInput_keep (i : Nat) (hi : i < 8) (r : Reg) (hr : r ∈ .r12 :: roundKept) :
+ (sboxInputs i).all (fun op => op.dst != some r) = true := by
+ have h := List.all_eq_true.mp (roundInput_keeps i hi) r hr
+ rw [sboxInputsLiteral_eq i hi] at h
+ exact h
+
+theorem roundOutput_keep (i : Nat) (hi : i < 8) (r : Reg) (hr : r ∈ roundKept) :
+ (sboxOutputs i).all (fun op => op.dst != some r) = true := by
+ have h := List.all_eq_true.mp (roundOutput_keeps i hi) r hr
+ rw [sboxOutputsLiteral_eq i hi] at h
+ exact h
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundBody.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundBody.lean
new file mode 100644
index 000000000..bc3cb49b1
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundBody.lean
@@ -0,0 +1,123 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Box
+import VerifiedGarbage.Proof.TripleDes.X86_64.RoundFunction
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Impl.TripleDes.X86_64
+
+def contribution (r k : BitVec 64) (i : Nat) : BitVec 64 :=
+ (boxPiece i (Spec.TripleDes.sBox i
+ (roundChunk i (r.setWidth 32) (k.setWidth 48)))).zeroExtend 64
+
+/-- Compose any ordered list of S-boxes. The schedule word and Feistel
+right half stay fixed; each contribution is XORed into the left half. -/
+theorem boxes_ok (indices : List Nat) (hindices : ∀ i ∈ indices, i < 8)
+ (r k : BitVec 64) (s : State) (hok : Ok sboxCfg s)
+ (hr : s.gpr .r13 = r) (hk : s.mem.readW (s.gpr .rdi) 64 = k)
+ (hread : InRegions (s.rd ++ s.wr) (s.gpr .rdi) 8)
+ (hsep : (⟨s.gpr .rdi, 8⟩ : Region).Disjoint (spillRegion s)) :
+ ∃ s', runBlock isa (indices.flatMap box) s = some s' ∧
+ s'.gpr .r12 = indices.foldl (fun out i => out ^^^ contribution r k i) (s.gpr .r12) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ q ∈ roundKept, s'.gpr q = s.gpr q) ∧
+ Frame [spillRegion s] s.mem s'.mem := by
+ induction indices generalizing s with
+ | nil =>
+ exact ⟨s, runBlock_nil, rfl, rfl, rfl, fun _ _ => rfl, Frame.refl _ _⟩
+ | cons i indices ih =>
+ have hi : i < 8 := hindices i (List.mem_cons_self)
+ obtain ⟨s₁, run₁, value₁, rd₁, wr₁, keep₁, frame₁⟩ := box_ok i hi s hok hread
+ have hregion : spillRegion s₁ = spillRegion s := by
+ simp only [spillRegion, keep₁ .rdx (by decide)]
+ have hr₁ : s₁.gpr .r13 = r := (keep₁ .r13 (by decide)).trans hr
+ have hk₁ : s₁.mem.readW (s₁.gpr .rdi) 64 = k := by
+ rw [keep₁ .rdi (by decide)]
+ refine Eq.trans (frame₁.readW (r := ⟨s.gpr .rdi, 8⟩) ?_ ?_ (by decide)) hk
+ · simp [Region.Contains]
+ · intro q hq
+ obtain rfl := List.mem_singleton.mp hq
+ exact hsep
+ have hread₁ : InRegions (s₁.rd ++ s₁.wr) (s₁.gpr .rdi) 8 := by
+ rw [rd₁, wr₁, keep₁ .rdi (by decide)]
+ exact hread
+ have hsep₁ : (⟨s₁.gpr .rdi, 8⟩ : Region).Disjoint (spillRegion s₁) := by
+ rw [keep₁ .rdi (by decide), hregion]
+ exact hsep
+ have hok₁ : Ok sboxCfg s₁ := hok.congr
+ (keep₁ .rdx (by decide)) (keep₁ .rdx (by decide)) rd₁ wr₁
+ obtain ⟨s₂, run₂, value₂, rd₂, wr₂, keep₂, frame₂⟩ := ih
+ (fun j hj => hindices j (List.mem_cons_of_mem _ hj)) s₁ hok₁ hr₁ hk₁ hread₁ hsep₁
+ refine ⟨s₂, ?_, ?_, rd₂.trans rd₁, wr₂.trans wr₁, ?_, ?_⟩
+ · simp only [List.flatMap_cons, runBoxes_append, run₁, Option.bind_some, run₂]
+ · rw [hr, hk] at value₁
+ change s₁.gpr .r12 = s.gpr .r12 ^^^ contribution r k i at value₁
+ simpa only [List.foldl_cons, ← value₁] using value₂
+ · exact fun q hq => (keep₂ q hq).trans (keep₁ q hq)
+ · rw [hregion] at frame₂
+ exact frame₁.trans frame₂
+
+theorem contributions_roundFunction (r k : BitVec 64) (l : BitVec 64) :
+ (List.range 8).foldl (fun out i => out ^^^ contribution r k i) l =
+ l ^^^ (Spec.TripleDes.roundFunction (r.setWidth 32) (k.setWidth 48)).zeroExtend 64 := by
+ rw [foldl_xor_start]
+ have hf := foldl_xor_extend (List.range 8)
+ (fun i => boxPiece i (Spec.TripleDes.sBox i
+ (roundChunk i (r.setWidth 32) (k.setWidth 48)))) 0
+ have hz : (0 : BitVec 32).setWidth 64 = 0 := BitVec.setWidth_zero 64 32
+ have hinit := congrArg (fun b : BitVec 64 =>
+ (List.range 8).foldl (fun out i => out ^^^ contribution r k i) b) hz
+ have hg := congrArg (BitVec.setWidth 64)
+ (boxPieces_eq_roundFunction (r.setWidth 32) (k.setWidth 48))
+ exact congrArg (fun x => l ^^^ x) ((hinit.symm.trans hf).trans hg)
+
+def roundOuterKept : List Reg := [.rdi, .rsi, .rdx, .rsp]
+
+theorem swapHalves_ok (s : State) :
+ ∃ s', runBlock isa swapHalves s = some s' ∧
+ s'.gpr .r12 = s.gpr .r13 ∧ s'.gpr .r13 = s.gpr .r12 ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧ s'.mem = s.mem ∧
+ (∀ q ∈ roundOuterKept, s'.gpr q = s.gpr q) := by
+ open VG.X86_64.RegUpd in
+ refine ⟨_, by
+ simp only [swapHalves, rr, runBlock_cons, runStep_some, runBlock_nil, exec,
+ readSrc, Option.map_some, gpr_setReg]
+ rfl, ?_, ?_, ?_, ?_, ?_, ?_⟩
+ · simp only [gpr_setReg]; rfl
+ · simp only [gpr_setReg]; rfl
+ · simp only [rd_setReg]
+ · simp only [wr_setReg]
+ · simp only [mem_setReg]
+ · intro q hq
+ have hneq : q ≠ .rax ∧ q ≠ .r12 ∧ q ≠ .r13 := by
+ revert hq; cases q <;> decide
+ simp only [gpr_setReg, hneq.1, hneq.2.1, hneq.2.2, ite_false]
+
+/-- One full Feistel round, with all eight S-boxes and the half swap. -/
+theorem roundBody_ok (s : State) (l r : BitVec 32) (k : BitVec 64)
+ (hl : s.gpr .r12 = l.setWidth 64) (hr : s.gpr .r13 = r.setWidth 64)
+ (hk : s.mem.readW (s.gpr .rdi) 64 = k) (hok : Ok sboxCfg s)
+ (hread : InRegions (s.rd ++ s.wr) (s.gpr .rdi) 8)
+ (hsep : (⟨s.gpr .rdi, 8⟩ : Region).Disjoint (spillRegion s)) :
+ ∃ s', runBlock isa roundBody s = some s' ∧
+ s'.gpr .r12 = r.setWidth 64 ∧
+ s'.gpr .r13 = (l ^^^ Spec.TripleDes.roundFunction r (k.setWidth 48)).setWidth 64 ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ q ∈ roundOuterKept, s'.gpr q = s.gpr q) ∧
+ Frame [spillRegion s] s.mem s'.mem := by
+ obtain ⟨s₁, run₁, value, rd₁, wr₁, keep₁, frame₁⟩ := boxes_ok (List.range 8)
+ (fun i hi => List.mem_range.mp hi) (r.setWidth 64) k s hok hr hk hread hsep
+ obtain ⟨s₂, run₂, left, right, rd₂, wr₂, mem₂, keep₂⟩ := swapHalves_ok s₁
+ refine ⟨s₂, ?_, ?_, ?_, rd₂.trans rd₁, wr₂.trans wr₁, ?_, ?_⟩
+ · simp only [roundBody, runBoxes_append, run₁, Option.bind_some, run₂]
+ · exact left.trans ((keep₁ .r13 (by decide)).trans hr)
+ · rw [right, value, contributions_roundFunction, hl]
+ have hwidth : (r.setWidth 64).setWidth 32 = r := by simp
+ rw [hwidth]
+ exact BitVec.setWidth_xor.symm
+ · intro q hq
+ have hq' : q ∈ roundKept := by revert hq; cases q <;> decide
+ exact (keep₂ q hq).trans (keep₁ q hq')
+ · rw [mem₂]
+ exact frame₁
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundFunction.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundFunction.lean
new file mode 100644
index 000000000..a0a5b05ae
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundFunction.lean
@@ -0,0 +1,82 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Round
+import VerifiedGarbage.Proof.TripleDes.Round
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.Bitslice VG.Spec.TripleDes
+
+theorem boxSource_shape : ∀ j < 32,
+ 7 - (32 - p.getD (31 - j) 1) / 4 = boxSource j / 4 ∧
+ (32 - p.getD (31 - j) 1) % 4 = 3 - boxSource j % 4 ∧
+ boxSource j / 4 < 8 := by
+ decide +kernel
+
+theorem boxPiece_round_bit (i : Nat) (r : BitVec 32) (k : BitVec 48)
+ (j : Nat) (hj : j < 32) :
+ (boxPiece i (sBox i (roundChunk i r k))).getLsbD j =
+ if boxSource j / 4 = i then (roundFunction r k).getLsbD j else false := by
+ simp only [boxPiece, getLsbD_ofBits, hj, decide_true, Bool.true_and]
+ by_cases heq : boxSource j / 4 = i
+ · simp only [heq, ite_true]
+ rw [VG.Proof.TripleDes.roundFunction_bit r k j hj]
+ obtain ⟨hidx, hbit, _⟩ := boxSource_shape j hj
+ simp only [hidx, hbit, heq, roundChunk]
+ · simp only [heq, ite_false]
+
+theorem foldl_xor_bits (xs : List Nat) (f : Nat → BitVec 32) (a : BitVec 32) (j : Nat) :
+ (xs.foldl (fun out i => out ^^^ f i) a).getLsbD j =
+ xs.foldl (fun out i => out ^^ (f i).getLsbD j) (a.getLsbD j) := by
+ induction xs generalizing a with
+ | nil => rfl
+ | cons i xs ih =>
+ simp only [List.foldl_cons, ih, BitVec.getLsbD_xor]
+
+theorem select_xor : ∀ n < 8, ∀ b : Bool,
+ (List.range 8).foldl (fun out i => out ^^ (if n = i then b else false)) false = b := by
+ decide +kernel
+
+/-- The eight S-box contributions give the standard DES round function. -/
+theorem boxPieces_eq_roundFunction (r : BitVec 32) (k : BitVec 48) :
+ (List.range 8).foldl (fun out i => out ^^^ boxPiece i (sBox i (roundChunk i r k)))
+ (0 : BitVec 32) = roundFunction r k := by
+ apply BitVec.eq_of_getLsbD_eq
+ intro j hj
+ have hfold : (fun (out : Bool) i => out ^^
+ (boxPiece i (sBox i (roundChunk i r k))).getLsbD j) =
+ (fun out i => out ^^ (if boxSource j / 4 = i then
+ (roundFunction r k).getLsbD j else false)) := by
+ funext out i
+ exact congrArg (fun b => out ^^ b) (boxPiece_round_bit i r k j hj)
+ have hbits := foldl_xor_bits (List.range 8)
+ (fun i => boxPiece i (sBox i (roundChunk i r k))) 0 j
+ have hz : (0 : BitVec 32).getLsbD j = false := by
+ change (BitVec.ofNat 32 0).getLsbD j = false
+ exact BitVec.getLsbD_zero
+ have hinit := congrArg (fun b : Bool => (List.range 8).foldl
+ (fun out i => out ^^ (boxPiece i (sBox i (roundChunk i r k))).getLsbD j) b) hz
+ have hchange := congrArg
+ (fun f : Bool → Nat → Bool => (List.range 8).foldl f false) hfold
+ exact hbits.trans (hinit.trans (hchange.trans (select_xor _ (boxSource_shape j hj).2.2 _)))
+
+theorem foldl_xor_start (xs : List Nat) (f : Nat → BitVec 64) (a : BitVec 64) :
+ xs.foldl (fun out i => out ^^^ f i) a =
+ a ^^^ xs.foldl (fun out i => out ^^^ f i) 0 := by
+ induction xs generalizing a with
+ | nil => simp
+ | cons i xs ih =>
+ simp only [List.foldl_cons]
+ have hz : (0 : BitVec 64) ^^^ f i = f i := BitVec.zero_xor
+ rw [hz, ih (a ^^^ f i), ih (f i)]
+ exact BitVec.xor_assoc _ _ _
+
+theorem foldl_xor_extend (xs : List Nat) (f : Nat → BitVec 32) (a : BitVec 32) :
+ xs.foldl (fun out i => out ^^^ (f i).setWidth 64) (a.setWidth 64) =
+ (xs.foldl (fun out i => out ^^^ f i) a).setWidth 64 := by
+ induction xs generalizing a with
+ | nil => rfl
+ | cons i xs ih =>
+ simp only [List.foldl_cons]
+ rw [← BitVec.setWidth_xor]
+ exact ih _
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundLit.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundLit.lean
new file mode 100644
index 000000000..1c35a9e1d
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundLit.lean
@@ -0,0 +1,25 @@
+import VerifiedGarbage.Impl.TripleDes.X86_64.Block
+import VerifiedGarbage.Proof.Framework.X86_64.Lit
+
+namespace VG.Impl.TripleDes.X86_64
+
+open VG.X86_64
+
+materialize_code sboxInputs0 := (.block (sboxInputs 0) : Prog isa)
+materialize_code sboxInputs1 := (.block (sboxInputs 1) : Prog isa)
+materialize_code sboxInputs2 := (.block (sboxInputs 2) : Prog isa)
+materialize_code sboxInputs3 := (.block (sboxInputs 3) : Prog isa)
+materialize_code sboxInputs4 := (.block (sboxInputs 4) : Prog isa)
+materialize_code sboxInputs5 := (.block (sboxInputs 5) : Prog isa)
+materialize_code sboxInputs6 := (.block (sboxInputs 6) : Prog isa)
+materialize_code sboxInputs7 := (.block (sboxInputs 7) : Prog isa)
+materialize_code sboxOutputs0 := (.block (sboxOutputs 0) : Prog isa)
+materialize_code sboxOutputs1 := (.block (sboxOutputs 1) : Prog isa)
+materialize_code sboxOutputs2 := (.block (sboxOutputs 2) : Prog isa)
+materialize_code sboxOutputs3 := (.block (sboxOutputs 3) : Prog isa)
+materialize_code sboxOutputs4 := (.block (sboxOutputs 4) : Prog isa)
+materialize_code sboxOutputs5 := (.block (sboxOutputs 5) : Prog isa)
+materialize_code sboxOutputs6 := (.block (sboxOutputs 6) : Prog isa)
+materialize_code sboxOutputs7 := (.block (sboxOutputs 7) : Prog isa)
+
+end VG.Impl.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundStep.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundStep.lean
new file mode 100644
index 000000000..bccde7ce7
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/RoundStep.lean
@@ -0,0 +1,86 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.PassSteps
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Impl.TripleDes.X86_64
+
+def workRegion (s : State) : Region := ⟨s.gpr .rdx + BitVec.ofNat 64 56, 392⟩
+
+theorem count_spill_disjoint (s : State) :
+ (⟨countAddr s, 8⟩ : Region).Disjoint (spillRegion s) :=
+ Offset.disjoint (s.gpr .rdx) (by decide) (by decide) (by decide)
+
+theorem spill_sub_work (s : State) : Region.Sub (spillRegion s) (workRegion s) :=
+ Offset.sub (s.gpr .rdx) (by decide) (by decide)
+
+theorem count_sub_work (s : State) : Region.Sub ⟨countAddr s, 8⟩ (workRegion s) :=
+ Offset.sub (s.gpr .rdx) (by decide) (by decide)
+
+theorem roundStep_ok (direction : Spec.TripleDes.Direction) (s : State)
+ (l r : BitVec 32) (k : BitVec 64) (n : Nat) (hn : 1 ≤ n) (hn' : n < 17)
+ (hl : s.gpr .r12 = l.setWidth 64) (hr : s.gpr .r13 = r.setWidth 64)
+ (hk : s.mem.readW (s.gpr .rdi) 64 = k) (hok : Ok sboxCfg s)
+ (hread : InRegions (s.rd ++ s.wr) (s.gpr .rdi) 8)
+ (hsep : (⟨s.gpr .rdi, 8⟩ : Region).Disjoint (spillRegion s))
+ (hcount : s.mem.readW (countAddr s) 64 = BitVec.ofNat 64 n)
+ (hcountRead : InRegions (s.rd ++ s.wr) (countAddr s) 8)
+ (hcountWrite : InRegions s.wr (countAddr s) 8) :
+ ∃ s', runBlock isa (roundBody ++ roundAdvance direction) s = some s' ∧
+ s'.gpr .r12 = r.setWidth 64 ∧
+ s'.gpr .r13 = (l ^^^ Spec.TripleDes.roundFunction r (k.setWidth 48)).setWidth 64 ∧
+ s'.gpr .rdi = (if direction = .encrypt then s.gpr .rdi + 8 else s.gpr .rdi - 8) ∧
+ s'.mem.readW (countAddr s') 64 = BitVec.ofNat 64 (n - 1) ∧
+ isa.eval .ne s' = some (decide (n ≠ 1)) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ q ∈ [Reg.rsi, .rdx, .rsp], s'.gpr q = s.gpr q) ∧
+ Frame [workRegion s] s.mem s'.mem := by
+ obtain ⟨s₁, run₁, left₁, right₁, rd₁, wr₁, keep₁, frame₁⟩ :=
+ roundBody_ok s l r k hl hr hk hok hread hsep
+ have haddr : countAddr s₁ = countAddr s := by
+ simp only [countAddr, keep₁ .rdx (by decide)]
+ have hcount₁ : s₁.mem.readW (countAddr s₁) 64 = BitVec.ofNat 64 n := by
+ rw [haddr]
+ refine Eq.trans (frame₁.readW (r := ⟨countAddr s, 8⟩) ?_ ?_ (by decide)) hcount
+ · exact Region.contains_self _ _
+ · intro q hq
+ obtain rfl := List.mem_singleton.mp hq
+ exact count_spill_disjoint s
+ have hread₁ : InRegions (s₁.rd ++ s₁.wr) (countAddr s₁) 8 := by
+ rw [rd₁, wr₁, haddr]; exact hcountRead
+ have hwrite₁ : InRegions s₁.wr (countAddr s₁) 8 := by
+ rw [wr₁, haddr]; exact hcountWrite
+ obtain ⟨s₂, run₂, ptr₂, mem₂, flag₂, rd₂, wr₂, keep₂⟩ :=
+ roundAdvance_ok direction s₁ hread₁ hwrite₁
+ have hcountAddr₂ : countAddr s₂ = countAddr s₁ := by
+ simp only [countAddr, keep₂ .rdx (by decide) (by decide)]
+ have hwork : workRegion s₁ = workRegion s := by
+ simp only [workRegion, keep₁ .rdx (by decide)]
+ obtain ⟨hsub, hzero⟩ := countDown_rules n hn' hn
+ refine ⟨s₂, ?_, ?_, ?_, ?_, ?_, ?_, rd₂.trans rd₁, wr₂.trans wr₁, ?_, ?_⟩
+ · simp only [runBoxes_append, run₁, Option.bind_some, run₂]
+ · exact (keep₂ .r12 (by decide) (by decide)).trans left₁
+ · exact (keep₂ .r13 (by decide) (by decide)).trans right₁
+ · rw [ptr₂, keep₁ .rdi (by decide)]
+ · rw [hcountAddr₂, mem₂, Mem.readW_writeW_self64, hcount₁, hsub]
+ · change VG.X86_64.eval .ne s₂ = some (decide (n ≠ 1))
+ simp only [VG.X86_64.eval, flag₂, hcount₁, hzero, Option.map_some]
+ simp
+ · intro q hq
+ have hq' : q ∈ roundOuterKept := by revert hq; cases q <;> decide
+ have hneq : q ≠ .rax ∧ q ≠ .rdi := by revert hq; cases q <;> decide
+ exact (keep₂ q hneq.1 hneq.2).trans (keep₁ q hq')
+ · have hf₁ : Frame [workRegion s] s.mem s₁.mem := frame₁.sub (by
+ intro q hq
+ obtain rfl := List.mem_singleton.mp hq
+ exact ⟨_, List.mem_singleton_self _, spill_sub_work s⟩)
+ have hf₂ := countWrite_frame s₁.mem (countAddr s₁) (s₁.mem.readW (countAddr s₁) 64 - 1)
+ have hf₂' : Frame [workRegion s₁] s₁.mem s₂.mem := by
+ rw [mem₂]
+ exact hf₂.sub (by
+ intro q hq
+ obtain rfl := List.mem_singleton.mp hq
+ exact ⟨_, List.mem_singleton_self _, count_sub_work s₁⟩)
+ rw [hwork] at hf₂'
+ exact hf₁.trans hf₂'
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Save.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Save.lean
new file mode 100644
index 000000000..b021aa091
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Save.lean
@@ -0,0 +1,69 @@
+import VerifiedGarbage.Proof.Rc2.X86_64.Save
+import VerifiedGarbage.Impl.TripleDes.X86_64.Block
+import VerifiedGarbage.Proof.TripleDes.X86_64.RoundStep
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+
+/-- The six callee-saved registers and the schedule pointer, in slot order. -/
+def savedReg (i : Nat) : Reg := (savedRegs ++ [Reg.rdi]).getD i .rdi
+
+theorem blockSave_eq : blockSave = VG.Proof.Rc2.X86_64.saveCode .rdx savedReg 7 := by
+ decide +kernel
+
+theorem blockRestore_eq : blockRestore = VG.Proof.Rc2.X86_64.restoreCode .rdx savedReg (List.range 7) := by
+ decide +kernel
+
+def Saved (original current : State) : Prop :=
+ ∀ i < 7, current.mem.readW (current.gpr .rdx + BitVec.ofNat 64 (8 * i)) 64 =
+ original.gpr (savedReg i)
+
+theorem blockSave_ok (s : State)
+ (hw : ∀ i < 7, InRegions s.wr (s.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8) :
+ WP isa (.block blockSave) s (fun s' =>
+ s'.gpr = s.gpr ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧ Saved s s' ∧
+ Frame [⟨s.gpr .rdx, 56⟩] s.mem s'.mem) := by
+ rw [blockSave_eq]
+ apply WP.mono (VG.Proof.Rc2.X86_64.saveCode_ok s .rdx savedReg 7 hw)
+ intro s' hs
+ refine ⟨hs.1, hs.2.1, hs.2.2.1, ?_, ?_⟩
+ · intro i hi
+ rw [hs.1, hs.2.2.2]
+ exact VG.Proof.Rc2.X86_64.saveMem_read _ _ _ 7 (by decide) i hi
+ · rw [hs.2.2.2]
+ exact VG.Proof.Rc2.X86_64.saveMem_frame _ _ _ 7 (by decide)
+
+theorem savedReg_separate : ∀ i < 7, savedReg i ≠ .rdx := by decide +kernel
+
+theorem blockRestore_ok (original s : State) (hsaved : Saved original s)
+ (hread : ∀ i < 7, InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8) :
+ WP isa (.block blockRestore) s (fun s' =>
+ (∀ r ∈ savedRegs ++ [Reg.rdi], s'.gpr r = original.gpr r) ∧
+ VG.Proof.Rc2.X86_64.Keep (savedRegs ++ [Reg.rdi]) s s') := by
+ rw [blockRestore_eq]
+ have hregs : (List.range 7).map savedReg = savedRegs ++ [Reg.rdi] := by decide +kernel
+ have h := VG.Proof.Rc2.X86_64.restoreCode_ok s .rdx savedReg (List.range 7) original.gpr
+ (fun i hi => savedReg_separate i (List.mem_range.mp hi))
+ (fun i hi => hread i (List.mem_range.mp hi))
+ (fun i hi => hsaved i (List.mem_range.mp hi))
+ rw [hregs] at h
+ exact h
+
+
+theorem savedSlot_work_disjoint (s : State) (i : Nat) (hi : i < 7) :
+ (⟨s.gpr .rdx + BitVec.ofNat 64 (8 * i), 8⟩ : Region).Disjoint (workRegion s) :=
+ Offset.disjoint (s.gpr .rdx) (by omega) (by omega) (by decide)
+
+theorem Saved.congr {original s t : State} (hs : Saved original s)
+ (hbase : t.gpr .rdx = s.gpr .rdx) (hf : Frame [workRegion s] s.mem t.mem) :
+ Saved original t := by
+ intro i hi
+ have hmem := hf.readW (a := s.gpr .rdx + BitVec.ofNat 64 (8 * i)) (w := 64)
+ (r := ⟨s.gpr .rdx + BitVec.ofNat 64 (8 * i), 8⟩) (Region.contains_self _ _)
+ (fun q hq => by obtain rfl := List.mem_singleton.mp hq; exact savedSlot_work_disjoint s i hi)
+ (by decide)
+ rw [hbase]
+ exact hmem.trans (hs i hi)
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Sbox.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Sbox.lean
new file mode 100644
index 000000000..d2f58cb0d
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Sbox.lean
@@ -0,0 +1,113 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Lit
+import VerifiedGarbage.Spec.TripleDes
+import VerifiedGarbage.Proof.Framework.X86_64.Straight
+import VerifiedGarbage.Proof.Framework.Bitslice.Table
+
+/-!
+# DES S-box machine-code correctness
+
+Untrusted. The kernel checks each allocated scalar circuit on all 64
+inputs, then the sound truth-table evaluator lifts that check to every
+bit position of arbitrary 64-bit words. This verifies both the circuits
+and the allocator's output, including spills.
+-/
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.Straight VG.Bitslice VG.Impl.TripleDes.X86_64
+
+noncomputable def sboxLiterals : Array (Prog isa) :=
+ #[sbox0.lit, sbox1.lit, sbox2.lit, sbox3.lit, sbox4.lit, sbox5.lit, sbox6.lit, sbox7.lit]
+
+noncomputable def sboxLiteral (i : Nat) : Prog isa := sboxLiterals.getD i (.block [])
+
+def sboxCfg : Cfg := { base := .rdx, slots := 64, ext := .rdx, exts := 0 }
+def inputTable (k : Nat) : Nat := tableOf (fun c => c.testBit k) 64
+def outputTable (i j : Nat) : Nat :=
+ tableOf (fun c => (Spec.TripleDes.sBox i (BitVec.ofNat 6 c)).getLsbD j) 64
+
+def sboxEnv : Env Nat :=
+ { reg := fun r => ((List.range 6).find? (fun k => q k == r)).map inputTable,
+ slot := fun _ => none }
+
+def sboxPost (i : Nat) (e : Env Nat) : Bool :=
+ (List.range 4).all fun j => e.reg (q j) == some (outputTable i j)
+
+theorem sbox_check : ∀ i < 8,
+ check (table 64 64) sboxCfg (fun _ => none) (instrs (sboxLiteral i))
+ sboxEnv (sboxPost i) = true := by
+ decide +kernel
+
+def sboxWrites : List Reg := [.rax, .rcx, .r8, .r9, .r10, .r11, .rbx, .rbp, .r14, .r15]
+
+theorem sbox_preserves : ∀ i < 8,
+ [Reg.rdi, .rsi, .rdx, .rsp, .r12, .r13].all
+ (fun r => (instrs (sboxLiteral i)).all fun op => op.dst != some r) = true := by
+ decide +kernel
+
+def inputAt (s : State) (p : Nat) : BitVec 6 :=
+ ofBits 6 fun j => (s.gpr (q j)).getLsbD p
+
+theorem inputAt_bit (s : State) (p k : Nat) (hk : k < 6) :
+ (inputAt s p).toNat.testBit k = (s.gpr (q k)).getLsbD p := by
+ simp only [inputAt, BitVec.testBit_toNat, getLsbD_ofBits, hk, decide_true, Bool.true_and]
+
+theorem sboxLiteral_eq : ∀ i < 8, sboxLiteral i = .block (sboxCode i)
+ | 0, _ => sbox0.lit_eq.symm
+ | 1, _ => sbox1.lit_eq.symm
+ | 2, _ => sbox2.lit_eq.symm
+ | 3, _ => sbox3.lit_eq.symm
+ | 4, _ => sbox4.lit_eq.symm
+ | 5, _ => sbox5.lit_eq.symm
+ | 6, _ => sbox6.lit_eq.symm
+ | 7, _ => sbox7.lit_eq.symm
+ | n + 8, h => by omega
+
+/-- Every S-box output bit, for arbitrary input words and any readable/
+writable scratch state. Only the fixed scratch region can change. -/
+theorem sbox_ok (i : Nat) (hi : i < 8) {s : State} (hok : Ok sboxCfg s) :
+ ∃ s', runBlock isa (sboxCode i) s = some s' ∧
+ (∀ j < 4, ∀ p < 64, (s'.gpr (q j)).getLsbD p =
+ (Spec.TripleDes.sBox i (inputAt s p)).getLsbD j) ∧
+ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ∉ sboxWrites → s'.gpr r = s.gpr r) ∧
+ Frame [slotRegion sboxCfg s] s.mem s'.mem := by
+ have codeEq : instrs (sboxLiteral i) = sboxCode i := by rw [sboxLiteral_eq i hi]; rfl
+ obtain ⟨e', he, hpost⟩ := of_check _ _ _ (sbox_check i hi)
+ rw [codeEq] at he
+ have hout : ∀ j < 4, e'.reg (q j) = some (outputTable i j) := by
+ intro j hj
+ have h := List.all_eq_true.mp hpost j (List.mem_range.mpr hj)
+ exact beq_iff_eq.mp h
+ have key : ∀ p < 64, ∃ s', runBlock isa (sboxCode i) s = some s' ∧
+ Post (TableRel p (inputAt s p).toNat) sboxCfg (fun _ => none) e' s s'
+ (fun r => ((sboxCode i).all fun op => op.dst != some r) = false) := by
+ intro p hp
+ have hc := (inputAt s p).isLt
+ refine run (table_sound hp hc) hok ⟨fun r a h => ?_,
+ (fun _ _ _ h => by cases h), (fun _ _ _ h => by cases h)⟩ he
+ simp only [sboxEnv, Option.map_eq_some_iff] at h
+ obtain ⟨k, hk, rfl⟩ := h
+ have hqr := List.find?_some hk
+ have hk6 := List.mem_range.mp (List.mem_of_find?_eq_some hk)
+ simp only [beq_iff_eq] at hqr
+ subst hqr
+ simp only [TableRel, inputTable, testBit_tableOf, hc, decide_true, Bool.true_and,
+ inputAt_bit s p k hk6]
+ obtain ⟨s', hs', p₀⟩ := key 0 (by decide)
+ refine ⟨s', hs', fun j hj p hp => ?_, p₀.rd, p₀.wr, fun r hr => ?_, p₀.frame⟩
+ · obtain ⟨s'', hs'', p₁⟩ := key p hp
+ obtain rfl := run_unique hs'' hs'
+ have h := p₁.rel.reg (q j) _ (hout j hj)
+ simp only [TableRel, outputTable, testBit_tableOf, (inputAt s p).isLt,
+ decide_true, Bool.true_and] at h
+ rw [BitVec.ofNat_toNat] at h
+ exact h.symm
+ · apply p₀.other r
+ have hrest : r ∈ [Reg.rdi, .rsi, .rdx, .rsp, .r12, .r13] := by
+ revert hr; cases r <;> decide
+ have h := List.all_eq_true.mp (sbox_preserves i hi) r hrest
+ rw [codeEq] at h
+ simp [h]
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Spills.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Spills.lean
new file mode 100644
index 000000000..26ea0a901
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Spills.lean
@@ -0,0 +1,87 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Sbox
+import VerifiedGarbage.Proof.Framework.X86_64.RegUpd
+import VerifiedGarbage.Proof.Framework.Offset
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.RegUpd VG.Impl.TripleDes.X86_64
+
+def spillRegion (s : State) : Region := ⟨s.gpr .rdx + BitVec.ofNat 64 64, 384⟩
+
+def spillSafe : Instr → Bool
+ | .mov d _ | .movImm64 d _ => d != .rdx
+ | .alu .and d _ | .alu .xor d _ => d != .rdx
+ | .store m _ => decide (m.base = .rdx ∧ m.index = none ∧
+ 64 ≤ m.disp ∧ m.disp + 8 ≤ 448)
+ | _ => false
+
+theorem spillSafe_check : ∀ i < 8,
+ (instrs (sboxLiteral i)).all spillSafe = true := by decide +kernel
+
+theorem spillStep_frame (i : Instr) (s s' : State)
+ (h : spillSafe i = true) (he : exec i s = some s') :
+ s'.gpr .rdx = s.gpr .rdx ∧ Frame [spillRegion s] s.mem s'.mem := by
+ cases i <;> simp only [spillSafe, Bool.false_eq_true] at h
+ case mov d src =>
+ have hd : .rdx ≠ d := by intro heq; subst d; simp at h
+ simp only [exec, Option.map_eq_some_iff] at he
+ obtain ⟨v, _, rfl⟩ := he
+ exact ⟨by simp only [gpr_setReg, hd, ite_false], by
+ simp only [mem_setReg]; exact Frame.refl _ _⟩
+ case movImm64 d v =>
+ have hd : .rdx ≠ d := by intro heq; subst d; simp at h
+ simp only [exec, Option.some.injEq] at he
+ subst s'
+ exact ⟨by simp only [gpr_setReg, hd, ite_false], by
+ simp only [mem_setReg]; exact Frame.refl _ _⟩
+ case alu op d src =>
+ cases op <;> simp only [Bool.false_eq_true] at h
+ all_goals
+ have hd : .rdx ≠ d := by intro heq; subst d; simp at h
+ simp only [exec, execAlu, Option.bind_eq_some_iff, Option.some.injEq] at he
+ obtain ⟨v, _, rfl⟩ := he
+ exact ⟨by simp only [gpr_setReg, gpr_arithFlags, hd, ite_false], by
+ simp only [mem_setReg, mem_arithFlags]; exact Frame.refl _ _⟩
+ case store m r =>
+ obtain ⟨hb, hi, hlo, hhi⟩ := of_decide_eq_true h
+ simp only [exec, State.store64] at he
+ split at he
+ · simp only [Option.some.injEq] at he
+ subst s'
+ refine ⟨rfl, (Frame.refl _ _).writeW (List.mem_singleton_self _) _ ?_⟩
+ have hnat : m.disp = (m.disp.toNat : Int) := by omega
+ simp only [State.ea, hi, hb]
+ rw [hnat, BitVec.ofInt_natCast]
+ exact Offset.contains (s.gpr .rdx) (by omega) (by omega) (by decide)
+ · cases he
+
+theorem spillBlock_frame (is : List Instr) (s s' : State)
+ (hsafe : is.all spillSafe = true) (he : runBlock isa is s = some s') :
+ s'.gpr .rdx = s.gpr .rdx ∧ Frame [spillRegion s] s.mem s'.mem := by
+ induction is generalizing s with
+ | nil =>
+ rw [runBlock_nil] at he
+ obtain rfl := Option.some.inj he
+ exact ⟨rfl, Frame.refl _ _⟩
+ | cons i is ih =>
+ simp only [List.all_cons, Bool.and_eq_true] at hsafe
+ rw [runBlock_cons] at he
+ change (exec i s).bind (runBlock isa is) = some s' at he
+ obtain ⟨s₁, hi, hrest⟩ := Option.bind_eq_some_iff.mp he
+ obtain ⟨hg, hf⟩ := spillStep_frame i s s₁ hsafe.1 hi
+ obtain ⟨hg', hf'⟩ := ih s₁ hsafe.2 hrest
+ refine ⟨hg'.trans hg, hf.trans ?_⟩
+ have hr : spillRegion s₁ = spillRegion s := by simp only [spillRegion, hg]
+ rw [hr] at hf'
+ exact hf'
+
+/-- The saved registers and round counter in scratch slots 0–7 are
+outside the S-box's frame, as are the key schedule and block data. -/
+theorem sbox_spillFrame (i : Nat) (hi : i < 8) (s s' : State)
+ (he : runBlock isa (sboxCode i) s = some s') :
+ Frame [spillRegion s] s.mem s'.mem := by
+ have h := spillSafe_check i hi
+ rw [sboxLiteral_eq i hi] at h
+ exact (spillBlock_frame _ _ _ h he).2
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Store.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Store.lean
new file mode 100644
index 000000000..4284ba4c7
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Store.lean
@@ -0,0 +1,98 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.BlockIO
+import VerifiedGarbage.Proof.TripleDes.Word
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.X86_64.RegUpd VG.Impl.TripleDes.X86_64
+
+theorem packHalves_ok (s : State) :
+ ∃ s', runBlock isa [rr .rax .r12, .shift .ror .rax 32, .alu .xor .rax (.reg .r13)] s = some s' ∧
+ s'.gpr .rax = (s.gpr .r12).rotateRight 32 ^^^ s.gpr .r13 ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .rax → s'.gpr r = s.gpr r) := by
+ refine ⟨_, by
+ simp only [rr, runBlock_cons, runStep_some, exec, execShift,
+ readSrc, Option.map_some, gpr_setReg, ite_true]
+ rfl, ?_, ?_, ?_, ?_, ?_⟩
+ · exact gpr_setReg_self _ _ _
+ · simp only [mem_setReg, mem_setFlags, mem_arithFlags]
+ · simp only [rd_setReg, rd_setFlags, rd_arithFlags]
+ · simp only [wr_setReg, wr_setFlags, wr_arithFlags]
+ · intro r hr
+ simp only [gpr_setReg, gpr_setFlags, gpr_arithFlags, hr, ite_false]
+
+theorem storeTail_ok (s : State) :
+ ∃ s', runBlock isa [.bswap .rbx, rr .rax .rbx] s = some s' ∧
+ s'.gpr .rax = bswap64 (s.gpr .rbx) ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ r, r ≠ .rax → r ≠ .rbx → s'.gpr r = s.gpr r) := by
+ refine ⟨_, by
+ simp only [rr, runBlock_cons, runStep_some, runBlock_nil, exec, readSrc,
+ Option.map_some, gpr_setReg_self]
+ rfl, ?_, ?_, ?_, ?_, ?_⟩
+ · exact gpr_setReg_self _ _ _
+ · simp only [mem_setReg]
+ · simp only [rd_setReg]
+ · simp only [wr_setReg]
+ · intro r hrax hrbx
+ simp only [gpr_setReg, hrax, hrbx, ite_false]
+
+
+theorem blockStore_run (s s₁ s₂ s₃ : State)
+ (h₁ : runBlock isa [rr .rax .r12, .shift .ror .rax 32, .alu .xor .rax (.reg .r13)] s = some s₁)
+ (h₂ : runBlock isa (permuteCode Spec.TripleDes.fp 64 .rbx .rax .rbp) s₁ = some s₂)
+ (h₃ : runBlock isa [.bswap .rbx, rr .rax .rbx] s₂ = some s₃) :
+ runBlock isa blockStore s = some s₃ := by
+ have hhead := runAppend_some _ _ _ _ _ h₁ h₂
+ have htail := runAppend_some _ _ _ _ _ hhead h₃
+ have hcode : blockStore =
+ (([rr .rax .r12, .shift .ror .rax 32, .alu .xor .rax (.reg .r13)] : List Instr) ++
+ permuteCode Spec.TripleDes.fp 64 .rbx .rax .rbp) ++ [.bswap .rbx, rr .rax .rbx] := rfl
+ exact (congrArg (fun is => runBlock isa is s) hcode).trans htail
+
+theorem blockStore_ok (s : State) (l r : BitVec 32)
+ (hl : s.gpr .r12 = l.setWidth 64) (hr : s.gpr .r13 = r.setWidth 64) :
+ ∃ s', runBlock isa blockStore s = some s' ∧
+ s'.gpr .rax = bswap64 (Spec.TripleDes.permute Spec.TripleDes.fp (l ++ r)) ∧
+ s'.mem = s.mem ∧ s'.rd = s.rd ∧ s'.wr = s.wr ∧
+ (∀ q ∈ [Reg.rdi, .rsi, .rdx, .rsp], s'.gpr q = s.gpr q) := by
+ obtain ⟨s₁, run₁, word₁, mem₁, rd₁, wr₁, regs₁⟩ := packHalves_ok s
+ obtain ⟨s₂, run₂, word₂, rd₂, wr₂, mem₂, regs₂⟩ := final_raw_ok s₁
+ obtain ⟨s₃, run₃, word₃, mem₃, rd₃, wr₃, regs₃⟩ := storeTail_ok s₂
+ have hword : s₁.gpr .rax = l ++ r := by
+ rw [hl, hr] at word₁
+ exact word₁.trans (VG.Proof.TripleDes.packHalves_word l r)
+ refine ⟨s₃, blockStore_run s s₁ s₂ s₃ run₁ run₂ run₃, ?_,
+ mem₃.trans (mem₂.trans mem₁), rd₃.trans (rd₂.trans rd₁), wr₃.trans (wr₂.trans wr₁), ?_⟩
+ · exact word₃.trans (congrArg bswap64 (word₂.trans
+ (congrArg (Spec.TripleDes.permute Spec.TripleDes.fp) hword)))
+ · intro q hq
+ have hneq : ∀ q ∈ [Reg.rdi, .rsi, .rdx, .rsp], q ≠ .rax ∧ q ≠ .rbx ∧ q ≠ .rbp := by decide
+ have hdst : (instrs finalPermutation.lit).all
+ (fun op => op.dst == some Reg.rbx || op.dst == some Reg.rbp) = true := by decide +kernel
+ have hno : (instrs finalPermutation.lit).all (fun op => op.dst != some q) = true := by
+ apply List.all_eq_true.mpr
+ intro op hop
+ have h := List.all_eq_true.mp hdst op hop
+ simp only [Bool.or_eq_true, beq_iff_eq] at h
+ rcases h with h | h
+ · rw [h, bne_iff_ne]
+ intro he
+ exact (hneq q hq).2.1 (Option.some.inj he).symm
+ · rw [h, bne_iff_ne]
+ intro he
+ exact (hneq q hq).2.2 (Option.some.inj he).symm
+ exact (regs₃ q (hneq q hq).1 (hneq q hq).2.1).trans
+ ((regs₂ q hno).trans (regs₁ q (hneq q hq).1))
+
+
+theorem writeData_ok (s : State) (hwrite : InRegions s.wr (s.gpr .rsi) 8) :
+ ∃ s', runBlock isa [.store (memOp .rsi 0) .rax] s = some s' ∧
+ s'.mem = s.mem.writeW (s.gpr .rsi) (s.gpr .rax) ∧
+ s'.gpr = s.gpr ∧ s'.rd = s.rd ∧ s'.wr = s.wr := by
+ have haddr : s.gpr .rsi + BitVec.ofInt 64 (Int.ofNat 0) = s.gpr .rsi := BitVec.add_zero _
+ refine ⟨{ s with mem := s.mem.writeW (s.gpr .rsi) (s.gpr .rax) }, by
+ simp only [runBlock_cons, runStep_some, runBlock_nil, exec, State.store64,
+ State.ea, memOp, haddr, hwrite, ite_true], rfl, rfl, rfl, rfl⟩
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/StrongBlock.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/StrongBlock.lean
new file mode 100644
index 000000000..2dd5e22ac
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/StrongBlock.lean
@@ -0,0 +1,45 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.VerifiedBlock
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction)
+
+def strongBlockContract (d : Direction) : Contract isa where
+ pre := (blockContract d).pre
+ pub := (blockContract d).pub
+ post s s' := BlockPost (Spec.TripleDes.scheduleAt s.mem (s.gpr .rdi)) d s s'
+
+theorem strongBlock_correct (d : Direction) (s : State) (hs : (strongBlockContract d).pre s) :
+ ∃ t s', Exec isa (block d) s t s' ∧ abiPreserved s s' ∧
+ (strongBlockContract d).post s s' := by
+ have hp := headPre_of_contract d s hs
+ have hwrite : InRegions s.wr (s.gpr .rsi) 8 := by
+ rw [hs.2.1]
+ exact ⟨⟨s.gpr .rsi, 8⟩, by simp, Region.contains_self _ _⟩
+ have hwp : WP isa (block d) s (fun s' => gprPreserved s s' ∧
+ (strongBlockContract d).post s s') := by
+ apply WP.mono (block_ok (Spec.TripleDes.scheduleAt s.mem (s.gpr .rdi)) (s.gpr .rdi) d s hp hwrite)
+ intro s' hpost
+ refine ⟨⟨?_, ?_⟩, hpost⟩
+ · intro r hr
+ have hkeep : ∀ q ∈ calleeSaved,
+ q ∈ savedRegs ++ [Reg.rdi] ∨ q ∈ [Reg.rsi, .rdx, .rsp] := by decide
+ rcases hkeep r hr with h | h
+ · exact hpost.saved r h
+ · exact hpost.regs r h
+ · apply hpost.frame.readW (r := ⟨s.gpr .rsp, 8⟩) (Region.contains_self _ _) _ (by decide)
+ intro r hr
+ simp only [blockRegions, List.mem_cons, List.not_mem_nil, or_false] at hr
+ rcases hr with rfl | rfl
+ · exact hs.2.2.2.2.1
+ · exact hs.2.2.2.2.2
+ obtain ⟨t, s', he, ha, hp⟩ := hwp
+ refine ⟨t, s', he, abiPreserved_of_exec ?_ he ha, hp⟩
+ cases d
+ · change (encryptBlock.allInstrs (fun i => !loadsMxcsr i)) = true
+ lit_decide
+ · change (decryptBlock.allInstrs (fun i => !loadsMxcsr i)) = true
+ lit_decide
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Tail.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Tail.lean
new file mode 100644
index 000000000..a295e3336
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/Tail.lean
@@ -0,0 +1,68 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Store
+import VerifiedGarbage.Proof.TripleDes.X86_64.Save
+import VerifiedGarbage.Proof.TripleDes.X86_64.WordState
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+
+structure TailPost (original origin : State) (x : BitVec 64) (s : State) : Prop where
+ result : Spec.TripleDes.blockAt s.mem (origin.gpr .rsi) =
+ Spec.TripleDes.encodeBlock (Spec.TripleDes.permute Spec.TripleDes.fp x)
+ saved : ∀ r ∈ savedRegs ++ [Reg.rdi], s.gpr r = original.gpr r
+ rd : s.rd = origin.rd
+ wr : s.wr = origin.wr
+ regs : ∀ q ∈ [Reg.rsi, .rdx, .rsp], s.gpr q = origin.gpr q
+ frame : Frame [⟨origin.gpr .rsi, 8⟩] origin.mem s.mem
+
+theorem blockTail_ok (original s : State) (x : BitVec 64)
+ (hword : WordState x s) (hsaved : Saved original s)
+ (hsavedRead : ∀ i < 7, InRegions (s.rd ++ s.wr) (s.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8)
+ (hwrite : InRegions s.wr (s.gpr .rsi) 8) :
+ WP isa (.block (blockStore ++ blockRestore ++ ([.store (memOp .rsi 0) .rax] : List Instr)))
+ s (TailPost original s x) := by
+ obtain ⟨s₁, run₁, word₁, mem₁, rd₁, wr₁, regs₁⟩ :=
+ blockStore_ok s ((x >>> 32).setWidth 32) (x.setWidth 32) hword.left hword.right
+ have word : s₁.gpr .rax = bswap64 (Spec.TripleDes.permute Spec.TripleDes.fp x) :=
+ word₁.trans (congrArg (fun v => bswap64 (Spec.TripleDes.permute Spec.TripleDes.fp v))
+ (VG.Proof.TripleDes.halves_append x))
+ have saved₁ : Saved original s₁ := by
+ intro i hi
+ rw [regs₁ .rdx (by decide), mem₁]
+ exact hsaved i hi
+ have savedRead₁ : ∀ i < 7, InRegions (s₁.rd ++ s₁.wr) (s₁.gpr .rdx + BitVec.ofNat 64 (8 * i)) 8 := by
+ rw [rd₁, wr₁, regs₁ .rdx (by decide)]
+ exact hsavedRead
+ apply WP.block_append
+ apply WP.block_append
+ apply WP.of_runBlock
+ refine ⟨s₁, run₁, ?_⟩
+ apply WP.mono (blockRestore_ok original s₁ saved₁ savedRead₁)
+ intro s₂ hs₂
+ have hnonsaved : ∀ q ∈ [Reg.rax, .rsi, .rdx, .rsp], q ∉ savedRegs ++ [Reg.rdi] := by decide
+ have hrax₂ : s₂.gpr .rax = bswap64 (Spec.TripleDes.permute Spec.TripleDes.fp x) :=
+ (hs₂.2.reg .rax (hnonsaved .rax (by decide))).trans word
+ have hregs₂ : ∀ q ∈ [Reg.rsi, .rdx, .rsp], s₂.gpr q = s.gpr q := by
+ intro q hq
+ have hkeep : ∀ r ∈ [Reg.rsi, .rdx, .rsp], r ∈ [Reg.rax, .rsi, .rdx, .rsp] ∧
+ r ∈ [Reg.rdi, .rsi, .rdx, .rsp] := by decide
+ exact (hs₂.2.reg q (hnonsaved q (hkeep q hq).1)).trans (regs₁ q (hkeep q hq).2)
+ have hwrite₂ : InRegions s₂.wr (s₂.gpr .rsi) 8 := by
+ rw [hs₂.2.wr, wr₁, hregs₂ .rsi (by decide)]
+ exact hwrite
+ obtain ⟨s₃, run₃, mem₃, gpr₃, rd₃, wr₃⟩ := writeData_ok s₂ hwrite₂
+ apply WP.of_runBlock
+ refine ⟨s₃, run₃, ?_, ?_, rd₃.trans (hs₂.2.rd.trans rd₁),
+ wr₃.trans (hs₂.2.wr.trans wr₁), ?_, ?_⟩
+ · rw [mem₃, hs₂.2.mem, mem₁, hregs₂ .rsi (by decide), hrax₂]
+ exact blockAt_writeW s.mem (s.gpr .rsi) (Spec.TripleDes.permute Spec.TripleDes.fp x)
+ · intro r hr
+ rw [gpr₃]
+ exact hs₂.1 r hr
+ · intro q hq
+ rw [gpr₃]
+ exact hregs₂ q hq
+ · rw [mem₃, hs₂.2.mem, mem₁, hregs₂ .rsi (by decide)]
+ exact countWrite_frame s.mem (s.gpr .rsi) (s₂.gpr .rax)
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/VerifiedBlock.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/VerifiedBlock.lean
new file mode 100644
index 000000000..9706999ab
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/VerifiedBlock.lean
@@ -0,0 +1,73 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Pre
+import VerifiedGarbage.Proof.Framework.Contract
+import VerifiedGarbage.Spec.TripleDes.Contract
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+open VG.Spec.TripleDes (Direction)
+
+theorem block_gprCorrect (d : Direction) (s : State) (hs : (blockContract d).pre s) :
+ WP isa (block d) s (fun s' => gprPreserved s s' ∧ (blockContract d).post s s') := by
+ have hp := headPre_of_contract d s hs
+ have hwrite : InRegions s.wr (s.gpr .rsi) 8 := by
+ rw [hs.2.1]
+ exact ⟨⟨s.gpr .rsi, 8⟩, by simp, Region.contains_self _ _⟩
+ apply WP.mono (block_ok (Spec.TripleDes.scheduleAt s.mem (s.gpr .rdi)) (s.gpr .rdi) d s hp hwrite)
+ intro s' hpost
+ refine ⟨⟨?_, ?_⟩, hpost.result⟩
+ · intro r hr
+ have hkeep : ∀ q ∈ calleeSaved,
+ q ∈ savedRegs ++ [Reg.rdi] ∨ q ∈ [Reg.rsi, .rdx, .rsp] := by decide
+ rcases hkeep r hr with h | h
+ · exact hpost.saved r h
+ · exact hpost.regs r h
+ · apply hpost.frame.readW (r := ⟨s.gpr .rsp, 8⟩) (Region.contains_self _ _) _ (by decide)
+ intro r hr
+ simp only [blockRegions, List.mem_cons, List.not_mem_nil, or_false] at hr
+ rcases hr with rfl | rfl
+ · exact hs.2.2.2.2.1
+ · exact hs.2.2.2.2.2
+
+theorem encrypt_correct (s : State) (hs : (blockContract .encrypt).pre s) :
+ ∃ t s', Exec isa encryptBlock s t s' ∧ abiPreserved s s' ∧
+ (blockContract .encrypt).post s s' := by
+ obtain ⟨t, s', he, ha, hp⟩ := block_gprCorrect .encrypt s hs
+ change Exec isa encryptBlock s t s' at he
+ exact ⟨t, s', he, abiPreserved_of_exec (by lit_decide) he ha, hp⟩
+
+theorem decrypt_correct (s : State) (hs : (blockContract .decrypt).pre s) :
+ ∃ t s', Exec isa decryptBlock s t s' ∧ abiPreserved s s' ∧
+ (blockContract .decrypt).post s s' := by
+ obtain ⟨t, s', he, ha, hp⟩ := block_gprCorrect .decrypt s hs
+ change Exec isa decryptBlock s t s' at he
+ exact ⟨t, s', he, abiPreserved_of_exec (by lit_decide) he ha, hp⟩
+
+def satState : State where
+ gpr r := match r with
+ | .rdi => 0x1000 | .rsi => 0x2000 | .rdx => 0x3000 | .rsp => 0x4000 | _ => 0
+ cf := none
+ zf := none
+ sf := none
+ of := none
+ mem _ := 0
+ rd := [⟨0x1000, 384⟩]
+ wr := [⟨0x2000, 8⟩, ⟨0x3000, 512⟩]
+
+theorem publicRegs_three (s t : State) : PublicRegs [.rdi, .rsi, .rdx] s t ↔
+ s.gpr .rdi = t.gpr .rdi ∧ s.gpr .rsi = t.gpr .rsi ∧ s.gpr .rdx = t.gpr .rdx := by
+ simp [PublicRegs]
+
+theorem encrypt_verified : Verified target encryptBlock (Spec.TripleDes.encryptBlockContract abi) := by
+ refine Verified.of_correct encrypt_correct
+ (encryptBlock_constantTime _ _ (blockTaint_agree .encrypt)) ?_
+ sig_implies [Spec.TripleDes.encryptBlockContract, Spec.TripleDes.blockSig, abi, argRegs,
+ blockContract, publicRegs_three, blockResult] [satState] using satState
+
+theorem decrypt_verified : Verified target decryptBlock (Spec.TripleDes.decryptBlockContract abi) := by
+ refine Verified.of_correct decrypt_correct
+ (decryptBlock_constantTime _ _ (blockTaint_agree .decrypt)) ?_
+ sig_implies [Spec.TripleDes.decryptBlockContract, Spec.TripleDes.blockSig, abi, argRegs,
+ blockContract, publicRegs_three, blockResult] [satState] using satState
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbage/Proof/TripleDes/X86_64/WordState.lean b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/WordState.lean
new file mode 100644
index 000000000..bf34dfc65
--- /dev/null
+++ b/lean/VerifiedGarbage/Proof/TripleDes/X86_64/WordState.lean
@@ -0,0 +1,28 @@
+import VerifiedGarbage.Proof.TripleDes.X86_64.Pass
+import VerifiedGarbage.Proof.TripleDes.Word
+
+namespace VG.Proof.TripleDes.X86_64
+
+open VG VG.X86_64 VG.Impl.TripleDes.X86_64
+open VG.Proof.TripleDes (desCore roundPrefix)
+
+/-- A DES word held as two zero-extended 32-bit Feistel registers. -/
+structure WordState (x : BitVec 64) (s : State) : Prop where
+ left : s.gpr .r12 = ((x >>> 32).setWidth 32).setWidth 64
+ right : s.gpr .r13 = (x.setWidth 32).setWidth 64
+
+theorem PassPost.wordState {keys : Spec.TripleDes.DesSchedule}
+ {direction : Spec.TripleDes.Direction} {origin s : State} {x : BitVec 64}
+ (hs : PassPost keys direction origin ((x >>> 32).setWidth 32, x.setWidth 32) s) :
+ WordState (desCore keys direction x) s := by
+ have hcore := VG.Proof.TripleDes.desCore_roundPrefix keys direction x
+ let halves := roundPrefix keys direction 16 ((x >>> 32).setWidth 32, x.setWidth 32)
+ have hleft : ((desCore keys direction x >>> 32).setWidth 32).setWidth 64 = halves.2.setWidth 64 :=
+ (congrArg (fun v : BitVec 64 => ((v >>> 32).setWidth 32).setWidth 64) hcore).trans
+ (congrArg (BitVec.setWidth 64) (VG.Proof.TripleDes.appended_left halves.2 halves.1))
+ have hright : ((desCore keys direction x).setWidth 32).setWidth 64 = halves.1.setWidth 64 :=
+ (congrArg (fun v : BitVec 64 => (v.setWidth 32).setWidth 64) hcore).trans
+ (congrArg (BitVec.setWidth 64) (VG.Proof.TripleDes.appended_right halves.2 halves.1))
+ exact ⟨hs.left.trans hleft.symm, hs.right.trans hright.symm⟩
+
+end VG.Proof.TripleDes.X86_64
diff --git a/lean/VerifiedGarbageTest/X86_64TripleDes.lean b/lean/VerifiedGarbageTest/X86_64TripleDes.lean
new file mode 100644
index 000000000..0d6189302
--- /dev/null
+++ b/lean/VerifiedGarbageTest/X86_64TripleDes.lean
@@ -0,0 +1,82 @@
+import VerifiedGarbage.Impl.TripleDes.X86_64.ExpandKey
+import VerifiedGarbage.Impl.TripleDes.X86_64.Ecb
+import VerifiedGarbage.Proof.Framework.X86_64.Exec
+import VerifiedGarbageTest.TripleDes
+
+/-! Model-level smoke checks of the complete scalar functions, using the
+published NIST files. Functional proofs and Rust vector tests accompany the
+final artifacts; this catches code-generation mistakes during development. -/
+
+namespace VG.Test.X86_64TripleDes
+
+open VG VG.X86_64
+
+/-- A bounded interpreter for model smoke tests, omitting leakage traces. -/
+def evaluate : Nat → Prog isa → State → Option State
+ | 0, _, _ => none
+ | _ + 1, .block is, s => runBlock isa is s
+ | fuel + 1, .seq a b, s => (evaluate fuel a s).bind (evaluate fuel b)
+ | fuel + 1, .ite c a b, s => do
+ let taken ← isa.eval c s
+ evaluate fuel (if taken then a else b) s
+ | fuel + 1, .loop body c, s => do
+ let s' ← evaluate fuel body s
+ let again ← isa.eval c s'
+ if again then evaluate fuel (.loop body c) s' else some s'
+ | fuel + 1, .call _ body, s => do
+ let s₁ ← isa.call s
+ let s₂ ← evaluate fuel body s₁
+ isa.ret s s₂
+ | fuel + 1, .frame push body pop, s => do
+ let s₁ ← isa.push push s
+ let s₂ ← evaluate fuel body s₁
+ isa.pop pop s s₂
+
+def initial (key input : List Byte) : State where
+ gpr r := if r = .rdi then 0x1000 else if r = .rsi then BitVec.ofNat 64 key.length
+ else if r = .rdx then 0x2000 else if r = .rcx then 0x3000 else if r = .rsp then 0x6000 else 0
+ cf := none
+ zf := none
+ sf := none
+ of := none
+ mem a := if 0x1000 ≤ a.toNat ∧ a.toNat < 0x1000 + key.length then
+ key.getD (a.toNat - 0x1000) 0
+ else if 0x4000 ≤ a.toNat ∧ a.toNat < 0x4000 + input.length then
+ input.getD (a.toNat - 0x4000) 0 else 0
+ rd := [⟨0x1000, key.length⟩]
+ wr := [⟨0x2000, 384⟩, ⟨0x3000, 1024⟩, ⟨0x4000, input.length⟩, ⟨0x5000, 4096⟩]
+
+def checkCase (key pt ct : List Byte) : Except String Unit := do
+ let some s := evaluate 128 Impl.TripleDes.X86_64.Key.expandKey (initial key pt)
+ | throw "key expansion faulted"
+ unless Spec.TripleDes.scheduleAt s.mem 0x2000 == Spec.TripleDes.expandKey key do
+ throw "key expansion differs from the specification"
+ let enc := (s.setReg .rdi 0x2000).setReg .rsi 0x4000 |>.setReg .rdx 0x3000
+ let some encrypted := evaluate 128 Impl.TripleDes.X86_64.encryptBlock enc
+ | throw "block encryption faulted"
+ unless Spec.TripleDes.bytesAt encrypted.mem 0x4000 pt.length == ct do
+ throw "block encryption differs from NIST"
+ let some decrypted := evaluate 128 Impl.TripleDes.X86_64.decryptBlock encrypted
+ | throw "block decryption faulted"
+ unless Spec.TripleDes.bytesAt decrypted.mem 0x4000 pt.length == pt do
+ throw "block decryption differs from NIST"
+
+run_cmd do
+ let file ← IO.FS.realPath (← Lean.getFileName)
+ let some root := file.parent >>= (·.parent) >>= (·.parent)
+ | throwError "no repository root"
+ let text ← IO.FS.readFile (root / "vectors" / "nist-cavp-tdes-mmt" / "TECBMMT3.rsp")
+ let record := ((text.replace "\r" "" |>.splitOn "COUNT = ").drop 1).headD ""
+ let fs := TripleDes.fields ((record.splitOn "\n\n").headD "")
+ let result := do
+ let a ← TripleDes.unhex (← TripleDes.get fs "KEY1")
+ let b ← TripleDes.unhex (← TripleDes.get fs "KEY2")
+ let c ← TripleDes.unhex (← TripleDes.get fs "KEY3")
+ let pt ← TripleDes.unhex (← TripleDes.get fs "PLAINTEXT")
+ let ct ← TripleDes.unhex (← TripleDes.get fs "CIPHERTEXT")
+ checkCase (a ++ b ++ c) pt ct
+ match result with
+ | .ok () => pure ()
+ | .error e => throwError "x86-64 Triple DES: {e}"
+
+end VG.Test.X86_64TripleDes
diff --git a/src/asm/x86_64/mod.rs b/src/asm/x86_64/mod.rs
index 7816e4666..84ea4f175 100644
--- a/src/asm/x86_64/mod.rs
+++ b/src/asm/x86_64/mod.rs
@@ -121,6 +121,9 @@ pub(crate) mod sha3;
#[rustfmt::skip]
pub(crate) mod sha512;
+#[rustfmt::skip]
+pub(crate) mod triple_des;
+
#[rustfmt::skip]
pub(crate) mod x25519;
diff --git a/src/asm/x86_64/triple_des.rs b/src/asm/x86_64/triple_des.rs
new file mode 100644
index 000000000..6f00a3dbf
--- /dev/null
+++ b/src/asm/x86_64/triple_des.rs
@@ -0,0 +1,13244 @@
+// @generated from lean/VerifiedGarbage/Artifacts.lean by lean/Emit.lean. DO NOT EDIT.
+//! Verified `triple_des` functions for `x86_64`.
+#![allow(dead_code)]
+
+/// Triple DES key expansion (FIPS 46-3 Appendix 1): expands a 16- or 24-byte key into three encryption-order DES schedules, each containing sixteen 48-bit round keys zero-extended into little-endian 64-bit slots. For a 16-byte key, K3 repeats K1. Parity bits are ignored and weak or repeated component keys are accepted.
+///
+/// Contract: `VG.Spec.TripleDes.expandKeyContract`. Constant time: only pointers and `key_len` may affect timing, not key bytes.
+///
+/// Baseline x86-64 scalar key expansion with fixed permutations and public round-count branches.
+///
+/// # Safety
+///
+/// * `key` must be valid for reads of `key_len` bytes.
+/// * `schedule` must be valid for reads and writes of 384 bytes.
+/// * `scratch` must be valid for reads and writes of 512 bytes.
+/// * `key_len` must be 16 or 24.
+/// * The contents of `scratch` on return are unspecified.
+/// * `schedule` and `scratch` must not overlap each other or `key` (distinct Rust objects never do).
+/// * None of `key`, `schedule` and `scratch` may overlap the return address on the stack, or wrap around the end of the address space (no Rust object does).
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_triple_des_expand_key(key: *const u8, key_len: usize, schedule: *mut [u8; 384], scratch: *mut [u64; 64]) {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rcx], rbx",
+ "mov QWORD PTR [rcx+8], rbp",
+ "mov QWORD PTR [rcx+16], r12",
+ "mov QWORD PTR [rcx+24], r13",
+ "mov QWORD PTR [rcx+32], r14",
+ "mov QWORD PTR [rcx+40], r15",
+ "mov rax, QWORD PTR [rdi]",
+ "bswap rax",
+ "mov rbx, 0",
+ "mov rbp, rax",
+ "shr rbp, 7",
+ "and rbp, 1",
+ "ror rbp, 9",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 15",
+ "and rbp, 1",
+ "ror rbp, 10",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 23",
+ "and rbp, 1",
+ "ror rbp, 11",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 31",
+ "and rbp, 1",
+ "ror rbp, 12",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 39",
+ "and rbp, 1",
+ "ror rbp, 13",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 47",
+ "and rbp, 1",
+ "ror rbp, 14",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 55",
+ "and rbp, 1",
+ "ror rbp, 15",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 63",
+ "and rbp, 1",
+ "ror rbp, 16",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 6",
+ "and rbp, 1",
+ "ror rbp, 17",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 14",
+ "and rbp, 1",
+ "ror rbp, 18",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 22",
+ "and rbp, 1",
+ "ror rbp, 19",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 30",
+ "and rbp, 1",
+ "ror rbp, 20",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 38",
+ "and rbp, 1",
+ "ror rbp, 21",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 46",
+ "and rbp, 1",
+ "ror rbp, 22",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 54",
+ "and rbp, 1",
+ "ror rbp, 23",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 62",
+ "and rbp, 1",
+ "ror rbp, 24",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 5",
+ "and rbp, 1",
+ "ror rbp, 25",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 13",
+ "and rbp, 1",
+ "ror rbp, 26",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 21",
+ "and rbp, 1",
+ "ror rbp, 27",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 29",
+ "and rbp, 1",
+ "ror rbp, 28",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 37",
+ "and rbp, 1",
+ "ror rbp, 29",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 45",
+ "and rbp, 1",
+ "ror rbp, 30",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 53",
+ "and rbp, 1",
+ "ror rbp, 31",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 61",
+ "and rbp, 1",
+ "ror rbp, 32",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 4",
+ "and rbp, 1",
+ "ror rbp, 33",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 12",
+ "and rbp, 1",
+ "ror rbp, 34",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 20",
+ "and rbp, 1",
+ "ror rbp, 35",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 28",
+ "and rbp, 1",
+ "ror rbp, 36",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 1",
+ "and rbp, 1",
+ "ror rbp, 37",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 9",
+ "and rbp, 1",
+ "ror rbp, 38",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 17",
+ "and rbp, 1",
+ "ror rbp, 39",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 25",
+ "and rbp, 1",
+ "ror rbp, 40",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 33",
+ "and rbp, 1",
+ "ror rbp, 41",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 41",
+ "and rbp, 1",
+ "ror rbp, 42",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 49",
+ "and rbp, 1",
+ "ror rbp, 43",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 57",
+ "and rbp, 1",
+ "ror rbp, 44",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 2",
+ "and rbp, 1",
+ "ror rbp, 45",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 10",
+ "and rbp, 1",
+ "ror rbp, 46",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 18",
+ "and rbp, 1",
+ "ror rbp, 47",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 26",
+ "and rbp, 1",
+ "ror rbp, 48",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 34",
+ "and rbp, 1",
+ "ror rbp, 49",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 42",
+ "and rbp, 1",
+ "ror rbp, 50",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 50",
+ "and rbp, 1",
+ "ror rbp, 51",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 58",
+ "and rbp, 1",
+ "ror rbp, 52",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 3",
+ "and rbp, 1",
+ "ror rbp, 53",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 11",
+ "and rbp, 1",
+ "ror rbp, 54",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 19",
+ "and rbp, 1",
+ "ror rbp, 55",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 27",
+ "and rbp, 1",
+ "ror rbp, 56",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 35",
+ "and rbp, 1",
+ "ror rbp, 57",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 43",
+ "and rbp, 1",
+ "ror rbp, 58",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 51",
+ "and rbp, 1",
+ "ror rbp, 59",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 59",
+ "and rbp, 1",
+ "ror rbp, 60",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 36",
+ "and rbp, 1",
+ "ror rbp, 61",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 44",
+ "and rbp, 1",
+ "ror rbp, 62",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 52",
+ "and rbp, 1",
+ "ror rbp, 63",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 60",
+ "and rbp, 1",
+ "xor rbx, rbp",
+ "mov r12, rbx",
+ "shr r12, 28",
+ "mov r13, rbx",
+ "and r13, 268435455",
+ "mov r14, 0",
+ "mov r15, rdx",
+ "add r15, 0",
+ "20:",
+ "cmp r14, 2",
+ "jb 21f",
+ "cmp r14, 8",
+ "je 23f",
+ "cmp r14, 15",
+ "je 25f",
+ "mov rax, r12",
+ "shr rax, 26",
+ "ror r12, 62",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 26",
+ "ror r13, 62",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "jmp 26f",
+ "25:",
+ "mov rax, r12",
+ "shr rax, 27",
+ "ror r12, 63",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 27",
+ "ror r13, 63",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "26:",
+ "jmp 24f",
+ "23:",
+ "mov rax, r12",
+ "shr rax, 27",
+ "ror r12, 63",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 27",
+ "ror r13, 63",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "24:",
+ "jmp 22f",
+ "21:",
+ "mov rax, r12",
+ "shr rax, 27",
+ "ror r12, 63",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 27",
+ "ror r13, 63",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "22:",
+ "mov rax, r12",
+ "ror rax, 36",
+ "xor rax, r13",
+ "mov rbx, 0",
+ "mov rbp, rax",
+ "shr rbp, 42",
+ "and rbp, 1",
+ "ror rbp, 17",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 39",
+ "and rbp, 1",
+ "ror rbp, 18",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 45",
+ "and rbp, 1",
+ "ror rbp, 19",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 32",
+ "and rbp, 1",
+ "ror rbp, 20",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 55",
+ "and rbp, 1",
+ "ror rbp, 21",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 51",
+ "and rbp, 1",
+ "ror rbp, 22",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 53",
+ "and rbp, 1",
+ "ror rbp, 23",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 28",
+ "and rbp, 1",
+ "ror rbp, 24",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 41",
+ "and rbp, 1",
+ "ror rbp, 25",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 50",
+ "and rbp, 1",
+ "ror rbp, 26",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 35",
+ "and rbp, 1",
+ "ror rbp, 27",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 46",
+ "and rbp, 1",
+ "ror rbp, 28",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 33",
+ "and rbp, 1",
+ "ror rbp, 29",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 37",
+ "and rbp, 1",
+ "ror rbp, 30",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 44",
+ "and rbp, 1",
+ "ror rbp, 31",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 52",
+ "and rbp, 1",
+ "ror rbp, 32",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 30",
+ "and rbp, 1",
+ "ror rbp, 33",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 48",
+ "and rbp, 1",
+ "ror rbp, 34",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 40",
+ "and rbp, 1",
+ "ror rbp, 35",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 49",
+ "and rbp, 1",
+ "ror rbp, 36",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 29",
+ "and rbp, 1",
+ "ror rbp, 37",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 36",
+ "and rbp, 1",
+ "ror rbp, 38",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 43",
+ "and rbp, 1",
+ "ror rbp, 39",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 54",
+ "and rbp, 1",
+ "ror rbp, 40",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 15",
+ "and rbp, 1",
+ "ror rbp, 41",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 4",
+ "and rbp, 1",
+ "ror rbp, 42",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 25",
+ "and rbp, 1",
+ "ror rbp, 43",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 19",
+ "and rbp, 1",
+ "ror rbp, 44",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 9",
+ "and rbp, 1",
+ "ror rbp, 45",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 1",
+ "and rbp, 1",
+ "ror rbp, 46",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 26",
+ "and rbp, 1",
+ "ror rbp, 47",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 16",
+ "and rbp, 1",
+ "ror rbp, 48",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 5",
+ "and rbp, 1",
+ "ror rbp, 49",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 11",
+ "and rbp, 1",
+ "ror rbp, 50",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 23",
+ "and rbp, 1",
+ "ror rbp, 51",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 8",
+ "and rbp, 1",
+ "ror rbp, 52",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 12",
+ "and rbp, 1",
+ "ror rbp, 53",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 7",
+ "and rbp, 1",
+ "ror rbp, 54",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 17",
+ "and rbp, 1",
+ "ror rbp, 55",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "and rbp, 1",
+ "ror rbp, 56",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 22",
+ "and rbp, 1",
+ "ror rbp, 57",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 3",
+ "and rbp, 1",
+ "ror rbp, 58",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 10",
+ "and rbp, 1",
+ "ror rbp, 59",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 14",
+ "and rbp, 1",
+ "ror rbp, 60",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 6",
+ "and rbp, 1",
+ "ror rbp, 61",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 20",
+ "and rbp, 1",
+ "ror rbp, 62",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 27",
+ "and rbp, 1",
+ "ror rbp, 63",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 24",
+ "and rbp, 1",
+ "xor rbx, rbp",
+ "mov QWORD PTR [r15], rbx",
+ "add r15, 8",
+ "add r14, 1",
+ "cmp r14, 16",
+ "jne 20b",
+ "mov rax, QWORD PTR [rdi+8]",
+ "bswap rax",
+ "mov rbx, 0",
+ "mov rbp, rax",
+ "shr rbp, 7",
+ "and rbp, 1",
+ "ror rbp, 9",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 15",
+ "and rbp, 1",
+ "ror rbp, 10",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 23",
+ "and rbp, 1",
+ "ror rbp, 11",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 31",
+ "and rbp, 1",
+ "ror rbp, 12",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 39",
+ "and rbp, 1",
+ "ror rbp, 13",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 47",
+ "and rbp, 1",
+ "ror rbp, 14",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 55",
+ "and rbp, 1",
+ "ror rbp, 15",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 63",
+ "and rbp, 1",
+ "ror rbp, 16",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 6",
+ "and rbp, 1",
+ "ror rbp, 17",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 14",
+ "and rbp, 1",
+ "ror rbp, 18",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 22",
+ "and rbp, 1",
+ "ror rbp, 19",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 30",
+ "and rbp, 1",
+ "ror rbp, 20",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 38",
+ "and rbp, 1",
+ "ror rbp, 21",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 46",
+ "and rbp, 1",
+ "ror rbp, 22",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 54",
+ "and rbp, 1",
+ "ror rbp, 23",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 62",
+ "and rbp, 1",
+ "ror rbp, 24",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 5",
+ "and rbp, 1",
+ "ror rbp, 25",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 13",
+ "and rbp, 1",
+ "ror rbp, 26",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 21",
+ "and rbp, 1",
+ "ror rbp, 27",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 29",
+ "and rbp, 1",
+ "ror rbp, 28",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 37",
+ "and rbp, 1",
+ "ror rbp, 29",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 45",
+ "and rbp, 1",
+ "ror rbp, 30",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 53",
+ "and rbp, 1",
+ "ror rbp, 31",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 61",
+ "and rbp, 1",
+ "ror rbp, 32",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 4",
+ "and rbp, 1",
+ "ror rbp, 33",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 12",
+ "and rbp, 1",
+ "ror rbp, 34",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 20",
+ "and rbp, 1",
+ "ror rbp, 35",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 28",
+ "and rbp, 1",
+ "ror rbp, 36",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 1",
+ "and rbp, 1",
+ "ror rbp, 37",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 9",
+ "and rbp, 1",
+ "ror rbp, 38",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 17",
+ "and rbp, 1",
+ "ror rbp, 39",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 25",
+ "and rbp, 1",
+ "ror rbp, 40",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 33",
+ "and rbp, 1",
+ "ror rbp, 41",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 41",
+ "and rbp, 1",
+ "ror rbp, 42",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 49",
+ "and rbp, 1",
+ "ror rbp, 43",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 57",
+ "and rbp, 1",
+ "ror rbp, 44",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 2",
+ "and rbp, 1",
+ "ror rbp, 45",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 10",
+ "and rbp, 1",
+ "ror rbp, 46",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 18",
+ "and rbp, 1",
+ "ror rbp, 47",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 26",
+ "and rbp, 1",
+ "ror rbp, 48",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 34",
+ "and rbp, 1",
+ "ror rbp, 49",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 42",
+ "and rbp, 1",
+ "ror rbp, 50",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 50",
+ "and rbp, 1",
+ "ror rbp, 51",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 58",
+ "and rbp, 1",
+ "ror rbp, 52",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 3",
+ "and rbp, 1",
+ "ror rbp, 53",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 11",
+ "and rbp, 1",
+ "ror rbp, 54",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 19",
+ "and rbp, 1",
+ "ror rbp, 55",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 27",
+ "and rbp, 1",
+ "ror rbp, 56",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 35",
+ "and rbp, 1",
+ "ror rbp, 57",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 43",
+ "and rbp, 1",
+ "ror rbp, 58",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 51",
+ "and rbp, 1",
+ "ror rbp, 59",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 59",
+ "and rbp, 1",
+ "ror rbp, 60",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 36",
+ "and rbp, 1",
+ "ror rbp, 61",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 44",
+ "and rbp, 1",
+ "ror rbp, 62",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 52",
+ "and rbp, 1",
+ "ror rbp, 63",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 60",
+ "and rbp, 1",
+ "xor rbx, rbp",
+ "mov r12, rbx",
+ "shr r12, 28",
+ "mov r13, rbx",
+ "and r13, 268435455",
+ "mov r14, 0",
+ "mov r15, rdx",
+ "add r15, 128",
+ "27:",
+ "cmp r14, 2",
+ "jb 28f",
+ "cmp r14, 8",
+ "je 210f",
+ "cmp r14, 15",
+ "je 212f",
+ "mov rax, r12",
+ "shr rax, 26",
+ "ror r12, 62",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 26",
+ "ror r13, 62",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "jmp 213f",
+ "212:",
+ "mov rax, r12",
+ "shr rax, 27",
+ "ror r12, 63",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 27",
+ "ror r13, 63",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "213:",
+ "jmp 211f",
+ "210:",
+ "mov rax, r12",
+ "shr rax, 27",
+ "ror r12, 63",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 27",
+ "ror r13, 63",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "211:",
+ "jmp 29f",
+ "28:",
+ "mov rax, r12",
+ "shr rax, 27",
+ "ror r12, 63",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 27",
+ "ror r13, 63",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "29:",
+ "mov rax, r12",
+ "ror rax, 36",
+ "xor rax, r13",
+ "mov rbx, 0",
+ "mov rbp, rax",
+ "shr rbp, 42",
+ "and rbp, 1",
+ "ror rbp, 17",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 39",
+ "and rbp, 1",
+ "ror rbp, 18",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 45",
+ "and rbp, 1",
+ "ror rbp, 19",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 32",
+ "and rbp, 1",
+ "ror rbp, 20",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 55",
+ "and rbp, 1",
+ "ror rbp, 21",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 51",
+ "and rbp, 1",
+ "ror rbp, 22",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 53",
+ "and rbp, 1",
+ "ror rbp, 23",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 28",
+ "and rbp, 1",
+ "ror rbp, 24",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 41",
+ "and rbp, 1",
+ "ror rbp, 25",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 50",
+ "and rbp, 1",
+ "ror rbp, 26",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 35",
+ "and rbp, 1",
+ "ror rbp, 27",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 46",
+ "and rbp, 1",
+ "ror rbp, 28",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 33",
+ "and rbp, 1",
+ "ror rbp, 29",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 37",
+ "and rbp, 1",
+ "ror rbp, 30",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 44",
+ "and rbp, 1",
+ "ror rbp, 31",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 52",
+ "and rbp, 1",
+ "ror rbp, 32",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 30",
+ "and rbp, 1",
+ "ror rbp, 33",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 48",
+ "and rbp, 1",
+ "ror rbp, 34",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 40",
+ "and rbp, 1",
+ "ror rbp, 35",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 49",
+ "and rbp, 1",
+ "ror rbp, 36",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 29",
+ "and rbp, 1",
+ "ror rbp, 37",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 36",
+ "and rbp, 1",
+ "ror rbp, 38",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 43",
+ "and rbp, 1",
+ "ror rbp, 39",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 54",
+ "and rbp, 1",
+ "ror rbp, 40",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 15",
+ "and rbp, 1",
+ "ror rbp, 41",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 4",
+ "and rbp, 1",
+ "ror rbp, 42",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 25",
+ "and rbp, 1",
+ "ror rbp, 43",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 19",
+ "and rbp, 1",
+ "ror rbp, 44",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 9",
+ "and rbp, 1",
+ "ror rbp, 45",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 1",
+ "and rbp, 1",
+ "ror rbp, 46",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 26",
+ "and rbp, 1",
+ "ror rbp, 47",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 16",
+ "and rbp, 1",
+ "ror rbp, 48",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 5",
+ "and rbp, 1",
+ "ror rbp, 49",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 11",
+ "and rbp, 1",
+ "ror rbp, 50",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 23",
+ "and rbp, 1",
+ "ror rbp, 51",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 8",
+ "and rbp, 1",
+ "ror rbp, 52",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 12",
+ "and rbp, 1",
+ "ror rbp, 53",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 7",
+ "and rbp, 1",
+ "ror rbp, 54",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 17",
+ "and rbp, 1",
+ "ror rbp, 55",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "and rbp, 1",
+ "ror rbp, 56",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 22",
+ "and rbp, 1",
+ "ror rbp, 57",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 3",
+ "and rbp, 1",
+ "ror rbp, 58",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 10",
+ "and rbp, 1",
+ "ror rbp, 59",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 14",
+ "and rbp, 1",
+ "ror rbp, 60",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 6",
+ "and rbp, 1",
+ "ror rbp, 61",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 20",
+ "and rbp, 1",
+ "ror rbp, 62",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 27",
+ "and rbp, 1",
+ "ror rbp, 63",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 24",
+ "and rbp, 1",
+ "xor rbx, rbp",
+ "mov QWORD PTR [r15], rbx",
+ "add r15, 8",
+ "add r14, 1",
+ "cmp r14, 16",
+ "jne 27b",
+ "cmp rsi, 16",
+ "je 214f",
+ "mov rax, QWORD PTR [rdi+16]",
+ "bswap rax",
+ "mov rbx, 0",
+ "mov rbp, rax",
+ "shr rbp, 7",
+ "and rbp, 1",
+ "ror rbp, 9",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 15",
+ "and rbp, 1",
+ "ror rbp, 10",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 23",
+ "and rbp, 1",
+ "ror rbp, 11",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 31",
+ "and rbp, 1",
+ "ror rbp, 12",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 39",
+ "and rbp, 1",
+ "ror rbp, 13",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 47",
+ "and rbp, 1",
+ "ror rbp, 14",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 55",
+ "and rbp, 1",
+ "ror rbp, 15",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 63",
+ "and rbp, 1",
+ "ror rbp, 16",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 6",
+ "and rbp, 1",
+ "ror rbp, 17",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 14",
+ "and rbp, 1",
+ "ror rbp, 18",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 22",
+ "and rbp, 1",
+ "ror rbp, 19",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 30",
+ "and rbp, 1",
+ "ror rbp, 20",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 38",
+ "and rbp, 1",
+ "ror rbp, 21",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 46",
+ "and rbp, 1",
+ "ror rbp, 22",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 54",
+ "and rbp, 1",
+ "ror rbp, 23",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 62",
+ "and rbp, 1",
+ "ror rbp, 24",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 5",
+ "and rbp, 1",
+ "ror rbp, 25",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 13",
+ "and rbp, 1",
+ "ror rbp, 26",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 21",
+ "and rbp, 1",
+ "ror rbp, 27",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 29",
+ "and rbp, 1",
+ "ror rbp, 28",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 37",
+ "and rbp, 1",
+ "ror rbp, 29",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 45",
+ "and rbp, 1",
+ "ror rbp, 30",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 53",
+ "and rbp, 1",
+ "ror rbp, 31",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 61",
+ "and rbp, 1",
+ "ror rbp, 32",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 4",
+ "and rbp, 1",
+ "ror rbp, 33",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 12",
+ "and rbp, 1",
+ "ror rbp, 34",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 20",
+ "and rbp, 1",
+ "ror rbp, 35",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 28",
+ "and rbp, 1",
+ "ror rbp, 36",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 1",
+ "and rbp, 1",
+ "ror rbp, 37",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 9",
+ "and rbp, 1",
+ "ror rbp, 38",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 17",
+ "and rbp, 1",
+ "ror rbp, 39",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 25",
+ "and rbp, 1",
+ "ror rbp, 40",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 33",
+ "and rbp, 1",
+ "ror rbp, 41",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 41",
+ "and rbp, 1",
+ "ror rbp, 42",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 49",
+ "and rbp, 1",
+ "ror rbp, 43",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 57",
+ "and rbp, 1",
+ "ror rbp, 44",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 2",
+ "and rbp, 1",
+ "ror rbp, 45",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 10",
+ "and rbp, 1",
+ "ror rbp, 46",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 18",
+ "and rbp, 1",
+ "ror rbp, 47",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 26",
+ "and rbp, 1",
+ "ror rbp, 48",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 34",
+ "and rbp, 1",
+ "ror rbp, 49",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 42",
+ "and rbp, 1",
+ "ror rbp, 50",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 50",
+ "and rbp, 1",
+ "ror rbp, 51",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 58",
+ "and rbp, 1",
+ "ror rbp, 52",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 3",
+ "and rbp, 1",
+ "ror rbp, 53",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 11",
+ "and rbp, 1",
+ "ror rbp, 54",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 19",
+ "and rbp, 1",
+ "ror rbp, 55",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 27",
+ "and rbp, 1",
+ "ror rbp, 56",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 35",
+ "and rbp, 1",
+ "ror rbp, 57",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 43",
+ "and rbp, 1",
+ "ror rbp, 58",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 51",
+ "and rbp, 1",
+ "ror rbp, 59",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 59",
+ "and rbp, 1",
+ "ror rbp, 60",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 36",
+ "and rbp, 1",
+ "ror rbp, 61",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 44",
+ "and rbp, 1",
+ "ror rbp, 62",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 52",
+ "and rbp, 1",
+ "ror rbp, 63",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 60",
+ "and rbp, 1",
+ "xor rbx, rbp",
+ "mov r12, rbx",
+ "shr r12, 28",
+ "mov r13, rbx",
+ "and r13, 268435455",
+ "mov r14, 0",
+ "mov r15, rdx",
+ "add r15, 256",
+ "216:",
+ "cmp r14, 2",
+ "jb 217f",
+ "cmp r14, 8",
+ "je 219f",
+ "cmp r14, 15",
+ "je 221f",
+ "mov rax, r12",
+ "shr rax, 26",
+ "ror r12, 62",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 26",
+ "ror r13, 62",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "jmp 222f",
+ "221:",
+ "mov rax, r12",
+ "shr rax, 27",
+ "ror r12, 63",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 27",
+ "ror r13, 63",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "222:",
+ "jmp 220f",
+ "219:",
+ "mov rax, r12",
+ "shr rax, 27",
+ "ror r12, 63",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 27",
+ "ror r13, 63",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "220:",
+ "jmp 218f",
+ "217:",
+ "mov rax, r12",
+ "shr rax, 27",
+ "ror r12, 63",
+ "xor r12, rax",
+ "and r12, 268435455",
+ "mov rax, r13",
+ "shr rax, 27",
+ "ror r13, 63",
+ "xor r13, rax",
+ "and r13, 268435455",
+ "218:",
+ "mov rax, r12",
+ "ror rax, 36",
+ "xor rax, r13",
+ "mov rbx, 0",
+ "mov rbp, rax",
+ "shr rbp, 42",
+ "and rbp, 1",
+ "ror rbp, 17",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 39",
+ "and rbp, 1",
+ "ror rbp, 18",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 45",
+ "and rbp, 1",
+ "ror rbp, 19",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 32",
+ "and rbp, 1",
+ "ror rbp, 20",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 55",
+ "and rbp, 1",
+ "ror rbp, 21",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 51",
+ "and rbp, 1",
+ "ror rbp, 22",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 53",
+ "and rbp, 1",
+ "ror rbp, 23",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 28",
+ "and rbp, 1",
+ "ror rbp, 24",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 41",
+ "and rbp, 1",
+ "ror rbp, 25",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 50",
+ "and rbp, 1",
+ "ror rbp, 26",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 35",
+ "and rbp, 1",
+ "ror rbp, 27",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 46",
+ "and rbp, 1",
+ "ror rbp, 28",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 33",
+ "and rbp, 1",
+ "ror rbp, 29",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 37",
+ "and rbp, 1",
+ "ror rbp, 30",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 44",
+ "and rbp, 1",
+ "ror rbp, 31",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 52",
+ "and rbp, 1",
+ "ror rbp, 32",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 30",
+ "and rbp, 1",
+ "ror rbp, 33",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 48",
+ "and rbp, 1",
+ "ror rbp, 34",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 40",
+ "and rbp, 1",
+ "ror rbp, 35",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 49",
+ "and rbp, 1",
+ "ror rbp, 36",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 29",
+ "and rbp, 1",
+ "ror rbp, 37",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 36",
+ "and rbp, 1",
+ "ror rbp, 38",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 43",
+ "and rbp, 1",
+ "ror rbp, 39",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 54",
+ "and rbp, 1",
+ "ror rbp, 40",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 15",
+ "and rbp, 1",
+ "ror rbp, 41",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 4",
+ "and rbp, 1",
+ "ror rbp, 42",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 25",
+ "and rbp, 1",
+ "ror rbp, 43",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 19",
+ "and rbp, 1",
+ "ror rbp, 44",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 9",
+ "and rbp, 1",
+ "ror rbp, 45",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 1",
+ "and rbp, 1",
+ "ror rbp, 46",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 26",
+ "and rbp, 1",
+ "ror rbp, 47",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 16",
+ "and rbp, 1",
+ "ror rbp, 48",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 5",
+ "and rbp, 1",
+ "ror rbp, 49",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 11",
+ "and rbp, 1",
+ "ror rbp, 50",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 23",
+ "and rbp, 1",
+ "ror rbp, 51",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 8",
+ "and rbp, 1",
+ "ror rbp, 52",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 12",
+ "and rbp, 1",
+ "ror rbp, 53",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 7",
+ "and rbp, 1",
+ "ror rbp, 54",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 17",
+ "and rbp, 1",
+ "ror rbp, 55",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "and rbp, 1",
+ "ror rbp, 56",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 22",
+ "and rbp, 1",
+ "ror rbp, 57",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 3",
+ "and rbp, 1",
+ "ror rbp, 58",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 10",
+ "and rbp, 1",
+ "ror rbp, 59",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 14",
+ "and rbp, 1",
+ "ror rbp, 60",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 6",
+ "and rbp, 1",
+ "ror rbp, 61",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 20",
+ "and rbp, 1",
+ "ror rbp, 62",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 27",
+ "and rbp, 1",
+ "ror rbp, 63",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 24",
+ "and rbp, 1",
+ "xor rbx, rbp",
+ "mov QWORD PTR [r15], rbx",
+ "add r15, 8",
+ "add r14, 1",
+ "cmp r14, 16",
+ "jne 216b",
+ "jmp 215f",
+ "214:",
+ "mov rax, QWORD PTR [rdx]",
+ "mov QWORD PTR [rdx+256], rax",
+ "mov rax, QWORD PTR [rdx+8]",
+ "mov QWORD PTR [rdx+264], rax",
+ "mov rax, QWORD PTR [rdx+16]",
+ "mov QWORD PTR [rdx+272], rax",
+ "mov rax, QWORD PTR [rdx+24]",
+ "mov QWORD PTR [rdx+280], rax",
+ "mov rax, QWORD PTR [rdx+32]",
+ "mov QWORD PTR [rdx+288], rax",
+ "mov rax, QWORD PTR [rdx+40]",
+ "mov QWORD PTR [rdx+296], rax",
+ "mov rax, QWORD PTR [rdx+48]",
+ "mov QWORD PTR [rdx+304], rax",
+ "mov rax, QWORD PTR [rdx+56]",
+ "mov QWORD PTR [rdx+312], rax",
+ "mov rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+320], rax",
+ "mov rax, QWORD PTR [rdx+72]",
+ "mov QWORD PTR [rdx+328], rax",
+ "mov rax, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+336], rax",
+ "mov rax, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+344], rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "mov QWORD PTR [rdx+352], rax",
+ "mov rax, QWORD PTR [rdx+104]",
+ "mov QWORD PTR [rdx+360], rax",
+ "mov rax, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+368], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+376], rax",
+ "215:",
+ "mov rbx, QWORD PTR [rcx]",
+ "mov rbp, QWORD PTR [rcx+8]",
+ "mov r12, QWORD PTR [rcx+16]",
+ "mov r13, QWORD PTR [rcx+24]",
+ "mov r14, QWORD PTR [rcx+32]",
+ "mov r15, QWORD PTR [rcx+40]",
+ "ret",
+ )
+}
+
+/// Triple DES block encryption (FIPS 46-3): transforms the 8 bytes at `data` in place under the three DES schedules at `schedule`. Each schedule contains sixteen encryption-order 48-bit round keys in little-endian 64-bit slots; upper bits are ignored.
+///
+/// Contract: `VG.Spec.TripleDes.encryptBlockContract`. Constant time: only pointers may affect timing, not the schedule or data, including S-box inputs.
+///
+/// Baseline x86-64 scalar Boolean S-box circuits; IP and FP shared across all three DES passes.
+///
+/// # Safety
+///
+/// * `schedule` must be valid for reads of 384 bytes.
+/// * `data` must be valid for reads and writes of 8 bytes.
+/// * `scratch` must be valid for reads and writes of 512 bytes.
+/// * The contents of `scratch` on return are unspecified.
+/// * `data` and `scratch` must not overlap each other or `schedule` (distinct Rust objects never do).
+/// * None of `schedule`, `data` and `scratch` may overlap the return address on the stack, or wrap around the end of the address space (no Rust object does).
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_triple_des_encrypt_block(schedule: *const [u8; 384], data: *mut [u8; 8], scratch: *mut [u64; 64]) {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rdx], rbx",
+ "mov QWORD PTR [rdx+8], rbp",
+ "mov QWORD PTR [rdx+16], r12",
+ "mov QWORD PTR [rdx+24], r13",
+ "mov QWORD PTR [rdx+32], r14",
+ "mov QWORD PTR [rdx+40], r15",
+ "mov QWORD PTR [rdx+48], rdi",
+ "mov rax, QWORD PTR [rsi]",
+ "bswap rax",
+ "mov rbx, 0",
+ "mov rbp, rax",
+ "shr rbp, 6",
+ "and rbp, 1",
+ "ror rbp, 1",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 14",
+ "and rbp, 1",
+ "ror rbp, 2",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 22",
+ "and rbp, 1",
+ "ror rbp, 3",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 30",
+ "and rbp, 1",
+ "ror rbp, 4",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 38",
+ "and rbp, 1",
+ "ror rbp, 5",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 46",
+ "and rbp, 1",
+ "ror rbp, 6",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 54",
+ "and rbp, 1",
+ "ror rbp, 7",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 62",
+ "and rbp, 1",
+ "ror rbp, 8",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 4",
+ "and rbp, 1",
+ "ror rbp, 9",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 12",
+ "and rbp, 1",
+ "ror rbp, 10",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 20",
+ "and rbp, 1",
+ "ror rbp, 11",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 28",
+ "and rbp, 1",
+ "ror rbp, 12",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 36",
+ "and rbp, 1",
+ "ror rbp, 13",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 44",
+ "and rbp, 1",
+ "ror rbp, 14",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 52",
+ "and rbp, 1",
+ "ror rbp, 15",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 60",
+ "and rbp, 1",
+ "ror rbp, 16",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 2",
+ "and rbp, 1",
+ "ror rbp, 17",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 10",
+ "and rbp, 1",
+ "ror rbp, 18",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 18",
+ "and rbp, 1",
+ "ror rbp, 19",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 26",
+ "and rbp, 1",
+ "ror rbp, 20",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 34",
+ "and rbp, 1",
+ "ror rbp, 21",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 42",
+ "and rbp, 1",
+ "ror rbp, 22",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 50",
+ "and rbp, 1",
+ "ror rbp, 23",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 58",
+ "and rbp, 1",
+ "ror rbp, 24",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "and rbp, 1",
+ "ror rbp, 25",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 8",
+ "and rbp, 1",
+ "ror rbp, 26",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 16",
+ "and rbp, 1",
+ "ror rbp, 27",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 24",
+ "and rbp, 1",
+ "ror rbp, 28",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 32",
+ "and rbp, 1",
+ "ror rbp, 29",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 40",
+ "and rbp, 1",
+ "ror rbp, 30",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 48",
+ "and rbp, 1",
+ "ror rbp, 31",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 56",
+ "and rbp, 1",
+ "ror rbp, 32",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 7",
+ "and rbp, 1",
+ "ror rbp, 33",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 15",
+ "and rbp, 1",
+ "ror rbp, 34",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 23",
+ "and rbp, 1",
+ "ror rbp, 35",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 31",
+ "and rbp, 1",
+ "ror rbp, 36",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 39",
+ "and rbp, 1",
+ "ror rbp, 37",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 47",
+ "and rbp, 1",
+ "ror rbp, 38",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 55",
+ "and rbp, 1",
+ "ror rbp, 39",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 63",
+ "and rbp, 1",
+ "ror rbp, 40",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 5",
+ "and rbp, 1",
+ "ror rbp, 41",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 13",
+ "and rbp, 1",
+ "ror rbp, 42",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 21",
+ "and rbp, 1",
+ "ror rbp, 43",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 29",
+ "and rbp, 1",
+ "ror rbp, 44",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 37",
+ "and rbp, 1",
+ "ror rbp, 45",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 45",
+ "and rbp, 1",
+ "ror rbp, 46",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 53",
+ "and rbp, 1",
+ "ror rbp, 47",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 61",
+ "and rbp, 1",
+ "ror rbp, 48",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 3",
+ "and rbp, 1",
+ "ror rbp, 49",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 11",
+ "and rbp, 1",
+ "ror rbp, 50",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 19",
+ "and rbp, 1",
+ "ror rbp, 51",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 27",
+ "and rbp, 1",
+ "ror rbp, 52",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 35",
+ "and rbp, 1",
+ "ror rbp, 53",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 43",
+ "and rbp, 1",
+ "ror rbp, 54",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 51",
+ "and rbp, 1",
+ "ror rbp, 55",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 59",
+ "and rbp, 1",
+ "ror rbp, 56",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 1",
+ "and rbp, 1",
+ "ror rbp, 57",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 9",
+ "and rbp, 1",
+ "ror rbp, 58",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 17",
+ "and rbp, 1",
+ "ror rbp, 59",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 25",
+ "and rbp, 1",
+ "ror rbp, 60",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 33",
+ "and rbp, 1",
+ "ror rbp, 61",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 41",
+ "and rbp, 1",
+ "ror rbp, 62",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 49",
+ "and rbp, 1",
+ "ror rbp, 63",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 57",
+ "and rbp, 1",
+ "xor rbx, rbp",
+ "mov r12, rbx",
+ "shr r12, 32",
+ "mov r13d, ebx",
+ "mov rdi, QWORD PTR [rdx+48]",
+ "add rdi, 0",
+ "mov rax, 16",
+ "mov QWORD PTR [rdx+56], rax",
+ "20:",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 27",
+ "mov rbp, rbx",
+ "shr rbp, 42",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 28",
+ "mov rbp, rbx",
+ "shr rbp, 43",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 29",
+ "mov rbp, rbx",
+ "shr rbp, 44",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 30",
+ "mov rbp, rbx",
+ "shr rbp, 45",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 31",
+ "mov rbp, rbx",
+ "shr rbp, 46",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "mov rbp, rbx",
+ "shr rbp, 47",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov r15, rax",
+ "xor r15, r10",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, rcx",
+ "and r8, r15",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, rcx",
+ "and r14, r15",
+ "xor r14, rax",
+ "and r14, r11",
+ "xor r8, r14",
+ "mov r14, r10",
+ "and r14, rax",
+ "mov QWORD PTR [rdx+96], rax",
+ "mov rax, r14",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rcx",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbx",
+ "mov rbx, r14",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+136], r15",
+ "mov r15, r11",
+ "and r15, rbx",
+ "xor rbp, r15",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "and r10, rcx",
+ "mov rbp, rax",
+ "xor rbp, r10",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, r15",
+ "and r10, r11",
+ "xor rbp, r10",
+ "mov r10, rcx",
+ "and r10, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, r10",
+ "and r14, r11",
+ "and r14, r9",
+ "xor rbp, r14",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r8, rbp",
+ "mov rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "mov r14, rbp",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor rbp, r8",
+ "mov QWORD PTR [rdx+112], rbx",
+ "mov rbx, r11",
+ "and rbx, rbp",
+ "xor r14, rbx",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r15, rbx",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r15",
+ "xor r10, rbx",
+ "and r10, r9",
+ "xor r14, r10",
+ "xor rbp, rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+96]",
+ "mov r10, r8",
+ "xor r10, rbx",
+ "and r10, r11",
+ "mov QWORD PTR [rdx+168], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "xor r8, r10",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r14, rbp",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, rbx",
+ "mov r8, r11",
+ "and r8, r15",
+ "xor rbp, r8",
+ "xor rax, QWORD PTR [rdx+88]",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+168]",
+ "and r8, r11",
+ "xor rax, r8",
+ "and rax, r9",
+ "xor rbp, rax",
+ "mov rax, r11",
+ "and rax, QWORD PTR [rdx+136]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, rbx",
+ "xor rax, r10",
+ "and rax, r9",
+ "xor r15, rax",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor rbp, r15",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+128]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "xor r15, rcx",
+ "mov rax, QWORD PTR [rdx+136]",
+ "xor rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r11",
+ "xor rax, r15",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r10, r11",
+ "xor r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor rax, r10",
+ "mov r10, QWORD PTR [rdx+104]",
+ "xor r10, QWORD PTR [rdx+144]",
+ "and r10, r11",
+ "xor rbx, r10",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and r11, rcx",
+ "xor r15, r11",
+ "and r9, r15",
+ "xor rbx, r9",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor rax, rbx",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r14",
+ "mov r8, rbp",
+ "mov r9, QWORD PTR [rdx+72]",
+ "and rax, 1",
+ "ror rax, 63",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 55",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 49",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 41",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 23",
+ "mov rbp, rbx",
+ "shr rbp, 36",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 24",
+ "mov rbp, rbx",
+ "shr rbp, 37",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 25",
+ "mov rbp, rbx",
+ "shr rbp, 38",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 26",
+ "mov rbp, rbx",
+ "shr rbp, 39",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 27",
+ "mov rbp, rbx",
+ "shr rbp, 40",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 28",
+ "mov rbp, rbx",
+ "shr rbp, 41",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r11",
+ "mov r11, rax",
+ "and r11, r8",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+88], rbp",
+ "mov rbp, r15",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, r10",
+ "xor r11, rbp",
+ "mov QWORD PTR [rdx+112], r15",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+120], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, rax",
+ "and r14, r8",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, rbp",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+144], r14",
+ "mov r14, rbp",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], rbp",
+ "mov rbp, rax",
+ "and rbp, r14",
+ "xor rbp, rcx",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "and r8, r9",
+ "xor r11, r8",
+ "mov r8, rax",
+ "and r8, r15",
+ "xor r8, QWORD PTR [rdx+88]",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+160], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rcx",
+ "xor r9, r15",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor r11, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, QWORD PTR [rdx+96]",
+ "mov r9, rbp",
+ "xor r9, r8",
+ "xor r15, QWORD PTR [rdx+136]",
+ "and r15, r10",
+ "xor r9, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+80]",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+104]",
+ "mov r15, rax",
+ "and r15, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, QWORD PTR [rdx+152]",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+152], r15",
+ "mov r15, r10",
+ "and r15, QWORD PTR [rdx+80]",
+ "xor r11, r15",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and r14, QWORD PTR [rdx+72]",
+ "xor r9, r14",
+ "mov r14, rbp",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, r8",
+ "and r11, r10",
+ "xor r11, rax",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and rax, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rax",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, QWORD PTR [rdx+112]",
+ "and r11, r10",
+ "xor rcx, r11",
+ "and rax, QWORD PTR [rdx+168]",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+72]",
+ "xor r14, rcx",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "mov rcx, r10",
+ "and rcx, QWORD PTR [rdx+144]",
+ "xor rbp, rcx",
+ "mov rcx, r8",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+168]",
+ "xor rbp, rcx",
+ "xor r8, QWORD PTR [rdx+160]",
+ "xor rbx, r8",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "and r10, rbx",
+ "xor r8, r10",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor rbp, r8",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r9",
+ "mov r8, r14",
+ "mov r9, rbp",
+ "and rax, 1",
+ "ror rax, 50",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 34",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 60",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 45",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 19",
+ "mov rbp, rbx",
+ "shr rbp, 30",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 20",
+ "mov rbp, rbx",
+ "shr rbp, 31",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 21",
+ "mov rbp, rbx",
+ "shr rbp, 32",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 22",
+ "mov rbp, rbx",
+ "shr rbp, 33",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 23",
+ "mov rbp, rbx",
+ "shr rbp, 34",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 24",
+ "mov rbp, rbx",
+ "shr rbp, 35",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r10",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r10",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r14",
+ "xor r10, r15",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, rax",
+ "and r14, r10",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+112], r8",
+ "mov r8, r10",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+120], rbx",
+ "mov rbx, r8",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+128], r8",
+ "mov r8, rcx",
+ "and r8, rbx",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+136], rbp",
+ "mov rbp, rcx",
+ "and rbp, r10",
+ "xor rbx, rbp",
+ "and rbx, r9",
+ "xor r8, rbx",
+ "and r11, rax",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, r11",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+96]",
+ "xor rbx, rbp",
+ "and r15, r9",
+ "xor rbx, r15",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r8, rbx",
+ "mov rbx, QWORD PTR [rdx+96]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "xor r14, rbx",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+120]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov rbp, rax",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+104], r8",
+ "mov r8, rcx",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, r14",
+ "xor r10, r8",
+ "mov QWORD PTR [rdx+152], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], r11",
+ "mov r11, rax",
+ "and r11, rbx",
+ "mov QWORD PTR [rdx+168], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, r11",
+ "mov QWORD PTR [rdx+88], r11",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+96]",
+ "mov QWORD PTR [rdx+176], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, r11",
+ "and r8, rcx",
+ "xor rbx, r8",
+ "and rbx, r9",
+ "xor r10, rbx",
+ "mov rbx, QWORD PTR [rdx+136]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "mov r14, QWORD PTR [rdx+112]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r15",
+ "xor r14, r8",
+ "mov QWORD PTR [rdx+96], r8",
+ "mov r8, r11",
+ "xor r8, QWORD PTR [rdx+120]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r8, rcx",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r10, rbx",
+ "mov rbx, rax",
+ "and rbx, r15",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "mov r14, rbp",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "and rbp, r9",
+ "xor rbx, rbp",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, QWORD PTR [rdx+88]",
+ "xor rbp, r8",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+80]",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, rcx",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rax, rbp",
+ "xor rax, QWORD PTR [rdx+168]",
+ "and rax, rcx",
+ "xor rax, QWORD PTR [rdx+144]",
+ "and rax, r9",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+112]",
+ "xor rax, r11",
+ "mov rbp, QWORD PTR [rdx+136]",
+ "xor rbp, QWORD PTR [rdx+96]",
+ "and rbp, rcx",
+ "xor rax, rbp",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+136]",
+ "and r9, rcx",
+ "xor rax, r9",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+104]",
+ "mov rcx, r10",
+ "mov r8, rbx",
+ "mov r9, r15",
+ "and rax, 1",
+ "ror rax, 38",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 62",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 48",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 56",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 15",
+ "mov rbp, rbx",
+ "shr rbp, 24",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 16",
+ "mov rbp, rbx",
+ "shr rbp, 25",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 17",
+ "mov rbp, rbx",
+ "shr rbp, 26",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 18",
+ "mov rbp, rbx",
+ "shr rbp, 27",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 19",
+ "mov rbp, rbx",
+ "shr rbp, 28",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 20",
+ "mov rbp, rbx",
+ "shr rbp, 29",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r9",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, r11",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+88], r15",
+ "mov r15, r14",
+ "xor r15, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, rbp",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r11",
+ "and r14, r9",
+ "mov QWORD PTR [rdx+120], r9",
+ "mov r9, rbp",
+ "xor r9, r14",
+ "and r9, r10",
+ "xor r15, r9",
+ "mov r9, rcx",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, rcx",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov QWORD PTR [rdx+144], rcx",
+ "mov rcx, r9",
+ "xor rcx, r14",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, rax",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+120]",
+ "and rcx, r10",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, QWORD PTR [rdx+80]",
+ "xor r9, r14",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r11",
+ "and rax, r9",
+ "xor rcx, rax",
+ "mov QWORD PTR [rdx+160], r9",
+ "mov r9, r10",
+ "and r9, QWORD PTR [rdx+128]",
+ "xor rcx, r9",
+ "and rcx, r8",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "and rcx, rbp",
+ "xor r15, rcx",
+ "mov rcx, r11",
+ "and rcx, r14",
+ "mov QWORD PTR [rdx+128], r15",
+ "mov r15, QWORD PTR [rdx+120]",
+ "xor r15, rcx",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "and r11, r10",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, r14",
+ "xor r9, rax",
+ "mov QWORD PTR [rdx+176], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, QWORD PTR [rdx+136]",
+ "and r14, r10",
+ "xor r9, r14",
+ "and r9, r8",
+ "xor r11, r9",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r11, rbp",
+ "xor rax, QWORD PTR [rdx+80]",
+ "mov rbp, r10",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rax, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "and r14, r8",
+ "xor rax, r14",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r14, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+96]",
+ "xor r14, QWORD PTR [rdx+168]",
+ "and r14, r8",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+72]",
+ "and r14, r15",
+ "xor rax, r14",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "xor rbp, rcx",
+ "and r10, rbp",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "xor r10, QWORD PTR [rdx+88]",
+ "and r8, r10",
+ "xor r14, r8",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+128]",
+ "mov rcx, r11",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r14",
+ "and rax, 1",
+ "ror rax, 33",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 42",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 52",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 58",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 11",
+ "mov rbp, rbx",
+ "shr rbp, 18",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 12",
+ "mov rbp, rbx",
+ "shr rbp, 19",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 13",
+ "mov rbp, rbx",
+ "shr rbp, 20",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 14",
+ "mov rbp, rbx",
+ "shr rbp, 21",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 15",
+ "mov rbp, rbx",
+ "shr rbp, 22",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 16",
+ "mov rbp, rbx",
+ "shr rbp, 23",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r14",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, rax",
+ "and rbp, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r11",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r11",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r11",
+ "mov r11, r14",
+ "and r11, rbp",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, rbp",
+ "xor r14, r11",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, r10",
+ "and r11, r14",
+ "xor r11, rcx",
+ "mov QWORD PTR [rdx+128], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rcx",
+ "xor r14, r9",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r14, r8",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, rbp",
+ "xor r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+144], r9",
+ "mov r9, QWORD PTR [rdx+104]",
+ "xor r9, QWORD PTR [rdx+112]",
+ "and r15, rax",
+ "xor r15, r9",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+136]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, rbp",
+ "xor r9, rax",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+88]",
+ "xor r9, r14",
+ "xor r9, r10",
+ "mov QWORD PTR [rdx+72], r11",
+ "mov r11, QWORD PTR [rdx+120]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rax",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "mov QWORD PTR [rdx+80], r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r15",
+ "mov r15, r10",
+ "and r15, r14",
+ "xor r11, r15",
+ "and r11, r8",
+ "xor r9, r11",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+104]",
+ "xor rbp, r11",
+ "mov r15, r10",
+ "and r15, rbp",
+ "xor r15, rbx",
+ "and r15, r8",
+ "xor r14, r15",
+ "and r14, QWORD PTR [rdx+120]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+136]",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r15, QWORD PTR [rdx+168]",
+ "xor r15, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r9",
+ "mov r9, QWORD PTR [rdx+152]",
+ "xor r9, rbx",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+152]",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r9, rax",
+ "and r9, r15",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, r9",
+ "and r11, r8",
+ "xor r11, QWORD PTR [rdx+88]",
+ "and r11, QWORD PTR [rdx+120]",
+ "xor r14, r11",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "mov r11, r10",
+ "and r11, QWORD PTR [rdx+128]",
+ "xor rbx, r11",
+ "mov r11, rcx",
+ "xor r11, rax",
+ "and r11, r10",
+ "xor rbp, r11",
+ "and rbp, r8",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+96]",
+ "and rax, QWORD PTR [rdx+144]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor r15, rax",
+ "xor rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor rcx, r9",
+ "mov r9, QWORD PTR [rdx+168]",
+ "xor r9, QWORD PTR [rdx+160]",
+ "xor r9, QWORD PTR [rdx+64]",
+ "and r10, r9",
+ "xor rcx, r10",
+ "and r8, rcx",
+ "xor r15, r8",
+ "and r15, QWORD PTR [rdx+120]",
+ "xor rbx, r15",
+ "mov rax, QWORD PTR [rdx+72]",
+ "mov rcx, QWORD PTR [rdx+80]",
+ "mov r8, r14",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 35",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 57",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 46",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 40",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 7",
+ "mov rbp, rbx",
+ "shr rbp, 12",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 8",
+ "mov rbp, rbx",
+ "shr rbp, 13",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 9",
+ "mov rbp, rbx",
+ "shr rbp, 14",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 10",
+ "mov rbp, rbx",
+ "shr rbp, 15",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 11",
+ "mov rbp, rbx",
+ "shr rbp, 16",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 12",
+ "mov rbp, rbx",
+ "shr rbp, 17",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r9",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], rbp",
+ "mov rbp, r15",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r10",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, rcx",
+ "and r10, r9",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "xor r15, r10",
+ "and r15, r8",
+ "xor rbp, r15",
+ "mov r15, r10",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r10",
+ "mov r10, r9",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rax",
+ "mov rax, rcx",
+ "and rax, r10",
+ "mov QWORD PTR [rdx+120], r10",
+ "mov r10, r9",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+128], rax",
+ "mov rax, r8",
+ "and rax, r10",
+ "xor r15, rax",
+ "and r15, r11",
+ "xor rbp, r15",
+ "mov r15, r14",
+ "xor r15, r9",
+ "mov QWORD PTR [rdx+136], r10",
+ "mov r10, rcx",
+ "and r10, r15",
+ "mov QWORD PTR [rdx+144], rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, r10",
+ "and rax, r8",
+ "and r9, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+152], rcx",
+ "mov rcx, r14",
+ "xor rcx, r9",
+ "mov QWORD PTR [rdx+160], r14",
+ "mov r14, r15",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "xor r14, r10",
+ "and r14, r8",
+ "xor r14, rcx",
+ "and r14, r11",
+ "xor rax, r14",
+ "and rax, QWORD PTR [rdx+80]",
+ "xor rbp, rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+96]",
+ "mov r14, r9",
+ "xor r14, rax",
+ "mov QWORD PTR [rdx+168], rbp",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "and rbp, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+72], r10",
+ "mov r10, r8",
+ "and r10, rcx",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and rbp, r8",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r14, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+152]",
+ "xor rcx, r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+120], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+160]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r8",
+ "and rbp, rax",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor rcx, r10",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r14, rcx",
+ "xor r15, QWORD PTR [rdx+128]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, QWORD PTR [rdx+96]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor r10, rcx",
+ "mov rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r15, r10",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, QWORD PTR [rdx+120]",
+ "xor r9, QWORD PTR [rdx+152]",
+ "and r9, r8",
+ "xor r10, r9",
+ "and r10, r11",
+ "xor rbx, r10",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r15, rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+152]",
+ "xor rbx, QWORD PTR [rdx+144]",
+ "mov r10, r11",
+ "and r10, QWORD PTR [rdx+136]",
+ "xor rbx, r10",
+ "mov r10, rcx",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and r10, r8",
+ "xor r10, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+152]",
+ "and r9, rcx",
+ "xor rcx, r9",
+ "xor rax, QWORD PTR [rdx+88]",
+ "and r8, rax",
+ "xor rcx, r8",
+ "and r11, rcx",
+ "xor r10, r11",
+ "and r10, QWORD PTR [rdx+80]",
+ "xor rbx, r10",
+ "mov rax, QWORD PTR [rdx+168]",
+ "mov rcx, r14",
+ "mov r8, r15",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 51",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 43",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 61",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 36",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 3",
+ "mov rbp, rbx",
+ "shr rbp, 6",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 4",
+ "mov rbp, rbx",
+ "shr rbp, 7",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 5",
+ "mov rbp, rbx",
+ "shr rbp, 8",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 6",
+ "mov rbp, rbx",
+ "shr rbp, 9",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 7",
+ "mov rbp, rbx",
+ "shr rbp, 10",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 8",
+ "mov rbp, rbx",
+ "shr rbp, 11",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rax",
+ "mov r15, rax",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, r8",
+ "and rcx, r15",
+ "mov QWORD PTR [rdx+80], r10",
+ "mov r10, r14",
+ "xor r10, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r15",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, r8",
+ "and r14, rcx",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r9",
+ "and r14, r15",
+ "xor r10, r14",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "and r11, r14",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, r8",
+ "and r14, r11",
+ "mov QWORD PTR [rdx+136], r11",
+ "mov r11, rbp",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+144], rbp",
+ "mov rbp, r9",
+ "and rbp, rcx",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r10, r11",
+ "mov r11, r9",
+ "and r11, QWORD PTR [rdx+112]",
+ "xor r15, r11",
+ "mov r11, r8",
+ "and r11, rax",
+ "xor r11, QWORD PTR [rdx+104]",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r15, r11",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r10, r15",
+ "mov r15, QWORD PTR [rdx+104]",
+ "xor r15, r8",
+ "mov r11, QWORD PTR [rdx+96]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r10",
+ "mov r10, r11",
+ "xor r10, r14",
+ "and r10, r9",
+ "xor r15, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, QWORD PTR [rdx+144]",
+ "xor rbp, r10",
+ "mov QWORD PTR [rdx+168], r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, QWORD PTR [rdx+104]",
+ "mov QWORD PTR [rdx+104], rcx",
+ "mov rcx, r10",
+ "xor rcx, r14",
+ "and rcx, r9",
+ "xor rbp, rcx",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor r15, rbp",
+ "mov rbp, QWORD PTR [rdx+128]",
+ "xor rbp, QWORD PTR [rdx+136]",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r8",
+ "xor rax, rbp",
+ "xor rax, rcx",
+ "mov rcx, r8",
+ "and rcx, r11",
+ "mov QWORD PTR [rdx+176], rbp",
+ "mov rbp, r9",
+ "and rbp, r10",
+ "xor rcx, rbp",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor rax, rcx",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov rbx, r8",
+ "and rbx, QWORD PTR [rdx+128]",
+ "mov rax, r10",
+ "xor rax, rbx",
+ "mov rcx, r9",
+ "and rcx, QWORD PTR [rdx+120]",
+ "xor rax, rcx",
+ "xor r11, QWORD PTR [rdx+112]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+168]",
+ "and rbp, r9",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor rax, r11",
+ "mov r11, r8",
+ "and r11, QWORD PTR [rdx+96]",
+ "and r11, r9",
+ "xor r11, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+80]",
+ "xor r11, r14",
+ "and r11, QWORD PTR [rdx+72]",
+ "xor rax, r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, QWORD PTR [rdx+168]",
+ "xor r11, QWORD PTR [rdx+160]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "and r8, QWORD PTR [rdx+176]",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "xor r10, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+120]",
+ "and r9, r8",
+ "xor r10, r9",
+ "xor rcx, QWORD PTR [rdx+168]",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r10, rcx",
+ "and r10, QWORD PTR [rdx+72]",
+ "xor r11, r10",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "mov rcx, r15",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r11",
+ "and rax, 1",
+ "ror rax, 39",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 54",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 44",
+ "xor r12, r8",
+ "and r9, 1",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 31",
+ "mov rbp, rbx",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "mov rbp, rbx",
+ "shr rbp, 1",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 1",
+ "mov rbp, rbx",
+ "shr rbp, 2",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 2",
+ "mov rbp, rbx",
+ "shr rbp, 3",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 3",
+ "mov rbp, rbx",
+ "shr rbp, 4",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 4",
+ "mov rbp, rbx",
+ "shr rbp, 5",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r11",
+ "xor r15, r14",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r15",
+ "xor r8, r9",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor r8, rcx",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r9",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+88], rax",
+ "mov rax, r14",
+ "and rax, r11",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, r14",
+ "xor r9, rbp",
+ "and r9, rcx",
+ "xor r9, r15",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r9, r10",
+ "xor r8, r9",
+ "mov r9, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "and rbp, r9",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, rcx",
+ "xor r14, rbp",
+ "mov rbp, r11",
+ "xor rbp, rax",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r15",
+ "mov r15, QWORD PTR [rdx+96]",
+ "xor r15, r8",
+ "mov QWORD PTR [rdx+96], r11",
+ "mov r11, rcx",
+ "and r11, r9",
+ "xor r15, r11",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "xor r9, r8",
+ "and r9, rcx",
+ "xor rax, r9",
+ "mov r9, QWORD PTR [rdx+112]",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rbp, r9",
+ "and rbp, r10",
+ "xor rax, rbp",
+ "mov rbp, QWORD PTR [rdx+96]",
+ "xor rbp, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rbp",
+ "xor r9, QWORD PTR [rdx+144]",
+ "mov QWORD PTR [rdx+144], r11",
+ "mov r11, rcx",
+ "and r11, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r8",
+ "mov r8, r9",
+ "xor r8, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor r9, rbp",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, r15",
+ "xor rax, r8",
+ "mov r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+112]",
+ "mov r9, QWORD PTR [rdx+104]",
+ "and r9, r14",
+ "xor r9, QWORD PTR [rdx+96]",
+ "mov rbp, rcx",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "mov rbp, r14",
+ "xor rbp, QWORD PTR [rdx+80]",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov rbp, QWORD PTR [rdx+72]",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+144]",
+ "and rbp, r10",
+ "xor r14, rbp",
+ "and r14, r15",
+ "xor r8, r14",
+ "mov r14, rcx",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "and r14, QWORD PTR [rdx+128]",
+ "xor r14, QWORD PTR [rdx+72]",
+ "mov rbp, QWORD PTR [rdx+88]",
+ "xor rbp, QWORD PTR [rdx+152]",
+ "and rbp, rcx",
+ "xor rbp, r14",
+ "and rbp, r10",
+ "xor r9, rbp",
+ "xor r11, QWORD PTR [rdx+136]",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and rcx, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r10, r14",
+ "xor r11, r10",
+ "and r15, r11",
+ "xor r9, r15",
+ "mov QWORD PTR [rdx+160], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "and rax, 1",
+ "ror rax, 53",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 47",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 59",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 37",
+ "xor r12, r9",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "add rdi, 8",
+ "mov rax, QWORD PTR [rdx+56]",
+ "sub rax, 1",
+ "mov QWORD PTR [rdx+56], rax",
+ "jne 20b",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "mov rdi, QWORD PTR [rdx+48]",
+ "add rdi, 248",
+ "mov rax, 16",
+ "mov QWORD PTR [rdx+56], rax",
+ "21:",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 27",
+ "mov rbp, rbx",
+ "shr rbp, 42",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 28",
+ "mov rbp, rbx",
+ "shr rbp, 43",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 29",
+ "mov rbp, rbx",
+ "shr rbp, 44",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 30",
+ "mov rbp, rbx",
+ "shr rbp, 45",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 31",
+ "mov rbp, rbx",
+ "shr rbp, 46",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "mov rbp, rbx",
+ "shr rbp, 47",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov r15, rax",
+ "xor r15, r10",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, rcx",
+ "and r8, r15",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, rcx",
+ "and r14, r15",
+ "xor r14, rax",
+ "and r14, r11",
+ "xor r8, r14",
+ "mov r14, r10",
+ "and r14, rax",
+ "mov QWORD PTR [rdx+96], rax",
+ "mov rax, r14",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rcx",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbx",
+ "mov rbx, r14",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+136], r15",
+ "mov r15, r11",
+ "and r15, rbx",
+ "xor rbp, r15",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "and r10, rcx",
+ "mov rbp, rax",
+ "xor rbp, r10",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, r15",
+ "and r10, r11",
+ "xor rbp, r10",
+ "mov r10, rcx",
+ "and r10, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, r10",
+ "and r14, r11",
+ "and r14, r9",
+ "xor rbp, r14",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r8, rbp",
+ "mov rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "mov r14, rbp",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor rbp, r8",
+ "mov QWORD PTR [rdx+112], rbx",
+ "mov rbx, r11",
+ "and rbx, rbp",
+ "xor r14, rbx",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r15, rbx",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r15",
+ "xor r10, rbx",
+ "and r10, r9",
+ "xor r14, r10",
+ "xor rbp, rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+96]",
+ "mov r10, r8",
+ "xor r10, rbx",
+ "and r10, r11",
+ "mov QWORD PTR [rdx+168], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "xor r8, r10",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r14, rbp",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, rbx",
+ "mov r8, r11",
+ "and r8, r15",
+ "xor rbp, r8",
+ "xor rax, QWORD PTR [rdx+88]",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+168]",
+ "and r8, r11",
+ "xor rax, r8",
+ "and rax, r9",
+ "xor rbp, rax",
+ "mov rax, r11",
+ "and rax, QWORD PTR [rdx+136]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, rbx",
+ "xor rax, r10",
+ "and rax, r9",
+ "xor r15, rax",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor rbp, r15",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+128]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "xor r15, rcx",
+ "mov rax, QWORD PTR [rdx+136]",
+ "xor rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r11",
+ "xor rax, r15",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r10, r11",
+ "xor r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor rax, r10",
+ "mov r10, QWORD PTR [rdx+104]",
+ "xor r10, QWORD PTR [rdx+144]",
+ "and r10, r11",
+ "xor rbx, r10",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and r11, rcx",
+ "xor r15, r11",
+ "and r9, r15",
+ "xor rbx, r9",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor rax, rbx",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r14",
+ "mov r8, rbp",
+ "mov r9, QWORD PTR [rdx+72]",
+ "and rax, 1",
+ "ror rax, 63",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 55",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 49",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 41",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 23",
+ "mov rbp, rbx",
+ "shr rbp, 36",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 24",
+ "mov rbp, rbx",
+ "shr rbp, 37",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 25",
+ "mov rbp, rbx",
+ "shr rbp, 38",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 26",
+ "mov rbp, rbx",
+ "shr rbp, 39",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 27",
+ "mov rbp, rbx",
+ "shr rbp, 40",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 28",
+ "mov rbp, rbx",
+ "shr rbp, 41",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r11",
+ "mov r11, rax",
+ "and r11, r8",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+88], rbp",
+ "mov rbp, r15",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, r10",
+ "xor r11, rbp",
+ "mov QWORD PTR [rdx+112], r15",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+120], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, rax",
+ "and r14, r8",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, rbp",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+144], r14",
+ "mov r14, rbp",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], rbp",
+ "mov rbp, rax",
+ "and rbp, r14",
+ "xor rbp, rcx",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "and r8, r9",
+ "xor r11, r8",
+ "mov r8, rax",
+ "and r8, r15",
+ "xor r8, QWORD PTR [rdx+88]",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+160], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rcx",
+ "xor r9, r15",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor r11, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, QWORD PTR [rdx+96]",
+ "mov r9, rbp",
+ "xor r9, r8",
+ "xor r15, QWORD PTR [rdx+136]",
+ "and r15, r10",
+ "xor r9, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+80]",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+104]",
+ "mov r15, rax",
+ "and r15, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, QWORD PTR [rdx+152]",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+152], r15",
+ "mov r15, r10",
+ "and r15, QWORD PTR [rdx+80]",
+ "xor r11, r15",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and r14, QWORD PTR [rdx+72]",
+ "xor r9, r14",
+ "mov r14, rbp",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, r8",
+ "and r11, r10",
+ "xor r11, rax",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and rax, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rax",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, QWORD PTR [rdx+112]",
+ "and r11, r10",
+ "xor rcx, r11",
+ "and rax, QWORD PTR [rdx+168]",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+72]",
+ "xor r14, rcx",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "mov rcx, r10",
+ "and rcx, QWORD PTR [rdx+144]",
+ "xor rbp, rcx",
+ "mov rcx, r8",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+168]",
+ "xor rbp, rcx",
+ "xor r8, QWORD PTR [rdx+160]",
+ "xor rbx, r8",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "and r10, rbx",
+ "xor r8, r10",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor rbp, r8",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r9",
+ "mov r8, r14",
+ "mov r9, rbp",
+ "and rax, 1",
+ "ror rax, 50",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 34",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 60",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 45",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 19",
+ "mov rbp, rbx",
+ "shr rbp, 30",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 20",
+ "mov rbp, rbx",
+ "shr rbp, 31",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 21",
+ "mov rbp, rbx",
+ "shr rbp, 32",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 22",
+ "mov rbp, rbx",
+ "shr rbp, 33",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 23",
+ "mov rbp, rbx",
+ "shr rbp, 34",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 24",
+ "mov rbp, rbx",
+ "shr rbp, 35",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r10",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r10",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r14",
+ "xor r10, r15",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, rax",
+ "and r14, r10",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+112], r8",
+ "mov r8, r10",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+120], rbx",
+ "mov rbx, r8",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+128], r8",
+ "mov r8, rcx",
+ "and r8, rbx",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+136], rbp",
+ "mov rbp, rcx",
+ "and rbp, r10",
+ "xor rbx, rbp",
+ "and rbx, r9",
+ "xor r8, rbx",
+ "and r11, rax",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, r11",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+96]",
+ "xor rbx, rbp",
+ "and r15, r9",
+ "xor rbx, r15",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r8, rbx",
+ "mov rbx, QWORD PTR [rdx+96]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "xor r14, rbx",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+120]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov rbp, rax",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+104], r8",
+ "mov r8, rcx",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, r14",
+ "xor r10, r8",
+ "mov QWORD PTR [rdx+152], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], r11",
+ "mov r11, rax",
+ "and r11, rbx",
+ "mov QWORD PTR [rdx+168], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, r11",
+ "mov QWORD PTR [rdx+88], r11",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+96]",
+ "mov QWORD PTR [rdx+176], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, r11",
+ "and r8, rcx",
+ "xor rbx, r8",
+ "and rbx, r9",
+ "xor r10, rbx",
+ "mov rbx, QWORD PTR [rdx+136]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "mov r14, QWORD PTR [rdx+112]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r15",
+ "xor r14, r8",
+ "mov QWORD PTR [rdx+96], r8",
+ "mov r8, r11",
+ "xor r8, QWORD PTR [rdx+120]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r8, rcx",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r10, rbx",
+ "mov rbx, rax",
+ "and rbx, r15",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "mov r14, rbp",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "and rbp, r9",
+ "xor rbx, rbp",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, QWORD PTR [rdx+88]",
+ "xor rbp, r8",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+80]",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, rcx",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rax, rbp",
+ "xor rax, QWORD PTR [rdx+168]",
+ "and rax, rcx",
+ "xor rax, QWORD PTR [rdx+144]",
+ "and rax, r9",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+112]",
+ "xor rax, r11",
+ "mov rbp, QWORD PTR [rdx+136]",
+ "xor rbp, QWORD PTR [rdx+96]",
+ "and rbp, rcx",
+ "xor rax, rbp",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+136]",
+ "and r9, rcx",
+ "xor rax, r9",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+104]",
+ "mov rcx, r10",
+ "mov r8, rbx",
+ "mov r9, r15",
+ "and rax, 1",
+ "ror rax, 38",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 62",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 48",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 56",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 15",
+ "mov rbp, rbx",
+ "shr rbp, 24",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 16",
+ "mov rbp, rbx",
+ "shr rbp, 25",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 17",
+ "mov rbp, rbx",
+ "shr rbp, 26",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 18",
+ "mov rbp, rbx",
+ "shr rbp, 27",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 19",
+ "mov rbp, rbx",
+ "shr rbp, 28",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 20",
+ "mov rbp, rbx",
+ "shr rbp, 29",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r9",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, r11",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+88], r15",
+ "mov r15, r14",
+ "xor r15, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, rbp",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r11",
+ "and r14, r9",
+ "mov QWORD PTR [rdx+120], r9",
+ "mov r9, rbp",
+ "xor r9, r14",
+ "and r9, r10",
+ "xor r15, r9",
+ "mov r9, rcx",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, rcx",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov QWORD PTR [rdx+144], rcx",
+ "mov rcx, r9",
+ "xor rcx, r14",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, rax",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+120]",
+ "and rcx, r10",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, QWORD PTR [rdx+80]",
+ "xor r9, r14",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r11",
+ "and rax, r9",
+ "xor rcx, rax",
+ "mov QWORD PTR [rdx+160], r9",
+ "mov r9, r10",
+ "and r9, QWORD PTR [rdx+128]",
+ "xor rcx, r9",
+ "and rcx, r8",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "and rcx, rbp",
+ "xor r15, rcx",
+ "mov rcx, r11",
+ "and rcx, r14",
+ "mov QWORD PTR [rdx+128], r15",
+ "mov r15, QWORD PTR [rdx+120]",
+ "xor r15, rcx",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "and r11, r10",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, r14",
+ "xor r9, rax",
+ "mov QWORD PTR [rdx+176], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, QWORD PTR [rdx+136]",
+ "and r14, r10",
+ "xor r9, r14",
+ "and r9, r8",
+ "xor r11, r9",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r11, rbp",
+ "xor rax, QWORD PTR [rdx+80]",
+ "mov rbp, r10",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rax, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "and r14, r8",
+ "xor rax, r14",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r14, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+96]",
+ "xor r14, QWORD PTR [rdx+168]",
+ "and r14, r8",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+72]",
+ "and r14, r15",
+ "xor rax, r14",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "xor rbp, rcx",
+ "and r10, rbp",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "xor r10, QWORD PTR [rdx+88]",
+ "and r8, r10",
+ "xor r14, r8",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+128]",
+ "mov rcx, r11",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r14",
+ "and rax, 1",
+ "ror rax, 33",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 42",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 52",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 58",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 11",
+ "mov rbp, rbx",
+ "shr rbp, 18",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 12",
+ "mov rbp, rbx",
+ "shr rbp, 19",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 13",
+ "mov rbp, rbx",
+ "shr rbp, 20",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 14",
+ "mov rbp, rbx",
+ "shr rbp, 21",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 15",
+ "mov rbp, rbx",
+ "shr rbp, 22",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 16",
+ "mov rbp, rbx",
+ "shr rbp, 23",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r14",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, rax",
+ "and rbp, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r11",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r11",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r11",
+ "mov r11, r14",
+ "and r11, rbp",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, rbp",
+ "xor r14, r11",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, r10",
+ "and r11, r14",
+ "xor r11, rcx",
+ "mov QWORD PTR [rdx+128], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rcx",
+ "xor r14, r9",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r14, r8",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, rbp",
+ "xor r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+144], r9",
+ "mov r9, QWORD PTR [rdx+104]",
+ "xor r9, QWORD PTR [rdx+112]",
+ "and r15, rax",
+ "xor r15, r9",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+136]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, rbp",
+ "xor r9, rax",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+88]",
+ "xor r9, r14",
+ "xor r9, r10",
+ "mov QWORD PTR [rdx+72], r11",
+ "mov r11, QWORD PTR [rdx+120]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rax",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "mov QWORD PTR [rdx+80], r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r15",
+ "mov r15, r10",
+ "and r15, r14",
+ "xor r11, r15",
+ "and r11, r8",
+ "xor r9, r11",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+104]",
+ "xor rbp, r11",
+ "mov r15, r10",
+ "and r15, rbp",
+ "xor r15, rbx",
+ "and r15, r8",
+ "xor r14, r15",
+ "and r14, QWORD PTR [rdx+120]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+136]",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r15, QWORD PTR [rdx+168]",
+ "xor r15, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r9",
+ "mov r9, QWORD PTR [rdx+152]",
+ "xor r9, rbx",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+152]",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r9, rax",
+ "and r9, r15",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, r9",
+ "and r11, r8",
+ "xor r11, QWORD PTR [rdx+88]",
+ "and r11, QWORD PTR [rdx+120]",
+ "xor r14, r11",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "mov r11, r10",
+ "and r11, QWORD PTR [rdx+128]",
+ "xor rbx, r11",
+ "mov r11, rcx",
+ "xor r11, rax",
+ "and r11, r10",
+ "xor rbp, r11",
+ "and rbp, r8",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+96]",
+ "and rax, QWORD PTR [rdx+144]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor r15, rax",
+ "xor rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor rcx, r9",
+ "mov r9, QWORD PTR [rdx+168]",
+ "xor r9, QWORD PTR [rdx+160]",
+ "xor r9, QWORD PTR [rdx+64]",
+ "and r10, r9",
+ "xor rcx, r10",
+ "and r8, rcx",
+ "xor r15, r8",
+ "and r15, QWORD PTR [rdx+120]",
+ "xor rbx, r15",
+ "mov rax, QWORD PTR [rdx+72]",
+ "mov rcx, QWORD PTR [rdx+80]",
+ "mov r8, r14",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 35",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 57",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 46",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 40",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 7",
+ "mov rbp, rbx",
+ "shr rbp, 12",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 8",
+ "mov rbp, rbx",
+ "shr rbp, 13",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 9",
+ "mov rbp, rbx",
+ "shr rbp, 14",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 10",
+ "mov rbp, rbx",
+ "shr rbp, 15",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 11",
+ "mov rbp, rbx",
+ "shr rbp, 16",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 12",
+ "mov rbp, rbx",
+ "shr rbp, 17",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r9",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], rbp",
+ "mov rbp, r15",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r10",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, rcx",
+ "and r10, r9",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "xor r15, r10",
+ "and r15, r8",
+ "xor rbp, r15",
+ "mov r15, r10",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r10",
+ "mov r10, r9",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rax",
+ "mov rax, rcx",
+ "and rax, r10",
+ "mov QWORD PTR [rdx+120], r10",
+ "mov r10, r9",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+128], rax",
+ "mov rax, r8",
+ "and rax, r10",
+ "xor r15, rax",
+ "and r15, r11",
+ "xor rbp, r15",
+ "mov r15, r14",
+ "xor r15, r9",
+ "mov QWORD PTR [rdx+136], r10",
+ "mov r10, rcx",
+ "and r10, r15",
+ "mov QWORD PTR [rdx+144], rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, r10",
+ "and rax, r8",
+ "and r9, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+152], rcx",
+ "mov rcx, r14",
+ "xor rcx, r9",
+ "mov QWORD PTR [rdx+160], r14",
+ "mov r14, r15",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "xor r14, r10",
+ "and r14, r8",
+ "xor r14, rcx",
+ "and r14, r11",
+ "xor rax, r14",
+ "and rax, QWORD PTR [rdx+80]",
+ "xor rbp, rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+96]",
+ "mov r14, r9",
+ "xor r14, rax",
+ "mov QWORD PTR [rdx+168], rbp",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "and rbp, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+72], r10",
+ "mov r10, r8",
+ "and r10, rcx",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and rbp, r8",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r14, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+152]",
+ "xor rcx, r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+120], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+160]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r8",
+ "and rbp, rax",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor rcx, r10",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r14, rcx",
+ "xor r15, QWORD PTR [rdx+128]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, QWORD PTR [rdx+96]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor r10, rcx",
+ "mov rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r15, r10",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, QWORD PTR [rdx+120]",
+ "xor r9, QWORD PTR [rdx+152]",
+ "and r9, r8",
+ "xor r10, r9",
+ "and r10, r11",
+ "xor rbx, r10",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r15, rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+152]",
+ "xor rbx, QWORD PTR [rdx+144]",
+ "mov r10, r11",
+ "and r10, QWORD PTR [rdx+136]",
+ "xor rbx, r10",
+ "mov r10, rcx",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and r10, r8",
+ "xor r10, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+152]",
+ "and r9, rcx",
+ "xor rcx, r9",
+ "xor rax, QWORD PTR [rdx+88]",
+ "and r8, rax",
+ "xor rcx, r8",
+ "and r11, rcx",
+ "xor r10, r11",
+ "and r10, QWORD PTR [rdx+80]",
+ "xor rbx, r10",
+ "mov rax, QWORD PTR [rdx+168]",
+ "mov rcx, r14",
+ "mov r8, r15",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 51",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 43",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 61",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 36",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 3",
+ "mov rbp, rbx",
+ "shr rbp, 6",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 4",
+ "mov rbp, rbx",
+ "shr rbp, 7",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 5",
+ "mov rbp, rbx",
+ "shr rbp, 8",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 6",
+ "mov rbp, rbx",
+ "shr rbp, 9",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 7",
+ "mov rbp, rbx",
+ "shr rbp, 10",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 8",
+ "mov rbp, rbx",
+ "shr rbp, 11",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rax",
+ "mov r15, rax",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, r8",
+ "and rcx, r15",
+ "mov QWORD PTR [rdx+80], r10",
+ "mov r10, r14",
+ "xor r10, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r15",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, r8",
+ "and r14, rcx",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r9",
+ "and r14, r15",
+ "xor r10, r14",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "and r11, r14",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, r8",
+ "and r14, r11",
+ "mov QWORD PTR [rdx+136], r11",
+ "mov r11, rbp",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+144], rbp",
+ "mov rbp, r9",
+ "and rbp, rcx",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r10, r11",
+ "mov r11, r9",
+ "and r11, QWORD PTR [rdx+112]",
+ "xor r15, r11",
+ "mov r11, r8",
+ "and r11, rax",
+ "xor r11, QWORD PTR [rdx+104]",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r15, r11",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r10, r15",
+ "mov r15, QWORD PTR [rdx+104]",
+ "xor r15, r8",
+ "mov r11, QWORD PTR [rdx+96]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r10",
+ "mov r10, r11",
+ "xor r10, r14",
+ "and r10, r9",
+ "xor r15, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, QWORD PTR [rdx+144]",
+ "xor rbp, r10",
+ "mov QWORD PTR [rdx+168], r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, QWORD PTR [rdx+104]",
+ "mov QWORD PTR [rdx+104], rcx",
+ "mov rcx, r10",
+ "xor rcx, r14",
+ "and rcx, r9",
+ "xor rbp, rcx",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor r15, rbp",
+ "mov rbp, QWORD PTR [rdx+128]",
+ "xor rbp, QWORD PTR [rdx+136]",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r8",
+ "xor rax, rbp",
+ "xor rax, rcx",
+ "mov rcx, r8",
+ "and rcx, r11",
+ "mov QWORD PTR [rdx+176], rbp",
+ "mov rbp, r9",
+ "and rbp, r10",
+ "xor rcx, rbp",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor rax, rcx",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov rbx, r8",
+ "and rbx, QWORD PTR [rdx+128]",
+ "mov rax, r10",
+ "xor rax, rbx",
+ "mov rcx, r9",
+ "and rcx, QWORD PTR [rdx+120]",
+ "xor rax, rcx",
+ "xor r11, QWORD PTR [rdx+112]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+168]",
+ "and rbp, r9",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor rax, r11",
+ "mov r11, r8",
+ "and r11, QWORD PTR [rdx+96]",
+ "and r11, r9",
+ "xor r11, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+80]",
+ "xor r11, r14",
+ "and r11, QWORD PTR [rdx+72]",
+ "xor rax, r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, QWORD PTR [rdx+168]",
+ "xor r11, QWORD PTR [rdx+160]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "and r8, QWORD PTR [rdx+176]",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "xor r10, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+120]",
+ "and r9, r8",
+ "xor r10, r9",
+ "xor rcx, QWORD PTR [rdx+168]",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r10, rcx",
+ "and r10, QWORD PTR [rdx+72]",
+ "xor r11, r10",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "mov rcx, r15",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r11",
+ "and rax, 1",
+ "ror rax, 39",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 54",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 44",
+ "xor r12, r8",
+ "and r9, 1",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 31",
+ "mov rbp, rbx",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "mov rbp, rbx",
+ "shr rbp, 1",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 1",
+ "mov rbp, rbx",
+ "shr rbp, 2",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 2",
+ "mov rbp, rbx",
+ "shr rbp, 3",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 3",
+ "mov rbp, rbx",
+ "shr rbp, 4",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 4",
+ "mov rbp, rbx",
+ "shr rbp, 5",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r11",
+ "xor r15, r14",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r15",
+ "xor r8, r9",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor r8, rcx",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r9",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+88], rax",
+ "mov rax, r14",
+ "and rax, r11",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, r14",
+ "xor r9, rbp",
+ "and r9, rcx",
+ "xor r9, r15",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r9, r10",
+ "xor r8, r9",
+ "mov r9, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "and rbp, r9",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, rcx",
+ "xor r14, rbp",
+ "mov rbp, r11",
+ "xor rbp, rax",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r15",
+ "mov r15, QWORD PTR [rdx+96]",
+ "xor r15, r8",
+ "mov QWORD PTR [rdx+96], r11",
+ "mov r11, rcx",
+ "and r11, r9",
+ "xor r15, r11",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "xor r9, r8",
+ "and r9, rcx",
+ "xor rax, r9",
+ "mov r9, QWORD PTR [rdx+112]",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rbp, r9",
+ "and rbp, r10",
+ "xor rax, rbp",
+ "mov rbp, QWORD PTR [rdx+96]",
+ "xor rbp, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rbp",
+ "xor r9, QWORD PTR [rdx+144]",
+ "mov QWORD PTR [rdx+144], r11",
+ "mov r11, rcx",
+ "and r11, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r8",
+ "mov r8, r9",
+ "xor r8, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor r9, rbp",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, r15",
+ "xor rax, r8",
+ "mov r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+112]",
+ "mov r9, QWORD PTR [rdx+104]",
+ "and r9, r14",
+ "xor r9, QWORD PTR [rdx+96]",
+ "mov rbp, rcx",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "mov rbp, r14",
+ "xor rbp, QWORD PTR [rdx+80]",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov rbp, QWORD PTR [rdx+72]",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+144]",
+ "and rbp, r10",
+ "xor r14, rbp",
+ "and r14, r15",
+ "xor r8, r14",
+ "mov r14, rcx",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "and r14, QWORD PTR [rdx+128]",
+ "xor r14, QWORD PTR [rdx+72]",
+ "mov rbp, QWORD PTR [rdx+88]",
+ "xor rbp, QWORD PTR [rdx+152]",
+ "and rbp, rcx",
+ "xor rbp, r14",
+ "and rbp, r10",
+ "xor r9, rbp",
+ "xor r11, QWORD PTR [rdx+136]",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and rcx, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r10, r14",
+ "xor r11, r10",
+ "and r15, r11",
+ "xor r9, r15",
+ "mov QWORD PTR [rdx+160], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "and rax, 1",
+ "ror rax, 53",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 47",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 59",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 37",
+ "xor r12, r9",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "sub rdi, 8",
+ "mov rax, QWORD PTR [rdx+56]",
+ "sub rax, 1",
+ "mov QWORD PTR [rdx+56], rax",
+ "jne 21b",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "mov rdi, QWORD PTR [rdx+48]",
+ "add rdi, 256",
+ "mov rax, 16",
+ "mov QWORD PTR [rdx+56], rax",
+ "22:",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 27",
+ "mov rbp, rbx",
+ "shr rbp, 42",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 28",
+ "mov rbp, rbx",
+ "shr rbp, 43",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 29",
+ "mov rbp, rbx",
+ "shr rbp, 44",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 30",
+ "mov rbp, rbx",
+ "shr rbp, 45",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 31",
+ "mov rbp, rbx",
+ "shr rbp, 46",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "mov rbp, rbx",
+ "shr rbp, 47",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov r15, rax",
+ "xor r15, r10",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, rcx",
+ "and r8, r15",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, rcx",
+ "and r14, r15",
+ "xor r14, rax",
+ "and r14, r11",
+ "xor r8, r14",
+ "mov r14, r10",
+ "and r14, rax",
+ "mov QWORD PTR [rdx+96], rax",
+ "mov rax, r14",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rcx",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbx",
+ "mov rbx, r14",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+136], r15",
+ "mov r15, r11",
+ "and r15, rbx",
+ "xor rbp, r15",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "and r10, rcx",
+ "mov rbp, rax",
+ "xor rbp, r10",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, r15",
+ "and r10, r11",
+ "xor rbp, r10",
+ "mov r10, rcx",
+ "and r10, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, r10",
+ "and r14, r11",
+ "and r14, r9",
+ "xor rbp, r14",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r8, rbp",
+ "mov rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "mov r14, rbp",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor rbp, r8",
+ "mov QWORD PTR [rdx+112], rbx",
+ "mov rbx, r11",
+ "and rbx, rbp",
+ "xor r14, rbx",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r15, rbx",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r15",
+ "xor r10, rbx",
+ "and r10, r9",
+ "xor r14, r10",
+ "xor rbp, rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+96]",
+ "mov r10, r8",
+ "xor r10, rbx",
+ "and r10, r11",
+ "mov QWORD PTR [rdx+168], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "xor r8, r10",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r14, rbp",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, rbx",
+ "mov r8, r11",
+ "and r8, r15",
+ "xor rbp, r8",
+ "xor rax, QWORD PTR [rdx+88]",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+168]",
+ "and r8, r11",
+ "xor rax, r8",
+ "and rax, r9",
+ "xor rbp, rax",
+ "mov rax, r11",
+ "and rax, QWORD PTR [rdx+136]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, rbx",
+ "xor rax, r10",
+ "and rax, r9",
+ "xor r15, rax",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor rbp, r15",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+128]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "xor r15, rcx",
+ "mov rax, QWORD PTR [rdx+136]",
+ "xor rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r11",
+ "xor rax, r15",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r10, r11",
+ "xor r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor rax, r10",
+ "mov r10, QWORD PTR [rdx+104]",
+ "xor r10, QWORD PTR [rdx+144]",
+ "and r10, r11",
+ "xor rbx, r10",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and r11, rcx",
+ "xor r15, r11",
+ "and r9, r15",
+ "xor rbx, r9",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor rax, rbx",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r14",
+ "mov r8, rbp",
+ "mov r9, QWORD PTR [rdx+72]",
+ "and rax, 1",
+ "ror rax, 63",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 55",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 49",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 41",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 23",
+ "mov rbp, rbx",
+ "shr rbp, 36",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 24",
+ "mov rbp, rbx",
+ "shr rbp, 37",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 25",
+ "mov rbp, rbx",
+ "shr rbp, 38",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 26",
+ "mov rbp, rbx",
+ "shr rbp, 39",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 27",
+ "mov rbp, rbx",
+ "shr rbp, 40",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 28",
+ "mov rbp, rbx",
+ "shr rbp, 41",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r11",
+ "mov r11, rax",
+ "and r11, r8",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+88], rbp",
+ "mov rbp, r15",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, r10",
+ "xor r11, rbp",
+ "mov QWORD PTR [rdx+112], r15",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+120], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, rax",
+ "and r14, r8",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, rbp",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+144], r14",
+ "mov r14, rbp",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], rbp",
+ "mov rbp, rax",
+ "and rbp, r14",
+ "xor rbp, rcx",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "and r8, r9",
+ "xor r11, r8",
+ "mov r8, rax",
+ "and r8, r15",
+ "xor r8, QWORD PTR [rdx+88]",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+160], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rcx",
+ "xor r9, r15",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor r11, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, QWORD PTR [rdx+96]",
+ "mov r9, rbp",
+ "xor r9, r8",
+ "xor r15, QWORD PTR [rdx+136]",
+ "and r15, r10",
+ "xor r9, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+80]",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+104]",
+ "mov r15, rax",
+ "and r15, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, QWORD PTR [rdx+152]",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+152], r15",
+ "mov r15, r10",
+ "and r15, QWORD PTR [rdx+80]",
+ "xor r11, r15",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and r14, QWORD PTR [rdx+72]",
+ "xor r9, r14",
+ "mov r14, rbp",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, r8",
+ "and r11, r10",
+ "xor r11, rax",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and rax, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rax",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, QWORD PTR [rdx+112]",
+ "and r11, r10",
+ "xor rcx, r11",
+ "and rax, QWORD PTR [rdx+168]",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+72]",
+ "xor r14, rcx",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "mov rcx, r10",
+ "and rcx, QWORD PTR [rdx+144]",
+ "xor rbp, rcx",
+ "mov rcx, r8",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+168]",
+ "xor rbp, rcx",
+ "xor r8, QWORD PTR [rdx+160]",
+ "xor rbx, r8",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "and r10, rbx",
+ "xor r8, r10",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor rbp, r8",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r9",
+ "mov r8, r14",
+ "mov r9, rbp",
+ "and rax, 1",
+ "ror rax, 50",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 34",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 60",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 45",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 19",
+ "mov rbp, rbx",
+ "shr rbp, 30",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 20",
+ "mov rbp, rbx",
+ "shr rbp, 31",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 21",
+ "mov rbp, rbx",
+ "shr rbp, 32",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 22",
+ "mov rbp, rbx",
+ "shr rbp, 33",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 23",
+ "mov rbp, rbx",
+ "shr rbp, 34",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 24",
+ "mov rbp, rbx",
+ "shr rbp, 35",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r10",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r10",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r14",
+ "xor r10, r15",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, rax",
+ "and r14, r10",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+112], r8",
+ "mov r8, r10",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+120], rbx",
+ "mov rbx, r8",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+128], r8",
+ "mov r8, rcx",
+ "and r8, rbx",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+136], rbp",
+ "mov rbp, rcx",
+ "and rbp, r10",
+ "xor rbx, rbp",
+ "and rbx, r9",
+ "xor r8, rbx",
+ "and r11, rax",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, r11",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+96]",
+ "xor rbx, rbp",
+ "and r15, r9",
+ "xor rbx, r15",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r8, rbx",
+ "mov rbx, QWORD PTR [rdx+96]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "xor r14, rbx",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+120]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov rbp, rax",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+104], r8",
+ "mov r8, rcx",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, r14",
+ "xor r10, r8",
+ "mov QWORD PTR [rdx+152], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], r11",
+ "mov r11, rax",
+ "and r11, rbx",
+ "mov QWORD PTR [rdx+168], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, r11",
+ "mov QWORD PTR [rdx+88], r11",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+96]",
+ "mov QWORD PTR [rdx+176], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, r11",
+ "and r8, rcx",
+ "xor rbx, r8",
+ "and rbx, r9",
+ "xor r10, rbx",
+ "mov rbx, QWORD PTR [rdx+136]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "mov r14, QWORD PTR [rdx+112]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r15",
+ "xor r14, r8",
+ "mov QWORD PTR [rdx+96], r8",
+ "mov r8, r11",
+ "xor r8, QWORD PTR [rdx+120]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r8, rcx",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r10, rbx",
+ "mov rbx, rax",
+ "and rbx, r15",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "mov r14, rbp",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "and rbp, r9",
+ "xor rbx, rbp",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, QWORD PTR [rdx+88]",
+ "xor rbp, r8",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+80]",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, rcx",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rax, rbp",
+ "xor rax, QWORD PTR [rdx+168]",
+ "and rax, rcx",
+ "xor rax, QWORD PTR [rdx+144]",
+ "and rax, r9",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+112]",
+ "xor rax, r11",
+ "mov rbp, QWORD PTR [rdx+136]",
+ "xor rbp, QWORD PTR [rdx+96]",
+ "and rbp, rcx",
+ "xor rax, rbp",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+136]",
+ "and r9, rcx",
+ "xor rax, r9",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+104]",
+ "mov rcx, r10",
+ "mov r8, rbx",
+ "mov r9, r15",
+ "and rax, 1",
+ "ror rax, 38",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 62",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 48",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 56",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 15",
+ "mov rbp, rbx",
+ "shr rbp, 24",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 16",
+ "mov rbp, rbx",
+ "shr rbp, 25",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 17",
+ "mov rbp, rbx",
+ "shr rbp, 26",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 18",
+ "mov rbp, rbx",
+ "shr rbp, 27",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 19",
+ "mov rbp, rbx",
+ "shr rbp, 28",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 20",
+ "mov rbp, rbx",
+ "shr rbp, 29",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r9",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, r11",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+88], r15",
+ "mov r15, r14",
+ "xor r15, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, rbp",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r11",
+ "and r14, r9",
+ "mov QWORD PTR [rdx+120], r9",
+ "mov r9, rbp",
+ "xor r9, r14",
+ "and r9, r10",
+ "xor r15, r9",
+ "mov r9, rcx",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, rcx",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov QWORD PTR [rdx+144], rcx",
+ "mov rcx, r9",
+ "xor rcx, r14",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, rax",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+120]",
+ "and rcx, r10",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, QWORD PTR [rdx+80]",
+ "xor r9, r14",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r11",
+ "and rax, r9",
+ "xor rcx, rax",
+ "mov QWORD PTR [rdx+160], r9",
+ "mov r9, r10",
+ "and r9, QWORD PTR [rdx+128]",
+ "xor rcx, r9",
+ "and rcx, r8",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "and rcx, rbp",
+ "xor r15, rcx",
+ "mov rcx, r11",
+ "and rcx, r14",
+ "mov QWORD PTR [rdx+128], r15",
+ "mov r15, QWORD PTR [rdx+120]",
+ "xor r15, rcx",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "and r11, r10",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, r14",
+ "xor r9, rax",
+ "mov QWORD PTR [rdx+176], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, QWORD PTR [rdx+136]",
+ "and r14, r10",
+ "xor r9, r14",
+ "and r9, r8",
+ "xor r11, r9",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r11, rbp",
+ "xor rax, QWORD PTR [rdx+80]",
+ "mov rbp, r10",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rax, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "and r14, r8",
+ "xor rax, r14",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r14, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+96]",
+ "xor r14, QWORD PTR [rdx+168]",
+ "and r14, r8",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+72]",
+ "and r14, r15",
+ "xor rax, r14",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "xor rbp, rcx",
+ "and r10, rbp",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "xor r10, QWORD PTR [rdx+88]",
+ "and r8, r10",
+ "xor r14, r8",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+128]",
+ "mov rcx, r11",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r14",
+ "and rax, 1",
+ "ror rax, 33",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 42",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 52",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 58",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 11",
+ "mov rbp, rbx",
+ "shr rbp, 18",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 12",
+ "mov rbp, rbx",
+ "shr rbp, 19",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 13",
+ "mov rbp, rbx",
+ "shr rbp, 20",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 14",
+ "mov rbp, rbx",
+ "shr rbp, 21",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 15",
+ "mov rbp, rbx",
+ "shr rbp, 22",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 16",
+ "mov rbp, rbx",
+ "shr rbp, 23",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r14",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, rax",
+ "and rbp, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r11",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r11",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r11",
+ "mov r11, r14",
+ "and r11, rbp",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, rbp",
+ "xor r14, r11",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, r10",
+ "and r11, r14",
+ "xor r11, rcx",
+ "mov QWORD PTR [rdx+128], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rcx",
+ "xor r14, r9",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r14, r8",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, rbp",
+ "xor r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+144], r9",
+ "mov r9, QWORD PTR [rdx+104]",
+ "xor r9, QWORD PTR [rdx+112]",
+ "and r15, rax",
+ "xor r15, r9",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+136]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, rbp",
+ "xor r9, rax",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+88]",
+ "xor r9, r14",
+ "xor r9, r10",
+ "mov QWORD PTR [rdx+72], r11",
+ "mov r11, QWORD PTR [rdx+120]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rax",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "mov QWORD PTR [rdx+80], r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r15",
+ "mov r15, r10",
+ "and r15, r14",
+ "xor r11, r15",
+ "and r11, r8",
+ "xor r9, r11",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+104]",
+ "xor rbp, r11",
+ "mov r15, r10",
+ "and r15, rbp",
+ "xor r15, rbx",
+ "and r15, r8",
+ "xor r14, r15",
+ "and r14, QWORD PTR [rdx+120]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+136]",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r15, QWORD PTR [rdx+168]",
+ "xor r15, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r9",
+ "mov r9, QWORD PTR [rdx+152]",
+ "xor r9, rbx",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+152]",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r9, rax",
+ "and r9, r15",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, r9",
+ "and r11, r8",
+ "xor r11, QWORD PTR [rdx+88]",
+ "and r11, QWORD PTR [rdx+120]",
+ "xor r14, r11",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "mov r11, r10",
+ "and r11, QWORD PTR [rdx+128]",
+ "xor rbx, r11",
+ "mov r11, rcx",
+ "xor r11, rax",
+ "and r11, r10",
+ "xor rbp, r11",
+ "and rbp, r8",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+96]",
+ "and rax, QWORD PTR [rdx+144]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor r15, rax",
+ "xor rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor rcx, r9",
+ "mov r9, QWORD PTR [rdx+168]",
+ "xor r9, QWORD PTR [rdx+160]",
+ "xor r9, QWORD PTR [rdx+64]",
+ "and r10, r9",
+ "xor rcx, r10",
+ "and r8, rcx",
+ "xor r15, r8",
+ "and r15, QWORD PTR [rdx+120]",
+ "xor rbx, r15",
+ "mov rax, QWORD PTR [rdx+72]",
+ "mov rcx, QWORD PTR [rdx+80]",
+ "mov r8, r14",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 35",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 57",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 46",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 40",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 7",
+ "mov rbp, rbx",
+ "shr rbp, 12",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 8",
+ "mov rbp, rbx",
+ "shr rbp, 13",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 9",
+ "mov rbp, rbx",
+ "shr rbp, 14",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 10",
+ "mov rbp, rbx",
+ "shr rbp, 15",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 11",
+ "mov rbp, rbx",
+ "shr rbp, 16",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 12",
+ "mov rbp, rbx",
+ "shr rbp, 17",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r9",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], rbp",
+ "mov rbp, r15",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r10",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, rcx",
+ "and r10, r9",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "xor r15, r10",
+ "and r15, r8",
+ "xor rbp, r15",
+ "mov r15, r10",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r10",
+ "mov r10, r9",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rax",
+ "mov rax, rcx",
+ "and rax, r10",
+ "mov QWORD PTR [rdx+120], r10",
+ "mov r10, r9",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+128], rax",
+ "mov rax, r8",
+ "and rax, r10",
+ "xor r15, rax",
+ "and r15, r11",
+ "xor rbp, r15",
+ "mov r15, r14",
+ "xor r15, r9",
+ "mov QWORD PTR [rdx+136], r10",
+ "mov r10, rcx",
+ "and r10, r15",
+ "mov QWORD PTR [rdx+144], rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, r10",
+ "and rax, r8",
+ "and r9, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+152], rcx",
+ "mov rcx, r14",
+ "xor rcx, r9",
+ "mov QWORD PTR [rdx+160], r14",
+ "mov r14, r15",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "xor r14, r10",
+ "and r14, r8",
+ "xor r14, rcx",
+ "and r14, r11",
+ "xor rax, r14",
+ "and rax, QWORD PTR [rdx+80]",
+ "xor rbp, rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+96]",
+ "mov r14, r9",
+ "xor r14, rax",
+ "mov QWORD PTR [rdx+168], rbp",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "and rbp, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+72], r10",
+ "mov r10, r8",
+ "and r10, rcx",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and rbp, r8",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r14, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+152]",
+ "xor rcx, r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+120], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+160]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r8",
+ "and rbp, rax",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor rcx, r10",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r14, rcx",
+ "xor r15, QWORD PTR [rdx+128]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, QWORD PTR [rdx+96]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor r10, rcx",
+ "mov rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r15, r10",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, QWORD PTR [rdx+120]",
+ "xor r9, QWORD PTR [rdx+152]",
+ "and r9, r8",
+ "xor r10, r9",
+ "and r10, r11",
+ "xor rbx, r10",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r15, rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+152]",
+ "xor rbx, QWORD PTR [rdx+144]",
+ "mov r10, r11",
+ "and r10, QWORD PTR [rdx+136]",
+ "xor rbx, r10",
+ "mov r10, rcx",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and r10, r8",
+ "xor r10, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+152]",
+ "and r9, rcx",
+ "xor rcx, r9",
+ "xor rax, QWORD PTR [rdx+88]",
+ "and r8, rax",
+ "xor rcx, r8",
+ "and r11, rcx",
+ "xor r10, r11",
+ "and r10, QWORD PTR [rdx+80]",
+ "xor rbx, r10",
+ "mov rax, QWORD PTR [rdx+168]",
+ "mov rcx, r14",
+ "mov r8, r15",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 51",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 43",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 61",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 36",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 3",
+ "mov rbp, rbx",
+ "shr rbp, 6",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 4",
+ "mov rbp, rbx",
+ "shr rbp, 7",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 5",
+ "mov rbp, rbx",
+ "shr rbp, 8",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 6",
+ "mov rbp, rbx",
+ "shr rbp, 9",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 7",
+ "mov rbp, rbx",
+ "shr rbp, 10",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 8",
+ "mov rbp, rbx",
+ "shr rbp, 11",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rax",
+ "mov r15, rax",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, r8",
+ "and rcx, r15",
+ "mov QWORD PTR [rdx+80], r10",
+ "mov r10, r14",
+ "xor r10, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r15",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, r8",
+ "and r14, rcx",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r9",
+ "and r14, r15",
+ "xor r10, r14",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "and r11, r14",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, r8",
+ "and r14, r11",
+ "mov QWORD PTR [rdx+136], r11",
+ "mov r11, rbp",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+144], rbp",
+ "mov rbp, r9",
+ "and rbp, rcx",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r10, r11",
+ "mov r11, r9",
+ "and r11, QWORD PTR [rdx+112]",
+ "xor r15, r11",
+ "mov r11, r8",
+ "and r11, rax",
+ "xor r11, QWORD PTR [rdx+104]",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r15, r11",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r10, r15",
+ "mov r15, QWORD PTR [rdx+104]",
+ "xor r15, r8",
+ "mov r11, QWORD PTR [rdx+96]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r10",
+ "mov r10, r11",
+ "xor r10, r14",
+ "and r10, r9",
+ "xor r15, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, QWORD PTR [rdx+144]",
+ "xor rbp, r10",
+ "mov QWORD PTR [rdx+168], r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, QWORD PTR [rdx+104]",
+ "mov QWORD PTR [rdx+104], rcx",
+ "mov rcx, r10",
+ "xor rcx, r14",
+ "and rcx, r9",
+ "xor rbp, rcx",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor r15, rbp",
+ "mov rbp, QWORD PTR [rdx+128]",
+ "xor rbp, QWORD PTR [rdx+136]",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r8",
+ "xor rax, rbp",
+ "xor rax, rcx",
+ "mov rcx, r8",
+ "and rcx, r11",
+ "mov QWORD PTR [rdx+176], rbp",
+ "mov rbp, r9",
+ "and rbp, r10",
+ "xor rcx, rbp",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor rax, rcx",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov rbx, r8",
+ "and rbx, QWORD PTR [rdx+128]",
+ "mov rax, r10",
+ "xor rax, rbx",
+ "mov rcx, r9",
+ "and rcx, QWORD PTR [rdx+120]",
+ "xor rax, rcx",
+ "xor r11, QWORD PTR [rdx+112]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+168]",
+ "and rbp, r9",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor rax, r11",
+ "mov r11, r8",
+ "and r11, QWORD PTR [rdx+96]",
+ "and r11, r9",
+ "xor r11, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+80]",
+ "xor r11, r14",
+ "and r11, QWORD PTR [rdx+72]",
+ "xor rax, r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, QWORD PTR [rdx+168]",
+ "xor r11, QWORD PTR [rdx+160]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "and r8, QWORD PTR [rdx+176]",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "xor r10, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+120]",
+ "and r9, r8",
+ "xor r10, r9",
+ "xor rcx, QWORD PTR [rdx+168]",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r10, rcx",
+ "and r10, QWORD PTR [rdx+72]",
+ "xor r11, r10",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "mov rcx, r15",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r11",
+ "and rax, 1",
+ "ror rax, 39",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 54",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 44",
+ "xor r12, r8",
+ "and r9, 1",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 31",
+ "mov rbp, rbx",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "mov rbp, rbx",
+ "shr rbp, 1",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 1",
+ "mov rbp, rbx",
+ "shr rbp, 2",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 2",
+ "mov rbp, rbx",
+ "shr rbp, 3",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 3",
+ "mov rbp, rbx",
+ "shr rbp, 4",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 4",
+ "mov rbp, rbx",
+ "shr rbp, 5",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r11",
+ "xor r15, r14",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r15",
+ "xor r8, r9",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor r8, rcx",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r9",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+88], rax",
+ "mov rax, r14",
+ "and rax, r11",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, r14",
+ "xor r9, rbp",
+ "and r9, rcx",
+ "xor r9, r15",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r9, r10",
+ "xor r8, r9",
+ "mov r9, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "and rbp, r9",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, rcx",
+ "xor r14, rbp",
+ "mov rbp, r11",
+ "xor rbp, rax",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r15",
+ "mov r15, QWORD PTR [rdx+96]",
+ "xor r15, r8",
+ "mov QWORD PTR [rdx+96], r11",
+ "mov r11, rcx",
+ "and r11, r9",
+ "xor r15, r11",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "xor r9, r8",
+ "and r9, rcx",
+ "xor rax, r9",
+ "mov r9, QWORD PTR [rdx+112]",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rbp, r9",
+ "and rbp, r10",
+ "xor rax, rbp",
+ "mov rbp, QWORD PTR [rdx+96]",
+ "xor rbp, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rbp",
+ "xor r9, QWORD PTR [rdx+144]",
+ "mov QWORD PTR [rdx+144], r11",
+ "mov r11, rcx",
+ "and r11, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r8",
+ "mov r8, r9",
+ "xor r8, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor r9, rbp",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, r15",
+ "xor rax, r8",
+ "mov r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+112]",
+ "mov r9, QWORD PTR [rdx+104]",
+ "and r9, r14",
+ "xor r9, QWORD PTR [rdx+96]",
+ "mov rbp, rcx",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "mov rbp, r14",
+ "xor rbp, QWORD PTR [rdx+80]",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov rbp, QWORD PTR [rdx+72]",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+144]",
+ "and rbp, r10",
+ "xor r14, rbp",
+ "and r14, r15",
+ "xor r8, r14",
+ "mov r14, rcx",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "and r14, QWORD PTR [rdx+128]",
+ "xor r14, QWORD PTR [rdx+72]",
+ "mov rbp, QWORD PTR [rdx+88]",
+ "xor rbp, QWORD PTR [rdx+152]",
+ "and rbp, rcx",
+ "xor rbp, r14",
+ "and rbp, r10",
+ "xor r9, rbp",
+ "xor r11, QWORD PTR [rdx+136]",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and rcx, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r10, r14",
+ "xor r11, r10",
+ "and r15, r11",
+ "xor r9, r15",
+ "mov QWORD PTR [rdx+160], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "and rax, 1",
+ "ror rax, 53",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 47",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 59",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 37",
+ "xor r12, r9",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "add rdi, 8",
+ "mov rax, QWORD PTR [rdx+56]",
+ "sub rax, 1",
+ "mov QWORD PTR [rdx+56], rax",
+ "jne 22b",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "mov rax, r12",
+ "ror rax, 32",
+ "xor rax, r13",
+ "mov rbx, 0",
+ "mov rbp, rax",
+ "shr rbp, 24",
+ "and rbp, 1",
+ "ror rbp, 1",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 56",
+ "and rbp, 1",
+ "ror rbp, 2",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 16",
+ "and rbp, 1",
+ "ror rbp, 3",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 48",
+ "and rbp, 1",
+ "ror rbp, 4",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 8",
+ "and rbp, 1",
+ "ror rbp, 5",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 40",
+ "and rbp, 1",
+ "ror rbp, 6",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "and rbp, 1",
+ "ror rbp, 7",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 32",
+ "and rbp, 1",
+ "ror rbp, 8",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 25",
+ "and rbp, 1",
+ "ror rbp, 9",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 57",
+ "and rbp, 1",
+ "ror rbp, 10",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 17",
+ "and rbp, 1",
+ "ror rbp, 11",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 49",
+ "and rbp, 1",
+ "ror rbp, 12",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 9",
+ "and rbp, 1",
+ "ror rbp, 13",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 41",
+ "and rbp, 1",
+ "ror rbp, 14",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 1",
+ "and rbp, 1",
+ "ror rbp, 15",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 33",
+ "and rbp, 1",
+ "ror rbp, 16",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 26",
+ "and rbp, 1",
+ "ror rbp, 17",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 58",
+ "and rbp, 1",
+ "ror rbp, 18",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 18",
+ "and rbp, 1",
+ "ror rbp, 19",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 50",
+ "and rbp, 1",
+ "ror rbp, 20",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 10",
+ "and rbp, 1",
+ "ror rbp, 21",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 42",
+ "and rbp, 1",
+ "ror rbp, 22",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 2",
+ "and rbp, 1",
+ "ror rbp, 23",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 34",
+ "and rbp, 1",
+ "ror rbp, 24",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 27",
+ "and rbp, 1",
+ "ror rbp, 25",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 59",
+ "and rbp, 1",
+ "ror rbp, 26",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 19",
+ "and rbp, 1",
+ "ror rbp, 27",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 51",
+ "and rbp, 1",
+ "ror rbp, 28",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 11",
+ "and rbp, 1",
+ "ror rbp, 29",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 43",
+ "and rbp, 1",
+ "ror rbp, 30",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 3",
+ "and rbp, 1",
+ "ror rbp, 31",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 35",
+ "and rbp, 1",
+ "ror rbp, 32",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 28",
+ "and rbp, 1",
+ "ror rbp, 33",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 60",
+ "and rbp, 1",
+ "ror rbp, 34",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 20",
+ "and rbp, 1",
+ "ror rbp, 35",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 52",
+ "and rbp, 1",
+ "ror rbp, 36",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 12",
+ "and rbp, 1",
+ "ror rbp, 37",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 44",
+ "and rbp, 1",
+ "ror rbp, 38",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 4",
+ "and rbp, 1",
+ "ror rbp, 39",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 36",
+ "and rbp, 1",
+ "ror rbp, 40",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 29",
+ "and rbp, 1",
+ "ror rbp, 41",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 61",
+ "and rbp, 1",
+ "ror rbp, 42",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 21",
+ "and rbp, 1",
+ "ror rbp, 43",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 53",
+ "and rbp, 1",
+ "ror rbp, 44",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 13",
+ "and rbp, 1",
+ "ror rbp, 45",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 45",
+ "and rbp, 1",
+ "ror rbp, 46",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 5",
+ "and rbp, 1",
+ "ror rbp, 47",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 37",
+ "and rbp, 1",
+ "ror rbp, 48",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 30",
+ "and rbp, 1",
+ "ror rbp, 49",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 62",
+ "and rbp, 1",
+ "ror rbp, 50",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 22",
+ "and rbp, 1",
+ "ror rbp, 51",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 54",
+ "and rbp, 1",
+ "ror rbp, 52",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 14",
+ "and rbp, 1",
+ "ror rbp, 53",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 46",
+ "and rbp, 1",
+ "ror rbp, 54",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 6",
+ "and rbp, 1",
+ "ror rbp, 55",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 38",
+ "and rbp, 1",
+ "ror rbp, 56",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 31",
+ "and rbp, 1",
+ "ror rbp, 57",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 63",
+ "and rbp, 1",
+ "ror rbp, 58",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 23",
+ "and rbp, 1",
+ "ror rbp, 59",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 55",
+ "and rbp, 1",
+ "ror rbp, 60",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 15",
+ "and rbp, 1",
+ "ror rbp, 61",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 47",
+ "and rbp, 1",
+ "ror rbp, 62",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 7",
+ "and rbp, 1",
+ "ror rbp, 63",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 39",
+ "and rbp, 1",
+ "xor rbx, rbp",
+ "bswap rbx",
+ "mov rax, rbx",
+ "mov rbx, QWORD PTR [rdx]",
+ "mov rbp, QWORD PTR [rdx+8]",
+ "mov r12, QWORD PTR [rdx+16]",
+ "mov r13, QWORD PTR [rdx+24]",
+ "mov r14, QWORD PTR [rdx+32]",
+ "mov r15, QWORD PTR [rdx+40]",
+ "mov rdi, QWORD PTR [rdx+48]",
+ "mov QWORD PTR [rsi], rax",
+ "ret",
+ )
+}
+
+/// Triple DES block decryption (FIPS 46-3): transforms the 8 bytes at `data` in place under the three DES schedules at `schedule`. Each schedule contains sixteen encryption-order 48-bit round keys in little-endian 64-bit slots; upper bits are ignored.
+///
+/// Contract: `VG.Spec.TripleDes.decryptBlockContract`. Constant time: only pointers may affect timing, not the schedule or data, including S-box inputs.
+///
+/// Baseline x86-64 scalar Boolean S-box circuits with reverse EDE key order.
+///
+/// # Safety
+///
+/// * `schedule` must be valid for reads of 384 bytes.
+/// * `data` must be valid for reads and writes of 8 bytes.
+/// * `scratch` must be valid for reads and writes of 512 bytes.
+/// * The contents of `scratch` on return are unspecified.
+/// * `data` and `scratch` must not overlap each other or `schedule` (distinct Rust objects never do).
+/// * None of `schedule`, `data` and `scratch` may overlap the return address on the stack, or wrap around the end of the address space (no Rust object does).
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_triple_des_decrypt_block(schedule: *const [u8; 384], data: *mut [u8; 8], scratch: *mut [u64; 64]) {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rdx], rbx",
+ "mov QWORD PTR [rdx+8], rbp",
+ "mov QWORD PTR [rdx+16], r12",
+ "mov QWORD PTR [rdx+24], r13",
+ "mov QWORD PTR [rdx+32], r14",
+ "mov QWORD PTR [rdx+40], r15",
+ "mov QWORD PTR [rdx+48], rdi",
+ "mov rax, QWORD PTR [rsi]",
+ "bswap rax",
+ "mov rbx, 0",
+ "mov rbp, rax",
+ "shr rbp, 6",
+ "and rbp, 1",
+ "ror rbp, 1",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 14",
+ "and rbp, 1",
+ "ror rbp, 2",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 22",
+ "and rbp, 1",
+ "ror rbp, 3",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 30",
+ "and rbp, 1",
+ "ror rbp, 4",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 38",
+ "and rbp, 1",
+ "ror rbp, 5",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 46",
+ "and rbp, 1",
+ "ror rbp, 6",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 54",
+ "and rbp, 1",
+ "ror rbp, 7",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 62",
+ "and rbp, 1",
+ "ror rbp, 8",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 4",
+ "and rbp, 1",
+ "ror rbp, 9",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 12",
+ "and rbp, 1",
+ "ror rbp, 10",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 20",
+ "and rbp, 1",
+ "ror rbp, 11",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 28",
+ "and rbp, 1",
+ "ror rbp, 12",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 36",
+ "and rbp, 1",
+ "ror rbp, 13",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 44",
+ "and rbp, 1",
+ "ror rbp, 14",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 52",
+ "and rbp, 1",
+ "ror rbp, 15",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 60",
+ "and rbp, 1",
+ "ror rbp, 16",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 2",
+ "and rbp, 1",
+ "ror rbp, 17",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 10",
+ "and rbp, 1",
+ "ror rbp, 18",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 18",
+ "and rbp, 1",
+ "ror rbp, 19",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 26",
+ "and rbp, 1",
+ "ror rbp, 20",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 34",
+ "and rbp, 1",
+ "ror rbp, 21",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 42",
+ "and rbp, 1",
+ "ror rbp, 22",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 50",
+ "and rbp, 1",
+ "ror rbp, 23",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 58",
+ "and rbp, 1",
+ "ror rbp, 24",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "and rbp, 1",
+ "ror rbp, 25",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 8",
+ "and rbp, 1",
+ "ror rbp, 26",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 16",
+ "and rbp, 1",
+ "ror rbp, 27",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 24",
+ "and rbp, 1",
+ "ror rbp, 28",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 32",
+ "and rbp, 1",
+ "ror rbp, 29",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 40",
+ "and rbp, 1",
+ "ror rbp, 30",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 48",
+ "and rbp, 1",
+ "ror rbp, 31",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 56",
+ "and rbp, 1",
+ "ror rbp, 32",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 7",
+ "and rbp, 1",
+ "ror rbp, 33",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 15",
+ "and rbp, 1",
+ "ror rbp, 34",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 23",
+ "and rbp, 1",
+ "ror rbp, 35",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 31",
+ "and rbp, 1",
+ "ror rbp, 36",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 39",
+ "and rbp, 1",
+ "ror rbp, 37",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 47",
+ "and rbp, 1",
+ "ror rbp, 38",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 55",
+ "and rbp, 1",
+ "ror rbp, 39",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 63",
+ "and rbp, 1",
+ "ror rbp, 40",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 5",
+ "and rbp, 1",
+ "ror rbp, 41",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 13",
+ "and rbp, 1",
+ "ror rbp, 42",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 21",
+ "and rbp, 1",
+ "ror rbp, 43",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 29",
+ "and rbp, 1",
+ "ror rbp, 44",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 37",
+ "and rbp, 1",
+ "ror rbp, 45",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 45",
+ "and rbp, 1",
+ "ror rbp, 46",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 53",
+ "and rbp, 1",
+ "ror rbp, 47",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 61",
+ "and rbp, 1",
+ "ror rbp, 48",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 3",
+ "and rbp, 1",
+ "ror rbp, 49",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 11",
+ "and rbp, 1",
+ "ror rbp, 50",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 19",
+ "and rbp, 1",
+ "ror rbp, 51",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 27",
+ "and rbp, 1",
+ "ror rbp, 52",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 35",
+ "and rbp, 1",
+ "ror rbp, 53",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 43",
+ "and rbp, 1",
+ "ror rbp, 54",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 51",
+ "and rbp, 1",
+ "ror rbp, 55",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 59",
+ "and rbp, 1",
+ "ror rbp, 56",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 1",
+ "and rbp, 1",
+ "ror rbp, 57",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 9",
+ "and rbp, 1",
+ "ror rbp, 58",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 17",
+ "and rbp, 1",
+ "ror rbp, 59",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 25",
+ "and rbp, 1",
+ "ror rbp, 60",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 33",
+ "and rbp, 1",
+ "ror rbp, 61",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 41",
+ "and rbp, 1",
+ "ror rbp, 62",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 49",
+ "and rbp, 1",
+ "ror rbp, 63",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 57",
+ "and rbp, 1",
+ "xor rbx, rbp",
+ "mov r12, rbx",
+ "shr r12, 32",
+ "mov r13d, ebx",
+ "mov rdi, QWORD PTR [rdx+48]",
+ "add rdi, 376",
+ "mov rax, 16",
+ "mov QWORD PTR [rdx+56], rax",
+ "20:",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 27",
+ "mov rbp, rbx",
+ "shr rbp, 42",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 28",
+ "mov rbp, rbx",
+ "shr rbp, 43",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 29",
+ "mov rbp, rbx",
+ "shr rbp, 44",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 30",
+ "mov rbp, rbx",
+ "shr rbp, 45",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 31",
+ "mov rbp, rbx",
+ "shr rbp, 46",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "mov rbp, rbx",
+ "shr rbp, 47",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov r15, rax",
+ "xor r15, r10",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, rcx",
+ "and r8, r15",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, rcx",
+ "and r14, r15",
+ "xor r14, rax",
+ "and r14, r11",
+ "xor r8, r14",
+ "mov r14, r10",
+ "and r14, rax",
+ "mov QWORD PTR [rdx+96], rax",
+ "mov rax, r14",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rcx",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbx",
+ "mov rbx, r14",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+136], r15",
+ "mov r15, r11",
+ "and r15, rbx",
+ "xor rbp, r15",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "and r10, rcx",
+ "mov rbp, rax",
+ "xor rbp, r10",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, r15",
+ "and r10, r11",
+ "xor rbp, r10",
+ "mov r10, rcx",
+ "and r10, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, r10",
+ "and r14, r11",
+ "and r14, r9",
+ "xor rbp, r14",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r8, rbp",
+ "mov rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "mov r14, rbp",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor rbp, r8",
+ "mov QWORD PTR [rdx+112], rbx",
+ "mov rbx, r11",
+ "and rbx, rbp",
+ "xor r14, rbx",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r15, rbx",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r15",
+ "xor r10, rbx",
+ "and r10, r9",
+ "xor r14, r10",
+ "xor rbp, rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+96]",
+ "mov r10, r8",
+ "xor r10, rbx",
+ "and r10, r11",
+ "mov QWORD PTR [rdx+168], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "xor r8, r10",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r14, rbp",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, rbx",
+ "mov r8, r11",
+ "and r8, r15",
+ "xor rbp, r8",
+ "xor rax, QWORD PTR [rdx+88]",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+168]",
+ "and r8, r11",
+ "xor rax, r8",
+ "and rax, r9",
+ "xor rbp, rax",
+ "mov rax, r11",
+ "and rax, QWORD PTR [rdx+136]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, rbx",
+ "xor rax, r10",
+ "and rax, r9",
+ "xor r15, rax",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor rbp, r15",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+128]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "xor r15, rcx",
+ "mov rax, QWORD PTR [rdx+136]",
+ "xor rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r11",
+ "xor rax, r15",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r10, r11",
+ "xor r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor rax, r10",
+ "mov r10, QWORD PTR [rdx+104]",
+ "xor r10, QWORD PTR [rdx+144]",
+ "and r10, r11",
+ "xor rbx, r10",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and r11, rcx",
+ "xor r15, r11",
+ "and r9, r15",
+ "xor rbx, r9",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor rax, rbx",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r14",
+ "mov r8, rbp",
+ "mov r9, QWORD PTR [rdx+72]",
+ "and rax, 1",
+ "ror rax, 63",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 55",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 49",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 41",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 23",
+ "mov rbp, rbx",
+ "shr rbp, 36",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 24",
+ "mov rbp, rbx",
+ "shr rbp, 37",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 25",
+ "mov rbp, rbx",
+ "shr rbp, 38",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 26",
+ "mov rbp, rbx",
+ "shr rbp, 39",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 27",
+ "mov rbp, rbx",
+ "shr rbp, 40",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 28",
+ "mov rbp, rbx",
+ "shr rbp, 41",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r11",
+ "mov r11, rax",
+ "and r11, r8",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+88], rbp",
+ "mov rbp, r15",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, r10",
+ "xor r11, rbp",
+ "mov QWORD PTR [rdx+112], r15",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+120], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, rax",
+ "and r14, r8",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, rbp",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+144], r14",
+ "mov r14, rbp",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], rbp",
+ "mov rbp, rax",
+ "and rbp, r14",
+ "xor rbp, rcx",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "and r8, r9",
+ "xor r11, r8",
+ "mov r8, rax",
+ "and r8, r15",
+ "xor r8, QWORD PTR [rdx+88]",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+160], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rcx",
+ "xor r9, r15",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor r11, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, QWORD PTR [rdx+96]",
+ "mov r9, rbp",
+ "xor r9, r8",
+ "xor r15, QWORD PTR [rdx+136]",
+ "and r15, r10",
+ "xor r9, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+80]",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+104]",
+ "mov r15, rax",
+ "and r15, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, QWORD PTR [rdx+152]",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+152], r15",
+ "mov r15, r10",
+ "and r15, QWORD PTR [rdx+80]",
+ "xor r11, r15",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and r14, QWORD PTR [rdx+72]",
+ "xor r9, r14",
+ "mov r14, rbp",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, r8",
+ "and r11, r10",
+ "xor r11, rax",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and rax, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rax",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, QWORD PTR [rdx+112]",
+ "and r11, r10",
+ "xor rcx, r11",
+ "and rax, QWORD PTR [rdx+168]",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+72]",
+ "xor r14, rcx",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "mov rcx, r10",
+ "and rcx, QWORD PTR [rdx+144]",
+ "xor rbp, rcx",
+ "mov rcx, r8",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+168]",
+ "xor rbp, rcx",
+ "xor r8, QWORD PTR [rdx+160]",
+ "xor rbx, r8",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "and r10, rbx",
+ "xor r8, r10",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor rbp, r8",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r9",
+ "mov r8, r14",
+ "mov r9, rbp",
+ "and rax, 1",
+ "ror rax, 50",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 34",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 60",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 45",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 19",
+ "mov rbp, rbx",
+ "shr rbp, 30",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 20",
+ "mov rbp, rbx",
+ "shr rbp, 31",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 21",
+ "mov rbp, rbx",
+ "shr rbp, 32",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 22",
+ "mov rbp, rbx",
+ "shr rbp, 33",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 23",
+ "mov rbp, rbx",
+ "shr rbp, 34",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 24",
+ "mov rbp, rbx",
+ "shr rbp, 35",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r10",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r10",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r14",
+ "xor r10, r15",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, rax",
+ "and r14, r10",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+112], r8",
+ "mov r8, r10",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+120], rbx",
+ "mov rbx, r8",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+128], r8",
+ "mov r8, rcx",
+ "and r8, rbx",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+136], rbp",
+ "mov rbp, rcx",
+ "and rbp, r10",
+ "xor rbx, rbp",
+ "and rbx, r9",
+ "xor r8, rbx",
+ "and r11, rax",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, r11",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+96]",
+ "xor rbx, rbp",
+ "and r15, r9",
+ "xor rbx, r15",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r8, rbx",
+ "mov rbx, QWORD PTR [rdx+96]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "xor r14, rbx",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+120]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov rbp, rax",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+104], r8",
+ "mov r8, rcx",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, r14",
+ "xor r10, r8",
+ "mov QWORD PTR [rdx+152], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], r11",
+ "mov r11, rax",
+ "and r11, rbx",
+ "mov QWORD PTR [rdx+168], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, r11",
+ "mov QWORD PTR [rdx+88], r11",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+96]",
+ "mov QWORD PTR [rdx+176], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, r11",
+ "and r8, rcx",
+ "xor rbx, r8",
+ "and rbx, r9",
+ "xor r10, rbx",
+ "mov rbx, QWORD PTR [rdx+136]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "mov r14, QWORD PTR [rdx+112]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r15",
+ "xor r14, r8",
+ "mov QWORD PTR [rdx+96], r8",
+ "mov r8, r11",
+ "xor r8, QWORD PTR [rdx+120]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r8, rcx",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r10, rbx",
+ "mov rbx, rax",
+ "and rbx, r15",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "mov r14, rbp",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "and rbp, r9",
+ "xor rbx, rbp",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, QWORD PTR [rdx+88]",
+ "xor rbp, r8",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+80]",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, rcx",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rax, rbp",
+ "xor rax, QWORD PTR [rdx+168]",
+ "and rax, rcx",
+ "xor rax, QWORD PTR [rdx+144]",
+ "and rax, r9",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+112]",
+ "xor rax, r11",
+ "mov rbp, QWORD PTR [rdx+136]",
+ "xor rbp, QWORD PTR [rdx+96]",
+ "and rbp, rcx",
+ "xor rax, rbp",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+136]",
+ "and r9, rcx",
+ "xor rax, r9",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+104]",
+ "mov rcx, r10",
+ "mov r8, rbx",
+ "mov r9, r15",
+ "and rax, 1",
+ "ror rax, 38",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 62",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 48",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 56",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 15",
+ "mov rbp, rbx",
+ "shr rbp, 24",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 16",
+ "mov rbp, rbx",
+ "shr rbp, 25",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 17",
+ "mov rbp, rbx",
+ "shr rbp, 26",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 18",
+ "mov rbp, rbx",
+ "shr rbp, 27",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 19",
+ "mov rbp, rbx",
+ "shr rbp, 28",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 20",
+ "mov rbp, rbx",
+ "shr rbp, 29",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r9",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, r11",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+88], r15",
+ "mov r15, r14",
+ "xor r15, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, rbp",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r11",
+ "and r14, r9",
+ "mov QWORD PTR [rdx+120], r9",
+ "mov r9, rbp",
+ "xor r9, r14",
+ "and r9, r10",
+ "xor r15, r9",
+ "mov r9, rcx",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, rcx",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov QWORD PTR [rdx+144], rcx",
+ "mov rcx, r9",
+ "xor rcx, r14",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, rax",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+120]",
+ "and rcx, r10",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, QWORD PTR [rdx+80]",
+ "xor r9, r14",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r11",
+ "and rax, r9",
+ "xor rcx, rax",
+ "mov QWORD PTR [rdx+160], r9",
+ "mov r9, r10",
+ "and r9, QWORD PTR [rdx+128]",
+ "xor rcx, r9",
+ "and rcx, r8",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "and rcx, rbp",
+ "xor r15, rcx",
+ "mov rcx, r11",
+ "and rcx, r14",
+ "mov QWORD PTR [rdx+128], r15",
+ "mov r15, QWORD PTR [rdx+120]",
+ "xor r15, rcx",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "and r11, r10",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, r14",
+ "xor r9, rax",
+ "mov QWORD PTR [rdx+176], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, QWORD PTR [rdx+136]",
+ "and r14, r10",
+ "xor r9, r14",
+ "and r9, r8",
+ "xor r11, r9",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r11, rbp",
+ "xor rax, QWORD PTR [rdx+80]",
+ "mov rbp, r10",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rax, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "and r14, r8",
+ "xor rax, r14",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r14, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+96]",
+ "xor r14, QWORD PTR [rdx+168]",
+ "and r14, r8",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+72]",
+ "and r14, r15",
+ "xor rax, r14",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "xor rbp, rcx",
+ "and r10, rbp",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "xor r10, QWORD PTR [rdx+88]",
+ "and r8, r10",
+ "xor r14, r8",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+128]",
+ "mov rcx, r11",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r14",
+ "and rax, 1",
+ "ror rax, 33",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 42",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 52",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 58",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 11",
+ "mov rbp, rbx",
+ "shr rbp, 18",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 12",
+ "mov rbp, rbx",
+ "shr rbp, 19",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 13",
+ "mov rbp, rbx",
+ "shr rbp, 20",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 14",
+ "mov rbp, rbx",
+ "shr rbp, 21",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 15",
+ "mov rbp, rbx",
+ "shr rbp, 22",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 16",
+ "mov rbp, rbx",
+ "shr rbp, 23",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r14",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, rax",
+ "and rbp, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r11",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r11",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r11",
+ "mov r11, r14",
+ "and r11, rbp",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, rbp",
+ "xor r14, r11",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, r10",
+ "and r11, r14",
+ "xor r11, rcx",
+ "mov QWORD PTR [rdx+128], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rcx",
+ "xor r14, r9",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r14, r8",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, rbp",
+ "xor r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+144], r9",
+ "mov r9, QWORD PTR [rdx+104]",
+ "xor r9, QWORD PTR [rdx+112]",
+ "and r15, rax",
+ "xor r15, r9",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+136]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, rbp",
+ "xor r9, rax",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+88]",
+ "xor r9, r14",
+ "xor r9, r10",
+ "mov QWORD PTR [rdx+72], r11",
+ "mov r11, QWORD PTR [rdx+120]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rax",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "mov QWORD PTR [rdx+80], r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r15",
+ "mov r15, r10",
+ "and r15, r14",
+ "xor r11, r15",
+ "and r11, r8",
+ "xor r9, r11",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+104]",
+ "xor rbp, r11",
+ "mov r15, r10",
+ "and r15, rbp",
+ "xor r15, rbx",
+ "and r15, r8",
+ "xor r14, r15",
+ "and r14, QWORD PTR [rdx+120]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+136]",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r15, QWORD PTR [rdx+168]",
+ "xor r15, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r9",
+ "mov r9, QWORD PTR [rdx+152]",
+ "xor r9, rbx",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+152]",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r9, rax",
+ "and r9, r15",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, r9",
+ "and r11, r8",
+ "xor r11, QWORD PTR [rdx+88]",
+ "and r11, QWORD PTR [rdx+120]",
+ "xor r14, r11",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "mov r11, r10",
+ "and r11, QWORD PTR [rdx+128]",
+ "xor rbx, r11",
+ "mov r11, rcx",
+ "xor r11, rax",
+ "and r11, r10",
+ "xor rbp, r11",
+ "and rbp, r8",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+96]",
+ "and rax, QWORD PTR [rdx+144]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor r15, rax",
+ "xor rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor rcx, r9",
+ "mov r9, QWORD PTR [rdx+168]",
+ "xor r9, QWORD PTR [rdx+160]",
+ "xor r9, QWORD PTR [rdx+64]",
+ "and r10, r9",
+ "xor rcx, r10",
+ "and r8, rcx",
+ "xor r15, r8",
+ "and r15, QWORD PTR [rdx+120]",
+ "xor rbx, r15",
+ "mov rax, QWORD PTR [rdx+72]",
+ "mov rcx, QWORD PTR [rdx+80]",
+ "mov r8, r14",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 35",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 57",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 46",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 40",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 7",
+ "mov rbp, rbx",
+ "shr rbp, 12",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 8",
+ "mov rbp, rbx",
+ "shr rbp, 13",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 9",
+ "mov rbp, rbx",
+ "shr rbp, 14",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 10",
+ "mov rbp, rbx",
+ "shr rbp, 15",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 11",
+ "mov rbp, rbx",
+ "shr rbp, 16",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 12",
+ "mov rbp, rbx",
+ "shr rbp, 17",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r9",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], rbp",
+ "mov rbp, r15",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r10",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, rcx",
+ "and r10, r9",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "xor r15, r10",
+ "and r15, r8",
+ "xor rbp, r15",
+ "mov r15, r10",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r10",
+ "mov r10, r9",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rax",
+ "mov rax, rcx",
+ "and rax, r10",
+ "mov QWORD PTR [rdx+120], r10",
+ "mov r10, r9",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+128], rax",
+ "mov rax, r8",
+ "and rax, r10",
+ "xor r15, rax",
+ "and r15, r11",
+ "xor rbp, r15",
+ "mov r15, r14",
+ "xor r15, r9",
+ "mov QWORD PTR [rdx+136], r10",
+ "mov r10, rcx",
+ "and r10, r15",
+ "mov QWORD PTR [rdx+144], rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, r10",
+ "and rax, r8",
+ "and r9, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+152], rcx",
+ "mov rcx, r14",
+ "xor rcx, r9",
+ "mov QWORD PTR [rdx+160], r14",
+ "mov r14, r15",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "xor r14, r10",
+ "and r14, r8",
+ "xor r14, rcx",
+ "and r14, r11",
+ "xor rax, r14",
+ "and rax, QWORD PTR [rdx+80]",
+ "xor rbp, rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+96]",
+ "mov r14, r9",
+ "xor r14, rax",
+ "mov QWORD PTR [rdx+168], rbp",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "and rbp, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+72], r10",
+ "mov r10, r8",
+ "and r10, rcx",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and rbp, r8",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r14, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+152]",
+ "xor rcx, r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+120], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+160]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r8",
+ "and rbp, rax",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor rcx, r10",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r14, rcx",
+ "xor r15, QWORD PTR [rdx+128]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, QWORD PTR [rdx+96]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor r10, rcx",
+ "mov rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r15, r10",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, QWORD PTR [rdx+120]",
+ "xor r9, QWORD PTR [rdx+152]",
+ "and r9, r8",
+ "xor r10, r9",
+ "and r10, r11",
+ "xor rbx, r10",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r15, rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+152]",
+ "xor rbx, QWORD PTR [rdx+144]",
+ "mov r10, r11",
+ "and r10, QWORD PTR [rdx+136]",
+ "xor rbx, r10",
+ "mov r10, rcx",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and r10, r8",
+ "xor r10, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+152]",
+ "and r9, rcx",
+ "xor rcx, r9",
+ "xor rax, QWORD PTR [rdx+88]",
+ "and r8, rax",
+ "xor rcx, r8",
+ "and r11, rcx",
+ "xor r10, r11",
+ "and r10, QWORD PTR [rdx+80]",
+ "xor rbx, r10",
+ "mov rax, QWORD PTR [rdx+168]",
+ "mov rcx, r14",
+ "mov r8, r15",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 51",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 43",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 61",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 36",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 3",
+ "mov rbp, rbx",
+ "shr rbp, 6",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 4",
+ "mov rbp, rbx",
+ "shr rbp, 7",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 5",
+ "mov rbp, rbx",
+ "shr rbp, 8",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 6",
+ "mov rbp, rbx",
+ "shr rbp, 9",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 7",
+ "mov rbp, rbx",
+ "shr rbp, 10",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 8",
+ "mov rbp, rbx",
+ "shr rbp, 11",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rax",
+ "mov r15, rax",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, r8",
+ "and rcx, r15",
+ "mov QWORD PTR [rdx+80], r10",
+ "mov r10, r14",
+ "xor r10, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r15",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, r8",
+ "and r14, rcx",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r9",
+ "and r14, r15",
+ "xor r10, r14",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "and r11, r14",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, r8",
+ "and r14, r11",
+ "mov QWORD PTR [rdx+136], r11",
+ "mov r11, rbp",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+144], rbp",
+ "mov rbp, r9",
+ "and rbp, rcx",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r10, r11",
+ "mov r11, r9",
+ "and r11, QWORD PTR [rdx+112]",
+ "xor r15, r11",
+ "mov r11, r8",
+ "and r11, rax",
+ "xor r11, QWORD PTR [rdx+104]",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r15, r11",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r10, r15",
+ "mov r15, QWORD PTR [rdx+104]",
+ "xor r15, r8",
+ "mov r11, QWORD PTR [rdx+96]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r10",
+ "mov r10, r11",
+ "xor r10, r14",
+ "and r10, r9",
+ "xor r15, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, QWORD PTR [rdx+144]",
+ "xor rbp, r10",
+ "mov QWORD PTR [rdx+168], r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, QWORD PTR [rdx+104]",
+ "mov QWORD PTR [rdx+104], rcx",
+ "mov rcx, r10",
+ "xor rcx, r14",
+ "and rcx, r9",
+ "xor rbp, rcx",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor r15, rbp",
+ "mov rbp, QWORD PTR [rdx+128]",
+ "xor rbp, QWORD PTR [rdx+136]",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r8",
+ "xor rax, rbp",
+ "xor rax, rcx",
+ "mov rcx, r8",
+ "and rcx, r11",
+ "mov QWORD PTR [rdx+176], rbp",
+ "mov rbp, r9",
+ "and rbp, r10",
+ "xor rcx, rbp",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor rax, rcx",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov rbx, r8",
+ "and rbx, QWORD PTR [rdx+128]",
+ "mov rax, r10",
+ "xor rax, rbx",
+ "mov rcx, r9",
+ "and rcx, QWORD PTR [rdx+120]",
+ "xor rax, rcx",
+ "xor r11, QWORD PTR [rdx+112]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+168]",
+ "and rbp, r9",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor rax, r11",
+ "mov r11, r8",
+ "and r11, QWORD PTR [rdx+96]",
+ "and r11, r9",
+ "xor r11, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+80]",
+ "xor r11, r14",
+ "and r11, QWORD PTR [rdx+72]",
+ "xor rax, r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, QWORD PTR [rdx+168]",
+ "xor r11, QWORD PTR [rdx+160]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "and r8, QWORD PTR [rdx+176]",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "xor r10, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+120]",
+ "and r9, r8",
+ "xor r10, r9",
+ "xor rcx, QWORD PTR [rdx+168]",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r10, rcx",
+ "and r10, QWORD PTR [rdx+72]",
+ "xor r11, r10",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "mov rcx, r15",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r11",
+ "and rax, 1",
+ "ror rax, 39",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 54",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 44",
+ "xor r12, r8",
+ "and r9, 1",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 31",
+ "mov rbp, rbx",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "mov rbp, rbx",
+ "shr rbp, 1",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 1",
+ "mov rbp, rbx",
+ "shr rbp, 2",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 2",
+ "mov rbp, rbx",
+ "shr rbp, 3",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 3",
+ "mov rbp, rbx",
+ "shr rbp, 4",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 4",
+ "mov rbp, rbx",
+ "shr rbp, 5",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r11",
+ "xor r15, r14",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r15",
+ "xor r8, r9",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor r8, rcx",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r9",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+88], rax",
+ "mov rax, r14",
+ "and rax, r11",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, r14",
+ "xor r9, rbp",
+ "and r9, rcx",
+ "xor r9, r15",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r9, r10",
+ "xor r8, r9",
+ "mov r9, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "and rbp, r9",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, rcx",
+ "xor r14, rbp",
+ "mov rbp, r11",
+ "xor rbp, rax",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r15",
+ "mov r15, QWORD PTR [rdx+96]",
+ "xor r15, r8",
+ "mov QWORD PTR [rdx+96], r11",
+ "mov r11, rcx",
+ "and r11, r9",
+ "xor r15, r11",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "xor r9, r8",
+ "and r9, rcx",
+ "xor rax, r9",
+ "mov r9, QWORD PTR [rdx+112]",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rbp, r9",
+ "and rbp, r10",
+ "xor rax, rbp",
+ "mov rbp, QWORD PTR [rdx+96]",
+ "xor rbp, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rbp",
+ "xor r9, QWORD PTR [rdx+144]",
+ "mov QWORD PTR [rdx+144], r11",
+ "mov r11, rcx",
+ "and r11, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r8",
+ "mov r8, r9",
+ "xor r8, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor r9, rbp",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, r15",
+ "xor rax, r8",
+ "mov r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+112]",
+ "mov r9, QWORD PTR [rdx+104]",
+ "and r9, r14",
+ "xor r9, QWORD PTR [rdx+96]",
+ "mov rbp, rcx",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "mov rbp, r14",
+ "xor rbp, QWORD PTR [rdx+80]",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov rbp, QWORD PTR [rdx+72]",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+144]",
+ "and rbp, r10",
+ "xor r14, rbp",
+ "and r14, r15",
+ "xor r8, r14",
+ "mov r14, rcx",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "and r14, QWORD PTR [rdx+128]",
+ "xor r14, QWORD PTR [rdx+72]",
+ "mov rbp, QWORD PTR [rdx+88]",
+ "xor rbp, QWORD PTR [rdx+152]",
+ "and rbp, rcx",
+ "xor rbp, r14",
+ "and rbp, r10",
+ "xor r9, rbp",
+ "xor r11, QWORD PTR [rdx+136]",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and rcx, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r10, r14",
+ "xor r11, r10",
+ "and r15, r11",
+ "xor r9, r15",
+ "mov QWORD PTR [rdx+160], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "and rax, 1",
+ "ror rax, 53",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 47",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 59",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 37",
+ "xor r12, r9",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "sub rdi, 8",
+ "mov rax, QWORD PTR [rdx+56]",
+ "sub rax, 1",
+ "mov QWORD PTR [rdx+56], rax",
+ "jne 20b",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "mov rdi, QWORD PTR [rdx+48]",
+ "add rdi, 128",
+ "mov rax, 16",
+ "mov QWORD PTR [rdx+56], rax",
+ "21:",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 27",
+ "mov rbp, rbx",
+ "shr rbp, 42",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 28",
+ "mov rbp, rbx",
+ "shr rbp, 43",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 29",
+ "mov rbp, rbx",
+ "shr rbp, 44",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 30",
+ "mov rbp, rbx",
+ "shr rbp, 45",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 31",
+ "mov rbp, rbx",
+ "shr rbp, 46",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "mov rbp, rbx",
+ "shr rbp, 47",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov r15, rax",
+ "xor r15, r10",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, rcx",
+ "and r8, r15",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, rcx",
+ "and r14, r15",
+ "xor r14, rax",
+ "and r14, r11",
+ "xor r8, r14",
+ "mov r14, r10",
+ "and r14, rax",
+ "mov QWORD PTR [rdx+96], rax",
+ "mov rax, r14",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rcx",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbx",
+ "mov rbx, r14",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+136], r15",
+ "mov r15, r11",
+ "and r15, rbx",
+ "xor rbp, r15",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "and r10, rcx",
+ "mov rbp, rax",
+ "xor rbp, r10",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, r15",
+ "and r10, r11",
+ "xor rbp, r10",
+ "mov r10, rcx",
+ "and r10, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, r10",
+ "and r14, r11",
+ "and r14, r9",
+ "xor rbp, r14",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r8, rbp",
+ "mov rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "mov r14, rbp",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor rbp, r8",
+ "mov QWORD PTR [rdx+112], rbx",
+ "mov rbx, r11",
+ "and rbx, rbp",
+ "xor r14, rbx",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r15, rbx",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r15",
+ "xor r10, rbx",
+ "and r10, r9",
+ "xor r14, r10",
+ "xor rbp, rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+96]",
+ "mov r10, r8",
+ "xor r10, rbx",
+ "and r10, r11",
+ "mov QWORD PTR [rdx+168], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "xor r8, r10",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r14, rbp",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, rbx",
+ "mov r8, r11",
+ "and r8, r15",
+ "xor rbp, r8",
+ "xor rax, QWORD PTR [rdx+88]",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+168]",
+ "and r8, r11",
+ "xor rax, r8",
+ "and rax, r9",
+ "xor rbp, rax",
+ "mov rax, r11",
+ "and rax, QWORD PTR [rdx+136]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, rbx",
+ "xor rax, r10",
+ "and rax, r9",
+ "xor r15, rax",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor rbp, r15",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+128]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "xor r15, rcx",
+ "mov rax, QWORD PTR [rdx+136]",
+ "xor rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r11",
+ "xor rax, r15",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r10, r11",
+ "xor r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor rax, r10",
+ "mov r10, QWORD PTR [rdx+104]",
+ "xor r10, QWORD PTR [rdx+144]",
+ "and r10, r11",
+ "xor rbx, r10",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and r11, rcx",
+ "xor r15, r11",
+ "and r9, r15",
+ "xor rbx, r9",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor rax, rbx",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r14",
+ "mov r8, rbp",
+ "mov r9, QWORD PTR [rdx+72]",
+ "and rax, 1",
+ "ror rax, 63",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 55",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 49",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 41",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 23",
+ "mov rbp, rbx",
+ "shr rbp, 36",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 24",
+ "mov rbp, rbx",
+ "shr rbp, 37",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 25",
+ "mov rbp, rbx",
+ "shr rbp, 38",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 26",
+ "mov rbp, rbx",
+ "shr rbp, 39",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 27",
+ "mov rbp, rbx",
+ "shr rbp, 40",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 28",
+ "mov rbp, rbx",
+ "shr rbp, 41",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r11",
+ "mov r11, rax",
+ "and r11, r8",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+88], rbp",
+ "mov rbp, r15",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, r10",
+ "xor r11, rbp",
+ "mov QWORD PTR [rdx+112], r15",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+120], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, rax",
+ "and r14, r8",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, rbp",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+144], r14",
+ "mov r14, rbp",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], rbp",
+ "mov rbp, rax",
+ "and rbp, r14",
+ "xor rbp, rcx",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "and r8, r9",
+ "xor r11, r8",
+ "mov r8, rax",
+ "and r8, r15",
+ "xor r8, QWORD PTR [rdx+88]",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+160], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rcx",
+ "xor r9, r15",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor r11, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, QWORD PTR [rdx+96]",
+ "mov r9, rbp",
+ "xor r9, r8",
+ "xor r15, QWORD PTR [rdx+136]",
+ "and r15, r10",
+ "xor r9, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+80]",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+104]",
+ "mov r15, rax",
+ "and r15, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, QWORD PTR [rdx+152]",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+152], r15",
+ "mov r15, r10",
+ "and r15, QWORD PTR [rdx+80]",
+ "xor r11, r15",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and r14, QWORD PTR [rdx+72]",
+ "xor r9, r14",
+ "mov r14, rbp",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, r8",
+ "and r11, r10",
+ "xor r11, rax",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and rax, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rax",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, QWORD PTR [rdx+112]",
+ "and r11, r10",
+ "xor rcx, r11",
+ "and rax, QWORD PTR [rdx+168]",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+72]",
+ "xor r14, rcx",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "mov rcx, r10",
+ "and rcx, QWORD PTR [rdx+144]",
+ "xor rbp, rcx",
+ "mov rcx, r8",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+168]",
+ "xor rbp, rcx",
+ "xor r8, QWORD PTR [rdx+160]",
+ "xor rbx, r8",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "and r10, rbx",
+ "xor r8, r10",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor rbp, r8",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r9",
+ "mov r8, r14",
+ "mov r9, rbp",
+ "and rax, 1",
+ "ror rax, 50",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 34",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 60",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 45",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 19",
+ "mov rbp, rbx",
+ "shr rbp, 30",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 20",
+ "mov rbp, rbx",
+ "shr rbp, 31",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 21",
+ "mov rbp, rbx",
+ "shr rbp, 32",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 22",
+ "mov rbp, rbx",
+ "shr rbp, 33",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 23",
+ "mov rbp, rbx",
+ "shr rbp, 34",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 24",
+ "mov rbp, rbx",
+ "shr rbp, 35",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r10",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r10",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r14",
+ "xor r10, r15",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, rax",
+ "and r14, r10",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+112], r8",
+ "mov r8, r10",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+120], rbx",
+ "mov rbx, r8",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+128], r8",
+ "mov r8, rcx",
+ "and r8, rbx",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+136], rbp",
+ "mov rbp, rcx",
+ "and rbp, r10",
+ "xor rbx, rbp",
+ "and rbx, r9",
+ "xor r8, rbx",
+ "and r11, rax",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, r11",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+96]",
+ "xor rbx, rbp",
+ "and r15, r9",
+ "xor rbx, r15",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r8, rbx",
+ "mov rbx, QWORD PTR [rdx+96]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "xor r14, rbx",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+120]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov rbp, rax",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+104], r8",
+ "mov r8, rcx",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, r14",
+ "xor r10, r8",
+ "mov QWORD PTR [rdx+152], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], r11",
+ "mov r11, rax",
+ "and r11, rbx",
+ "mov QWORD PTR [rdx+168], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, r11",
+ "mov QWORD PTR [rdx+88], r11",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+96]",
+ "mov QWORD PTR [rdx+176], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, r11",
+ "and r8, rcx",
+ "xor rbx, r8",
+ "and rbx, r9",
+ "xor r10, rbx",
+ "mov rbx, QWORD PTR [rdx+136]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "mov r14, QWORD PTR [rdx+112]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r15",
+ "xor r14, r8",
+ "mov QWORD PTR [rdx+96], r8",
+ "mov r8, r11",
+ "xor r8, QWORD PTR [rdx+120]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r8, rcx",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r10, rbx",
+ "mov rbx, rax",
+ "and rbx, r15",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "mov r14, rbp",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "and rbp, r9",
+ "xor rbx, rbp",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, QWORD PTR [rdx+88]",
+ "xor rbp, r8",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+80]",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, rcx",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rax, rbp",
+ "xor rax, QWORD PTR [rdx+168]",
+ "and rax, rcx",
+ "xor rax, QWORD PTR [rdx+144]",
+ "and rax, r9",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+112]",
+ "xor rax, r11",
+ "mov rbp, QWORD PTR [rdx+136]",
+ "xor rbp, QWORD PTR [rdx+96]",
+ "and rbp, rcx",
+ "xor rax, rbp",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+136]",
+ "and r9, rcx",
+ "xor rax, r9",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+104]",
+ "mov rcx, r10",
+ "mov r8, rbx",
+ "mov r9, r15",
+ "and rax, 1",
+ "ror rax, 38",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 62",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 48",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 56",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 15",
+ "mov rbp, rbx",
+ "shr rbp, 24",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 16",
+ "mov rbp, rbx",
+ "shr rbp, 25",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 17",
+ "mov rbp, rbx",
+ "shr rbp, 26",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 18",
+ "mov rbp, rbx",
+ "shr rbp, 27",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 19",
+ "mov rbp, rbx",
+ "shr rbp, 28",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 20",
+ "mov rbp, rbx",
+ "shr rbp, 29",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r9",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, r11",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+88], r15",
+ "mov r15, r14",
+ "xor r15, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, rbp",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r11",
+ "and r14, r9",
+ "mov QWORD PTR [rdx+120], r9",
+ "mov r9, rbp",
+ "xor r9, r14",
+ "and r9, r10",
+ "xor r15, r9",
+ "mov r9, rcx",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, rcx",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov QWORD PTR [rdx+144], rcx",
+ "mov rcx, r9",
+ "xor rcx, r14",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, rax",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+120]",
+ "and rcx, r10",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, QWORD PTR [rdx+80]",
+ "xor r9, r14",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r11",
+ "and rax, r9",
+ "xor rcx, rax",
+ "mov QWORD PTR [rdx+160], r9",
+ "mov r9, r10",
+ "and r9, QWORD PTR [rdx+128]",
+ "xor rcx, r9",
+ "and rcx, r8",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "and rcx, rbp",
+ "xor r15, rcx",
+ "mov rcx, r11",
+ "and rcx, r14",
+ "mov QWORD PTR [rdx+128], r15",
+ "mov r15, QWORD PTR [rdx+120]",
+ "xor r15, rcx",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "and r11, r10",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, r14",
+ "xor r9, rax",
+ "mov QWORD PTR [rdx+176], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, QWORD PTR [rdx+136]",
+ "and r14, r10",
+ "xor r9, r14",
+ "and r9, r8",
+ "xor r11, r9",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r11, rbp",
+ "xor rax, QWORD PTR [rdx+80]",
+ "mov rbp, r10",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rax, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "and r14, r8",
+ "xor rax, r14",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r14, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+96]",
+ "xor r14, QWORD PTR [rdx+168]",
+ "and r14, r8",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+72]",
+ "and r14, r15",
+ "xor rax, r14",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "xor rbp, rcx",
+ "and r10, rbp",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "xor r10, QWORD PTR [rdx+88]",
+ "and r8, r10",
+ "xor r14, r8",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+128]",
+ "mov rcx, r11",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r14",
+ "and rax, 1",
+ "ror rax, 33",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 42",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 52",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 58",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 11",
+ "mov rbp, rbx",
+ "shr rbp, 18",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 12",
+ "mov rbp, rbx",
+ "shr rbp, 19",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 13",
+ "mov rbp, rbx",
+ "shr rbp, 20",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 14",
+ "mov rbp, rbx",
+ "shr rbp, 21",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 15",
+ "mov rbp, rbx",
+ "shr rbp, 22",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 16",
+ "mov rbp, rbx",
+ "shr rbp, 23",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r14",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, rax",
+ "and rbp, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r11",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r11",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r11",
+ "mov r11, r14",
+ "and r11, rbp",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, rbp",
+ "xor r14, r11",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, r10",
+ "and r11, r14",
+ "xor r11, rcx",
+ "mov QWORD PTR [rdx+128], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rcx",
+ "xor r14, r9",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r14, r8",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, rbp",
+ "xor r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+144], r9",
+ "mov r9, QWORD PTR [rdx+104]",
+ "xor r9, QWORD PTR [rdx+112]",
+ "and r15, rax",
+ "xor r15, r9",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+136]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, rbp",
+ "xor r9, rax",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+88]",
+ "xor r9, r14",
+ "xor r9, r10",
+ "mov QWORD PTR [rdx+72], r11",
+ "mov r11, QWORD PTR [rdx+120]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rax",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "mov QWORD PTR [rdx+80], r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r15",
+ "mov r15, r10",
+ "and r15, r14",
+ "xor r11, r15",
+ "and r11, r8",
+ "xor r9, r11",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+104]",
+ "xor rbp, r11",
+ "mov r15, r10",
+ "and r15, rbp",
+ "xor r15, rbx",
+ "and r15, r8",
+ "xor r14, r15",
+ "and r14, QWORD PTR [rdx+120]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+136]",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r15, QWORD PTR [rdx+168]",
+ "xor r15, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r9",
+ "mov r9, QWORD PTR [rdx+152]",
+ "xor r9, rbx",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+152]",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r9, rax",
+ "and r9, r15",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, r9",
+ "and r11, r8",
+ "xor r11, QWORD PTR [rdx+88]",
+ "and r11, QWORD PTR [rdx+120]",
+ "xor r14, r11",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "mov r11, r10",
+ "and r11, QWORD PTR [rdx+128]",
+ "xor rbx, r11",
+ "mov r11, rcx",
+ "xor r11, rax",
+ "and r11, r10",
+ "xor rbp, r11",
+ "and rbp, r8",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+96]",
+ "and rax, QWORD PTR [rdx+144]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor r15, rax",
+ "xor rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor rcx, r9",
+ "mov r9, QWORD PTR [rdx+168]",
+ "xor r9, QWORD PTR [rdx+160]",
+ "xor r9, QWORD PTR [rdx+64]",
+ "and r10, r9",
+ "xor rcx, r10",
+ "and r8, rcx",
+ "xor r15, r8",
+ "and r15, QWORD PTR [rdx+120]",
+ "xor rbx, r15",
+ "mov rax, QWORD PTR [rdx+72]",
+ "mov rcx, QWORD PTR [rdx+80]",
+ "mov r8, r14",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 35",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 57",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 46",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 40",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 7",
+ "mov rbp, rbx",
+ "shr rbp, 12",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 8",
+ "mov rbp, rbx",
+ "shr rbp, 13",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 9",
+ "mov rbp, rbx",
+ "shr rbp, 14",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 10",
+ "mov rbp, rbx",
+ "shr rbp, 15",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 11",
+ "mov rbp, rbx",
+ "shr rbp, 16",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 12",
+ "mov rbp, rbx",
+ "shr rbp, 17",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r9",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], rbp",
+ "mov rbp, r15",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r10",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, rcx",
+ "and r10, r9",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "xor r15, r10",
+ "and r15, r8",
+ "xor rbp, r15",
+ "mov r15, r10",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r10",
+ "mov r10, r9",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rax",
+ "mov rax, rcx",
+ "and rax, r10",
+ "mov QWORD PTR [rdx+120], r10",
+ "mov r10, r9",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+128], rax",
+ "mov rax, r8",
+ "and rax, r10",
+ "xor r15, rax",
+ "and r15, r11",
+ "xor rbp, r15",
+ "mov r15, r14",
+ "xor r15, r9",
+ "mov QWORD PTR [rdx+136], r10",
+ "mov r10, rcx",
+ "and r10, r15",
+ "mov QWORD PTR [rdx+144], rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, r10",
+ "and rax, r8",
+ "and r9, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+152], rcx",
+ "mov rcx, r14",
+ "xor rcx, r9",
+ "mov QWORD PTR [rdx+160], r14",
+ "mov r14, r15",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "xor r14, r10",
+ "and r14, r8",
+ "xor r14, rcx",
+ "and r14, r11",
+ "xor rax, r14",
+ "and rax, QWORD PTR [rdx+80]",
+ "xor rbp, rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+96]",
+ "mov r14, r9",
+ "xor r14, rax",
+ "mov QWORD PTR [rdx+168], rbp",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "and rbp, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+72], r10",
+ "mov r10, r8",
+ "and r10, rcx",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and rbp, r8",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r14, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+152]",
+ "xor rcx, r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+120], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+160]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r8",
+ "and rbp, rax",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor rcx, r10",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r14, rcx",
+ "xor r15, QWORD PTR [rdx+128]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, QWORD PTR [rdx+96]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor r10, rcx",
+ "mov rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r15, r10",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, QWORD PTR [rdx+120]",
+ "xor r9, QWORD PTR [rdx+152]",
+ "and r9, r8",
+ "xor r10, r9",
+ "and r10, r11",
+ "xor rbx, r10",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r15, rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+152]",
+ "xor rbx, QWORD PTR [rdx+144]",
+ "mov r10, r11",
+ "and r10, QWORD PTR [rdx+136]",
+ "xor rbx, r10",
+ "mov r10, rcx",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and r10, r8",
+ "xor r10, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+152]",
+ "and r9, rcx",
+ "xor rcx, r9",
+ "xor rax, QWORD PTR [rdx+88]",
+ "and r8, rax",
+ "xor rcx, r8",
+ "and r11, rcx",
+ "xor r10, r11",
+ "and r10, QWORD PTR [rdx+80]",
+ "xor rbx, r10",
+ "mov rax, QWORD PTR [rdx+168]",
+ "mov rcx, r14",
+ "mov r8, r15",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 51",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 43",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 61",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 36",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 3",
+ "mov rbp, rbx",
+ "shr rbp, 6",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 4",
+ "mov rbp, rbx",
+ "shr rbp, 7",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 5",
+ "mov rbp, rbx",
+ "shr rbp, 8",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 6",
+ "mov rbp, rbx",
+ "shr rbp, 9",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 7",
+ "mov rbp, rbx",
+ "shr rbp, 10",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 8",
+ "mov rbp, rbx",
+ "shr rbp, 11",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rax",
+ "mov r15, rax",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, r8",
+ "and rcx, r15",
+ "mov QWORD PTR [rdx+80], r10",
+ "mov r10, r14",
+ "xor r10, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r15",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, r8",
+ "and r14, rcx",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r9",
+ "and r14, r15",
+ "xor r10, r14",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "and r11, r14",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, r8",
+ "and r14, r11",
+ "mov QWORD PTR [rdx+136], r11",
+ "mov r11, rbp",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+144], rbp",
+ "mov rbp, r9",
+ "and rbp, rcx",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r10, r11",
+ "mov r11, r9",
+ "and r11, QWORD PTR [rdx+112]",
+ "xor r15, r11",
+ "mov r11, r8",
+ "and r11, rax",
+ "xor r11, QWORD PTR [rdx+104]",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r15, r11",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r10, r15",
+ "mov r15, QWORD PTR [rdx+104]",
+ "xor r15, r8",
+ "mov r11, QWORD PTR [rdx+96]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r10",
+ "mov r10, r11",
+ "xor r10, r14",
+ "and r10, r9",
+ "xor r15, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, QWORD PTR [rdx+144]",
+ "xor rbp, r10",
+ "mov QWORD PTR [rdx+168], r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, QWORD PTR [rdx+104]",
+ "mov QWORD PTR [rdx+104], rcx",
+ "mov rcx, r10",
+ "xor rcx, r14",
+ "and rcx, r9",
+ "xor rbp, rcx",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor r15, rbp",
+ "mov rbp, QWORD PTR [rdx+128]",
+ "xor rbp, QWORD PTR [rdx+136]",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r8",
+ "xor rax, rbp",
+ "xor rax, rcx",
+ "mov rcx, r8",
+ "and rcx, r11",
+ "mov QWORD PTR [rdx+176], rbp",
+ "mov rbp, r9",
+ "and rbp, r10",
+ "xor rcx, rbp",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor rax, rcx",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov rbx, r8",
+ "and rbx, QWORD PTR [rdx+128]",
+ "mov rax, r10",
+ "xor rax, rbx",
+ "mov rcx, r9",
+ "and rcx, QWORD PTR [rdx+120]",
+ "xor rax, rcx",
+ "xor r11, QWORD PTR [rdx+112]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+168]",
+ "and rbp, r9",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor rax, r11",
+ "mov r11, r8",
+ "and r11, QWORD PTR [rdx+96]",
+ "and r11, r9",
+ "xor r11, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+80]",
+ "xor r11, r14",
+ "and r11, QWORD PTR [rdx+72]",
+ "xor rax, r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, QWORD PTR [rdx+168]",
+ "xor r11, QWORD PTR [rdx+160]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "and r8, QWORD PTR [rdx+176]",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "xor r10, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+120]",
+ "and r9, r8",
+ "xor r10, r9",
+ "xor rcx, QWORD PTR [rdx+168]",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r10, rcx",
+ "and r10, QWORD PTR [rdx+72]",
+ "xor r11, r10",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "mov rcx, r15",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r11",
+ "and rax, 1",
+ "ror rax, 39",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 54",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 44",
+ "xor r12, r8",
+ "and r9, 1",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 31",
+ "mov rbp, rbx",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "mov rbp, rbx",
+ "shr rbp, 1",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 1",
+ "mov rbp, rbx",
+ "shr rbp, 2",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 2",
+ "mov rbp, rbx",
+ "shr rbp, 3",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 3",
+ "mov rbp, rbx",
+ "shr rbp, 4",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 4",
+ "mov rbp, rbx",
+ "shr rbp, 5",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r11",
+ "xor r15, r14",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r15",
+ "xor r8, r9",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor r8, rcx",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r9",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+88], rax",
+ "mov rax, r14",
+ "and rax, r11",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, r14",
+ "xor r9, rbp",
+ "and r9, rcx",
+ "xor r9, r15",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r9, r10",
+ "xor r8, r9",
+ "mov r9, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "and rbp, r9",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, rcx",
+ "xor r14, rbp",
+ "mov rbp, r11",
+ "xor rbp, rax",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r15",
+ "mov r15, QWORD PTR [rdx+96]",
+ "xor r15, r8",
+ "mov QWORD PTR [rdx+96], r11",
+ "mov r11, rcx",
+ "and r11, r9",
+ "xor r15, r11",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "xor r9, r8",
+ "and r9, rcx",
+ "xor rax, r9",
+ "mov r9, QWORD PTR [rdx+112]",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rbp, r9",
+ "and rbp, r10",
+ "xor rax, rbp",
+ "mov rbp, QWORD PTR [rdx+96]",
+ "xor rbp, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rbp",
+ "xor r9, QWORD PTR [rdx+144]",
+ "mov QWORD PTR [rdx+144], r11",
+ "mov r11, rcx",
+ "and r11, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r8",
+ "mov r8, r9",
+ "xor r8, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor r9, rbp",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, r15",
+ "xor rax, r8",
+ "mov r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+112]",
+ "mov r9, QWORD PTR [rdx+104]",
+ "and r9, r14",
+ "xor r9, QWORD PTR [rdx+96]",
+ "mov rbp, rcx",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "mov rbp, r14",
+ "xor rbp, QWORD PTR [rdx+80]",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov rbp, QWORD PTR [rdx+72]",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+144]",
+ "and rbp, r10",
+ "xor r14, rbp",
+ "and r14, r15",
+ "xor r8, r14",
+ "mov r14, rcx",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "and r14, QWORD PTR [rdx+128]",
+ "xor r14, QWORD PTR [rdx+72]",
+ "mov rbp, QWORD PTR [rdx+88]",
+ "xor rbp, QWORD PTR [rdx+152]",
+ "and rbp, rcx",
+ "xor rbp, r14",
+ "and rbp, r10",
+ "xor r9, rbp",
+ "xor r11, QWORD PTR [rdx+136]",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and rcx, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r10, r14",
+ "xor r11, r10",
+ "and r15, r11",
+ "xor r9, r15",
+ "mov QWORD PTR [rdx+160], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "and rax, 1",
+ "ror rax, 53",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 47",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 59",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 37",
+ "xor r12, r9",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "add rdi, 8",
+ "mov rax, QWORD PTR [rdx+56]",
+ "sub rax, 1",
+ "mov QWORD PTR [rdx+56], rax",
+ "jne 21b",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "mov rdi, QWORD PTR [rdx+48]",
+ "add rdi, 120",
+ "mov rax, 16",
+ "mov QWORD PTR [rdx+56], rax",
+ "22:",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 27",
+ "mov rbp, rbx",
+ "shr rbp, 42",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 28",
+ "mov rbp, rbx",
+ "shr rbp, 43",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 29",
+ "mov rbp, rbx",
+ "shr rbp, 44",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 30",
+ "mov rbp, rbx",
+ "shr rbp, 45",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 31",
+ "mov rbp, rbx",
+ "shr rbp, 46",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "mov rbp, rbx",
+ "shr rbp, 47",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov r15, rax",
+ "xor r15, r10",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, rcx",
+ "and r8, r15",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, rcx",
+ "and r14, r15",
+ "xor r14, rax",
+ "and r14, r11",
+ "xor r8, r14",
+ "mov r14, r10",
+ "and r14, rax",
+ "mov QWORD PTR [rdx+96], rax",
+ "mov rax, r14",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rcx",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbx",
+ "mov rbx, r14",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+136], r15",
+ "mov r15, r11",
+ "and r15, rbx",
+ "xor rbp, r15",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "and r10, rcx",
+ "mov rbp, rax",
+ "xor rbp, r10",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, r15",
+ "and r10, r11",
+ "xor rbp, r10",
+ "mov r10, rcx",
+ "and r10, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, r10",
+ "and r14, r11",
+ "and r14, r9",
+ "xor rbp, r14",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r8, rbp",
+ "mov rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "mov r14, rbp",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor rbp, r8",
+ "mov QWORD PTR [rdx+112], rbx",
+ "mov rbx, r11",
+ "and rbx, rbp",
+ "xor r14, rbx",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r15, rbx",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r15",
+ "xor r10, rbx",
+ "and r10, r9",
+ "xor r14, r10",
+ "xor rbp, rbx",
+ "mov rbx, rcx",
+ "and rbx, QWORD PTR [rdx+96]",
+ "mov r10, r8",
+ "xor r10, rbx",
+ "and r10, r11",
+ "mov QWORD PTR [rdx+168], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "xor r8, r10",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r14, rbp",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, rbx",
+ "mov r8, r11",
+ "and r8, r15",
+ "xor rbp, r8",
+ "xor rax, QWORD PTR [rdx+88]",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+168]",
+ "and r8, r11",
+ "xor rax, r8",
+ "and rax, r9",
+ "xor rbp, rax",
+ "mov rax, r11",
+ "and rax, QWORD PTR [rdx+136]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, rbx",
+ "xor rax, r10",
+ "and rax, r9",
+ "xor r15, rax",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor rbp, r15",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+128]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "xor r15, rcx",
+ "mov rax, QWORD PTR [rdx+136]",
+ "xor rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r11",
+ "xor rax, r15",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r10, r11",
+ "xor r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor rax, r10",
+ "mov r10, QWORD PTR [rdx+104]",
+ "xor r10, QWORD PTR [rdx+144]",
+ "and r10, r11",
+ "xor rbx, r10",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and r11, rcx",
+ "xor r15, r11",
+ "and r9, r15",
+ "xor rbx, r9",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor rax, rbx",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r14",
+ "mov r8, rbp",
+ "mov r9, QWORD PTR [rdx+72]",
+ "and rax, 1",
+ "ror rax, 63",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 55",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 49",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 41",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 23",
+ "mov rbp, rbx",
+ "shr rbp, 36",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 24",
+ "mov rbp, rbx",
+ "shr rbp, 37",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 25",
+ "mov rbp, rbx",
+ "shr rbp, 38",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 26",
+ "mov rbp, rbx",
+ "shr rbp, 39",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 27",
+ "mov rbp, rbx",
+ "shr rbp, 40",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 28",
+ "mov rbp, rbx",
+ "shr rbp, 41",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r11",
+ "mov r11, rax",
+ "and r11, r8",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+88], rbp",
+ "mov rbp, r15",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, r10",
+ "xor r11, rbp",
+ "mov QWORD PTR [rdx+112], r15",
+ "mov r15, rcx",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+120], rbp",
+ "mov rbp, r14",
+ "xor rbp, r15",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, rax",
+ "and r14, r8",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, rbp",
+ "xor r8, r14",
+ "mov QWORD PTR [rdx+144], r14",
+ "mov r14, rbp",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], rbp",
+ "mov rbp, rax",
+ "and rbp, r14",
+ "xor rbp, rcx",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "and r8, r9",
+ "xor r11, r8",
+ "mov r8, rax",
+ "and r8, r15",
+ "xor r8, QWORD PTR [rdx+88]",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+160], r15",
+ "mov r15, rax",
+ "and r15, rbp",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rcx",
+ "xor r9, r15",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor r11, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, QWORD PTR [rdx+96]",
+ "mov r9, rbp",
+ "xor r9, r8",
+ "xor r15, QWORD PTR [rdx+136]",
+ "and r15, r10",
+ "xor r9, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+80]",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+104]",
+ "mov r15, rax",
+ "and r15, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, QWORD PTR [rdx+152]",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+152], r15",
+ "mov r15, r10",
+ "and r15, QWORD PTR [rdx+80]",
+ "xor r11, r15",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and r14, QWORD PTR [rdx+72]",
+ "xor r9, r14",
+ "mov r14, rbp",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, r8",
+ "and r11, r10",
+ "xor r11, rax",
+ "and r11, QWORD PTR [rdx+168]",
+ "xor r14, r11",
+ "and rax, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rax",
+ "mov r11, QWORD PTR [rdx+104]",
+ "xor r11, QWORD PTR [rdx+112]",
+ "and r11, r10",
+ "xor rcx, r11",
+ "and rax, QWORD PTR [rdx+168]",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+72]",
+ "xor r14, rcx",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "mov rcx, r10",
+ "and rcx, QWORD PTR [rdx+144]",
+ "xor rbp, rcx",
+ "mov rcx, r8",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov rax, QWORD PTR [rdx+128]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor rcx, rax",
+ "and rcx, QWORD PTR [rdx+168]",
+ "xor rbp, rcx",
+ "xor r8, QWORD PTR [rdx+160]",
+ "xor rbx, r8",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "and r10, rbx",
+ "xor r8, r10",
+ "and r8, QWORD PTR [rdx+72]",
+ "xor rbp, r8",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, r9",
+ "mov r8, r14",
+ "mov r9, rbp",
+ "and rax, 1",
+ "ror rax, 50",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 34",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 60",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 45",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 19",
+ "mov rbp, rbx",
+ "shr rbp, 30",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 20",
+ "mov rbp, rbx",
+ "shr rbp, 31",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 21",
+ "mov rbp, rbx",
+ "shr rbp, 32",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 22",
+ "mov rbp, rbx",
+ "shr rbp, 33",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 23",
+ "mov rbp, rbx",
+ "shr rbp, 34",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 24",
+ "mov rbp, rbx",
+ "shr rbp, 35",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r10",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r11",
+ "xor r8, r15",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r10",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, r14",
+ "xor r10, r15",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, rax",
+ "and r14, r10",
+ "mov QWORD PTR [rdx+104], rbp",
+ "mov rbp, r8",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+112], r8",
+ "mov r8, r10",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+120], rbx",
+ "mov rbx, r8",
+ "xor rbx, r15",
+ "mov QWORD PTR [rdx+128], r8",
+ "mov r8, rcx",
+ "and r8, rbx",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+136], rbp",
+ "mov rbp, rcx",
+ "and rbp, r10",
+ "xor rbx, rbp",
+ "and rbx, r9",
+ "xor r8, rbx",
+ "and r11, rax",
+ "mov rbx, QWORD PTR [rdx+104]",
+ "xor rbx, r11",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+96]",
+ "xor rbx, rbp",
+ "and r15, r9",
+ "xor rbx, r15",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r8, rbx",
+ "mov rbx, QWORD PTR [rdx+96]",
+ "xor rbx, QWORD PTR [rdx+88]",
+ "xor r14, rbx",
+ "mov r15, QWORD PTR [rdx+80]",
+ "xor r15, QWORD PTR [rdx+120]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov rbp, rax",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor rbp, r15",
+ "mov QWORD PTR [rdx+104], r8",
+ "mov r8, rcx",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r10",
+ "mov r10, r14",
+ "xor r10, r8",
+ "mov QWORD PTR [rdx+152], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], r11",
+ "mov r11, rax",
+ "and r11, rbx",
+ "mov QWORD PTR [rdx+168], rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, r11",
+ "mov QWORD PTR [rdx+88], r11",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+96]",
+ "mov QWORD PTR [rdx+176], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, r11",
+ "and r8, rcx",
+ "xor rbx, r8",
+ "and rbx, r9",
+ "xor r10, rbx",
+ "mov rbx, QWORD PTR [rdx+136]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "mov r14, QWORD PTR [rdx+112]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r8, rax",
+ "and r8, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r15",
+ "xor r14, r8",
+ "mov QWORD PTR [rdx+96], r8",
+ "mov r8, r11",
+ "xor r8, QWORD PTR [rdx+120]",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r8, rcx",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+72]",
+ "xor r10, rbx",
+ "mov rbx, rax",
+ "and rbx, r15",
+ "xor rbx, QWORD PTR [rdx+128]",
+ "mov r14, rbp",
+ "xor r14, QWORD PTR [rdx+120]",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and r14, rcx",
+ "xor rbx, r14",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "and rbp, r9",
+ "xor rbx, rbp",
+ "mov rbp, QWORD PTR [rdx+80]",
+ "xor rbp, QWORD PTR [rdx+88]",
+ "xor rbp, r8",
+ "mov r8, rcx",
+ "and r8, QWORD PTR [rdx+160]",
+ "xor r8, QWORD PTR [rdx+80]",
+ "and r8, r9",
+ "xor rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, rcx",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "xor rbp, QWORD PTR [rdx+120]",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rax, rbp",
+ "xor rax, QWORD PTR [rdx+168]",
+ "and rax, rcx",
+ "xor rax, QWORD PTR [rdx+144]",
+ "and rax, r9",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+112]",
+ "xor rax, r11",
+ "mov rbp, QWORD PTR [rdx+136]",
+ "xor rbp, QWORD PTR [rdx+96]",
+ "and rbp, rcx",
+ "xor rax, rbp",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+136]",
+ "and r9, rcx",
+ "xor rax, r9",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "mov rax, QWORD PTR [rdx+104]",
+ "mov rcx, r10",
+ "mov r8, rbx",
+ "mov r9, r15",
+ "and rax, 1",
+ "ror rax, 38",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 62",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 48",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 56",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 15",
+ "mov rbp, rbx",
+ "shr rbp, 24",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 16",
+ "mov rbp, rbx",
+ "shr rbp, 25",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 17",
+ "mov rbp, rbx",
+ "shr rbp, 26",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 18",
+ "mov rbp, rbx",
+ "shr rbp, 27",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 19",
+ "mov rbp, rbx",
+ "shr rbp, 28",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 20",
+ "mov rbp, rbx",
+ "shr rbp, 29",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, rcx",
+ "and r15, r9",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, r11",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+88], r15",
+ "mov r15, r14",
+ "xor r15, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, rbp",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r11",
+ "and r14, r9",
+ "mov QWORD PTR [rdx+120], r9",
+ "mov r9, rbp",
+ "xor r9, r14",
+ "and r9, r10",
+ "xor r15, r9",
+ "mov r9, rcx",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, rcx",
+ "xor rbp, r14",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rbp",
+ "mov QWORD PTR [rdx+144], rcx",
+ "mov rcx, r9",
+ "xor rcx, r14",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, rax",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "and rcx, r11",
+ "xor rcx, QWORD PTR [rdx+120]",
+ "and rcx, r10",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+88]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+88], r14",
+ "mov r14, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, QWORD PTR [rdx+80]",
+ "xor r9, r14",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r11",
+ "and rax, r9",
+ "xor rcx, rax",
+ "mov QWORD PTR [rdx+160], r9",
+ "mov r9, r10",
+ "and r9, QWORD PTR [rdx+128]",
+ "xor rcx, r9",
+ "and rcx, r8",
+ "xor rbp, rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "and rcx, rbp",
+ "xor r15, rcx",
+ "mov rcx, r11",
+ "and rcx, r14",
+ "mov QWORD PTR [rdx+128], r15",
+ "mov r15, QWORD PTR [rdx+120]",
+ "xor r15, rcx",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "and r11, r10",
+ "xor r11, r15",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, r14",
+ "xor r9, rax",
+ "mov QWORD PTR [rdx+176], r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "xor r14, QWORD PTR [rdx+136]",
+ "and r14, r10",
+ "xor r9, r14",
+ "and r9, r8",
+ "xor r11, r9",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r11, rbp",
+ "xor rax, QWORD PTR [rdx+80]",
+ "mov rbp, r10",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rax, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "and r14, r8",
+ "xor rax, r14",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r14, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+152]",
+ "xor r14, QWORD PTR [rdx+96]",
+ "xor r14, QWORD PTR [rdx+168]",
+ "and r14, r8",
+ "xor r15, r14",
+ "mov r14, QWORD PTR [rdx+72]",
+ "and r14, r15",
+ "xor rax, r14",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+176]",
+ "xor rbp, rcx",
+ "and r10, rbp",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "xor r10, QWORD PTR [rdx+88]",
+ "and r8, r10",
+ "xor r14, r8",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r14, r15",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+128]",
+ "mov rcx, r11",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r14",
+ "and rax, 1",
+ "ror rax, 33",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 42",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 52",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 58",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 11",
+ "mov rbp, rbx",
+ "shr rbp, 18",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 12",
+ "mov rbp, rbx",
+ "shr rbp, 19",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 13",
+ "mov rbp, rbx",
+ "shr rbp, 20",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 14",
+ "mov rbp, rbx",
+ "shr rbp, 21",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 15",
+ "mov rbp, rbx",
+ "shr rbp, 22",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 16",
+ "mov rbp, rbx",
+ "shr rbp, 23",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r9",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r14",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+80], rbp",
+ "mov rbp, rax",
+ "and rbp, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r11",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r11",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r11",
+ "mov r11, r14",
+ "and r11, rbp",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, rbp",
+ "xor r14, r11",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, r10",
+ "and r11, r14",
+ "xor r11, rcx",
+ "mov QWORD PTR [rdx+128], rcx",
+ "mov rcx, rbp",
+ "xor rcx, r15",
+ "mov QWORD PTR [rdx+136], r14",
+ "mov r14, r10",
+ "and r14, rcx",
+ "xor r14, r9",
+ "xor r8, rbx",
+ "xor r8, QWORD PTR [rdx+64]",
+ "and r14, r8",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, rbp",
+ "xor r14, QWORD PTR [rdx+112]",
+ "mov QWORD PTR [rdx+144], r9",
+ "mov r9, QWORD PTR [rdx+104]",
+ "xor r9, QWORD PTR [rdx+112]",
+ "and r15, rax",
+ "xor r15, r9",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+136]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+152], r9",
+ "mov r9, rbp",
+ "xor r9, rax",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r11, r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+88]",
+ "xor r9, r14",
+ "xor r9, r10",
+ "mov QWORD PTR [rdx+72], r11",
+ "mov r11, QWORD PTR [rdx+120]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbx",
+ "mov rbx, rax",
+ "and rbx, r11",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "mov QWORD PTR [rdx+80], r14",
+ "mov r14, rax",
+ "and r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r15",
+ "mov r15, r10",
+ "and r15, r14",
+ "xor r11, r15",
+ "and r11, r8",
+ "xor r9, r11",
+ "xor r14, rcx",
+ "and r14, r10",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov r11, rax",
+ "and r11, QWORD PTR [rdx+104]",
+ "xor rbp, r11",
+ "mov r15, r10",
+ "and r15, rbp",
+ "xor r15, rbx",
+ "and r15, r8",
+ "xor r14, r15",
+ "and r14, QWORD PTR [rdx+120]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+136]",
+ "xor r14, rax",
+ "xor r14, r10",
+ "mov r15, QWORD PTR [rdx+168]",
+ "xor r15, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r9",
+ "mov r9, QWORD PTR [rdx+152]",
+ "xor r9, rbx",
+ "and r9, r10",
+ "xor r15, r9",
+ "and r15, r8",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+152]",
+ "xor r15, QWORD PTR [rdx+160]",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov r9, rax",
+ "and r9, r15",
+ "mov QWORD PTR [rdx+168], r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, r9",
+ "and r11, r8",
+ "xor r11, QWORD PTR [rdx+88]",
+ "and r11, QWORD PTR [rdx+120]",
+ "xor r14, r11",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "mov r11, r10",
+ "and r11, QWORD PTR [rdx+128]",
+ "xor rbx, r11",
+ "mov r11, rcx",
+ "xor r11, rax",
+ "and r11, r10",
+ "xor rbp, r11",
+ "and rbp, r8",
+ "xor rbx, rbp",
+ "xor r15, QWORD PTR [rdx+96]",
+ "and rax, QWORD PTR [rdx+144]",
+ "xor rax, QWORD PTR [rdx+152]",
+ "and rax, r10",
+ "xor r15, rax",
+ "xor rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor rcx, r9",
+ "mov r9, QWORD PTR [rdx+168]",
+ "xor r9, QWORD PTR [rdx+160]",
+ "xor r9, QWORD PTR [rdx+64]",
+ "and r10, r9",
+ "xor rcx, r10",
+ "and r8, rcx",
+ "xor r15, r8",
+ "and r15, QWORD PTR [rdx+120]",
+ "xor rbx, r15",
+ "mov rax, QWORD PTR [rdx+72]",
+ "mov rcx, QWORD PTR [rdx+80]",
+ "mov r8, r14",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 35",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 57",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 46",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 40",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 7",
+ "mov rbp, rbx",
+ "shr rbp, 12",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 8",
+ "mov rbp, rbx",
+ "shr rbp, 13",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 9",
+ "mov rbp, rbx",
+ "shr rbp, 14",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 10",
+ "mov rbp, rbx",
+ "shr rbp, 15",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 11",
+ "mov rbp, rbx",
+ "shr rbp, 16",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 12",
+ "mov rbp, rbx",
+ "shr rbp, 17",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r10",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r9",
+ "and r15, r14",
+ "mov QWORD PTR [rdx+72], rbp",
+ "mov rbp, r15",
+ "xor rbp, rcx",
+ "mov QWORD PTR [rdx+80], rax",
+ "mov rax, r10",
+ "xor rax, r15",
+ "mov QWORD PTR [rdx+88], r10",
+ "mov r10, rcx",
+ "and r10, r9",
+ "mov QWORD PTR [rdx+96], r15",
+ "mov r15, rax",
+ "xor r15, r10",
+ "and r15, r8",
+ "xor rbp, r15",
+ "mov r15, r10",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+104], r10",
+ "mov r10, r9",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rax",
+ "mov rax, rcx",
+ "and rax, r10",
+ "mov QWORD PTR [rdx+120], r10",
+ "mov r10, r9",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+128], rax",
+ "mov rax, r8",
+ "and rax, r10",
+ "xor r15, rax",
+ "and r15, r11",
+ "xor rbp, r15",
+ "mov r15, r14",
+ "xor r15, r9",
+ "mov QWORD PTR [rdx+136], r10",
+ "mov r10, rcx",
+ "and r10, r15",
+ "mov QWORD PTR [rdx+144], rax",
+ "mov rax, QWORD PTR [rdx+96]",
+ "xor rax, r10",
+ "and rax, r8",
+ "and r9, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+152], rcx",
+ "mov rcx, r14",
+ "xor rcx, r9",
+ "mov QWORD PTR [rdx+160], r14",
+ "mov r14, r15",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "xor r14, r10",
+ "and r14, r8",
+ "xor r14, rcx",
+ "and r14, r11",
+ "xor rax, r14",
+ "and rax, QWORD PTR [rdx+80]",
+ "xor rbp, rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+96]",
+ "mov r14, r9",
+ "xor r14, rax",
+ "mov QWORD PTR [rdx+168], rbp",
+ "mov rbp, QWORD PTR [rdx+152]",
+ "and rbp, QWORD PTR [rdx+88]",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, QWORD PTR [rdx+72]",
+ "xor rcx, rbp",
+ "mov QWORD PTR [rdx+72], r10",
+ "mov r10, r8",
+ "and r10, rcx",
+ "xor r14, r10",
+ "mov r10, QWORD PTR [rdx+112]",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and rbp, r8",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r14, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+152]",
+ "xor rcx, r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, rax",
+ "mov QWORD PTR [rdx+120], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "and rax, QWORD PTR [rdx+160]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r8",
+ "and rbp, rax",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor rcx, r10",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r14, rcx",
+ "xor r15, QWORD PTR [rdx+128]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "xor rcx, QWORD PTR [rdx+104]",
+ "and rcx, r8",
+ "xor r15, rcx",
+ "mov rcx, QWORD PTR [rdx+96]",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+152]",
+ "and r10, r9",
+ "xor r10, rcx",
+ "mov rbp, r8",
+ "and rbp, QWORD PTR [rdx+72]",
+ "xor r10, rbp",
+ "and r10, r11",
+ "xor r15, r10",
+ "xor rbx, QWORD PTR [rdx+112]",
+ "xor rbx, QWORD PTR [rdx+64]",
+ "mov r10, QWORD PTR [rdx+96]",
+ "xor r10, QWORD PTR [rdx+120]",
+ "xor r9, QWORD PTR [rdx+152]",
+ "and r9, r8",
+ "xor r10, r9",
+ "and r10, r11",
+ "xor rbx, r10",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r15, rbx",
+ "mov rbx, QWORD PTR [rdx+88]",
+ "xor rbx, QWORD PTR [rdx+152]",
+ "xor rbx, QWORD PTR [rdx+144]",
+ "mov r10, r11",
+ "and r10, QWORD PTR [rdx+136]",
+ "xor rbx, r10",
+ "mov r10, rcx",
+ "xor r10, QWORD PTR [rdx+128]",
+ "and r10, r8",
+ "xor r10, QWORD PTR [rdx+136]",
+ "mov r9, QWORD PTR [rdx+152]",
+ "and r9, rcx",
+ "xor rcx, r9",
+ "xor rax, QWORD PTR [rdx+88]",
+ "and r8, rax",
+ "xor rcx, r8",
+ "and r11, rcx",
+ "xor r10, r11",
+ "and r10, QWORD PTR [rdx+80]",
+ "xor rbx, r10",
+ "mov rax, QWORD PTR [rdx+168]",
+ "mov rcx, r14",
+ "mov r8, r15",
+ "mov r9, rbx",
+ "and rax, 1",
+ "ror rax, 51",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 43",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 61",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 36",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 3",
+ "mov rbp, rbx",
+ "shr rbp, 6",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "shr rcx, 4",
+ "mov rbp, rbx",
+ "shr rbp, 7",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 5",
+ "mov rbp, rbx",
+ "shr rbp, 8",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 6",
+ "mov rbp, rbx",
+ "shr rbp, 9",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 7",
+ "mov rbp, rbx",
+ "shr rbp, 10",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 8",
+ "mov rbp, rbx",
+ "shr rbp, 11",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, r11",
+ "xor r14, rax",
+ "mov r15, rax",
+ "and r15, r11",
+ "mov QWORD PTR [rdx+72], rcx",
+ "mov rcx, r8",
+ "and rcx, r15",
+ "mov QWORD PTR [rdx+80], r10",
+ "mov r10, r14",
+ "xor r10, rcx",
+ "mov QWORD PTR [rdx+88], rcx",
+ "mov rcx, r15",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+96], r14",
+ "mov r14, r8",
+ "and r14, rcx",
+ "mov QWORD PTR [rdx+104], r15",
+ "mov r15, rbp",
+ "xor r15, r14",
+ "mov QWORD PTR [rdx+112], r14",
+ "mov r14, r9",
+ "and r14, r15",
+ "xor r10, r14",
+ "mov r14, r11",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+120], r11",
+ "mov r11, rax",
+ "and r11, r14",
+ "mov QWORD PTR [rdx+128], r14",
+ "mov r14, r8",
+ "and r14, r11",
+ "mov QWORD PTR [rdx+136], r11",
+ "mov r11, rbp",
+ "xor r11, r14",
+ "mov QWORD PTR [rdx+144], rbp",
+ "mov rbp, r9",
+ "and rbp, rcx",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r10, r11",
+ "mov r11, r9",
+ "and r11, QWORD PTR [rdx+112]",
+ "xor r15, r11",
+ "mov r11, r8",
+ "and r11, rax",
+ "xor r11, QWORD PTR [rdx+104]",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor r15, r11",
+ "and r15, QWORD PTR [rdx+72]",
+ "xor r10, r15",
+ "mov r15, QWORD PTR [rdx+104]",
+ "xor r15, r8",
+ "mov r11, QWORD PTR [rdx+96]",
+ "xor r11, rbx",
+ "xor r11, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r10",
+ "mov r10, r11",
+ "xor r10, r14",
+ "and r10, r9",
+ "xor r15, r10",
+ "mov r10, r8",
+ "and r10, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, QWORD PTR [rdx+144]",
+ "xor rbp, r10",
+ "mov QWORD PTR [rdx+168], r10",
+ "mov r10, QWORD PTR [rdx+120]",
+ "xor r10, QWORD PTR [rdx+104]",
+ "mov QWORD PTR [rdx+104], rcx",
+ "mov rcx, r10",
+ "xor rcx, r14",
+ "and rcx, r9",
+ "xor rbp, rcx",
+ "and rbp, QWORD PTR [rdx+80]",
+ "xor r15, rbp",
+ "mov rbp, QWORD PTR [rdx+128]",
+ "xor rbp, QWORD PTR [rdx+136]",
+ "xor rax, rbx",
+ "xor rax, QWORD PTR [rdx+64]",
+ "and rax, r8",
+ "xor rax, rbp",
+ "xor rax, rcx",
+ "mov rcx, r8",
+ "and rcx, r11",
+ "mov QWORD PTR [rdx+176], rbp",
+ "mov rbp, r9",
+ "and rbp, r10",
+ "xor rcx, rbp",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor rax, rcx",
+ "and rax, QWORD PTR [rdx+72]",
+ "xor r15, rax",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "mov rbx, r8",
+ "and rbx, QWORD PTR [rdx+128]",
+ "mov rax, r10",
+ "xor rax, rbx",
+ "mov rcx, r9",
+ "and rcx, QWORD PTR [rdx+120]",
+ "xor rax, rcx",
+ "xor r11, QWORD PTR [rdx+112]",
+ "mov rbp, QWORD PTR [rdx+104]",
+ "xor rbp, QWORD PTR [rdx+168]",
+ "and rbp, r9",
+ "xor r11, rbp",
+ "and r11, QWORD PTR [rdx+80]",
+ "xor rax, r11",
+ "mov r11, r8",
+ "and r11, QWORD PTR [rdx+96]",
+ "and r11, r9",
+ "xor r11, QWORD PTR [rdx+144]",
+ "and r14, QWORD PTR [rdx+80]",
+ "xor r11, r14",
+ "and r11, QWORD PTR [rdx+72]",
+ "xor rax, r11",
+ "mov r11, QWORD PTR [rdx+136]",
+ "xor r11, QWORD PTR [rdx+168]",
+ "xor r11, QWORD PTR [rdx+160]",
+ "xor rbx, QWORD PTR [rdx+120]",
+ "and r8, QWORD PTR [rdx+176]",
+ "mov r14, QWORD PTR [rdx+176]",
+ "xor r14, r8",
+ "and r14, r9",
+ "xor rbx, r14",
+ "and rbx, QWORD PTR [rdx+80]",
+ "xor r11, rbx",
+ "xor r10, QWORD PTR [rdx+88]",
+ "xor r8, QWORD PTR [rdx+120]",
+ "and r9, r8",
+ "xor r10, r9",
+ "xor rcx, QWORD PTR [rdx+168]",
+ "and rcx, QWORD PTR [rdx+80]",
+ "xor r10, rcx",
+ "and r10, QWORD PTR [rdx+72]",
+ "xor r11, r10",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, QWORD PTR [rdx+152]",
+ "mov rcx, r15",
+ "mov r8, QWORD PTR [rdx+72]",
+ "mov r9, r11",
+ "and rax, 1",
+ "ror rax, 39",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 54",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 44",
+ "xor r12, r8",
+ "and r9, 1",
+ "xor r12, r9",
+ "mov rbx, QWORD PTR [rdi]",
+ "mov rax, r13",
+ "shr rax, 31",
+ "mov rbp, rbx",
+ "xor rax, rbp",
+ "and rax, 1",
+ "mov rcx, r13",
+ "mov rbp, rbx",
+ "shr rbp, 1",
+ "xor rcx, rbp",
+ "and rcx, 1",
+ "mov r8, r13",
+ "shr r8, 1",
+ "mov rbp, rbx",
+ "shr rbp, 2",
+ "xor r8, rbp",
+ "and r8, 1",
+ "mov r9, r13",
+ "shr r9, 2",
+ "mov rbp, rbx",
+ "shr rbp, 3",
+ "xor r9, rbp",
+ "and r9, 1",
+ "mov r10, r13",
+ "shr r10, 3",
+ "mov rbp, rbx",
+ "shr rbp, 4",
+ "xor r10, rbp",
+ "and r10, 1",
+ "mov r11, r13",
+ "shr r11, 4",
+ "mov rbp, rbx",
+ "shr rbp, 5",
+ "xor r11, rbp",
+ "and r11, 1",
+ "movabs rbx, -1",
+ "mov QWORD PTR [rdx+64], rbx",
+ "mov rbx, rax",
+ "xor rbx, rax",
+ "mov rbp, rax",
+ "xor rbp, rax",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov r15, r11",
+ "xor r15, r14",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], r8",
+ "mov r8, r15",
+ "xor r8, r9",
+ "xor rcx, rbx",
+ "xor rcx, QWORD PTR [rdx+64]",
+ "xor r8, rcx",
+ "mov QWORD PTR [rdx+80], r15",
+ "mov r15, r9",
+ "and r15, rax",
+ "mov QWORD PTR [rdx+88], rax",
+ "mov rax, r14",
+ "and rax, r11",
+ "mov QWORD PTR [rdx+96], rbp",
+ "mov rbp, r9",
+ "and rbp, rax",
+ "mov QWORD PTR [rdx+104], r9",
+ "mov r9, r14",
+ "xor r9, rbp",
+ "and r9, rcx",
+ "xor r9, r15",
+ "xor r10, rbx",
+ "xor r10, QWORD PTR [rdx+64]",
+ "and r9, r10",
+ "xor r8, r9",
+ "mov r9, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+112], rbp",
+ "mov rbp, r14",
+ "and rbp, r9",
+ "mov QWORD PTR [rdx+120], r8",
+ "mov r8, QWORD PTR [rdx+96]",
+ "xor r8, rbp",
+ "mov QWORD PTR [rdx+128], rbp",
+ "mov rbp, r8",
+ "xor rbp, r15",
+ "and rbp, rcx",
+ "xor r14, rbp",
+ "mov rbp, r11",
+ "xor rbp, rax",
+ "mov QWORD PTR [rdx+136], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "mov QWORD PTR [rdx+144], r15",
+ "mov r15, QWORD PTR [rdx+96]",
+ "xor r15, r8",
+ "mov QWORD PTR [rdx+96], r11",
+ "mov r11, rcx",
+ "and r11, r9",
+ "xor r15, r11",
+ "and r15, r10",
+ "xor r14, r15",
+ "mov r15, QWORD PTR [rdx+72]",
+ "xor r15, rbx",
+ "xor r15, QWORD PTR [rdx+64]",
+ "and r14, r15",
+ "xor r14, QWORD PTR [rdx+120]",
+ "mov QWORD PTR [rdx+120], r14",
+ "mov r14, rax",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+72], rax",
+ "mov rax, r14",
+ "xor rax, r8",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+152], r8",
+ "mov r8, QWORD PTR [rdx+104]",
+ "and r8, rbp",
+ "xor r9, r8",
+ "and r9, rcx",
+ "xor rax, r9",
+ "mov r9, QWORD PTR [rdx+112]",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "mov QWORD PTR [rdx+160], rbp",
+ "mov rbp, rcx",
+ "and rbp, QWORD PTR [rdx+112]",
+ "xor rbp, r9",
+ "and rbp, r10",
+ "xor rax, rbp",
+ "mov rbp, QWORD PTR [rdx+96]",
+ "xor rbp, QWORD PTR [rdx+128]",
+ "mov QWORD PTR [rdx+168], r9",
+ "mov r9, rbp",
+ "xor r9, QWORD PTR [rdx+144]",
+ "mov QWORD PTR [rdx+144], r11",
+ "mov r11, rcx",
+ "and r11, QWORD PTR [rdx+80]",
+ "mov QWORD PTR [rdx+80], r8",
+ "mov r8, r9",
+ "xor r8, r11",
+ "xor r9, rbx",
+ "xor r9, QWORD PTR [rdx+64]",
+ "xor rbp, rbx",
+ "xor rbp, QWORD PTR [rdx+64]",
+ "and rbp, rcx",
+ "xor r9, rbp",
+ "and r9, r10",
+ "xor r8, r9",
+ "and r8, r15",
+ "xor rax, r8",
+ "mov r8, QWORD PTR [rdx+128]",
+ "xor r8, QWORD PTR [rdx+112]",
+ "mov r9, QWORD PTR [rdx+104]",
+ "and r9, r14",
+ "xor r9, QWORD PTR [rdx+96]",
+ "mov rbp, rcx",
+ "and rbp, r9",
+ "xor r8, rbp",
+ "mov rbp, r14",
+ "xor rbp, QWORD PTR [rdx+80]",
+ "and rbp, r10",
+ "xor r8, rbp",
+ "xor r14, QWORD PTR [rdx+144]",
+ "mov rbp, QWORD PTR [rdx+72]",
+ "xor rbp, QWORD PTR [rdx+112]",
+ "xor rbp, QWORD PTR [rdx+144]",
+ "and rbp, r10",
+ "xor r14, rbp",
+ "and r14, r15",
+ "xor r8, r14",
+ "mov r14, rcx",
+ "and r14, QWORD PTR [rdx+168]",
+ "xor r9, r14",
+ "mov r14, QWORD PTR [rdx+104]",
+ "and r14, QWORD PTR [rdx+128]",
+ "xor r14, QWORD PTR [rdx+72]",
+ "mov rbp, QWORD PTR [rdx+88]",
+ "xor rbp, QWORD PTR [rdx+152]",
+ "and rbp, rcx",
+ "xor rbp, r14",
+ "and rbp, r10",
+ "xor r9, rbp",
+ "xor r11, QWORD PTR [rdx+136]",
+ "xor r14, rbx",
+ "xor r14, QWORD PTR [rdx+64]",
+ "and rcx, QWORD PTR [rdx+160]",
+ "xor r14, rcx",
+ "and r10, r14",
+ "xor r11, r10",
+ "and r15, r11",
+ "xor r9, r15",
+ "mov QWORD PTR [rdx+160], rax",
+ "mov rax, QWORD PTR [rdx+120]",
+ "mov rcx, QWORD PTR [rdx+160]",
+ "and rax, 1",
+ "ror rax, 53",
+ "xor r12, rax",
+ "and rcx, 1",
+ "ror rcx, 47",
+ "xor r12, rcx",
+ "and r8, 1",
+ "ror r8, 59",
+ "xor r12, r8",
+ "and r9, 1",
+ "ror r9, 37",
+ "xor r12, r9",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "sub rdi, 8",
+ "mov rax, QWORD PTR [rdx+56]",
+ "sub rax, 1",
+ "mov QWORD PTR [rdx+56], rax",
+ "jne 22b",
+ "mov rax, r12",
+ "mov r12, r13",
+ "mov r13, rax",
+ "mov rax, r12",
+ "ror rax, 32",
+ "xor rax, r13",
+ "mov rbx, 0",
+ "mov rbp, rax",
+ "shr rbp, 24",
+ "and rbp, 1",
+ "ror rbp, 1",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 56",
+ "and rbp, 1",
+ "ror rbp, 2",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 16",
+ "and rbp, 1",
+ "ror rbp, 3",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 48",
+ "and rbp, 1",
+ "ror rbp, 4",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 8",
+ "and rbp, 1",
+ "ror rbp, 5",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 40",
+ "and rbp, 1",
+ "ror rbp, 6",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "and rbp, 1",
+ "ror rbp, 7",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 32",
+ "and rbp, 1",
+ "ror rbp, 8",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 25",
+ "and rbp, 1",
+ "ror rbp, 9",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 57",
+ "and rbp, 1",
+ "ror rbp, 10",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 17",
+ "and rbp, 1",
+ "ror rbp, 11",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 49",
+ "and rbp, 1",
+ "ror rbp, 12",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 9",
+ "and rbp, 1",
+ "ror rbp, 13",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 41",
+ "and rbp, 1",
+ "ror rbp, 14",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 1",
+ "and rbp, 1",
+ "ror rbp, 15",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 33",
+ "and rbp, 1",
+ "ror rbp, 16",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 26",
+ "and rbp, 1",
+ "ror rbp, 17",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 58",
+ "and rbp, 1",
+ "ror rbp, 18",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 18",
+ "and rbp, 1",
+ "ror rbp, 19",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 50",
+ "and rbp, 1",
+ "ror rbp, 20",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 10",
+ "and rbp, 1",
+ "ror rbp, 21",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 42",
+ "and rbp, 1",
+ "ror rbp, 22",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 2",
+ "and rbp, 1",
+ "ror rbp, 23",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 34",
+ "and rbp, 1",
+ "ror rbp, 24",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 27",
+ "and rbp, 1",
+ "ror rbp, 25",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 59",
+ "and rbp, 1",
+ "ror rbp, 26",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 19",
+ "and rbp, 1",
+ "ror rbp, 27",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 51",
+ "and rbp, 1",
+ "ror rbp, 28",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 11",
+ "and rbp, 1",
+ "ror rbp, 29",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 43",
+ "and rbp, 1",
+ "ror rbp, 30",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 3",
+ "and rbp, 1",
+ "ror rbp, 31",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 35",
+ "and rbp, 1",
+ "ror rbp, 32",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 28",
+ "and rbp, 1",
+ "ror rbp, 33",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 60",
+ "and rbp, 1",
+ "ror rbp, 34",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 20",
+ "and rbp, 1",
+ "ror rbp, 35",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 52",
+ "and rbp, 1",
+ "ror rbp, 36",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 12",
+ "and rbp, 1",
+ "ror rbp, 37",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 44",
+ "and rbp, 1",
+ "ror rbp, 38",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 4",
+ "and rbp, 1",
+ "ror rbp, 39",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 36",
+ "and rbp, 1",
+ "ror rbp, 40",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 29",
+ "and rbp, 1",
+ "ror rbp, 41",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 61",
+ "and rbp, 1",
+ "ror rbp, 42",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 21",
+ "and rbp, 1",
+ "ror rbp, 43",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 53",
+ "and rbp, 1",
+ "ror rbp, 44",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 13",
+ "and rbp, 1",
+ "ror rbp, 45",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 45",
+ "and rbp, 1",
+ "ror rbp, 46",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 5",
+ "and rbp, 1",
+ "ror rbp, 47",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 37",
+ "and rbp, 1",
+ "ror rbp, 48",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 30",
+ "and rbp, 1",
+ "ror rbp, 49",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 62",
+ "and rbp, 1",
+ "ror rbp, 50",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 22",
+ "and rbp, 1",
+ "ror rbp, 51",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 54",
+ "and rbp, 1",
+ "ror rbp, 52",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 14",
+ "and rbp, 1",
+ "ror rbp, 53",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 46",
+ "and rbp, 1",
+ "ror rbp, 54",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 6",
+ "and rbp, 1",
+ "ror rbp, 55",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 38",
+ "and rbp, 1",
+ "ror rbp, 56",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 31",
+ "and rbp, 1",
+ "ror rbp, 57",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 63",
+ "and rbp, 1",
+ "ror rbp, 58",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 23",
+ "and rbp, 1",
+ "ror rbp, 59",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 55",
+ "and rbp, 1",
+ "ror rbp, 60",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 15",
+ "and rbp, 1",
+ "ror rbp, 61",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 47",
+ "and rbp, 1",
+ "ror rbp, 62",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 7",
+ "and rbp, 1",
+ "ror rbp, 63",
+ "xor rbx, rbp",
+ "mov rbp, rax",
+ "shr rbp, 39",
+ "and rbp, 1",
+ "xor rbx, rbp",
+ "bswap rbx",
+ "mov rax, rbx",
+ "mov rbx, QWORD PTR [rdx]",
+ "mov rbp, QWORD PTR [rdx+8]",
+ "mov r12, QWORD PTR [rdx+16]",
+ "mov r13, QWORD PTR [rdx+24]",
+ "mov r14, QWORD PTR [rdx+32]",
+ "mov r15, QWORD PTR [rdx+40]",
+ "mov rdi, QWORD PTR [rdx+48]",
+ "mov QWORD PTR [rsi], rax",
+ "ret",
+ )
+}
+
+/// Triple DES ECB encryption (SP 800-38A §6.1) of `n` complete 8-byte blocks at `data`, in place, under the schedule written by `vg_triple_des_expand_key`. No padding is added or removed. For `n = 0`, no data is transformed.
+///
+/// Contract: `VG.Spec.TripleDes.ecbEncryptContract`. Constant time: only pointers and `n` may affect timing, not the schedule or data.
+///
+/// Baseline x86-64, calling the verified Triple DES block primitive for each complete block.
+///
+/// # Safety
+///
+/// * `schedule` must be valid for reads of 384 bytes.
+/// * `data` must be valid for reads and writes of `8 * n` bytes.
+/// * `scratch` must be valid for reads and writes of 1024 bytes.
+/// * The contents of `scratch` on return are unspecified.
+/// * `data` and `scratch` must not overlap each other or `schedule` (distinct Rust objects never do).
+/// * None of `schedule`, `data` and `scratch` may overlap the return address on the stack or the 8 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_triple_des_ecb_encrypt(schedule: *const [u8; 384], data: *mut [u8; 8], n: usize, scratch: *mut [u64; 128]) {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rcx+512], rbp",
+ "mov rbp, rdx",
+ "mov rdx, rcx",
+ "cmp rbp, 0",
+ "je 20f",
+ "22:",
+ "call {vg_triple_des_encrypt_block}",
+ "add rsi, 8",
+ "sub rbp, 1",
+ "jne 22b",
+ "jmp 21f",
+ "20:",
+ "21:",
+ "mov rbp, QWORD PTR [rdx+512]",
+ "ret",
+ vg_triple_des_encrypt_block = sym super::triple_des::vg_triple_des_encrypt_block,
+ )
+}
+
+/// Triple DES ECB decryption (SP 800-38A §6.1) of `n` complete 8-byte blocks at `data`, in place, under the schedule written by `vg_triple_des_expand_key`. No padding is added or removed. For `n = 0`, no data is transformed.
+///
+/// Contract: `VG.Spec.TripleDes.ecbDecryptContract`. Constant time: only pointers and `n` may affect timing, not the schedule or data.
+///
+/// Baseline x86-64, calling the verified Triple DES block primitive for each complete block.
+///
+/// # Safety
+///
+/// * `schedule` must be valid for reads of 384 bytes.
+/// * `data` must be valid for reads and writes of `8 * n` bytes.
+/// * `scratch` must be valid for reads and writes of 1024 bytes.
+/// * The contents of `scratch` on return are unspecified.
+/// * `data` and `scratch` must not overlap each other or `schedule` (distinct Rust objects never do).
+/// * None of `schedule`, `data` and `scratch` may overlap the return address on the stack or the 8 bytes of stack below it, or wrap around the end of the address space (no Rust object does).
+#[unsafe(naked)]
+pub(crate) unsafe extern "sysv64" fn vg_triple_des_ecb_decrypt(schedule: *const [u8; 384], data: *mut [u8; 8], n: usize, scratch: *mut [u64; 128]) {
+ core::arch::naked_asm!(
+ "mov QWORD PTR [rcx+512], rbp",
+ "mov rbp, rdx",
+ "mov rdx, rcx",
+ "cmp rbp, 0",
+ "je 20f",
+ "22:",
+ "call {vg_triple_des_decrypt_block}",
+ "add rsi, 8",
+ "sub rbp, 1",
+ "jne 22b",
+ "jmp 21f",
+ "20:",
+ "21:",
+ "mov rbp, QWORD PTR [rdx+512]",
+ "ret",
+ vg_triple_des_decrypt_block = sym super::triple_des::vg_triple_des_decrypt_block,
+ )
+}
diff --git a/src/lib.rs b/src/lib.rs
index 210dc7a78..314540673 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -96,6 +96,7 @@ pub mod pbkdf2;
pub mod poly1305;
pub mod rc2_cbc;
pub mod scrypt;
+pub mod triple_des_ecb;
pub mod x25519;
pub mod x448;
mod zeroize;
diff --git a/src/triple_des_ecb.rs b/src/triple_des_ecb.rs
new file mode 100644
index 000000000..ce230249f
--- /dev/null
+++ b/src/triple_des_ecb.rs
@@ -0,0 +1,94 @@
+//! Triple DES ECB (FIPS 46-3), in place and without padding.
+//!
+//! Key expansion and ECB encryption/decryption use verified primitives.
+//! Each operation accepts complete eight-byte blocks, including empty input.
+
+#![cfg(target_arch = "x86_64")]
+
+use crate::arch::triple_des::{
+ vg_triple_des_ecb_decrypt, vg_triple_des_ecb_encrypt, vg_triple_des_expand_key,
+};
+use crate::zeroize::zeroize;
+
+/// Why a Triple DES ECB operation failed.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Error {
+ /// The key does not contain 16 or 24 bytes.
+ InvalidKeyLength,
+ /// The input length is not a multiple of eight bytes.
+ IncompleteBlock,
+}
+
+/// An expanded Triple DES key for ECB encryption and decryption.
+///
+/// A 24-byte key encodes K1, K2 and K3. A 16-byte key encodes K1 and K2,
+/// with K3 repeating K1. Each byte's parity bit is ignored; weak and
+/// repeated component keys are accepted. No padding is added or removed.
+pub struct TripleDesEcb {
+ schedule: [u8; 384],
+}
+
+impl TripleDesEcb {
+ /// Expands a 16- or 24-byte key for use in either direction.
+ pub fn new(key: &[u8]) -> Result {
+ if !matches!(key.len(), 16 | 24) {
+ return Err(Error::InvalidKeyLength);
+ }
+ let mut schedule = [0; 384];
+ let mut scratch = [0u64; 64];
+ // SAFETY: the key has a validated length; key, schedule and scratch
+ // are separate valid buffers of the required sizes.
+ unsafe {
+ vg_triple_des_expand_key(key.as_ptr(), key.len(), &mut schedule, &mut scratch);
+ }
+ zeroize(&mut scratch);
+ Ok(Self { schedule })
+ }
+
+ /// Encrypts complete eight-byte blocks in place. Empty input is valid.
+ /// Returns an error without changing the buffer if its length is invalid.
+ pub fn encrypt(&self, buffer: &mut [u8]) -> Result<(), Error> {
+ self.crypt(buffer, true)
+ }
+
+ /// Decrypts complete eight-byte blocks in place. Empty input is valid.
+ /// Returns an error without changing the buffer if its length is invalid.
+ pub fn decrypt(&self, buffer: &mut [u8]) -> Result<(), Error> {
+ self.crypt(buffer, false)
+ }
+
+ fn crypt(&self, buffer: &mut [u8], encrypt: bool) -> Result<(), Error> {
+ if !buffer.len().is_multiple_of(8) {
+ return Err(Error::IncompleteBlock);
+ }
+ let mut scratch = [0u64; 128];
+ // SAFETY: buffer contains complete eight-byte blocks, including zero
+ // blocks. The buffer, schedule and scratch are separate valid objects
+ // and do not overlap the callee's stack.
+ unsafe {
+ if encrypt {
+ vg_triple_des_ecb_encrypt(
+ &self.schedule,
+ buffer.as_mut_ptr().cast(),
+ buffer.len() / 8,
+ &mut scratch,
+ );
+ } else {
+ vg_triple_des_ecb_decrypt(
+ &self.schedule,
+ buffer.as_mut_ptr().cast(),
+ buffer.len() / 8,
+ &mut scratch,
+ );
+ }
+ }
+ zeroize(&mut scratch);
+ Ok(())
+ }
+}
+
+impl Drop for TripleDesEcb {
+ fn drop(&mut self) {
+ zeroize(&mut self.schedule);
+ }
+}
diff --git a/tests/cavp/main.rs b/tests/cavp/main.rs
index ac84ee685..ce75fc6d4 100644
--- a/tests/cavp/main.rs
+++ b/tests/cavp/main.rs
@@ -21,6 +21,7 @@ mod sha224;
mod sha256;
mod sha3;
mod sha512;
+mod triple_des_ecb;
/// The `key = value` lines of a CAVP response file, in order, without the
/// comments, blank lines and `[L = ...]` section headers.
diff --git a/tests/cavp/triple_des_ecb.rs b/tests/cavp/triple_des_ecb.rs
new file mode 100644
index 000000000..631471115
--- /dev/null
+++ b/tests/cavp/triple_des_ecb.rs
@@ -0,0 +1,154 @@
+//! NIST CAVP ECB vectors, with unmodified sources under vectors/.
+
+#![cfg(target_arch = "x86_64")]
+
+use std::collections::BTreeMap;
+
+use verified_garbage::triple_des_ecb::{Error, TripleDesEcb};
+
+use super::unhex;
+
+fn check(key: &[u8], plaintext: &[u8], ciphertext: &[u8], split: bool) {
+ assert_eq!(plaintext.len(), ciphertext.len());
+ let ctx = TripleDesEcb::new(key).unwrap();
+ let parity: Vec<_> = key.iter().map(|byte| byte ^ 1).collect();
+ let parity_ctx = TripleDesEcb::new(&parity).unwrap();
+ for (operation, input, expected) in [
+ (
+ TripleDesEcb::encrypt as fn(&TripleDesEcb, &mut [u8]) -> Result<(), Error>,
+ plaintext,
+ ciphertext,
+ ),
+ (
+ TripleDesEcb::decrypt as fn(&TripleDesEcb, &mut [u8]) -> Result<(), Error>,
+ ciphertext,
+ plaintext,
+ ),
+ ] {
+ for key_ctx in [&ctx, &parity_ctx] {
+ let mut output = input.to_vec();
+ operation(key_ctx, &mut output).unwrap();
+ assert_eq!(output, expected);
+ }
+ if split {
+ for offset in (0..=input.len()).step_by(8) {
+ let mut output = input.to_vec();
+ operation(&ctx, &mut []).unwrap();
+ operation(&ctx, &mut output[..offset]).unwrap();
+ operation(&ctx, &mut []).unwrap();
+ operation(&ctx, &mut output[offset..]).unwrap();
+ assert_eq!(output, expected);
+ }
+ let mut output = input.to_vec();
+ for block in output.chunks_mut(8) {
+ operation(&ctx, block).unwrap();
+ }
+ assert_eq!(output, expected);
+ }
+ }
+}
+
+fn check_file(text: &str, stream: bool) -> usize {
+ let mut count = 0;
+ for record in text.replace('\r', "").split("\n\n") {
+ let fields: BTreeMap<_, _> = record
+ .lines()
+ .filter_map(|line| line.trim().split_once(" = "))
+ .collect();
+ if !fields.contains_key("COUNT") {
+ continue;
+ }
+ let key = if let Some(key) = fields.get("KEYs") {
+ let key = unhex(key);
+ key.repeat(3)
+ } else {
+ let mut key = unhex(fields["KEY1"]);
+ key.extend(unhex(fields["KEY2"]));
+ key.extend(unhex(fields["KEY3"]));
+ key
+ };
+ let plaintext = unhex(fields["PLAINTEXT"]);
+ let ciphertext = unhex(fields["CIPHERTEXT"]);
+ check(&key, &plaintext, &ciphertext, stream);
+ if key[..8] == key[16..] {
+ check(&key[..16], &plaintext, &ciphertext, stream);
+ }
+ count += 1;
+ }
+ count
+}
+
+#[test]
+fn nist_ecb() {
+ let files = [
+ (
+ include_str!("../../vectors/nist-cavp-tdes-kat/TECBsubtab.rsp"),
+ 38,
+ false,
+ ),
+ (
+ include_str!("../../vectors/nist-cavp-tdes-kat/TECBpermop.rsp"),
+ 64,
+ false,
+ ),
+ (
+ include_str!("../../vectors/nist-cavp-tdes-kat/TECBvarkey.rsp"),
+ 112,
+ false,
+ ),
+ (
+ include_str!("../../vectors/nist-cavp-tdes-kat/TECBvartext.rsp"),
+ 128,
+ false,
+ ),
+ (
+ include_str!("../../vectors/nist-cavp-tdes-kat/TECBinvperm.rsp"),
+ 128,
+ false,
+ ),
+ (
+ include_str!("../../vectors/nist-cavp-tdes-mmt/TECBMMT2.rsp"),
+ 10,
+ true,
+ ),
+ (
+ include_str!("../../vectors/nist-cavp-tdes-mmt/TECBMMT3.rsp"),
+ 20,
+ true,
+ ),
+ ];
+ let mut total = 0;
+ for (text, expected, stream) in files {
+ let count = check_file(text, stream);
+ assert_eq!(count, expected);
+ total += count;
+ }
+ assert_eq!(total, 500);
+}
+
+#[test]
+fn limits_and_empty_input() {
+ for len in 0..=33 {
+ let key: Vec<_> = (0..len).map(|i| (17 * i + 3) as u8).collect();
+ if len == 16 || len == 24 {
+ let ctx = TripleDesEcb::new(&key).unwrap();
+ ctx.encrypt(&mut []).unwrap();
+ ctx.decrypt(&mut []).unwrap();
+ for n in 1usize..24 {
+ if n.is_multiple_of(8) {
+ continue;
+ }
+ let mut buffer = vec![0x5a; n];
+ assert_eq!(ctx.encrypt(&mut buffer), Err(Error::IncompleteBlock));
+ assert_eq!(buffer, vec![0x5a; n]);
+ assert_eq!(ctx.decrypt(&mut buffer), Err(Error::IncompleteBlock));
+ assert_eq!(buffer, vec![0x5a; n]);
+ }
+ } else {
+ assert!(matches!(
+ TripleDesEcb::new(&key),
+ Err(Error::InvalidKeyLength)
+ ));
+ }
+ }
+}