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) + )); + } + } +}